diff --git a/.eslintignore b/.eslintignore index 6188469f2c..c3b14aeff3 100644 --- a/.eslintignore +++ b/.eslintignore @@ -20,3 +20,4 @@ website/src/_posts/2021-03-*.md website/src/_posts/2021-04-*.md website/src/_posts/2021-05-*.md website/src/_posts/2021-06-*.md +private/remark-lint-uppy/index.js diff --git a/.remarkignore b/.remarkignore new file mode 100644 index 0000000000..d6ba4f2afb --- /dev/null +++ b/.remarkignore @@ -0,0 +1,6 @@ +website/src/_posts/201* +website/src/_posts/2020-* +website/src/_posts/2021-0* +examples/ +CHANGELOG.md +BACKLOG.md diff --git a/BUNDLE-README.md b/BUNDLE-README.md index e55b3bdc1f..25c80939df 100644 --- a/BUNDLE-README.md +++ b/BUNDLE-README.md @@ -1,17 +1,17 @@ # Uppy Hi, thanks for trying out the bundled version of the Uppy File Uploader. You can use -this from a CDN (e.g. ``) or bundle it with your webapp. +this from a CDN (``) or bundle it with your webapp. -Note that the recommended way to use Uppy is to install it with yarn/npm and use a -bundler like Webpack so that you can create a smaller custom build with just the +Note that the recommended way to use Uppy is to install it with yarn/npm and use a +bundler like Webpack so that you can create a smaller custom build with only the things that you need. More info on . ## How to use this bundle -You can extract the contents of this zip to e.g. `./js/uppy` +You can extract the contents of this zip to a directory, such as `./js/uppy`. -Now you can create an HTML file, e.g.: `./upload.html` with the following contents: +Now you can create an HTML file, for example `./upload.html`, with the following contents: ```html @@ -62,10 +62,10 @@ Now open `upload.html` in your browser, and the Uppy Dashboard will appear. ## Next steps -In the example you just built, Uppy uploads to a demo server where files will be deleted -shortly after uploading. You'll want to target your own tusd server, S3 bucket, or Nginx/Apache server. For the latter, use the Xhr plugin: which uploads using regular multipart form posts, that you'll existing Ruby or PHP backend will be able to make sense of, just as if a `` had been used. +In the example you built, Uppy uploads to a demo server where files will be deleted +shortly after uploading. You’ll want to target your own tusd server, S3 bucket, or Nginx/Apache server. For the latter, use the Xhr plugin: which uploads using regular multipart form posts, that you’ll existing Ruby or PHP backend will be able to make sense of, as if a `` had been used. -The Dashboard currently opens when clicking the button, but you can also draw it inline into the page. This, and many more configuration options can be found here: . +The Dashboard now opens when clicking the button, but you can also draw it inline into the page. This, and many more configuration options can be found here: . Uppy has many more Plugins besides Xhr and the Dashboard. For example, you can enable Webcam, Instagram, or video encoding support. For a full list of Plugins check here: . @@ -73,4 +73,4 @@ Note that for some Plugins, you will need to run a server side component called: ## Getting help -Stuck with anything? We're welcoming all your questions and feedback over at . +Stuck with anything? We’re welcoming all your questions and feedback over at . diff --git a/CHANGELOG.md b/CHANGELOG.md index f6554e8e9f..76ba4d280c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,42 @@ Please add your entries in this format: In the current stage we aim to release a new version at least every month. +## 2.2.1 + +Released: 2021-10-14 + +| Package | Version | Package | Version | +|-|-|-|-| +| @uppy/angular | 0.2.5 | @uppy/provider-views | 2.0.4 | +| @uppy/aws-s3-multipart | 2.1.1 | @uppy/react-native | 0.2.4 | +| @uppy/aws-s3 | 2.0.5 | @uppy/react | 2.1.1 | +| @uppy/box | 1.0.4 | @uppy/redux-dev-tools | 2.0.3 | +| @uppy/companion-client | 2.0.3 | @uppy/robodog | 2.1.1 | +| @uppy/companion | 3.1.1 | @uppy/screen-capture | 2.0.4 | +| @uppy/core | 2.1.1 | @uppy/status-bar | 2.1.1 | +| @uppy/dashboard | 2.1.1 | @uppy/store-default | 2.0.2 | +| @uppy/drag-drop | 2.0.4 | @uppy/store-redux | 2.0.2 | +| @uppy/drop-target | 1.1.1 | @uppy/svelte | 1.0.5 | +| @uppy/dropbox | 2.0.4 | @uppy/thumbnail-generator | 2.0.5 | +| @uppy/facebook | 2.0.4 | @uppy/transloadit | 2.0.4 | +| @uppy/file-input | 2.0.4 | @uppy/tus | 2.1.1 | +| @uppy/form | 2.0.4 | @uppy/unsplash | 2.0.1 | +| @uppy/golden-retriever | 2.0.5 | @uppy/url | 2.0.4 | +| @uppy/google-drive | 2.0.4 | @uppy/utils | 4.0.3 | +| @uppy/image-editor | 1.0.4 | @uppy/vue | 0.4.3 | +| @uppy/informer | 2.0.4 | @uppy/webcam | 2.0.4 | +| @uppy/instagram | 2.0.4 | @uppy/xhr-upload | 2.0.5 | +| @uppy/locales | 2.0.3 | @uppy/zoom | 1.0.4 | +| @uppy/onedrive | 2.0.4 | uppy | 2.2.1 | +| @uppy/progress-bar | 2.0.4 | - | - | + +- @uppy/locale: Update ar_SA.js (issa.ahmd@gmail.com / #3192) +- @uppy/status-bar: fix `calculateProcessingProgress` is not a function (@aduh95 / #3261) +- @uppy/status-bar: Progress object is nested (@arturi / #3262) +- build: Add retext to markdown linter (@aduh95 / #3024) +- build: Bump tar from 6.1.2 to 6.1.9 (dependabot / #3152) +- website: Revert "Remove broken link in `plugin_list.ejs` (@aduh95 / #3166) + ## 2.2.0 Released: 2021-10-06 diff --git a/README.md b/README.md index f94fb8e337..2d7cfd72a6 100644 --- a/README.md +++ b/README.md @@ -9,11 +9,11 @@ | Tests | CI status for Uppy tests | CI status for Companion tests | CI status for browser tests | | Deploys | CI status for CDN deployment | CI status for Companion deployment | CI status for website deployment | -Uppy is a sleek, modular JavaScript file uploader that integrates seamlessly with any application. It’s fast, easy to use and lets you worry about more important problems than building a file uploader. +Uppy is a sleek, modular JavaScript file uploader that integrates seamlessly with any application. It’s fast, has a comprehensible API and lets you worry about more important problems than building a file uploader. -- **Fetch** files from local disk, remote URLs, Google Drive, Dropbox, Box, Instagram or snap and record selfies with a camera -- **Preview** and edit metadata with a nice interface -- **Upload** to the final destination, optionally process/encode +* **Fetch** files from local disk, remote URLs, Google Drive, Dropbox, Box, Instagram or snap and record selfies with a camera +* **Preview** and edit metadata with a nice interface +* **Upload** to the final destination, optionally process/encode @@ -50,37 +50,37 @@ const uppy = new Uppy({ autoProceed: false }) ## Features -- Lightweight, modular plugin-based architecture, easy on dependencies :zap: -- Resumable file uploads via the open [tus](https://tus.io/) standard, so large uploads survive network hiccups -- Supports picking files from: Webcam, Dropbox, Box, Google Drive, Instagram, bypassing the user’s device where possible, syncing between servers directly via [@uppy/companion](https://uppy.io/docs/companion) -- Works great with file encoding and processing backends, such as [Transloadit](https://transloadit.com), works great without (just roll your own Apache/Nginx/Node/FFmpeg/etc backend) -- Sleek user interface :sparkles: -- Optional file recovery (after a browser crash) with [Golden Retriever](https://uppy.io/docs/golden-retriever/) -- Speaks multiple languages (i18n) :earth_africa: -- Built with accessibility in mind -- Free for the world, forever (as in beer 🍺, pizza 🍕, and liberty 🗽) -- Cute as a puppy, also accepts cat pictures :dog: +* Lightweight, modular plugin-based architecture, light on dependencies :zap: +* Resumable file uploads via the open [tus](https://tus.io/) standard, so large uploads survive network hiccups +* Supports picking files from: Webcam, Dropbox, Box, Google Drive, Instagram, bypassing the user’s device where possible, syncing between servers directly via [@uppy/companion](https://uppy.io/docs/companion) +* Works great with file encoding and processing backends, such as [Transloadit](https://transloadit.com), works great without (all you need is to roll your own Apache/Nginx/Node/FFmpeg/etc backend) +* Sleek user interface :sparkles: +* Optional file recovery (after a browser crash) with [Golden Retriever](https://uppy.io/docs/golden-retriever/) +* Speaks several languages (i18n) :earth\_africa: +* Built with accessibility in mind +* Free for the world, forever (as in beer 🍺, pizza 🍕, and liberty 🗽) +* Cute as a puppy, also accepts cat pictures :dog: ## Installation -``` bash +```bash $ npm install @uppy/core @uppy/dashboard @uppy/tus ``` We recommend installing from npm and then using a module bundler such as [Webpack](https://webpack.js.org/), [Browserify](http://browserify.org/) or [Rollup.js](http://rollupjs.org/). -Add CSS [uppy.min.css](https://releases.transloadit.com/uppy/v2.2.0/uppy.min.css), either to your HTML page's `` or include in JS, if your bundler of choice supports it — transforms and plugins are available for Browserify and Webpack. +Add CSS [uppy.min.css](https://releases.transloadit.com/uppy/v2.2.1/uppy.min.css), either to your HTML page’s `` or include in JS, if your bundler of choice supports it — transforms and plugins are available for Browserify and Webpack. -Alternatively, you can also use a pre-built bundle from Transloadit's CDN: Edgly. In that case `Uppy` will attach itself to the global `window.Uppy` object. +Alternatively, you can also use a pre-built bundle from Transloadit’s CDN: Edgly. In that case `Uppy` will attach itself to the global `window.Uppy` object. -> ⚠️ The bundle currently consists of most Uppy plugins, so this method is not recommended for production, as your users will have to download all plugins when you are likely using just a few. +> ⚠️ The bundle consists of most Uppy plugins, so this method is not recommended for production, as your users will have to download all plugins when you are likely using only a few. ```html - + - +
@@ -93,11 +93,11 @@ Alternatively, you can also use a pre-built bundle from Transloadit's CDN: Edgly ## Documentation -- [Uppy](https://uppy.io/docs/uppy/) — full list of options, methods and events -- [Plugins](https://uppy.io/docs/plugins/) — list of Uppy plugins and their options -- [Companion](https://uppy.io/docs/companion/) — setting up and running a Companion instance, which adds support for Instagram, Dropbox, Box, Google Drive and remote URLs -- [React](https://uppy.io/docs/react/) — components to integrate Uppy UI plugins with React apps -- [Architecture & Writing a Plugin](https://uppy.io/docs/writing-plugins/) — how to write a plugin for Uppy +* [Uppy](https://uppy.io/docs/uppy/) — full list of options, methods and events +* [Plugins](https://uppy.io/docs/plugins/) — list of Uppy plugins and their options +* [Companion](https://uppy.io/docs/companion/) — setting up and running a Companion instance, which adds support for Instagram, Dropbox, Box, Google Drive and remote URLs +* [React](https://uppy.io/docs/react/) — components to integrate Uppy UI plugins with React apps +* [Architecture & Writing a Plugin](https://uppy.io/docs/writing-plugins/) — how to write a plugin for Uppy ## Plugins @@ -105,49 +105,49 @@ Alternatively, you can also use a pre-built bundle from Transloadit's CDN: Edgly ### UI Elements -- [`Dashboard`](https://uppy.io/docs/dashboard/) — universal UI with previews, progress bars, metadata editor and all the cool stuff. Required for most UI plugins like Webcam and Instagram -- [`Progress Bar`](https://uppy.io/docs/progress-bar/) — minimal progress bar that fills itself when upload progresses -- [`Status Bar`](https://uppy.io/docs/status-bar/) — more detailed progress, pause/resume/cancel buttons, percentage, speed, uploaded/total sizes (included by default with `Dashboard`) -- [`Informer`](https://uppy.io/docs/informer/) — send notifications like “smile” before taking a selfie or “upload failed” when all is lost (also included by default with `Dashboard`) +* [`Dashboard`](https://uppy.io/docs/dashboard/) — universal UI with previews, progress bars, metadata editor and all the cool stuff. Required for most UI plugins like Webcam and Instagram +* [`Progress Bar`](https://uppy.io/docs/progress-bar/) — minimal progress bar that fills itself when upload progresses +* [`Status Bar`](https://uppy.io/docs/status-bar/) — more detailed progress, pause/resume/cancel buttons, percentage, speed, uploaded/total sizes (included by default with `Dashboard`) +* [`Informer`](https://uppy.io/docs/informer/) — send notifications like “smile” before taking a selfie or “upload failed” when all is lost (also included by default with `Dashboard`) ### Sources -- [`Drag & Drop`](https://uppy.io/docs/drag-drop/) — plain and simple drag and drop area -- [`File Input`](https://uppy.io/docs/file-input/) — even plainer “select files” button -- [`Webcam`](https://uppy.io/docs/webcam/) — snap and record those selfies 📷 -- ⓒ [`Google Drive`](https://uppy.io/docs/google-drive/) — import files from Google Drive -- ⓒ [`Dropbox`](https://uppy.io/docs/dropbox/) — import files from Dropbox -- ⓒ [`Box`](https://uppy.io/docs/box/) — import files from Box -- ⓒ [`Instagram`](https://uppy.io/docs/instagram/) — import images and videos from Instagram -- ⓒ [`Facebook`](https://uppy.io/docs/facebook/) — import images and videos from Facebook -- ⓒ [`OneDrive`](https://uppy.io/docs/onedrive/) — import files from Microsoft OneDrive -- ⓒ [`Import From URL`](https://uppy.io/docs/url/) — import direct URLs from anywhere on the web +* [`Drag & Drop`](https://uppy.io/docs/drag-drop/) — plain drag and drop area +* [`File Input`](https://uppy.io/docs/file-input/) — even plainer “select files” button +* [`Webcam`](https://uppy.io/docs/webcam/) — snap and record those selfies 📷 +* ⓒ [`Google Drive`](https://uppy.io/docs/google-drive/) — import files from Google Drive +* ⓒ [`Dropbox`](https://uppy.io/docs/dropbox/) — import files from Dropbox +* ⓒ [`Box`](https://uppy.io/docs/box/) — import files from Box +* ⓒ [`Instagram`](https://uppy.io/docs/instagram/) — import images and videos from Instagram +* ⓒ [`Facebook`](https://uppy.io/docs/facebook/) — import images and videos from Facebook +* ⓒ [`OneDrive`](https://uppy.io/docs/onedrive/) — import files from Microsoft OneDrive +* ⓒ [`Import From URL`](https://uppy.io/docs/url/) — import direct URLs from anywhere on the web The ⓒ mark means that [`@uppy/companion`](https://uppy.io/docs/companion), a server-side component, is needed for a plugin to work. ### Destinations -- [`Tus`](https://uppy.io/docs/tus/) — resumable uploads via the open [tus](http://tus.io) standard -- [`XHR Upload`](https://uppy.io/docs/xhr-upload/) — regular uploads for any backend out there (like Apache, Nginx) -- [`AWS S3`](https://uppy.io/docs/aws-s3/) — plain upload to AWS S3 or compatible services -- [`AWS S3 Multipart`](https://uppy.io/docs/aws-s3-multipart/) — S3-style "Multipart" upload to AWS or compatible services +* [`Tus`](https://uppy.io/docs/tus/) — resumable uploads via the open [tus](http://tus.io) standard +* [`XHR Upload`](https://uppy.io/docs/xhr-upload/) — regular uploads for any backend out there (like Apache, Nginx) +* [`AWS S3`](https://uppy.io/docs/aws-s3/) — plain upload to AWS S3 or compatible services +* [`AWS S3 Multipart`](https://uppy.io/docs/aws-s3-multipart/) — S3-style “Multipart” upload to AWS or compatible services ### File Processing -- [`Robodog`](https://uppy.io/docs/robodog/) — user friendly abstraction to do file processing with Transloadit -- [`Transloadit`](https://uppy.io/docs/transloadit/) — support for [Transloadit](http://transloadit.com)’s robust file uploading and encoding backend +* [`Robodog`](https://uppy.io/docs/robodog/) — user friendly abstraction to do file processing with Transloadit +* [`Transloadit`](https://uppy.io/docs/transloadit/) — support for [Transloadit](http://transloadit.com)’s robust file uploading and encoding backend ### Miscellaneous -- [`Golden Retriever`](https://uppy.io/docs/golden-retriever/) — restores files after a browser crash, like it’s nothing -- [`Thumbnail Generator`](https://uppy.io/docs/thumbnail-generator/) — generates image previews (included by default with `Dashboard`) -- [`Form`](https://uppy.io/docs/form/) — collects metadata from `
` right before an Uppy upload, then optionally appends results back to the form -- [`Redux`](https://uppy.io/docs/redux/) — for your emerging [time traveling](https://github.com/gaearon/redux-devtools) needs +* [`Golden Retriever`](https://uppy.io/docs/golden-retriever/) — restores files after a browser crash, like it’s nothing +* [`Thumbnail Generator`](https://uppy.io/docs/thumbnail-generator/) — generates image previews (included by default with `Dashboard`) +* [`Form`](https://uppy.io/docs/form/) — collects metadata from `` right before an Uppy upload, then optionally appends results back to the form +* [`Redux`](https://uppy.io/docs/redux/) — for your emerging [time traveling](https://github.com/gaearon/redux-devtools) needs ## React -- [React](https://uppy.io/docs/react/) — components to integrate Uppy UI plugins with React apps -- [React Native](https://uppy.io//docs/react/native/) — basic Uppy component for React Native with Expo +* [React](https://uppy.io/docs/react/) — components to integrate Uppy UI plugins with React apps +* [React Native](https://uppy.io//docs/react/native/) — basic Uppy component for React Native with Expo ## Browser Support @@ -161,15 +161,15 @@ We still provide a bundle which should work on IE11, but we are not running test ### Polyfills -Here's a list of polyfills you'll need to include to make Uppy work in older browsers, such as IE11: +Here’s a list of polyfills you’ll need to include to make Uppy work in older browsers, such as IE11: -- [abortcontroller-polyfill](https://github.com/mo/abortcontroller-polyfill) -- [core-js](https://github.com/zloirock/core-js) -- [md-gum-polyfill](https://github.com/mozdevs/mediaDevices-getUserMedia-polyfill) -- [resize-observer-polyfill](https://github.com/que-etc/resize-observer-polyfill) -- [whatwg-fetch](https://github.com/github/fetch) +* [abortcontroller-polyfill](https://github.com/mo/abortcontroller-polyfill) +* [core-js](https://github.com/zloirock/core-js) +* [md-gum-polyfill](https://github.com/mozdevs/mediaDevices-getUserMedia-polyfill) +* [resize-observer-polyfill](https://github.com/que-etc/resize-observer-polyfill) +* [whatwg-fetch](https://github.com/github/fetch) -If you're using a bundler, you need import them before Uppy: +If you’re using a bundler, you need import them before Uppy: ```js import 'core-js' @@ -186,36 +186,36 @@ export { default } from '@uppy/core' export * from '@uppy/core' ``` -If you're using Uppy from CDN, those polyfills are already included in the legacy +If you’re using Uppy from CDN, those polyfills are already included in the legacy bundle, so no need to include anything additionally: ```html - + ``` ## FAQ -### Why not just use ``? +### Why not use ``? Having no JavaScript beats having a lot of it, so that’s a fair question! Running an uploading & encoding business for ten years though we found that in cases, the file input leaves some to be desired: -- We received complaints about broken uploads and found that resumable uploads are important, especially for big files and to be inclusive towards people on poorer connections (we also launched [tus.io](https://tus.io) to attack that problem). Uppy uploads can survive network outages and browser crashes or accidental navigate-aways. -- Uppy supports editing meta information before uploading (and e.g. cropping is planned). -- There’s the situation where people are using their mobile devices and want to upload on the go, but they have their picture on Instagram, files in Dropbox or just a plain file URL from anywhere on the open web. Uppy allows to pick files from those and push it to the destination without downloading it to your mobile device first. -- Accurate upload progress reporting is an issue on many platforms. -- Some file validation — size, type, number of files — can be done on the client with Uppy. -- Uppy integrates webcam support, in case your users want to upload a picture/video/audio that does not exist yet :) -- A larger drag and drop surface can be pleasant to work with. Some people also like that you can control the styling, language, etc. -- Uppy is aware of encoding backends. Often after an upload, the server needs to rotate, detect faces, optimize for iPad, or what have you. Uppy can track progress of this and report back to the user in different ways. -- Sometimes you might want your uploads to happen while you continue to interact on the same single page. +* We received complaints about broken uploads and found that resumable uploads are important, especially for big files and to be inclusive towards people on poorer connections (we also launched [tus.io](https://tus.io) to attack that problem). Uppy uploads can survive network outages and browser crashes or accidental navigate-aways. +* Uppy supports editing meta information before uploading (such as cropping of images). +* There’s the situation where people are using their mobile devices and want to upload on the go, but they have their picture on Instagram, files in Dropbox or a plain file URL from anywhere on the open web. Uppy allows to pick files from those and push it to the destination without downloading it to your mobile device first. +* Accurate upload progress reporting is an issue on many platforms. +* Some file validation — size, type, number of files — can be done on the client with Uppy. +* Uppy integrates webcam support, in case your users want to upload a picture/video/audio that does not exist yet :) +* A larger drag and drop surface can be pleasant to work with. Some people also like that you can control the styling, language, etc. +* Uppy is aware of encoding backends. Often after an upload, the server needs to rotate, detect faces, optimize for iPad, or what have you. Uppy can track progress of this and report back to the user in different ways. +* Sometimes you might want your uploads to happen while you continue to interact on the same single page. -Not all apps need all of these features. An `` is fine in many situations. But these were a few things that our customers hit / asked about enough to spark us to develop Uppy. +Not all apps need all these features. An `` is fine in many situations. But these were a few things that our customers hit / asked about enough to spark us to develop Uppy. ### Why is all this goodness free? Transloadit’s team is small and we have a shared ambition to make a living from open source. By giving away projects like [tus.io](https://tus.io) and [Uppy](https://uppy.io), we’re hoping to advance the state of the art, make life a tiny little bit better for everyone and in doing so have rewarding jobs and get some eyes on our commercial service: [a content ingestion & processing platform](https://transloadit.com). -Our thinking is that if just a fraction of our open source userbase can see the appeal of hosted versions straight from the source, that could already be enough to sustain our work. So far this is working out! We’re able to dedicate 80% of our time to open source and haven’t gone bankrupt yet. :D +Our thinking is that if only a fraction of our open source userbase can see the appeal of hosted versions straight from the source, that could already be enough to sustain our work. So far this is working out! We’re able to dedicate 80% of our time to open source and haven’t gone bankrupt yet. :D ### Does Uppy support React? @@ -223,11 +223,11 @@ Yep, we have Uppy React components, please see [Uppy React docs](https://uppy.io ### Does Uppy support S3 uploads? -Yes, there is an S3 plugin, please check out the [docs](https://uppy.io/docs/aws-s3/) for more. +Yes, please check out the [docs](https://uppy.io/docs/aws-s3/) for more information. -### Do I need to install a special service/server for Uppy? Can I use it with Rails/Node/Go/PHP? +### Can I use Uppy with Rails/Node.js/Go/PHP? -Yes, whatever you want on the backend will work with `@uppy/xhr-upload` plugin, since it just does a `POST` or `PUT` request. Here’s a [PHP backend example](https://uppy.io/docs/xhr-upload/#Uploading-to-a-PHP-Server). +Yes, whatever you want on the backend will work with `@uppy/xhr-upload` plugin, since it only does a `POST` or `PUT` request. Here’s a [PHP backend example](https://uppy.io/docs/xhr-upload/#Uploading-to-a-PHP-Server). If you want resumability with the Tus plugin, use [one of the tus server implementations](https://tus.io/implementations.html) 👌🏼 @@ -235,8 +235,8 @@ And you’ll need [`@uppy/companion`](https://uppy.io/docs/companion) if you’d ## Contributions are welcome -- Contributor’s guide in [`.github/CONTRIBUTING.md`](.github/CONTRIBUTING.md) -- Changelog to track our release progress (we aim to roll out a release every month): [`CHANGELOG.md`](CHANGELOG.md) +* Contributor’s guide in [`.github/CONTRIBUTING.md`](.github/CONTRIBUTING.md) +* Changelog to track our release progress (we aim to roll out a release every month): [`CHANGELOG.md`](CHANGELOG.md) ## Used by @@ -247,6 +247,7 @@ Use Uppy in your project? [Let us know](https://github.com/transloadit/uppy/issu ## Contributors + [arturi](https://github.com/arturi) |[goto-bus-stop](https://github.com/goto-bus-stop) |[kvz](https://github.com/kvz) |[ifedapoolarewaju](https://github.com/ifedapoolarewaju) |[hedgerh](https://github.com/hedgerh) |[AJvanLoon](https://github.com/AJvanLoon) | :---: |:---: |:---: |:---: |:---: |:---: | [arturi](https://github.com/arturi) |[goto-bus-stop](https://github.com/goto-bus-stop) |[kvz](https://github.com/kvz) |[ifedapoolarewaju](https://github.com/ifedapoolarewaju) |[hedgerh](https://github.com/hedgerh) |[AJvanLoon](https://github.com/AJvanLoon) | @@ -257,7 +258,7 @@ Use Uppy in your project? [Let us know](https://github.com/transloadit/uppy/issu [samuelayo](https://github.com/samuelayo) |[richardwillars](https://github.com/richardwillars) |[mifi](https://github.com/mifi) |[ajkachnic](https://github.com/ajkachnic) |[dependabot[bot]](https://github.com/apps/dependabot) |[zcallan](https://github.com/zcallan) | :---: |:---: |:---: |:---: |:---: |:---: | -[samuelayo](https://github.com/samuelayo) |[richardwillars](https://github.com/richardwillars) |[mifi](https://github.com/mifi) |[ajkachnic](https://github.com/ajkachnic) |[dependabot[bot]](https://github.com/apps/dependabot) |[zcallan](https://github.com/zcallan) | +[samuelayo](https://github.com/samuelayo) |[richardwillars](https://github.com/richardwillars) |[mifi](https://github.com/mifi) |[ajkachnic](https://github.com/ajkachnic) |[dependabot\[bot\]](https://github.com/apps/dependabot) |[zcallan](https://github.com/zcallan) | [tim-kos](https://github.com/tim-kos) |[janko](https://github.com/janko) |[wilkoklak](https://github.com/wilkoklak) |[oliverpool](https://github.com/oliverpool) |[Botz](https://github.com/Botz) |[mcallistertyler](https://github.com/mcallistertyler) | :---: |:---: |:---: |:---: |:---: |:---: | @@ -315,143 +316,139 @@ Use Uppy in your project? [Let us know](https://github.com/transloadit/uppy/issu :---: |:---: |:---: |:---: |:---: |:---: | [olemoign](https://github.com/olemoign) |[ajschmidt8](https://github.com/ajschmidt8) |[superhawk610](https://github.com/superhawk610) |[abannach](https://github.com/abannach) |[adamelmore](https://github.com/adamelmore) |[ajh-sr](https://github.com/ajh-sr) | -[adamvigneault](https://github.com/adamvigneault) |[Adrrei](https://github.com/Adrrei) |[adritasharma](https://github.com/adritasharma) |[asmt3](https://github.com/asmt3) |[alexnj](https://github.com/alexnj) |[aalepis](https://github.com/aalepis) | +[adamvigneault](https://github.com/adamvigneault) |[Adrrei](https://github.com/Adrrei) |[adritasharma](https://github.com/adritasharma) |[ahmadissa](https://github.com/ahmadissa) |[asmt3](https://github.com/asmt3) |[alexnj](https://github.com/alexnj) | :---: |:---: |:---: |:---: |:---: |:---: | -[adamvigneault](https://github.com/adamvigneault) |[Adrrei](https://github.com/Adrrei) |[adritasharma](https://github.com/adritasharma) |[asmt3](https://github.com/asmt3) |[alexnj](https://github.com/alexnj) |[aalepis](https://github.com/aalepis) | +[adamvigneault](https://github.com/adamvigneault) |[Adrrei](https://github.com/Adrrei) |[adritasharma](https://github.com/adritasharma) |[ahmadissa](https://github.com/ahmadissa) |[asmt3](https://github.com/asmt3) |[alexnj](https://github.com/alexnj) | -[Dogfalo](https://github.com/Dogfalo) |[tekacs](https://github.com/tekacs) |[amitport](https://github.com/amitport) |[functino](https://github.com/functino) |[radarhere](https://github.com/radarhere) |[superandrew213](https://github.com/superandrew213) | +[aalepis](https://github.com/aalepis) |[Dogfalo](https://github.com/Dogfalo) |[tekacs](https://github.com/tekacs) |[amitport](https://github.com/amitport) |[functino](https://github.com/functino) |[radarhere](https://github.com/radarhere) | :---: |:---: |:---: |:---: |:---: |:---: | -[Dogfalo](https://github.com/Dogfalo) |[tekacs](https://github.com/tekacs) |[amitport](https://github.com/amitport) |[functino](https://github.com/functino) |[radarhere](https://github.com/radarhere) |[superandrew213](https://github.com/superandrew213) | +[aalepis](https://github.com/aalepis) |[Dogfalo](https://github.com/Dogfalo) |[tekacs](https://github.com/tekacs) |[amitport](https://github.com/amitport) |[functino](https://github.com/functino) |[radarhere](https://github.com/radarhere) | -[andychongyz](https://github.com/andychongyz) |[anthony0030](https://github.com/anthony0030) |[Abourass](https://github.com/Abourass) |[arthurdenner](https://github.com/arthurdenner) |[apuyou](https://github.com/apuyou) |[atsawin](https://github.com/atsawin) | +[superandrew213](https://github.com/superandrew213) |[andychongyz](https://github.com/andychongyz) |[anthony0030](https://github.com/anthony0030) |[Abourass](https://github.com/Abourass) |[arthurdenner](https://github.com/arthurdenner) |[apuyou](https://github.com/apuyou) | :---: |:---: |:---: |:---: |:---: |:---: | -[andychongyz](https://github.com/andychongyz) |[anthony0030](https://github.com/anthony0030) |[Abourass](https://github.com/Abourass) |[arthurdenner](https://github.com/arthurdenner) |[apuyou](https://github.com/apuyou) |[atsawin](https://github.com/atsawin) | +[superandrew213](https://github.com/superandrew213) |[andychongyz](https://github.com/andychongyz) |[anthony0030](https://github.com/anthony0030) |[Abourass](https://github.com/Abourass) |[arthurdenner](https://github.com/arthurdenner) |[apuyou](https://github.com/apuyou) | -[ayhankesicioglu](https://github.com/ayhankesicioglu) |[azeemba](https://github.com/azeemba) |[azizk](https://github.com/azizk) |[bducharme](https://github.com/bducharme) |[Quorafind](https://github.com/Quorafind) |[wbaaron](https://github.com/wbaaron) | +[atsawin](https://github.com/atsawin) |[ayhankesicioglu](https://github.com/ayhankesicioglu) |[azeemba](https://github.com/azeemba) |[azizk](https://github.com/azizk) |[bducharme](https://github.com/bducharme) |[Quorafind](https://github.com/Quorafind) | :---: |:---: |:---: |:---: |:---: |:---: | -[ayhankesicioglu](https://github.com/ayhankesicioglu) |[azeemba](https://github.com/azeemba) |[azizk](https://github.com/azizk) |[bducharme](https://github.com/bducharme) |[Quorafind](https://github.com/Quorafind) |[wbaaron](https://github.com/wbaaron) | +[atsawin](https://github.com/atsawin) |[ayhankesicioglu](https://github.com/ayhankesicioglu) |[azeemba](https://github.com/azeemba) |[azizk](https://github.com/azizk) |[bducharme](https://github.com/bducharme) |[Quorafind](https://github.com/Quorafind) | -[bedgerotto](https://github.com/bedgerotto) |[cyu](https://github.com/cyu) |[cartfisk](https://github.com/cartfisk) |[cellvinchung](https://github.com/cellvinchung) |[chao](https://github.com/chao) |[Cretezy](https://github.com/Cretezy) | +[wbaaron](https://github.com/wbaaron) |[bedgerotto](https://github.com/bedgerotto) |[cyu](https://github.com/cyu) |[cartfisk](https://github.com/cartfisk) |[cellvinchung](https://github.com/cellvinchung) |[chao](https://github.com/chao) | :---: |:---: |:---: |:---: |:---: |:---: | -[bedgerotto](https://github.com/bedgerotto) |[cyu](https://github.com/cyu) |[cartfisk](https://github.com/cartfisk) |[cellvinchung](https://github.com/cellvinchung) |[chao](https://github.com/chao) |[Cretezy](https://github.com/Cretezy) | +[wbaaron](https://github.com/wbaaron) |[bedgerotto](https://github.com/bedgerotto) |[cyu](https://github.com/cyu) |[cartfisk](https://github.com/cartfisk) |[cellvinchung](https://github.com/cellvinchung) |[chao](https://github.com/chao) | -[csprance](https://github.com/csprance) |[Aarbel](https://github.com/Aarbel) |[cbush06](https://github.com/cbush06) |[czj](https://github.com/czj) |[ardeois](https://github.com/ardeois) |[sercraig](https://github.com/sercraig) | +[Cretezy](https://github.com/Cretezy) |[csprance](https://github.com/csprance) |[Aarbel](https://github.com/Aarbel) |[cbush06](https://github.com/cbush06) |[czj](https://github.com/czj) |[ardeois](https://github.com/ardeois) | :---: |:---: |:---: |:---: |:---: |:---: | -[csprance](https://github.com/csprance) |[Aarbel](https://github.com/Aarbel) |[cbush06](https://github.com/cbush06) |[czj](https://github.com/czj) |[ardeois](https://github.com/ardeois) |[sercraig](https://github.com/sercraig) | +[Cretezy](https://github.com/Cretezy) |[csprance](https://github.com/csprance) |[Aarbel](https://github.com/Aarbel) |[cbush06](https://github.com/cbush06) |[czj](https://github.com/czj) |[ardeois](https://github.com/ardeois) | -[Cruaier](https://github.com/Cruaier) |[danmichaelo](https://github.com/danmichaelo) |[danilat](https://github.com/danilat) |[mrboomer](https://github.com/mrboomer) |[akizor](https://github.com/akizor) |[davilima6](https://github.com/davilima6) | +[sercraig](https://github.com/sercraig) |[Cruaier](https://github.com/Cruaier) |[danmichaelo](https://github.com/danmichaelo) |[danilat](https://github.com/danilat) |[mrboomer](https://github.com/mrboomer) |[akizor](https://github.com/akizor) | :---: |:---: |:---: |:---: |:---: |:---: | -[Cruaier](https://github.com/Cruaier) |[danmichaelo](https://github.com/danmichaelo) |[danilat](https://github.com/danilat) |[mrboomer](https://github.com/mrboomer) |[akizor](https://github.com/akizor) |[davilima6](https://github.com/davilima6) | +[sercraig](https://github.com/sercraig) |[Cruaier](https://github.com/Cruaier) |[danmichaelo](https://github.com/danmichaelo) |[danilat](https://github.com/danilat) |[mrboomer](https://github.com/mrboomer) |[akizor](https://github.com/akizor) | -[DennisKofflard](https://github.com/DennisKofflard) |[jeetiss](https://github.com/jeetiss) |[sweetro](https://github.com/sweetro) |[efbautista](https://github.com/efbautista) |[yoldar](https://github.com/yoldar) |[eliOcs](https://github.com/eliOcs) | +[davilima6](https://github.com/davilima6) |[DennisKofflard](https://github.com/DennisKofflard) |[jeetiss](https://github.com/jeetiss) |[sweetro](https://github.com/sweetro) |[efbautista](https://github.com/efbautista) |[yoldar](https://github.com/yoldar) | :---: |:---: |:---: |:---: |:---: |:---: | -[DennisKofflard](https://github.com/DennisKofflard) |[jeetiss](https://github.com/jeetiss) |[sweetro](https://github.com/sweetro) |[efbautista](https://github.com/efbautista) |[yoldar](https://github.com/yoldar) |[eliOcs](https://github.com/eliOcs) | +[davilima6](https://github.com/davilima6) |[DennisKofflard](https://github.com/DennisKofflard) |[jeetiss](https://github.com/jeetiss) |[sweetro](https://github.com/sweetro) |[efbautista](https://github.com/efbautista) |[yoldar](https://github.com/yoldar) | -[EnricoSottile](https://github.com/EnricoSottile) |[epexa](https://github.com/epexa) |[Gkleinereva](https://github.com/Gkleinereva) |[fgallinari](https://github.com/fgallinari) |[ferdiusa](https://github.com/ferdiusa) |[dtrucs](https://github.com/dtrucs) | +[eliOcs](https://github.com/eliOcs) |[EnricoSottile](https://github.com/EnricoSottile) |[epexa](https://github.com/epexa) |[Gkleinereva](https://github.com/Gkleinereva) |[fgallinari](https://github.com/fgallinari) |[ferdiusa](https://github.com/ferdiusa) | :---: |:---: |:---: |:---: |:---: |:---: | -[EnricoSottile](https://github.com/EnricoSottile) |[epexa](https://github.com/epexa) |[Gkleinereva](https://github.com/Gkleinereva) |[fgallinari](https://github.com/fgallinari) |[ferdiusa](https://github.com/ferdiusa) |[dtrucs](https://github.com/dtrucs) | +[eliOcs](https://github.com/eliOcs) |[EnricoSottile](https://github.com/EnricoSottile) |[epexa](https://github.com/epexa) |[Gkleinereva](https://github.com/Gkleinereva) |[fgallinari](https://github.com/fgallinari) |[ferdiusa](https://github.com/ferdiusa) | -[geoffappleford](https://github.com/geoffappleford) |[gjungb](https://github.com/gjungb) |[roenschg](https://github.com/roenschg) |[HughbertD](https://github.com/HughbertD) |[HussainAlkhalifah](https://github.com/HussainAlkhalifah) |[huydod](https://github.com/huydod) | +[dtrucs](https://github.com/dtrucs) |[geoffappleford](https://github.com/geoffappleford) |[gjungb](https://github.com/gjungb) |[roenschg](https://github.com/roenschg) |[HughbertD](https://github.com/HughbertD) |[HussainAlkhalifah](https://github.com/HussainAlkhalifah) | :---: |:---: |:---: |:---: |:---: |:---: | -[geoffappleford](https://github.com/geoffappleford) |[gjungb](https://github.com/gjungb) |[roenschg](https://github.com/roenschg) |[HughbertD](https://github.com/HughbertD) |[HussainAlkhalifah](https://github.com/HussainAlkhalifah) |[huydod](https://github.com/huydod) | +[dtrucs](https://github.com/dtrucs) |[geoffappleford](https://github.com/geoffappleford) |[gjungb](https://github.com/gjungb) |[roenschg](https://github.com/roenschg) |[HughbertD](https://github.com/HughbertD) |[HussainAlkhalifah](https://github.com/HussainAlkhalifah) | -[IanVS](https://github.com/IanVS) |[ishendyweb](https://github.com/ishendyweb) |[NaxYo](https://github.com/NaxYo) |[eltociear](https://github.com/eltociear) |[intenzive](https://github.com/intenzive) |[GreenJimmy](https://github.com/GreenJimmy) | +[huydod](https://github.com/huydod) |[IanVS](https://github.com/IanVS) |[ishendyweb](https://github.com/ishendyweb) |[NaxYo](https://github.com/NaxYo) |[eltociear](https://github.com/eltociear) |[intenzive](https://github.com/intenzive) | :---: |:---: |:---: |:---: |:---: |:---: | -[IanVS](https://github.com/IanVS) |[ishendyweb](https://github.com/ishendyweb) |[NaxYo](https://github.com/NaxYo) |[eltociear](https://github.com/eltociear) |[intenzive](https://github.com/intenzive) |[GreenJimmy](https://github.com/GreenJimmy) | +[huydod](https://github.com/huydod) |[IanVS](https://github.com/IanVS) |[ishendyweb](https://github.com/ishendyweb) |[NaxYo](https://github.com/NaxYo) |[eltociear](https://github.com/eltociear) |[intenzive](https://github.com/intenzive) | -[mazoruss](https://github.com/mazoruss) |[JacobMGEvans](https://github.com/JacobMGEvans) |[jdssem](https://github.com/jdssem) |[Jbithell](https://github.com/Jbithell) |[jcjmcclean](https://github.com/jcjmcclean) |[janklimo](https://github.com/janklimo) | +[GreenJimmy](https://github.com/GreenJimmy) |[mazoruss](https://github.com/mazoruss) |[JacobMGEvans](https://github.com/JacobMGEvans) |[jdssem](https://github.com/jdssem) |[Jbithell](https://github.com/Jbithell) |[jcjmcclean](https://github.com/jcjmcclean) | :---: |:---: |:---: |:---: |:---: |:---: | -[mazoruss](https://github.com/mazoruss) |[JacobMGEvans](https://github.com/JacobMGEvans) |[jdssem](https://github.com/jdssem) |[Jbithell](https://github.com/Jbithell) |[jcjmcclean](https://github.com/jcjmcclean) |[janklimo](https://github.com/janklimo) | +[GreenJimmy](https://github.com/GreenJimmy) |[mazoruss](https://github.com/mazoruss) |[JacobMGEvans](https://github.com/JacobMGEvans) |[jdssem](https://github.com/jdssem) |[Jbithell](https://github.com/Jbithell) |[jcjmcclean](https://github.com/jcjmcclean) | -[janwilts](https://github.com/janwilts) |[vith](https://github.com/vith) |[jessica-coursera](https://github.com/jessica-coursera) |[Jmales](https://github.com/Jmales) |[theJoeBiz](https://github.com/theJoeBiz) |[profsmallpine](https://github.com/profsmallpine) | +[janklimo](https://github.com/janklimo) |[janwilts](https://github.com/janwilts) |[vith](https://github.com/vith) |[jessica-coursera](https://github.com/jessica-coursera) |[Jmales](https://github.com/Jmales) |[theJoeBiz](https://github.com/theJoeBiz) | :---: |:---: |:---: |:---: |:---: |:---: | -[janwilts](https://github.com/janwilts) |[vith](https://github.com/vith) |[jessica-coursera](https://github.com/jessica-coursera) |[Jmales](https://github.com/Jmales) |[theJoeBiz](https://github.com/theJoeBiz) |[profsmallpine](https://github.com/profsmallpine) | +[janklimo](https://github.com/janklimo) |[janwilts](https://github.com/janwilts) |[vith](https://github.com/vith) |[jessica-coursera](https://github.com/jessica-coursera) |[Jmales](https://github.com/Jmales) |[theJoeBiz](https://github.com/theJoeBiz) | -[jonathanarbely](https://github.com/jonathanarbely) |[jderrough](https://github.com/jderrough) |[jonathanly](https://github.com/jonathanly) |[jorgeepc](https://github.com/jorgeepc) |[jszobody](https://github.com/jszobody) |[julianocomg](https://github.com/julianocomg) | +[profsmallpine](https://github.com/profsmallpine) |[jonathanarbely](https://github.com/jonathanarbely) |[jderrough](https://github.com/jderrough) |[jonathanly](https://github.com/jonathanly) |[jorgeepc](https://github.com/jorgeepc) |[jszobody](https://github.com/jszobody) | :---: |:---: |:---: |:---: |:---: |:---: | -[jonathanarbely](https://github.com/jonathanarbely) |[jderrough](https://github.com/jderrough) |[jonathanly](https://github.com/jonathanly) |[jorgeepc](https://github.com/jorgeepc) |[jszobody](https://github.com/jszobody) |[julianocomg](https://github.com/julianocomg) | +[profsmallpine](https://github.com/profsmallpine) |[jonathanarbely](https://github.com/jonathanarbely) |[jderrough](https://github.com/jderrough) |[jonathanly](https://github.com/jonathanly) |[jorgeepc](https://github.com/jorgeepc) |[jszobody](https://github.com/jszobody) | -[jmontoyaa](https://github.com/jmontoyaa) |[tykarol](https://github.com/tykarol) |[firesharkstudios](https://github.com/firesharkstudios) |[elkebab](https://github.com/elkebab) |[kyleparisi](https://github.com/kyleparisi) |[lafe](https://github.com/lafe) | +[julianocomg](https://github.com/julianocomg) |[jmontoyaa](https://github.com/jmontoyaa) |[tykarol](https://github.com/tykarol) |[firesharkstudios](https://github.com/firesharkstudios) |[elkebab](https://github.com/elkebab) |[kyleparisi](https://github.com/kyleparisi) | :---: |:---: |:---: |:---: |:---: |:---: | -[jmontoyaa](https://github.com/jmontoyaa) |[tykarol](https://github.com/tykarol) |[firesharkstudios](https://github.com/firesharkstudios) |[elkebab](https://github.com/elkebab) |[kyleparisi](https://github.com/kyleparisi) |[lafe](https://github.com/lafe) | +[julianocomg](https://github.com/julianocomg) |[jmontoyaa](https://github.com/jmontoyaa) |[tykarol](https://github.com/tykarol) |[firesharkstudios](https://github.com/firesharkstudios) |[elkebab](https://github.com/elkebab) |[kyleparisi](https://github.com/kyleparisi) | -[leaanthony](https://github.com/leaanthony) |[larowlan](https://github.com/larowlan) |[dviry](https://github.com/dviry) |[galli-leo](https://github.com/galli-leo) |[leods92](https://github.com/leods92) |[louim](https://github.com/louim) | +[lafe](https://github.com/lafe) |[leaanthony](https://github.com/leaanthony) |[larowlan](https://github.com/larowlan) |[dviry](https://github.com/dviry) |[galli-leo](https://github.com/galli-leo) |[leods92](https://github.com/leods92) | :---: |:---: |:---: |:---: |:---: |:---: | -[leaanthony](https://github.com/leaanthony) |[larowlan](https://github.com/larowlan) |[dviry](https://github.com/dviry) |[galli-leo](https://github.com/galli-leo) |[leods92](https://github.com/leods92) |[louim](https://github.com/louim) | +[lafe](https://github.com/lafe) |[leaanthony](https://github.com/leaanthony) |[larowlan](https://github.com/larowlan) |[dviry](https://github.com/dviry) |[galli-leo](https://github.com/galli-leo) |[leods92](https://github.com/leods92) | -[lucaperret](https://github.com/lucaperret) |[lucax88x](https://github.com/lucax88x) |[onhate](https://github.com/onhate) |[mperrando](https://github.com/mperrando) |[marcosthejew](https://github.com/marcosthejew) |[marcusforsberg](https://github.com/marcusforsberg) | +[louim](https://github.com/louim) |[lucaperret](https://github.com/lucaperret) |[lucax88x](https://github.com/lucax88x) |[onhate](https://github.com/onhate) |[mperrando](https://github.com/mperrando) |[marcosthejew](https://github.com/marcosthejew) | :---: |:---: |:---: |:---: |:---: |:---: | -[lucaperret](https://github.com/lucaperret) |[lucax88x](https://github.com/lucax88x) |[onhate](https://github.com/onhate) |[mperrando](https://github.com/mperrando) |[marcosthejew](https://github.com/marcosthejew) |[marcusforsberg](https://github.com/marcusforsberg) | +[louim](https://github.com/louim) |[lucaperret](https://github.com/lucaperret) |[lucax88x](https://github.com/lucax88x) |[onhate](https://github.com/onhate) |[mperrando](https://github.com/mperrando) |[marcosthejew](https://github.com/marcosthejew) | -[Acconut](https://github.com/Acconut) |[martin-brennan](https://github.com/martin-brennan) |[masaok](https://github.com/masaok) |[mattfik](https://github.com/mattfik) |[matthewhartstonge](https://github.com/matthewhartstonge) |[hrsh](https://github.com/hrsh) | +[marcusforsberg](https://github.com/marcusforsberg) |[Acconut](https://github.com/Acconut) |[martin-brennan](https://github.com/martin-brennan) |[masaok](https://github.com/masaok) |[mattfik](https://github.com/mattfik) |[matthewhartstonge](https://github.com/matthewhartstonge) | :---: |:---: |:---: |:---: |:---: |:---: | -[Acconut](https://github.com/Acconut) |[martin-brennan](https://github.com/martin-brennan) |[masaok](https://github.com/masaok) |[mattfik](https://github.com/mattfik) |[matthewhartstonge](https://github.com/matthewhartstonge) |[hrsh](https://github.com/hrsh) | +[marcusforsberg](https://github.com/marcusforsberg) |[Acconut](https://github.com/Acconut) |[martin-brennan](https://github.com/martin-brennan) |[masaok](https://github.com/masaok) |[mattfik](https://github.com/mattfik) |[matthewhartstonge](https://github.com/matthewhartstonge) | -[mhulet](https://github.com/mhulet) |[mkopinsky](https://github.com/mkopinsky) |[achmiral](https://github.com/achmiral) |[mnafees](https://github.com/mnafees) |[shahimclt](https://github.com/shahimclt) |[pleasespammelater](https://github.com/pleasespammelater) | +[hrsh](https://github.com/hrsh) |[mhulet](https://github.com/mhulet) |[mkopinsky](https://github.com/mkopinsky) |[achmiral](https://github.com/achmiral) |[mnafees](https://github.com/mnafees) |[shahimclt](https://github.com/shahimclt) | :---: |:---: |:---: |:---: |:---: |:---: | -[mhulet](https://github.com/mhulet) |[mkopinsky](https://github.com/mkopinsky) |[achmiral](https://github.com/achmiral) |[mnafees](https://github.com/mnafees) |[shahimclt](https://github.com/shahimclt) |[pleasespammelater](https://github.com/pleasespammelater) | +[hrsh](https://github.com/hrsh) |[mhulet](https://github.com/mhulet) |[mkopinsky](https://github.com/mkopinsky) |[achmiral](https://github.com/achmiral) |[mnafees](https://github.com/mnafees) |[shahimclt](https://github.com/shahimclt) | -[naveed-ahmad](https://github.com/naveed-ahmad) |[nicojones](https://github.com/nicojones) |[coreprocess](https://github.com/coreprocess) |[nil1511](https://github.com/nil1511) |[leftdevel](https://github.com/leftdevel) |[cryptic022](https://github.com/cryptic022) | +[pleasespammelater](https://github.com/pleasespammelater) |[naveed-ahmad](https://github.com/naveed-ahmad) |[nicojones](https://github.com/nicojones) |[coreprocess](https://github.com/coreprocess) |[nil1511](https://github.com/nil1511) |[leftdevel](https://github.com/leftdevel) | :---: |:---: |:---: |:---: |:---: |:---: | -[naveed-ahmad](https://github.com/naveed-ahmad) |[nicojones](https://github.com/nicojones) |[coreprocess](https://github.com/coreprocess) |[nil1511](https://github.com/nil1511) |[leftdevel](https://github.com/leftdevel) |[cryptic022](https://github.com/cryptic022) | +[pleasespammelater](https://github.com/pleasespammelater) |[naveed-ahmad](https://github.com/naveed-ahmad) |[nicojones](https://github.com/nicojones) |[coreprocess](https://github.com/coreprocess) |[nil1511](https://github.com/nil1511) |[leftdevel](https://github.com/leftdevel) | -[patricklindsay](https://github.com/patricklindsay) |[pedrofs](https://github.com/pedrofs) |[phillipalexander](https://github.com/phillipalexander) |[ppadmavilasom](https://github.com/ppadmavilasom) |[Pzoco](https://github.com/Pzoco) |[eman8519](https://github.com/eman8519) | +[cryptic022](https://github.com/cryptic022) |[patricklindsay](https://github.com/patricklindsay) |[pedrofs](https://github.com/pedrofs) |[phillipalexander](https://github.com/phillipalexander) |[ppadmavilasom](https://github.com/ppadmavilasom) |[Pzoco](https://github.com/Pzoco) | :---: |:---: |:---: |:---: |:---: |:---: | -[patricklindsay](https://github.com/patricklindsay) |[pedrofs](https://github.com/pedrofs) |[phillipalexander](https://github.com/phillipalexander) |[ppadmavilasom](https://github.com/ppadmavilasom) |[Pzoco](https://github.com/Pzoco) |[eman8519](https://github.com/eman8519) | +[cryptic022](https://github.com/cryptic022) |[patricklindsay](https://github.com/patricklindsay) |[pedrofs](https://github.com/pedrofs) |[phillipalexander](https://github.com/phillipalexander) |[ppadmavilasom](https://github.com/ppadmavilasom) |[Pzoco](https://github.com/Pzoco) | -[luarmr](https://github.com/luarmr) |[SxDx](https://github.com/SxDx) |[robwilson1](https://github.com/robwilson1) |[romain-preston](https://github.com/romain-preston) |[scherroman](https://github.com/scherroman) |[rossng](https://github.com/rossng) | +[eman8519](https://github.com/eman8519) |[luarmr](https://github.com/luarmr) |[SxDx](https://github.com/SxDx) |[robwilson1](https://github.com/robwilson1) |[romain-preston](https://github.com/romain-preston) |[scherroman](https://github.com/scherroman) | :---: |:---: |:---: |:---: |:---: |:---: | -[luarmr](https://github.com/luarmr) |[SxDx](https://github.com/SxDx) |[robwilson1](https://github.com/robwilson1) |[romain-preston](https://github.com/romain-preston) |[scherroman](https://github.com/scherroman) |[rossng](https://github.com/rossng) | +[eman8519](https://github.com/eman8519) |[luarmr](https://github.com/luarmr) |[SxDx](https://github.com/SxDx) |[robwilson1](https://github.com/robwilson1) |[romain-preston](https://github.com/romain-preston) |[scherroman](https://github.com/scherroman) | -[rart](https://github.com/rart) |[fortunto2](https://github.com/fortunto2) |[samuelcolburn](https://github.com/samuelcolburn) |[sebasegovia01](https://github.com/sebasegovia01) |[sergei-zelinsky](https://github.com/sergei-zelinsky) |[szh](https://github.com/szh) | +[rossng](https://github.com/rossng) |[rart](https://github.com/rart) |[fortunto2](https://github.com/fortunto2) |[samuelcolburn](https://github.com/samuelcolburn) |[sebasegovia01](https://github.com/sebasegovia01) |[sergei-zelinsky](https://github.com/sergei-zelinsky) | :---: |:---: |:---: |:---: |:---: |:---: | -[rart](https://github.com/rart) |[fortunto2](https://github.com/fortunto2) |[samuelcolburn](https://github.com/samuelcolburn) |[sebasegovia01](https://github.com/sebasegovia01) |[sergei-zelinsky](https://github.com/sergei-zelinsky) |[szh](https://github.com/szh) | +[rossng](https://github.com/rossng) |[rart](https://github.com/rart) |[fortunto2](https://github.com/fortunto2) |[samuelcolburn](https://github.com/samuelcolburn) |[sebasegovia01](https://github.com/sebasegovia01) |[sergei-zelinsky](https://github.com/sergei-zelinsky) | -[SpazzMarticus](https://github.com/SpazzMarticus) |[waptik](https://github.com/waptik) |[steverob](https://github.com/steverob) |[taj](https://github.com/taj) |[Tashows](https://github.com/Tashows) |[twarlop](https://github.com/twarlop) | +[szh](https://github.com/szh) |[SpazzMarticus](https://github.com/SpazzMarticus) |[waptik](https://github.com/waptik) |[steverob](https://github.com/steverob) |[taj](https://github.com/taj) |[Tashows](https://github.com/Tashows) | :---: |:---: |:---: |:---: |:---: |:---: | -[SpazzMarticus](https://github.com/SpazzMarticus) |[waptik](https://github.com/waptik) |[steverob](https://github.com/steverob) |[taj](https://github.com/taj) |[Tashows](https://github.com/Tashows) |[twarlop](https://github.com/twarlop) | +[szh](https://github.com/szh) |[SpazzMarticus](https://github.com/SpazzMarticus) |[waptik](https://github.com/waptik) |[steverob](https://github.com/steverob) |[taj](https://github.com/taj) |[Tashows](https://github.com/Tashows) | -[tmaier](https://github.com/tmaier) |[tomsaleeba](https://github.com/tomsaleeba) |[tvaliasek](https://github.com/tvaliasek) |[vially](https://github.com/vially) |[valentinoli](https://github.com/valentinoli) |[nagyv](https://github.com/nagyv) | +[twarlop](https://github.com/twarlop) |[tmaier](https://github.com/tmaier) |[tomsaleeba](https://github.com/tomsaleeba) |[tvaliasek](https://github.com/tvaliasek) |[vially](https://github.com/vially) |[valentinoli](https://github.com/valentinoli) | :---: |:---: |:---: |:---: |:---: |:---: | -[tmaier](https://github.com/tmaier) |[tomsaleeba](https://github.com/tomsaleeba) |[tvaliasek](https://github.com/tvaliasek) |[vially](https://github.com/vially) |[valentinoli](https://github.com/valentinoli) |[nagyv](https://github.com/nagyv) | +[twarlop](https://github.com/twarlop) |[tmaier](https://github.com/tmaier) |[tomsaleeba](https://github.com/tomsaleeba) |[tvaliasek](https://github.com/tvaliasek) |[vially](https://github.com/vially) |[valentinoli](https://github.com/valentinoli) | -[dwnste](https://github.com/dwnste) |[willycamargo](https://github.com/willycamargo) |[xhocquet](https://github.com/xhocquet) |[yaegor](https://github.com/yaegor) |[YehudaKremer](https://github.com/YehudaKremer) |[zachconner](https://github.com/zachconner) | +[nagyv](https://github.com/nagyv) |[dwnste](https://github.com/dwnste) |[willycamargo](https://github.com/willycamargo) |[xhocquet](https://github.com/xhocquet) |[yaegor](https://github.com/yaegor) |[YehudaKremer](https://github.com/YehudaKremer) | :---: |:---: |:---: |:---: |:---: |:---: | -[dwnste](https://github.com/dwnste) |[willycamargo](https://github.com/willycamargo) |[xhocquet](https://github.com/xhocquet) |[yaegor](https://github.com/yaegor) |[YehudaKremer](https://github.com/YehudaKremer) |[zachconner](https://github.com/zachconner) | +[nagyv](https://github.com/nagyv) |[dwnste](https://github.com/dwnste) |[willycamargo](https://github.com/willycamargo) |[xhocquet](https://github.com/xhocquet) |[yaegor](https://github.com/yaegor) |[YehudaKremer](https://github.com/YehudaKremer) | -[zacharylawson](https://github.com/zacharylawson) |[agreene-coursera](https://github.com/agreene-coursera) |[alfatv](https://github.com/alfatv) |[arggh](https://github.com/arggh) |[avalla](https://github.com/avalla) |[bdirito](https://github.com/bdirito) | +[zachconner](https://github.com/zachconner) |[zacharylawson](https://github.com/zacharylawson) |[agreene-coursera](https://github.com/agreene-coursera) |[alfatv](https://github.com/alfatv) |[arggh](https://github.com/arggh) |[avalla](https://github.com/avalla) | :---: |:---: |:---: |:---: |:---: |:---: | -[zacharylawson](https://github.com/zacharylawson) |[agreene-coursera](https://github.com/agreene-coursera) |[alfatv](https://github.com/alfatv) |[arggh](https://github.com/arggh) |[avalla](https://github.com/avalla) |[bdirito](https://github.com/bdirito) | +[zachconner](https://github.com/zachconner) |[zacharylawson](https://github.com/zacharylawson) |[agreene-coursera](https://github.com/agreene-coursera) |[alfatv](https://github.com/alfatv) |[arggh](https://github.com/arggh) |[avalla](https://github.com/avalla) | -[bencergazda](https://github.com/bencergazda) |[c0b41](https://github.com/c0b41) |[canvasbh](https://github.com/canvasbh) |[christianwengert](https://github.com/christianwengert) |[craigcbrunner](https://github.com/craigcbrunner) |[darthf1](https://github.com/darthf1) | +[bdirito](https://github.com/bdirito) |[bencergazda](https://github.com/bencergazda) |[c0b41](https://github.com/c0b41) |[canvasbh](https://github.com/canvasbh) |[christianwengert](https://github.com/christianwengert) |[craigcbrunner](https://github.com/craigcbrunner) | :---: |:---: |:---: |:---: |:---: |:---: | -[bencergazda](https://github.com/bencergazda) |[c0b41](https://github.com/c0b41) |[canvasbh](https://github.com/canvasbh) |[christianwengert](https://github.com/christianwengert) |[craigcbrunner](https://github.com/craigcbrunner) |[darthf1](https://github.com/darthf1) | +[bdirito](https://github.com/bdirito) |[bencergazda](https://github.com/bencergazda) |[c0b41](https://github.com/c0b41) |[canvasbh](https://github.com/canvasbh) |[christianwengert](https://github.com/christianwengert) |[craigcbrunner](https://github.com/craigcbrunner) | -[dkisic](https://github.com/dkisic) |[fingul](https://github.com/fingul) |[franckl](https://github.com/franckl) |[gaelicwinter](https://github.com/gaelicwinter) |[green-mike](https://github.com/green-mike) |[hxgf](https://github.com/hxgf) | +[darthf1](https://github.com/darthf1) |[dkisic](https://github.com/dkisic) |[fingul](https://github.com/fingul) |[franckl](https://github.com/franckl) |[gaelicwinter](https://github.com/gaelicwinter) |[green-mike](https://github.com/green-mike) | :---: |:---: |:---: |:---: |:---: |:---: | -[dkisic](https://github.com/dkisic) |[fingul](https://github.com/fingul) |[franckl](https://github.com/franckl) |[gaelicwinter](https://github.com/gaelicwinter) |[green-mike](https://github.com/green-mike) |[hxgf](https://github.com/hxgf) | +[darthf1](https://github.com/darthf1) |[dkisic](https://github.com/dkisic) |[fingul](https://github.com/fingul) |[franckl](https://github.com/franckl) |[gaelicwinter](https://github.com/gaelicwinter) |[green-mike](https://github.com/green-mike) | -[johnmanjiro13](https://github.com/johnmanjiro13) |[kode-ninja](https://github.com/kode-ninja) |[magumbo](https://github.com/magumbo) |[ninesalt](https://github.com/ninesalt) |[phil714](https://github.com/phil714) |[luntta](https://github.com/luntta) | +[hxgf](https://github.com/hxgf) |[johnmanjiro13](https://github.com/johnmanjiro13) |[kode-ninja](https://github.com/kode-ninja) |[magumbo](https://github.com/magumbo) |[ninesalt](https://github.com/ninesalt) |[phil714](https://github.com/phil714) | :---: |:---: |:---: |:---: |:---: |:---: | -[johnmanjiro13](https://github.com/johnmanjiro13) |[kode-ninja](https://github.com/kode-ninja) |[magumbo](https://github.com/magumbo) |[ninesalt](https://github.com/ninesalt) |[phil714](https://github.com/phil714) |[luntta](https://github.com/luntta) | +[hxgf](https://github.com/hxgf) |[johnmanjiro13](https://github.com/johnmanjiro13) |[kode-ninja](https://github.com/kode-ninja) |[magumbo](https://github.com/magumbo) |[ninesalt](https://github.com/ninesalt) |[phil714](https://github.com/phil714) | -[rhymes](https://github.com/rhymes) |[rlebosse](https://github.com/rlebosse) |[rtaieb](https://github.com/rtaieb) |[slawexxx44](https://github.com/slawexxx44) |[thanhthot](https://github.com/thanhthot) |[tinny77](https://github.com/tinny77) | +[luntta](https://github.com/luntta) |[rhymes](https://github.com/rhymes) |[rlebosse](https://github.com/rlebosse) |[rtaieb](https://github.com/rtaieb) |[slawexxx44](https://github.com/slawexxx44) |[thanhthot](https://github.com/thanhthot) | :---: |:---: |:---: |:---: |:---: |:---: | -[rhymes](https://github.com/rhymes) |[rlebosse](https://github.com/rlebosse) |[rtaieb](https://github.com/rtaieb) |[slawexxx44](https://github.com/slawexxx44) |[thanhthot](https://github.com/thanhthot) |[tinny77](https://github.com/tinny77) | - -[vedran555](https://github.com/vedran555) |[yoann-hellopret](https://github.com/yoann-hellopret) |[olitomas](https://github.com/olitomas) |[JimmyLv](https://github.com/JimmyLv) | -:---: |:---: |:---: |:---: | -[vedran555](https://github.com/vedran555) |[yoann-hellopret](https://github.com/yoann-hellopret) |[olitomas](https://github.com/olitomas) |[JimmyLv](https://github.com/JimmyLv) | +[luntta](https://github.com/luntta) |[rhymes](https://github.com/rhymes) |[rlebosse](https://github.com/rlebosse) |[rtaieb](https://github.com/rtaieb) |[slawexxx44](https://github.com/slawexxx44) |[thanhthot](https://github.com/thanhthot) | +[tinny77](https://github.com/tinny77) |[vedran555](https://github.com/vedran555) |[yoann-hellopret](https://github.com/yoann-hellopret) |[olitomas](https://github.com/olitomas) |[JimmyLv](https://github.com/JimmyLv) | +:---: |:---: |:---: |:---: |:---: | +[tinny77](https://github.com/tinny77) |[vedran555](https://github.com/vedran555) |[yoann-hellopret](https://github.com/yoann-hellopret) |[olitomas](https://github.com/olitomas) |[JimmyLv](https://github.com/JimmyLv) | ## Software -We use Browserstack for manual testing - - BrowserStack logo - +We use Browserstack for manual testing BrowserStack logo ## License diff --git a/examples/aws-companion/readme.md b/examples/aws-companion/readme.md index 2774e6755a..5f7f3e52b5 100644 --- a/examples/aws-companion/readme.md +++ b/examples/aws-companion/readme.md @@ -6,15 +6,18 @@ Files are uploaded to a randomly named directory inside the `whatever/` director ## Run it To run this example, make sure you've correctly installed the **repository root**: + ```bash npm install npm run build ``` + That will also install the dependencies for this example. Then, set up the `COMPANION_AWS_KEY`, `COMPANION_AWS_SECRET`, `COMPANION_AWS_REGION`, and `COMPANION_AWS_BUCKET` environment variables for @uppy/companion. Then, again in the **repository root**, start this example by doing: + ```bash npm run example aws-companion ``` diff --git a/examples/aws-presigned-url/readme.md b/examples/aws-presigned-url/readme.md index 8f16528e16..bd760fe457 100644 --- a/examples/aws-presigned-url/readme.md +++ b/examples/aws-presigned-url/readme.md @@ -5,10 +5,12 @@ This example uses a server-side PHP endpoint to sign uploads to S3. ## Running It To run this example, make sure you've correctly installed the **repository root**: + ```bash npm install npm run build ``` + That will also install the npm dependencies for this example. This example also uses the AWS PHP SDK. @@ -23,17 +25,21 @@ Configure AWS S3 credentials using [environment variables](https://docs.aws.amaz Configure a bucket name and region in the `s3-sign.php` file. Then, again in the **repository root**, start this example by doing: + ```bash npm run example aws-presigned-url ``` + The demo should now be available at http://localhost:8080. Optionally, provide a port in the `PORT` environment variable: + ```bash PORT=8080 npm run example aws-presigned-url ``` You can use a different S3-compatible service like GCS by configuring that service in `~/.aws/config` and `~/.aws/credentials`, and then providing appropriate environment variables: + ```bash AWS_PROFILE="gcs" \ COMPANION_AWS_ENDPOINT="https://storage.googleapis.com" \ diff --git a/examples/cdn-example/index.html b/examples/cdn-example/index.html index 6c46941653..6edbf67f49 100644 --- a/examples/cdn-example/index.html +++ b/examples/cdn-example/index.html @@ -4,11 +4,11 @@ - + - + + + + ``` Then, a global `Robodog` variable will be available. For usage instructions, please see the [main Robodog documentation](https://uppy.io/docs/robodog). diff --git a/packages/@uppy/robodog/package.json b/packages/@uppy/robodog/package.json index 00c03a5f9f..733ab44c81 100644 --- a/packages/@uppy/robodog/package.json +++ b/packages/@uppy/robodog/package.json @@ -1,7 +1,7 @@ { "name": "@uppy/robodog", "description": "Transloadit SDK for browsers based on Uppy", - "version": "2.1.0", + "version": "2.1.1", "license": "MIT", "main": "lib/index.js", "jsnext:main": "src/index.js", diff --git a/packages/@uppy/screen-capture/README.md b/packages/@uppy/screen-capture/README.md index 16ee865b44..6fb81a7340 100644 --- a/packages/@uppy/screen-capture/README.md +++ b/packages/@uppy/screen-capture/README.md @@ -2,8 +2,10 @@ Uppy logo: a superman puppy in a pink suit - -CI status for Uppy tests CI status for Companion tests CI status for browser tests +[![npm version](https://img.shields.io/npm/v/@uppy/screen-capture.svg?style=flat-square)](https://www.npmjs.com/package/@uppy/screen-capture) +![CI status for Uppy tests](https://github.com/transloadit/uppy/workflows/Tests/badge.svg) +![CI status for Companion tests](https://github.com/transloadit/uppy/workflows/Companion/badge.svg) +![CI status for browser tests](https://github.com/transloadit/uppy/workflows/End-to-end%20tests/badge.svg) The Webcam plugin for Uppy lets you take photos and record videos with a built-in camera on desktop and mobile devices. @@ -27,7 +29,7 @@ $ npm install @uppy/screen-capture We recommend installing from npm and then using a module bundler such as [Webpack](https://webpack.js.org/), [Browserify](http://browserify.org/) or [Rollup.js](http://rollupjs.org/). -Alternatively, you can also use this plugin in a pre-built bundle from Transloadit's CDN: Edgly. In that case `Uppy` will attach itself to the global `window.Uppy` object. See the [main Uppy documentation](https://uppy.io/docs/#Installation) for instructions. +Alternatively, you can also use this plugin in a pre-built bundle from Transloadit’s CDN: Edgly. In that case `Uppy` will attach itself to the global `window.Uppy` object. See the [main Uppy documentation](https://uppy.io/docs/#Installation) for instructions. ## Documentation diff --git a/packages/@uppy/screen-capture/package.json b/packages/@uppy/screen-capture/package.json index 566aaf207c..46bec3352f 100644 --- a/packages/@uppy/screen-capture/package.json +++ b/packages/@uppy/screen-capture/package.json @@ -1,7 +1,7 @@ { "name": "@uppy/screen-capture", "description": "Uppy plugin that captures video from display or application.", - "version": "2.0.3", + "version": "2.0.4", "license": "MIT", "main": "lib/index.js", "style": "dist/style.min.css", diff --git a/packages/@uppy/status-bar/README.md b/packages/@uppy/status-bar/README.md index d47e9dc7d1..a35426af41 100644 --- a/packages/@uppy/status-bar/README.md +++ b/packages/@uppy/status-bar/README.md @@ -2,11 +2,13 @@ Uppy logo: a superman puppy in a pink suit - -CI status for Uppy tests CI status for Companion tests CI status for browser tests +[![npm version](https://img.shields.io/npm/v/@uppy/status-bar.svg?style=flat-square)](https://www.npmjs.com/package/@uppy/status-bar) +![CI status for Uppy tests](https://github.com/transloadit/uppy/workflows/Tests/badge.svg) +![CI status for Companion tests](https://github.com/transloadit/uppy/workflows/Companion/badge.svg) +![CI status for browser tests](https://github.com/transloadit/uppy/workflows/End-to-end%20tests/badge.svg) The status-bar shows upload progress and speed, ETAs, pre- and post-processing information, and allows users to control (pause/resume/cancel) the upload. -Best used together with a simple file source plugin, such as [@uppy/file-input](https://uppy.io/docs/file-input) or [@uppy/drag-drop](https://uppy.io/docs/drag-drop), or a custom implementation. It is also included in the [@uppy/dashboard](https://uppy.io/docs/dashboard) plugin. +Best used together with a basic file source plugin, such as [@uppy/file-input](https://uppy.io/docs/file-input) or [@uppy/drag-drop](https://uppy.io/docs/drag-drop), or a custom implementation. It’s also included in the [@uppy/dashboard](https://uppy.io/docs/dashboard) plugin. Uppy is being developed by the folks at [Transloadit](https://transloadit.com), a versatile file encoding service. @@ -33,7 +35,7 @@ $ npm install @uppy/status-bar We recommend installing from npm and then using a module bundler such as [Webpack](https://webpack.js.org/), [Browserify](http://browserify.org/) or [Rollup.js](http://rollupjs.org/). -Alternatively, you can also use this plugin in a pre-built bundle from Transloadit's CDN: Edgly. In that case `Uppy` will attach itself to the global `window.Uppy` object. See the [main Uppy documentation](https://uppy.io/docs/#Installation) for instructions. +Alternatively, you can also use this plugin in a pre-built bundle from Transloadit’s CDN: Edgly. In that case `Uppy` will attach itself to the global `window.Uppy` object. See the [main Uppy documentation](https://uppy.io/docs/#Installation) for instructions. ## Documentation diff --git a/packages/@uppy/status-bar/package.json b/packages/@uppy/status-bar/package.json index 428bb1385a..bd0f5f96fc 100644 --- a/packages/@uppy/status-bar/package.json +++ b/packages/@uppy/status-bar/package.json @@ -1,7 +1,7 @@ { "name": "@uppy/status-bar", "description": "A progress bar for Uppy, with many bells and whistles.", - "version": "2.1.0", + "version": "2.1.1", "license": "MIT", "main": "lib/index.js", "style": "dist/style.min.css", diff --git a/packages/@uppy/status-bar/src/Components.js b/packages/@uppy/status-bar/src/Components.js index 24b8902be5..083a432567 100644 --- a/packages/@uppy/status-bar/src/Components.js +++ b/packages/@uppy/status-bar/src/Components.js @@ -192,7 +192,8 @@ function LoadingSpinner () { } function ProgressBarProcessing (props) { - const { value, mode, message } = props + const { progress } = props + const { value, mode, message } = progress const roundedValue = Math.round(value * 100) const dot = `\u00B7` diff --git a/packages/@uppy/status-bar/src/calculateProcessingProgress.js b/packages/@uppy/status-bar/src/calculateProcessingProgress.js index 2864022fbf..b2589b56ac 100644 --- a/packages/@uppy/status-bar/src/calculateProcessingProgress.js +++ b/packages/@uppy/status-bar/src/calculateProcessingProgress.js @@ -1,4 +1,4 @@ -module.export = function calculateProcessingProgress (files) { +module.exports = function calculateProcessingProgress (files) { const values = [] let mode let message diff --git a/packages/@uppy/store-default/README.md b/packages/@uppy/store-default/README.md index badef180e7..e1912fb0f6 100644 --- a/packages/@uppy/store-default/README.md +++ b/packages/@uppy/store-default/README.md @@ -2,10 +2,12 @@ Uppy logo: a superman puppy in a pink suit - -CI status for Uppy tests CI status for Companion tests CI status for browser tests +[![npm version](https://img.shields.io/npm/v/@uppy/store-default.svg?style=flat-square)](https://www.npmjs.com/package/@uppy/store-default) +![CI status for Uppy tests](https://github.com/transloadit/uppy/workflows/Tests/badge.svg) +![CI status for Companion tests](https://github.com/transloadit/uppy/workflows/Companion/badge.svg) +![CI status for browser tests](https://github.com/transloadit/uppy/workflows/End-to-end%20tests/badge.svg) -A simple object-based store for Uppy. This one is used by default, you do not need to add it manually. +A basic object-based store for Uppy. This one is used by default, you do not need to add it manually. Uppy is being developed by the folks at [Transloadit](https://transloadit.com), a versatile file encoding service. @@ -28,7 +30,7 @@ $ npm install @uppy/store-default We recommend installing from npm and then using a module bundler such as [Webpack](https://webpack.js.org/), [Browserify](http://browserify.org/) or [Rollup.js](http://rollupjs.org/). -Alternatively, you can also use this package in a pre-built bundle from Transloadit's CDN: Edgly. In that case `Uppy` will attach itself to the global `window.Uppy` object. See the [main Uppy documentation](https://uppy.io/docs/#Installation) for instructions. +Alternatively, you can also use this package in a pre-built bundle from Transloadit’s CDN: Edgly. In that case `Uppy` will attach itself to the global `window.Uppy` object. See the [main Uppy documentation](https://uppy.io/docs/#Installation) for instructions. ## Documentation diff --git a/packages/@uppy/store-default/package.json b/packages/@uppy/store-default/package.json index 5175513a90..2c30d8cb91 100644 --- a/packages/@uppy/store-default/package.json +++ b/packages/@uppy/store-default/package.json @@ -1,7 +1,7 @@ { "name": "@uppy/store-default", "description": "The default simple object-based store for Uppy.", - "version": "2.0.1", + "version": "2.0.2", "license": "MIT", "main": "lib/index.js", "types": "types/index.d.ts", diff --git a/packages/@uppy/store-redux/README.md b/packages/@uppy/store-redux/README.md index 8636d8ddad..9cdd016393 100644 --- a/packages/@uppy/store-redux/README.md +++ b/packages/@uppy/store-redux/README.md @@ -2,8 +2,10 @@ Uppy logo: a superman puppy in a pink suit - -CI status for Uppy tests CI status for Companion tests CI status for browser tests +[![npm version](https://img.shields.io/npm/v/@uppy/store-redux.svg?style=flat-square)](https://www.npmjs.com/package/@uppy/store-redux) +![CI status for Uppy tests](https://github.com/transloadit/uppy/workflows/Tests/badge.svg) +![CI status for Companion tests](https://github.com/transloadit/uppy/workflows/Companion/badge.svg) +![CI status for browser tests](https://github.com/transloadit/uppy/workflows/End-to-end%20tests/badge.svg) The `ReduxStore` stores Uppy state on a key in an existing Redux store. The `ReduxStore` dispatches `uppy/STATE_UPDATE` actions to update state. @@ -36,7 +38,7 @@ $ npm install @uppy/store-redux We recommend installing from npm and then using a module bundler such as [Webpack](https://webpack.js.org/), [Browserify](http://browserify.org/) or [Rollup.js](http://rollupjs.org/). -Alternatively, you can also use this plugin in a pre-built bundle from Transloadit's CDN: Edgly. In that case `Uppy` will attach itself to the global `window.Uppy` object. See the [main Uppy documentation](https://uppy.io/docs/#Installation) for instructions. +Alternatively, you can also use this plugin in a pre-built bundle from Transloadit’s CDN: Edgly. In that case `Uppy` will attach itself to the global `window.Uppy` object. See the [main Uppy documentation](https://uppy.io/docs/#Installation) for instructions. ## Documentation diff --git a/packages/@uppy/store-redux/package.json b/packages/@uppy/store-redux/package.json index fa391d9214..eb4d4f1679 100644 --- a/packages/@uppy/store-redux/package.json +++ b/packages/@uppy/store-redux/package.json @@ -1,7 +1,7 @@ { "name": "@uppy/store-redux", "description": "Make Uppy use your existing Redux store.", - "version": "2.0.1", + "version": "2.0.2", "license": "MIT", "main": "lib/index.js", "types": "types/index.d.ts", diff --git a/packages/@uppy/svelte/README.md b/packages/@uppy/svelte/README.md index 8ed7acbe90..d3a49a7f44 100644 --- a/packages/@uppy/svelte/README.md +++ b/packages/@uppy/svelte/README.md @@ -2,8 +2,10 @@ Uppy logo: a superman puppy in a pink suit - -CI status for Uppy tests CI status for Companion tests CI status for browser tests +[![npm version](https://img.shields.io/npm/v/@uppy/svelte.svg?style=flat-square)](https://www.npmjs.com/package/@uppy/svelte) +![CI status for Uppy tests](https://github.com/transloadit/uppy/workflows/Tests/badge.svg) +![CI status for Companion tests](https://github.com/transloadit/uppy/workflows/Companion/badge.svg) +![CI status for browser tests](https://github.com/transloadit/uppy/workflows/End-to-end%20tests/badge.svg) Svelte component wrappers around Uppy’s officially maintained UI plugins. @@ -23,7 +25,7 @@ yarn add @uppy/svelte ## Documentation -Documentation for this plugin can be found on the [Uppy website](https://uppy.io/docs/svelte). At the moment, there is no documentation yet, so this link won't work. Stay tuned for more info +Documentation for this plugin can be found on the [Uppy website](https://uppy.io/docs/svelte). At the moment, there’s no documentation yet, so this link won’t work. Stay tuned for more info ## License diff --git a/packages/@uppy/svelte/package.json b/packages/@uppy/svelte/package.json index 513fcce79d..52dd6b4a82 100644 --- a/packages/@uppy/svelte/package.json +++ b/packages/@uppy/svelte/package.json @@ -3,7 +3,7 @@ "svelte": "src/index.js", "module": "dist/index.mjs", "main": "dist/index.js", - "version": "1.0.4", + "version": "1.0.5", "scripts": { "build": "rollup -c", "prepublishOnly": "npm run build", diff --git a/packages/@uppy/thumbnail-generator/README.md b/packages/@uppy/thumbnail-generator/README.md index 4cd4c59c78..a0a7ee0711 100644 --- a/packages/@uppy/thumbnail-generator/README.md +++ b/packages/@uppy/thumbnail-generator/README.md @@ -2,8 +2,10 @@ Uppy logo: a superman puppy in a pink suit - -CI status for Uppy tests CI status for Companion tests CI status for browser tests +[![npm version](https://img.shields.io/npm/v/@uppy/thumbnail-generator.svg?style=flat-square)](https://www.npmjs.com/package/@uppy/thumbnail-generator) +![CI status for Uppy tests](https://github.com/transloadit/uppy/workflows/Tests/badge.svg) +![CI status for Companion tests](https://github.com/transloadit/uppy/workflows/Companion/badge.svg) +![CI status for browser tests](https://github.com/transloadit/uppy/workflows/End-to-end%20tests/badge.svg) Uppy plugin that generates small previews of images to show on your upload UI. @@ -29,7 +31,7 @@ $ npm install @uppy/thumbnail-generator We recommend installing from npm and then using a module bundler such as [Webpack](https://webpack.js.org/), [Browserify](http://browserify.org/) or [Rollup.js](http://rollupjs.org/). -Alternatively, you can also use this plugin in a pre-built bundle from Transloadit's CDN: Edgly. In that case `Uppy` will attach itself to the global `window.Uppy` object. See the [main Uppy documentation](https://uppy.io/docs/#Installation) for instructions. +Alternatively, you can also use this plugin in a pre-built bundle from Transloadit’s CDN: Edgly. In that case `Uppy` will attach itself to the global `window.Uppy` object. See the [main Uppy documentation](https://uppy.io/docs/#Installation) for instructions. -Transloadit is providing Uppy free of charge. If you want, you can self-host all of its components and never pay us a dime. There are docs and tests, and your Bug Reports and Feature Requests are always welcome on GitHub. +Transloadit is providing Uppy free of charge. If you want, you can self-host all its components and never pay us a dime. You can access docs and tests, and your Bug Reports and Feature Requests are always welcome on GitHub. -There is also a different category of support that we like to call Integration Help: assistance to make things work for your environment, that have already been reported as working for the larger community. +We offer also a different category of support that we like to call Integration Help: help to make things work for your environment, that have already been reported as working for the larger community. -As much as we at Transloadit would like to provide detailed Integration Help to every non-paying user, Uppy has reached a point where this is no longer sustainable for our small crew. If we end up investing our time in a million different apps that use Uppy, as long as there is no money flowing back, we won't be able to ramp up our team to meet the demand. This would spread the team ever thinner and eventually grind development to a halt. +As much as we at Transloadit would like to provide detailed Integration Help to every non-paying user, Uppy has reached a point where this is no longer sustainable for our small crew. If we end up investing our time in a million different apps that use Uppy, as long as no money is flowing back, we won’t be able to ramp up our team to meet the demand. This would spread the team ever thinner and eventually grind development to a halt. -That is not where we want to be. So, in order to offer enthusiasts, businesses, and enterprises assistance in a sustainable way, we're providing community-based Integration Help for free at . If you are unable to solve your problem with help of the Uppy community, we offer paid Integration Help via . +That is not where we want to be. So, to offer enthusiasts, businesses, and enterprises help in a sustainable way, we’re providing community-based Integration Help for free at . If you are unable to solve your problem with help of the Uppy community, we offer paid Integration Help via . diff --git a/website/src/docs/angular.md b/website/src/docs/angular.md index 63a6bf1b0e..96951e8b08 100644 --- a/website/src/docs/angular.md +++ b/website/src/docs/angular.md @@ -77,10 +77,10 @@ export class AppComponent { The following plugins are available as Angular component wrappers: -- `` - renders a `@uppy/dashboard` -- `` - renders a `@uppy/drag-drop` area -- `` - renders a `@uppy/progress-bar` -- `` - renders a `@uppy/status-bar` +* `` - renders a `@uppy/dashboard` +* `` - renders a `@uppy/drag-drop` area +* `` - renders a `@uppy/progress-bar` +* `` - renders a `@uppy/status-bar` Each component takes a `props` prop that will be passed to the UI Plugin. @@ -160,7 +160,7 @@ The `` cannot be passed to a `target:` option of a remot #### CSS -The `UppyAngularDragDropModule` component includes some simple styles, like shown in the [example](/examples/dragdrop). You can also choose not to use it and provide your own styles instead: +The `UppyAngularDragDropModule` component includes some basic styles, like shown in the [example](/examples/dragdrop). You can also choose not to use it and provide your own styles instead: ```typescript @Component({ diff --git a/website/src/docs/aws-s3-multipart.md b/website/src/docs/aws-s3-multipart.md index b81e9534aa..e8c4272cae 100644 --- a/website/src/docs/aws-s3-multipart.md +++ b/website/src/docs/aws-s3-multipart.md @@ -8,7 +8,7 @@ category: "Destinations" tagline: "uploader for AWS S3 using its resumable Multipart protocol" --- -The `@uppy/aws-s3-multipart` plugin can be used to upload files directly to an S3 bucket using S3's Multipart upload strategy. With this strategy, files are chopped up in parts of 5MB+ each, so they can be uploaded concurrently. It is also very reliable: if a single part fails to upload, only that 5MB chunk has to be retried. +The `@uppy/aws-s3-multipart` plugin can be used to upload files directly to an S3 bucket using S3’s Multipart upload strategy. With this strategy, files are chopped up in parts of 5MB+ each, so they can be uploaded concurrently. It’s also quite reliable: if a single part fails to upload, only that 5MB chunk has to be retried. ```js import AwsS3Multipart from '@uppy/aws-s3-multipart' @@ -29,7 +29,7 @@ Install from NPM: npm install @uppy/aws-s3-multipart ``` -In the [CDN package](/docs/#With-a-script-tag), it is available on the `Uppy` global object: +In the [CDN package](/docs/#With-a-script-tag), the plugin class is available on the `Uppy` global object: ```js const { AwsS3Multipart } = Uppy @@ -67,7 +67,7 @@ This will be used by the default implementations of the upload-related functions ### `companionCookiesRule: 'same-origin'` -This option correlates to the [RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials), which tells the plugin whether or not to send cookies to [Companion](/docs/companion). +This option correlates to the [RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials), which tells the plugin whether to send cookies to [Companion](/docs/companion). ### `getChunkSize(file)` @@ -75,48 +75,49 @@ A function that returns the minimum chunk size to use when uploading the given f The S3 Multipart plugin uploads files in chunks. Chunks are sent in batches to have presigned URLs generated via ([`prepareUploadParts()`](#prepareUploadParts-file-partData)). To reduce the amount of requests for large files, you can choose a larger chunk size, at the cost of having to re-upload more data if one chunk fails to upload. -S3 requires a minimum chunk size of 5MB, and supports at most 10,000 chunks per multipart upload. If `getChunkSize()` returns a size that's too small, Uppy will increase it to S3's minimum requirements. +S3 requires a minimum chunk size of 5MB, and supports at most 10,000 chunks per multipart upload. If `getChunkSize()` returns a size that’s too small, Uppy will increase it to S3’s minimum requirements. ### `createMultipartUpload(file)` -A function that calls the S3 Multipart API to create a new upload. `file` is the file object from Uppy's state. The most relevant keys are `file.name` and `file.type`. +A function that calls the S3 Multipart API to create a new upload. `file` is the file object from Uppy’s state. The most relevant keys are `file.name` and `file.type`. Return a Promise for an object with keys: - - `uploadId` - The UploadID returned by S3. - - `key` - The object key for the file. This needs to be returned to allow it to be different from the `file.name`. +* `uploadId` - The UploadID returned by S3. +* `key` - The object key for the file. This needs to be returned to allow it to be different from the `file.name`. -The default implementation calls out to Companion's S3 signing endpoints. +The default implementation calls out to Companion’s S3 signing endpoints. ### `listParts(file, { uploadId, key })` -A function that calls the S3 Multipart API to list the parts of a file that have already been uploaded. Receives the `file` object from Uppy's state, and an object with keys: +A function that calls the S3 Multipart API to list the parts of a file that have already been uploaded. Receives the `file` object from Uppy’s state, and an object with keys: - - `uploadId` - The UploadID of this Multipart upload. - - `key` - The object key of this Multipart upload. +* `uploadId` - The UploadID of this Multipart upload. +* `key` - The object key of this Multipart upload. Return a Promise for an array of S3 Part objects, as returned by the S3 Multipart API. Each object has keys: - - `PartNumber` - The index in the file of the uploaded part. - - `Size` - The size of the part in bytes. - - `ETag` - The ETag of the part, used to identify it when completing the multipart upload and combining all parts into a single file. +* `PartNumber` - The index in the file of the uploaded part. +* `Size` - The size of the part in bytes. +* `ETag` - The ETag of the part, used to identify it when completing the multipart upload and combining all parts into a single file. -The default implementation calls out to Companion's S3 signing endpoints. +The default implementation calls out to Companion’s S3 signing endpoints. ### `prepareUploadParts(file, partData)` -A function that generates a batch of signed URLs for the specified part numbers. Receives the `file` object from Uppy's state. The `partData` argument is an object with keys: +A function that generates a batch of signed URLs for the specified part numbers. Receives the `file` object from Uppy’s state. The `partData` argument is an object with keys: - - `uploadId` - The UploadID of this Multipart upload. - - `key` - The object key in the S3 bucket. - - `partNumbers` - An array of indecies of this part in the file (`PartNumber` in S3 terminology). Note that part numbers are _not_ zero-based. +* `uploadId` - The UploadID of this Multipart upload. +* `key` - The object key in the S3 bucket. +* `partNumbers` - An array of indecies of this part in the file (`PartNumber` in S3 terminology). Note that part numbers are _not_ zero-based. `prepareUploadParts` should return a `Promise` with an `Object` with keys: - - `presignedUrls` - A JavaScript object with the part numbers as keys and the presigned URL for each part as the value. - - `headers` - **(Optional)** Custom headers that should be sent to the S3 presigned URL. +* `presignedUrls` - A JavaScript object with the part numbers as keys and the presigned URL for each part as the value. +* `headers` - **(Optional)** Custom headers that should be sent to the S3 presigned URL. An example of what the return value should look like: + ```json { "presignedUrls": { @@ -131,6 +132,7 @@ An example of what the return value should look like: If an error occured, reject the `Promise` with an `Object` with the following keys: + ```json { "source": { "status": 500 } } ``` @@ -139,32 +141,32 @@ If an error occured, reject the `Promise` with an `Object` with the following ke ### `abortMultipartUpload(file, { uploadId, key })` -A function that calls the S3 Multipart API to abort a Multipart upload, and delete all parts that have been uploaded so far. Receives the `file` object from Uppy's state, and an object with keys: +A function that calls the S3 Multipart API to abort a Multipart upload, and removes all parts that have been uploaded so far. Receives the `file` object from Uppy’s state, and an object with keys: - - `uploadId` - The UploadID of this Multipart upload. - - `key` - The object key of this Multipart upload. +* `uploadId` - The UploadID of this Multipart upload. +* `key` - The object key of this Multipart upload. This is typically called when the user cancels an upload. Cancellation cannot fail in Uppy, so the result of this function is ignored. -The default implementation calls out to Companion's S3 signing endpoints. +The default implementation calls out to Companion’s S3 signing endpoints. ### `completeMultipartUpload(file, { uploadId, key, parts })` -A function that calls the S3 Multipart API to complete a Multipart upload, combining all parts into a single object in the S3 bucket. Receives the `file` object from Uppy's state, and an object with keys: +A function that calls the S3 Multipart API to complete a Multipart upload, combining all parts into a single object in the S3 bucket. Receives the `file` object from Uppy’s state, and an object with keys: - - `uploadId` - The UploadID of this Multipart upload. - - `key` - The object key of this Multipart upload. - - `parts` - S3-style list of parts, an array of objects with `ETag` and `PartNumber` properties. This can be passed straight to S3's Multipart API. +* `uploadId` - The UploadID of this Multipart upload. +* `key` - The object key of this Multipart upload. +* `parts` - S3-style list of parts, an array of objects with `ETag` and `PartNumber` properties. This can be passed straight to S3’s Multipart API. Return a Promise for an object with properties: - - `location` - **(Optional)** A publically accessible URL to the object in the S3 bucket. +* `location` - **(Optional)** A publically accessible URL to the object in the S3 bucket. -The default implementation calls out to Companion's S3 signing endpoints. +The default implementation calls out to Companion’s S3 signing endpoints. ## S3 Bucket Configuration -S3 buckets do not allow public uploads by default. In order to allow Uppy to upload to a bucket directly, its CORS permissions need to be configured. This process is described in the [AwsS3 documentation](/docs/aws-s3/#S3-Bucket-configuration). +S3 buckets do not allow public uploads by default. To allow Uppy to upload to a bucket directly, its CORS permissions need to be configured. This process is described in the [AwsS3 documentation](/docs/aws-s3/#S3-Bucket-configuration). While the Uppy AWS S3 plugin uses `POST` requests when uploading files to an S3 bucket, the AWS S3 Multipart plugin uses `PUT` requests when uploading file parts. Additionally, the `ETag` header must also be exposed (in the response): diff --git a/website/src/docs/aws-s3.md b/website/src/docs/aws-s3.md index 123dd147ee..ee88a04e58 100644 --- a/website/src/docs/aws-s3.md +++ b/website/src/docs/aws-s3.md @@ -22,9 +22,9 @@ uppy.use(AwsS3, { }) ``` -There are broadly two ways of uploading to S3 in a browser. A server can generate a presigned URL for a [PUT upload](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPUT.html), or a server can generate form data for a [POST upload](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html). Companion uses a POST upload. See [POST Uploads](#POST-uploads) for some caveats if you would like to use POST uploads without Companion. See [Generating a presigned upload URL server-side](#example-presigned-url) for an example of a PUT upload. +Uploading to S3 from a browser can be done in broadly two ways. A server can generate a presigned URL for a [PUT upload](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPUT.html), or a server can generate form data for a [POST upload](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html). Companion uses a POST upload. See [POST Uploads](#POST-uploads) for some caveats if you would like to use POST uploads without Companion. See [Generating a presigned upload URL server-side](#example-presigned-url) for an example of a PUT upload. -There is also a separate plugin for S3 Multipart uploads. Multipart in this sense refers to Amazon's proprietary chunked, resumable upload mechanism for large files. See the [`@uppy/aws-s3-multipart`](/docs/aws-s3-multipart) documentation. +You can also use a separate plugin for S3 Multipart uploads. Multipart in this sense refers to Amazon’s proprietary chunked, resumable upload mechanism for large files. See the [`@uppy/aws-s3-multipart`](/docs/aws-s3-multipart) documentation. ## Installation @@ -36,7 +36,7 @@ Install from NPM: npm install @uppy/aws-s3 ``` -In the [CDN package](/docs/#With-a-script-tag), it is available on the `Uppy` global object: +In the [CDN package](/docs/#With-a-script-tag), the plugin class is available on the `Uppy` global object: ```js const { AwsS3 } = Uppy @@ -68,10 +68,10 @@ Custom headers that should be sent along to [Companion][companion docs] on every ### `metaFields: []` -Pass an array of field names to specify the metadata fields that should be stored in S3 as Object Metadata. This takes values from each file's `file.meta` property. +Pass an array of field names to specify the metadata fields that should be stored in S3 as Object Metadata. This takes values from each file’s `file.meta` property. -- Set this to `['name']` to only send the name field. -- Set this to an empty array `[]` (the default) to not send any fields. +* Set this to `['name']` to only send the name field. +* Set this to an empty array `[]` (the default) to not send any fields. ### `getUploadParameters(file)` @@ -91,7 +91,7 @@ The `fields` field is an object with form fields to send along with the upload r For presigned PUT uploads, this should be left empty. The `headers` field is an object with request headers to send along with the upload request. -When using a presigned PUT upload, it's a good idea to provide `headers['content-type']`. That will ensure that the request uses the same content-type that was used to generate the signature. Without it, the browser may decide on a different content-type instead, causing S3 to reject the upload. +When using a presigned PUT upload, it’s a good idea to provide `headers['content-type']`. That will make sure that the request uses the same content-type that was used to generate the signature. Without it, the browser may decide on a different content-type instead, causing S3 to reject the upload. ### `timeout: 30 * 1000` @@ -111,7 +111,7 @@ Set to `0` to disable limiting. Customize response handling once an upload is completed. This passes the function through to @uppy/xhr-upload, see its [documentation](https://uppy.io/docs/xhr-upload/#getResponseData-responseText-response) for API details. -This option is useful when uploading to an S3-like service that doesn't reply with an XML document, but with something else such as JSON. +This option is useful when uploading to an S3-like service that doesn’t reply with an XML document, but with something else such as JSON. ### `locale: {}` @@ -131,13 +131,13 @@ const locales = { ## S3 Bucket configuration S3 buckets do not allow public uploads by default. -In order to allow Uppy to upload directly to a bucket, at least its CORS permissions need to be configured, and you potentially need to change some of the *Public access settings* that provide an extra layer of public access protection even if the correct CORS permissions are in place. +To allow Uppy to upload directly to a bucket, at least its CORS permissions need to be configured, and you potentially need to change some of the _Public access settings_ that provide an extra layer of public access protection even if the correct CORS permissions are in place. CORS permissions can be found in the [S3 Management Console](https://console.aws.amazon.com/s3/home). -Click the bucket that will receive the uploads, then go into the "Permissions" tab and select the "CORS configuration" button. -A JSON document will be shown that contains the CORS configuration. (AWS used to use XML but now only allow JSON). More information about the [S3 CORS format here](https://docs.amazonaws.cn/en_us/AmazonS3/latest/userguide/ManageCorsUsing.html). +Click the bucket that will receive the uploads, then go into the `Permissions` tab and select the `CORS configuration` button. +A JSON document will be shown that defines the CORS configuration. (AWS used to use XML but now only allow JSON). More information about the [S3 CORS format here](https://docs.amazonaws.cn/en\_us/AmazonS3/latest/userguide/ManageCorsUsing.html). -It is good practice to use two CORS rules: one for viewing the uploaded files, and one for uploading files. +A good practice is to use two CORS rules: one for viewing the uploaded files, and one for uploading files. Depending on which settings were enabled during bucket creation, AWS S3 may have defined a CORS rule that allows public reading already. This rule looks like: @@ -155,7 +155,7 @@ If uploaded files should be publically viewable, but a rule like this is not pre A different rule is necessary to allow uploading. This rule should come _before_ the existing rule, because S3 only uses the first rule that matches the origin of the request. -At minimum, the domain from which the uploads will happen must be whitelisted, and the definitions from the previous rule must be added: +At minimum, the domain from which the uploads will happen must be allow-listed, and the definitions from the earlier rule must be added: ```json { @@ -187,7 +187,7 @@ When using a presigned upload URL, the following permissions must be granted: } ``` -The final configuration should look something like this (note that it contains two rules in an array `[]`): +The final configuration should look something like this (note that it defines two rules in an array `[]`): ```json [ @@ -210,9 +210,9 @@ The final configuration should look something like this (note that it contains t ] ``` -Even with these CORS rules in place, you browser might still encounter HTTP status 403 responses with `AccessDenied` in the response body when it tries to `POST` to your bucket. In this case, within the "Permissions" tab of the [S3 Management Console](https://console.aws.amazon.com/s3/home), choose "Public access settings". +Even with these CORS rules in place, you browser might still receive HTTP status 403 responses with `AccessDenied` in the response body when it tries to `POST` to your bucket. In this case, within the `Permissions` tab of the [S3 Management Console](https://console.aws.amazon.com/s3/home), choose `Public access settings`. -It will list general *Public access settings for this bucket*, which can override the rules imposed by your CORS settings. Click on *edit* to manage these settings. Under *Manage public access control lists (ACLs) for this bucket*, make sure that *Block new public ACLs and uploading public objects (Recommended)* is unchecked, and *Save* these settings. +It will list general _Public access settings for this bucket_, which can override the rules imposed by your CORS settings. Click on _edit_ to manage these settings. Under _Manage public access control lists (ACLs) for this bucket_, make sure that _Block new public ACLs and uploading public objects (Recommended)_ is unchecked, and _Save_ these settings. If you are using an IAM policy to allow access to the S3 bucket, the policy must have at least the `s3:PutObject` and `s3:PutObjectAcl` permissions scoped to the bucket in question. @@ -220,23 +220,23 @@ In-depth documentation about CORS rules is available on the [AWS documentation s ## POST uploads -Companion uses POST uploads by default, but you can also use them with your own endpoints. There are a few things to be aware of when doing so: +Companion uses POST uploads by default, but you can also use them with your own endpoints. A few things to be aware of when doing so: - - The `@uppy/aws-s3` plugin attempts to read the `` XML tag from POST upload responses. S3 does not respond with an XML document by default. When generating the form data for POST uploads, you must set the `success_action_status` field to `201`. - ```js - // `s3` is an instance of the AWS JavaScript SDK's S3 client - s3.createPresignedPost({ - // ... - Fields: { - // ... - success_action_status: '201', - }, - }) - ``` +* The `@uppy/aws-s3` plugin attempts to read the `` XML tag from POST upload responses. S3 does not respond with an XML document by default. When generating the form data for POST uploads, you must set the `success_action_status` field to `201`. + ```js + // `s3` is an instance of the AWS JavaScript SDK's S3 client + s3.createPresignedPost({ + // ... + Fields: { + // ... + success_action_status: '201', + }, + }) + ``` ## S3 alternatives -Many other object storage providers have an identical API to S3, so you can use the `@uppy/aws-s3` plugin with them as well. To use them with Companion, you can set the `COMPANION_AWS_ENDPOINT` variable to the endpoint of your preferred service. +Many other object storage providers have a same API to S3, so you can use the `@uppy/aws-s3` plugin with them as well. To use them with Companion, you can set the `COMPANION_AWS_ENDPOINT` variable to the endpoint of your preferred service. ### DigitalOcean Spaces @@ -249,7 +249,7 @@ export COMPANION_AWS_BUCKET="my-space-name" The `{region}` string will be replaced by the contents of the `COMPANION_AWS_REGION` environment variable. -For a working example that you can run and play around with, see the [digitalocean-spaces](https://github.com/transloadit/uppy/tree/master/examples/digitalocean-spaces) folder in the Uppy repository. +For a working example that you can run and play around with, see the [digitalocean-spaces](https://github.com/transloadit/uppy/tree/main/examples/digitalocean-spaces) folder in the Uppy repository. ### Google Cloud Storage @@ -264,9 +264,9 @@ export COMPANION_AWS_SECRET="YOUR-GCS-SECRET" # The Secret You do not need to configure the region with GCS. -You also need to configure CORS differently. Unlike Amazon, Google does not offer a UI for CORS configurations. Instead, an HTTP API must be used. If you haven't done this already, see [Configuring CORS on a Bucket](https://cloud.google.com/storage/docs/configuring-cors#Configuring-CORS-on-a-Bucket) in the GCS documentation, or follow the steps below to do it using Google's API playground. +You also need to configure CORS differently. Unlike Amazon, Google does not offer a UI for CORS configurations. Instead, an HTTP API must be used. If you haven’t done this already, see [Configuring CORS on a Bucket](https://cloud.google.com/storage/docs/configuring-cors#Configuring-CORS-on-a-Bucket) in the GCS documentation, or follow the steps below to do it using Google’s API playground. -GCS has multiple CORS formats, both XML and JSON. Unfortunately, their formats are different from Amazon's, so we can't simply use the one from the [S3 Bucket configuration](#S3-Bucket-configuration) section. Google appears to favour the JSON format, so we will use that. +GCS has several CORS formats, both XML and JSON. Unfortunately, their formats are different from Amazon’s, so we can’t use the one from the [S3 Bucket configuration](#S3-Bucket-configuration) section. Google appears to favour the JSON format, so we will use that. #### JSON CORS configuration @@ -289,7 +289,7 @@ The JSON format consists of an array of CORS configuration objects. An example u } ``` -Most AWS configurations should be fairly simple to port to this format. When using presigned `PUT` uploads, replace the `"POST"` method by `"PUT"` in the first entry. +When using presigned `PUT` uploads, replace the `"POST"` method by `"PUT"` in the first entry. If you have the [gsutil](https://cloud.google.com/storage/docs/gsutil) command-line tool, you can apply this configuration using the [gsutil cors](https://cloud.google.com/storage/docs/configuring-cors#configure-cors-bucket) command. @@ -299,20 +299,23 @@ gsutil cors set THAT-FILE.json gs://BUCKET-NAME Otherwise, you can manually apply it through the OAuth playground: - 1. Get a temporary API token from the [Google OAuth2.0 playground](https://developers.google.com/oauthplayground/) - 1. Select the "Cloud Storage JSON API v1" » "devstorage.full_control" scope - 1. Press "Authorize APIs" and allow access - 1. Click "Step 3 - Configure request to API" - 1. Configure it as follows: - - HTTP Method: PATCH - - Request URI: `https://www.googleapis.com/storage/v1/b/YOUR_BUCKET_NAME` - - Content-Type: application/json (should be the default) - - Press "Enter request body" and input your CORS configuration - 1. Then, finally, press "Send the request". +1. Get a temporary API token from the [Google OAuth2.0 playground](https://developers.google.com/oauthplayground/) +2. Select the `Cloud Storage JSON API v1` » `devstorage.full_control` scope +3. Press `Authorize APIs` and allow access +4. Click `Step 3 - Configure request to API` +5. Configure it as follows: + +* HTTP Method: PATCH +* Request URI: `https://www.googleapis.com/storage/v1/b/YOUR_BUCKET_NAME` +* Content-Type: application/json (should be the default) +* Press `Enter request body` and input your CORS configuration + +1. Then, finally, press `Send the request`. ## Examples + ### Generating a presigned upload URL server-side The `getUploadParameters` function can return a Promise, so upload parameters can be prepared server-side. @@ -353,11 +356,11 @@ uppy.use(AwsS3, { }) ``` -See the [aws-presigned-url example in the uppy repository](https://github.com/transloadit/uppy/tree/master/examples/aws-presigned-url) for a small example that implements both the server-side and the client-side. +See the [aws-presigned-url example in the uppy repository](https://github.com/transloadit/uppy/tree/main/examples/aws-presigned-url) for a small example that implements both the server-side and the client-side. ### Retrieving presign parameters of the uploaded file -Once the file is uploaded, it is possible to retrieve the parameters that were +Once the file is uploaded, it’s possible to retrieve the parameters that were generated in `getUploadParameters(file)` via the `file.meta` field: ```js diff --git a/website/src/docs/box.md b/website/src/docs/box.md index 0348dc1663..4cc33f6025 100644 --- a/website/src/docs/box.md +++ b/website/src/docs/box.md @@ -33,7 +33,7 @@ Install from NPM: npm install @uppy/box ``` -In the [CDN package](/docs/#With-a-script-tag), it is available on the `Uppy` global object: +In the [CDN package](/docs/#With-a-script-tag), the plugin class is available on the `Uppy` global object: ```js const { Box } = Uppy @@ -42,12 +42,14 @@ const { Box } = Uppy ## Setting Up To use the Box provider, you need to configure the Box keys that Companion should use. With the standalone Companion server, specify environment variables: + ```shell export COMPANION_BOX_KEY="Box API key" export COMPANION_BOX_SECRET="Box API secret" ``` When using the Companion Node.js API, configure these options: + ```js companion.app({ providerOptions: { @@ -62,15 +64,15 @@ companion.app({ You can create a Box App on the [Box Developers site](https://app.box.com/developers/console). Things to note: -- Choose "Custom App" and select the "Standard OAuth 2.0 (User Authentication)" app type. -- Oddly you must enable full write access, or you will get [403 when downloading files](https://support.box.com/hc/en-us/community/posts/360049195613-403-error-while-file-download-API-Call) -You'll be redirected to the app page. This page lists the client ID (app key) and client secret (app secret), which you should use to configure Companion as shown above. +* Choose `Custom App` and select the `Standard OAuth 2.0 (User Authentication)` app type. +* Oddly you must enable full write access, or you will get [403 when downloading files](https://support.box.com/hc/en-us/community/posts/360049195613-403-error-while-file-download-API-Call) -The app page has a "Redirect URIs" field. Here, add: -``` -https://$YOUR_COMPANION_HOST_NAME/box/redirect -``` +You’ll be redirected to the app page. This page lists the client ID (app key) and client secret (app secret), which you should use to configure Companion as shown above. + +The app page has a `"Redirect URIs"` field. Here, add: + + https://$YOUR_COMPANION_HOST_NAME/box/redirect You can only use the integration with your own account initially—make sure to apply for production status on the app page before you publish your app, or your users will not be able to sign in! @@ -117,11 +119,11 @@ The valid and authorised URL(s) from which OAuth responses should be accepted. This value can be a `String`, a `Regex` pattern, or an `Array` of both. -This is useful when you have your [Companion](/docs/companion) running on multiple hosts. Otherwise, the default value should do just fine. +This is useful when you have your [Companion](/docs/companion) running on several hosts. Otherwise, the default value should do fine. ### `companionCookiesRule: 'same-origin'` -This option correlates to the [RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials), which tells the plugin whether or not to send cookies to [Companion](/docs/companion). +This option correlates to the [RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials), which tells the plugin whether to send cookies to [Companion](/docs/companion). ### `locale: {}` diff --git a/website/src/docs/community-projects.md b/website/src/docs/community-projects.md index ac21535996..26f96049a3 100644 --- a/website/src/docs/community-projects.md +++ b/website/src/docs/community-projects.md @@ -7,13 +7,13 @@ permalink: docs/community-projects/ category: "Docs" --- -Uppy has a large community of enthusiasts building plugins, integrations with js frameworks, etc! Here's a non-exhaustive list as we just started indexing these. +Uppy has a large community of enthusiasts building plugins, integrations with js frameworks, etc! Here’s a non-exhaustive list: -- [vue-uppy](https://github.com/toast38coza/vue-uppy) — A Vue wrapper for Uppy.io -- [uppy-angular-library](https://github.com/adritasharma/uppy-angular-library) — Angular 8/9 component wrapper -- [ng-uppy](https://github.com/sunil-shrestha/ng-uppy) — Sample angular (5.x) app for uppy.io with resumable uploads -- [uppy-aws-amplify](https://github.com/joelvh/uppy-aws-amplify) — Upload to AWS Amplify Storage (S3) with Uppy -- [uppy-image-compressor](https://github.com/arturi/uppy-plugin-image-compressor/blob/master/src/index.js) — Uppy’s own [Artur Paikin](https://github.com/arturi) received a [question](https://github.com/transloadit/uppy/issues/1582#issuecomment-495787004) about creating plugins and wanted to showcase how you could for example, do image optimization before uploading with Uppy even starts. This could save bandwidth and time, at the tradeoff of not having the original version on the server. We thought the result might be useful to others too so this project is currently under consideration of becoming an official Plugin, depending on your feedback. -- [nova-s3-multipart-upload](https://github.com/ahmedkandel/nova-s3-multipart-upload) — Uppy tool for [Laravel Nova](https://nova.laravel.com) +* [vue-uppy](https://github.com/toast38coza/vue-uppy) — A Vue wrapper for Uppy.io +* [uppy-angular-library](https://github.com/adritasharma/uppy-angular-library) — Angular 8/9 component wrapper +* [ng-uppy](https://github.com/sunil-shrestha/ng-uppy) — Sample angular (5.x) app for uppy.io with resumable uploads +* [uppy-aws-amplify](https://github.com/joelvh/uppy-aws-amplify) — Upload to AWS Amplify Storage (S3) with Uppy +* [uppy-image-compressor](https://github.com/arturi/uppy-plugin-image-compressor/blob/master/src/index.js) — Uppy’s own [Artur Paikin](https://github.com/arturi) received a [question](https://github.com/transloadit/uppy/issues/1582#issuecomment-495787004) about creating plugins and wanted to showcase how you could for example, do image optimization before uploading with Uppy even starts. This could save bandwidth and time, at the tradeoff of not having the original version on the server. We thought the result might be useful to others too so this project is under consideration of becoming an official Plugin, depending on your feedback. +* [nova-s3-multipart-upload](https://github.com/ahmedkandel/nova-s3-multipart-upload) — Uppy tool for [Laravel Nova](https://nova.laravel.com) -We'd like to list more community projects, do you know one that should be on this page? Send us a PR via the link down below. +We’d like to list more community projects, do you know one that should be on this page? Send us a PR via the link down below. diff --git a/website/src/docs/companion.md b/website/src/docs/companion.md index 8bead815b4..156cd7de77 100644 --- a/website/src/docs/companion.md +++ b/website/src/docs/companion.md @@ -9,24 +9,26 @@ category: "Docs" tagline: "Server-side proxy that enables remote sources like Instagram, Google Drive, and Dropbox" --- -Drag and drop, webcam, basic file manipulation (adding metadata, for example) and uploading via tus-resumable uploads or XHR/Multipart are all possible using just the Uppy client module. +Drag and drop, webcam, basic file manipulation (adding metadata, for example) and uploading via tus-resumable uploads or XHR/Multipart are all possible using only the Uppy client module. + + However, if you add [Companion](https://github.com/transloadit/uppy/tree/master/packages/@uppy/companion) to the mix, your users will be able to select files from remote sources, such as Instagram, Google Drive and Dropbox, bypassing the client (so a 5 GB video isn’t eating into your users’ data plans), and then uploaded to the final destination. Files are removed from Companion after an upload is complete, or after a reasonable timeout. Access tokens also don’t stick around for long, for security reasons. -Companion handles the server-to-server communication between your server and file storage providers such as Google Drive, Dropbox, Instagram, etc. Note that you can **not** upload files **to** Companion, it just handles the third party integrations. +Companion handles the server-to-server communication between your server and file storage providers such as Google Drive, Dropbox, Instagram, etc. Note that you can **not** upload files **to** Companion, it only handles the third party integrations. ## Supported providers As of now, Companion is integrated to work with: -- Google Drive (name `drive`) - [Set up instructions](/docs/google-drive/#Setting-Up) -- Dropbox (name `dropbox`) - [Set up instructions](/docs/dropbox/#Setting-Up) -- Box (name `box`) - [Set up instructions](/docs/box/#Setting-Up) -- Instagram (name `instagram`) -- Facebook (name `facebook`) -- OneDrive (name `onedrive`) -- Remote URLs (name `url`) -- Amazon S3 (name `s3`) +* Google Drive (name `drive`) - [Set up instructions](/docs/google-drive/#Setting-Up) +* Dropbox (name `dropbox`) - [Set up instructions](/docs/dropbox/#Setting-Up) +* Box (name `box`) - [Set up instructions](/docs/box/#Setting-Up) +* Instagram (name `instagram`) +* Facebook (name `facebook`) +* OneDrive (name `onedrive`) +* Remote URLs (name `url`) +* Amazon S3 (name `s3`) ## Installation @@ -36,19 +38,21 @@ Install from NPM: npm install @uppy/companion ``` -If you don't have a Node.js project with a `package.json` you might want to install/run Companion globally like so: `[sudo] npm install -g @uppy/companion@2.x`. +If you don’t have a Node.js project with a `package.json` you might want to install/run Companion globally like so: `[sudo] npm install -g @uppy/companion@2.x`. ### Prerequisite Since v2, you now need to be running `node.js >= v10.20.1` to use Companion. Please see [Migrating v1 to v2](#Migrating-v1-to-v2) -Unfortunately, Windows is not a supported platform right now. It may work, and we're happy to accept improvements in this area, but we can't provide assistance. +Unfortunately, Windows is not a supported platform right now. It may work, and we’re happy to accept improvements in this area, but we can’t provide support. ## Usage -Companion may either be used as a pluggable express app, which you plug into your already existing server, or it may simply be run as a standalone server: + + +Companion may either be used as a pluggable express app, which you plug into your already existing server, or it may also be run as a standalone server: -### Plugging into an already existing server +### Plugging into an existing server To plug Companion into an existing server, call its `.app` method, passing in an [options](#Options) object as a parameter. This returns a server instance that you can mount on a subpath in your Express or app. @@ -101,7 +105,7 @@ This takes your `server` instance and [Options](#Options) as parameters. ### Running as a standalone server -> Please ensure that the required environment variables are set before running/using Companion as a standalone server. See [Configure Standalone](#Configuring-a-standalone-server) for the variables required. +> Please make sure that the required environment variables are set before running/using Companion as a standalone server. See [Configure Standalone](#Configuring-a-standalone-server) for the variables required. Set environment variables first: @@ -295,7 +299,7 @@ const options = { 2. **secret(recommended)** - A secret string which Companion uses to generate authorization tokens. -3. **uploadUrls(recommended)** - An allowlist (array) of strings (exact URLs) or regular expressions. If specified, Companion will only accept uploads to these URLs. This is needed to make sure a Companion instance is only allowed to upload to your servers. **Omitting this leaves your system open to potential [SSRF](https://en.wikipedia.org/wiki/Server-side_request_forgery) attacks, and may throw an error in future `@uppy/companion` releases.** +3. **uploadUrls(recommended)** - An allowlist (array) of strings (exact URLs) or regular expressions. If specified, Companion will only accept uploads to these URLs. This is needed to make sure a Companion instance is only allowed to upload to your servers. **Omitting this leaves your system open to potential [SSRF](https://en.wikipedia.org/wiki/Server-side\_request\_forgery) attacks, and may throw an error in future `@uppy/companion` releases.** 4. **redisUrl(optional)** - URL to running Redis server. If this is set, the state of uploads would be stored temporarily. This helps for resumed uploads after a browser crash from the client. The stored upload would be sent back to the client on reconnection. @@ -303,30 +307,30 @@ const options = { 6. **redisPubSubScope(optional)** - Use a scope for the companion events at the Redis server. Setting this option will prefix all events with the name provided and a colon. -7. **server(optional)** - An object with details, mainly used to carry out oauth authentication from any of the enabled providers above. Though it is optional, it is required if you would be enabling any of the supported providers. The following are the server options you may set: +7. **server(optional)** - An object with details, mainly used to carry out oauth authentication from any of the enabled providers above. Though it’s optional, it’s required if you would be enabling any of the supported providers. The following are the server options you may set: - - `protocol` - `http | https` - - `host` (required) - your server host (e.g localhost:3020, mydomain.com) - - `path` - the server path to where the Uppy app is sitting (e.g if Companion is at `mydomain.com/companion`, then the path would be `/companion`). - - `oauthDomain` - if you have multiple instances of Companion with different (and perhaps dynamic) subdomains, you can set a single fixed domain (e.g `sub1.mydomain.com`) to handle your oauth authentication for you. This would then redirect back to the correct instance with the required credentials on completion. This way you only need to configure a single callback URL for OAuth providers. - - `validHosts` - if you are setting an `oauthDomain`, you need to set a list of valid hosts, so the oauth handler can validate the host of the Uppy instance requesting the authentication. This is basically a list of valid domains running your Companion instances. The list may also contain regex patterns. e.g `['sub2.mydomain.com', 'sub3.mydomain.com', '(\\w+).mydomain.com']` - - `implicitPath` - if the URL path to your Companion server is set in your NGINX server (or any other Http server) instead of your express app, then you need to set this path as `implicitPath`. So if your Companion URL is `mydomain.com/mypath/companion`. Where the path `/mypath` is defined in your NGINX server, while `/companion` is set in your express app. Then you need to set the option `implicitPath` to `/mypath`, and set the `path` option to `/companion`. +* `protocol` - `http | https` +* `host` (required) - your server host (e.g localhost:3020, mydomain.com) +* `path` - the server path to where the Uppy app is sitting (e.g if Companion is at `mydomain.com/companion`, then the path would be `/companion`). +* `oauthDomain` - if you have several instances of Companion with different (and perhaps dynamic) subdomains, you can set a single fixed domain (e.g `sub1.mydomain.com`) to handle your oauth authentication for you. This would then redirect back to the correct instance with the required credentials on completion. This way you only need to configure a single callback URL for OAuth providers. +* `validHosts` - if you are setting an `oauthDomain`, you need to set a list of valid hosts, so the oauth handler can validate the host of the Uppy instance requesting the authentication. This is essentially a list of valid domains running your Companion instances. The list may also contain regex patterns. e.g `['sub2.mydomain.com', 'sub3.mydomain.com', '(\\w+).mydomain.com']` +* `implicitPath` - if the URL path to your Companion server is set in your NGINX server (or any other Http server) instead of your express app, then you need to set this path as `implicitPath`. So if your Companion URL is `mydomain.com/mypath/companion`. Where the path `/mypath` is defined in your NGINX server, while `/companion` is set in your express app. Then you need to set the option `implicitPath` to `/mypath`, and set the `path` option to `/companion`. -8. **sendSelfEndpoint(optional)** - This is basically the same as the `server.host + server.path` attributes. The major reason for this attribute is that, when set, it adds the value as the `i-am` header of every request response. +8. **sendSelfEndpoint(optional)** - This is essentially the same as the `server.host + server.path` attributes. The major reason for this attribute is that, when set, it adds the value as the `i-am` header of every request response. 9. **providerOptions(optional)** - An object containing credentials (`key` and `secret`) for each provider you would like to enable. Please see [the list of supported providers](#Supported-providers). 10. **customProviders(optional)** - This option enables you to add custom providers along with the already supported providers. See [Adding Custom Providers](#Adding-custom-providers) for more information. -11. **debug(optional)** - A boolean flag to tell Companion whether or not to log useful debug information while running. +11. **debug(optional)** - A boolean flag to tell Companion whether to log useful debug information while running. -12. **logClientVersion(optional)** - A boolean flag to tell Companion whether or not to log its version upon startup. +12. **logClientVersion(optional)** - A boolean flag to tell Companion whether to log its version upon startup. -13. **metrics(optional)** - A boolean flag to tell Companion whether or not to provide an endpoint `/metrics` with Prometheus metrics. +13. **metrics(optional)** - A boolean flag to tell Companion whether to provide an endpoint `/metrics` with Prometheus metrics. ### Provider Redirect URIs -When generating your provider API keys on their corresponding developer platforms (e.g [Google Developer Console](https://console.developers.google.com/)), you'd need to provide a `redirect URI` for the OAuth authorization process. In general the redirect URI for each provider takes the format: +When generating your provider API keys on their corresponding developer platforms (e.g [Google Developer Console](https://console.developers.google.com/)), you’d need to provide a `redirect URI` for the OAuth authorization process. In general the redirect URI for each provider takes the format: `http(s)://$YOUR_COMPANION_HOST_NAME/$PROVIDER_NAME/redirect` @@ -362,17 +366,18 @@ The datacenter region where the target bucket is located. The standalone Compani You can supply any [S3 option supported by the AWS SDK](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#constructor-property) in the `providerOptions.s3.awsClientOptions` object, _except for_ the below: -- `accessKeyId`. Instead, use the `providerOptions.s3.key` property. This is to make configuration names consistent between different Companion features. -- `secretAccessKey`. Instead, use the `providerOptions.s3.secret` property. This is to make configuration names consistent between different Companion features. +* `accessKeyId`. Instead, use the `providerOptions.s3.key` property. This is to make configuration names consistent between different Companion features. +* `secretAccessKey`. Instead, use the `providerOptions.s3.secret` property. This is to make configuration names consistent between different Companion features. -Be aware that some options may cause wrong behaviour if they conflict with Companion's assumptions. If you find that a particular option does not work as expected, please [open an issue on the Uppy repository](https://github.com/transloadit/uppy/issues/new) so we can document it here. +Be aware that some options may cause wrong behaviour if they conflict with Companion’s assumptions. If you find that a particular option does not work as expected, please [open an issue on the Uppy repository](https://github.com/transloadit/uppy/issues/new) so we can document it here. #### `providerOptions.s3.getKey(req, filename, metadata)` Get the key name for a file. The key is the file path to which the file will be uploaded in your bucket. This option should be a function receiving three arguments: -- `req`, the HTTP request, for _regular_ S3 uploads using the `@uppy/aws-s3` plugin. This parameter is _not_ available for multipart uploads using the `@uppy/aws-s3-multipart` plugin; -- `filename`, the original name of the uploaded file; -- `metadata`, user-provided metadata for the file. See the [`@uppy/aws-s3`](https://uppy.io/docs/aws-s3/#metaFields) docs. Currently, the `@uppy/aws-s3-multipart` plugin unconditionally sends all metadata fields, so all of them are available here. + +* `req`, the HTTP request, for _regular_ S3 uploads using the `@uppy/aws-s3` plugin. This parameter is _not_ available for multipart uploads using the `@uppy/aws-s3-multipart` plugin; +* `filename`, the original name of the uploaded file; +* `metadata`, user-provided metadata for the file. See the [`@uppy/aws-s3`](https://uppy.io/docs/aws-s3/#metaFields) docs. The `@uppy/aws-s3-multipart` plugin unconditionally sends all metadata fields, so they all are available here. This function should return a string `key`. The `req` parameter can be used to upload to a user-specific folder in your bucket, for example: @@ -389,6 +394,7 @@ app.use(uppy.app({ ``` The default implementation returns the `filename`, so all files will be uploaded to the root of the bucket as their original file name. + ```js app.use(uppy.app({ providerOptions: { @@ -401,7 +407,7 @@ app.use(uppy.app({ ### Running in Kubernetes -We have [a detailed guide on running Companion in Kubernetes](https://github.com/transloadit/uppy/blob/master/packages/%40uppy/companion/KUBERNETES.md) for you, that’s how we currently run our example server at . +We have [a detailed guide on running Companion in Kubernetes](https://github.com/transloadit/uppy/blob/master/packages/%40uppy/companion/KUBERNETES.md) for you, that’s how we run our example server at . ### Adding custom providers @@ -433,25 +439,30 @@ The `customProviders` option should be an object containing each custom provider To work well with Companion, the **Module** must be a class with the following methods. -1. `list (options, done)` - lists JSON data of user files (e.g. list of all the files in a particular directory). - - `options` - is an object containing the following attributes - - token - authorization token (retrieved from oauth process) to send along with your request - - directory - the `id/name` of the directory from which data is to be retrieved. This may be ignored if it doesn't apply to your provider - - query - expressjs query params object received by the server (just in case there is some data you need in there). - - `done (err, data)` - the callback that should be called when the request to your provider is made. As the signature indicates, the following data should be passed along to the callback `err`, and [`data`](#list-data). +1. `list (options, done)` - lists JSON data of user files (for example list of all the files in a particular directory). + +* `options` - is an object containing the following attributes + \* token - authorization token (retrieved from oauth process) to send along with your request + \* directory - the `id/name` of the directory from which data is to be retrieved. This may be ignored if it doesn’t apply to your provider + \* query - expressjs query params object received by the server (in case there’s some data you need in there). +* `done (err, data)` - the callback that should be called when the request to your provider is made. As the signature indicates, the following data should be passed along to the callback `err`, and [`data`](#list-data). + 2. `download (options, onData)` - downloads a particular file from the provider. - - `options` - is an object containing the following attributes: - - token - authorization token (retrieved from oauth process) to send along with your request. - - id - ID of the file being downloaded. - - query - expressjs query params object received by the server (just in case there is some data you need in there). - - `onData (err, chunk)` - a callback that should be called with each data chunk received as download is happening. The `err` argument is an error that should be passed if an error occurs during download. It should be `null` if there's no error. Once the download is completed and there are no more chunks to receive, `onData` should be called with `null` values like so `onData(null, null)` + +* `options` - is an object containing the following attributes: + \* token - authorization token (retrieved from oauth process) to send along with your request. + \* id - ID of the file being downloaded. + \* query - expressjs query params object received by the server (in case there’s some data you need in there). +* `onData (err, chunk)` - a callback that should be called with each data chunk received as download is happening. The `err` argument is an error that should be passed if an error occurs during download. It should be `null` if there’s no error. Once the download is completed and no more chunks are to be received, `onData` should be called with `null` values like so `onData(null, null)` + 3. `size (options, done)` - returns the byte size of the file that needs to be downloaded. - - `options` - is an object containing the following attributes: - - token - authorization token (retrieved from oauth process) to send along with your request. - - id - ID of the file being downloaded. - - `done (err, size)` - the callback that should be called after the request to your provider is completed. As the signature indicates, the following data should be passed along to the callback `err`, and `size` (number). -The class must also have an `authProvider` string (lowercased) field which typically indicates the name of the provider (e.g "dropbox"). +* `options` - is an object containing the following attributes: + \* token - authorization token (retrieved from oauth process) to send along with your request. + \* id - ID of the file being downloaded. +* `done (err, size)` - the callback that should be called after the request to your provider is completed. As the signature indicates, the following data should be passed along to the callback `err`, and `size` (number). + +The class must also have an `authProvider` string (lowercased) field which typically indicates the name of the provider (e.g `"dropbox"`). #### list data @@ -507,7 +518,7 @@ In v2 the `google` and `microsoft` [providerOptions](https://uppy.io/docs/compan ### OAuth Redirect URIs -On your Providers' respective developer platforms, the OAuth redirect URIs that you should supply has now changed from: +On your Providers’ respective developer platforms, the OAuth redirect URIs that you should supply has now changed from: `http(s)://$COMPANION_HOST_NAME/connect/$AUTH_PROVIDER/callback` in v1 @@ -557,21 +568,20 @@ This would get the Companion instance running on `http://localhost:3020`. It use An example server is running at , which is deployed with [Kubernetes](https://github.com/transloadit/uppy/blob/master/packages/%40uppy/companion/KUBERNETES.md) - ## How the Authentication and Token mechanism works This section describes how Authentication works between Companion and Providers. While this behaviour is the same for all Providers (Dropbox, Instagram, Google Drive, etc.), we are going to be referring to Dropbox in place of any Provider throughout this section. The following steps describe the actions that take place when a user Authenticates and Uploads from Dropbox through Companion: -- The visitor to a website with Uppy clicks "Connect to Dropbox". -- Uppy sends a request to Companion, which in turn sends an OAuth request to Dropbox (Requires that OAuth credentials from Dropbox have been added to Companion). -- Dropbox asks the visitor to log in, and whether the Website should be allowed to access your files -- If the visitor agrees, Companion will receive a token from Dropbox, with which we can temporarily download files. -- Companion encrypts the token with a secret key and sends the encrypted token to Uppy (client) -- Every time the visitor clicks on a folder in Uppy, it asks Companion for the new list of files, with this question, the token (still encrypted by Companion) is sent along. -- Companion decrypts the token, requests the list of files from Dropbox and sends it to Uppy. -- When a file is selected for upload, Companion receives the token again according to this procedure, decrypts it again, and thereby downloads the file from Dropbox. -- As the bytes arrive, Companion uploads the bytes to the final destination (depending on the configuration: Apache, a Tus server, S3 bucket, etc). -- Companion reports progress to Uppy, as if it were a local upload. -- Completed! +* The visitor to a website with Uppy clicks `Connect to Dropbox`. +* Uppy sends a request to Companion, which in turn sends an OAuth request to Dropbox (Requires that OAuth credentials from Dropbox have been added to Companion). +* Dropbox asks the visitor to log in, and whether the Website should be allowed to access your files +* If the visitor agrees, Companion will receive a token from Dropbox, with which we can temporarily download files. +* Companion encrypts the token with a secret key and sends the encrypted token to Uppy (client) +* Every time the visitor clicks on a folder in Uppy, it asks Companion for the new list of files, with this question, the token (still encrypted by Companion) is sent along. +* Companion decrypts the token, requests the list of files from Dropbox and sends it to Uppy. +* When a file is selected for upload, Companion receives the token again according to this procedure, decrypts it again, and thereby downloads the file from Dropbox. +* As the bytes arrive, Companion uploads the bytes to the final destination (depending on the configuration: Apache, a Tus server, S3 bucket, etc). +* Companion reports progress to Uppy, as if it were a local upload. +* Completed! diff --git a/website/src/docs/dashboard.md b/website/src/docs/dashboard.md index 3ab60486c4..73ce6c7721 100644 --- a/website/src/docs/dashboard.md +++ b/website/src/docs/dashboard.md @@ -10,12 +10,12 @@ tagline: "full-featured sleek UI with file previews, metadata editing, upload/pa `@uppy/dashboard` is a universal UI plugin for Uppy, offering several useful features: -- Drag and drop, paste, select from local disk / my device -- UI for the Webcam plugin and remote sources, such as Google Drive, Dropbox, Instagram, Facebook and OneDrive (all optional, added via plugins) -- Image previews -- Metadata editor -- Upload progress -- Ability to pause or cancel (depending on the uploader plugin) uploads +* Drag and drop, paste, select from local disk / my device +* UI for the Webcam plugin and remote sources, such as Google Drive, Dropbox, Instagram, Facebook and OneDrive (all optional, added via plugins) +* Image previews +* Metadata editor +* Upload progress +* Ability to pause or cancel (depending on the uploader plugin) uploads ```js import Dashboard from '@uppy/dashboard' @@ -37,7 +37,7 @@ Install from NPM: npm install @uppy/dashboard ``` -In the [CDN package](/docs/#With-a-script-tag), it is available on the `Uppy` global object: +In the [CDN package](/docs/#With-a-script-tag), the plugin class is available on the `Uppy` global object: ```js const { Dashboard } = Uppy @@ -106,12 +106,12 @@ uppy.use(Dashboard, { ### `id: 'Dashboard'` -A unique identifier for this plugin. It defaults to `'Dashboard'`, but you can change this if you need multiple Dashboard instances. +A unique identifier for this plugin. It defaults to `'Dashboard'`, but you can change this if you need several Dashboard instances. Plugins that are added by the Dashboard get unique IDs based on this ID, like `'Dashboard:StatusBar'` and `'Dashboard:Informer'`. ### `target: 'body'` -Dashboard is rendered into `body`, because it is hidden by default and only opened as a modal when `trigger` is clicked. +Dashboard is rendered into `body`, because it’s hidden by default and only opened as a modal when `trigger` is clicked. ### `inline: false` @@ -119,11 +119,11 @@ By default, Dashboard will be rendered as a modal, which is opened by clicking o ### `trigger: null` -String with a CSS selector for a button that will trigger opening the Dashboard modal. Multiple buttons or links can be used, as long as it is a class selector (`.select-file-button`, for example). +String with a CSS selector for a button that will trigger opening the Dashboard modal. Several buttons or links can be used, as long as they are selected using a class selector (`.select-file-button`, for example). ### `plugins: []` -List of plugin IDs that should be shown in the Dashboard's top bar. For example, to show the Webcam plugin: +List of plugin IDs that should be shown in the Dashboard’s top bar. For example, to show the Webcam plugin: ```js uppy.use(Webcam) @@ -132,7 +132,7 @@ uppy.use(Dashboard, { }) ``` -Of course, you can also use the `target` option in the Webcam plugin to achieve this. However, that does not work with the React components. The `target` option may be changed in the future to only accept DOM elements, so it is recommended to use this `plugins` array instead. +You could also use the `target` option in the Webcam plugin to achieve this, but that does not work with the React components. The `target` option may be changed in the future to only accept DOM elements, so it’s recommended to use this `plugins` array instead. ### `width: 750` @@ -156,7 +156,7 @@ Turn the file icon and thumbnail in the Dashboard into a link to the uploaded fi Passed to the Status Bar plugin used in the Dashboard. -By default, progress in Status Bar is shown as a simple percentage. If you would like to also display remaining upload size and time, set this to `true`. +By default, progress in Status Bar is shown as a percentage. If you would like to also display remaining upload size and time, set this to `true`. `showProgressDetails: false`: Uploading: 45% `showProgressDetails: true`: Uploading: 45%・43 MB of 101 MB・8s left @@ -204,7 +204,7 @@ Set to `null` to disable the “Done” button. ### `showSelectedFiles: true` -Show the list (grid) of selected files with preview and file name. In case you are showing selected files in your own app’s UI and want the Uppy Dashboard to just be a picker, the list can be hidden with this option. +Show the list (grid) of selected files with preview and file name. In case you are showing selected files in your own app’s UI and want the Uppy Dashboard to only be a picker, the list can be hidden with this option. See also `disableStatusBar` option, which can hide the progress and upload button. @@ -230,12 +230,12 @@ Optionally, specify a string of text that explains something about the upload fo An array of UI field objects, or a function that takes a [File Object](https://uppy.io/docs/uppy/#File-Objects) and returns an array of UI field objects, that will be shown when a user clicks the “edit” button on that file. Configuring this enables the “edit” button on file cards. Each object requires: -- `id`, the name of the meta field. Note: this will also be used in CSS/HTML as part of the `id` attribute, so it’s better to [avoid using characters like periods, semicolons, etc](https://stackoverflow.com/a/79022). -- `name`, the label shown in the interface. -- `placeholder`, the text shown when no value is set in the field. (Not needed when a custom render function is provided) +* `id`, the name of the meta field. Note: this will also be used in CSS/HTML as part of the `id` attribute, so it’s better to [avoid using characters like periods, semicolons, etc](https://stackoverflow.com/a/79022). +* `name`, the label shown in the interface. +* `placeholder`, the text shown when no value is set in the field. (Not needed when a custom render function is provided) Optionally, you can specify `render: ({value, onChange, required, form}, h) => void`, a function for rendering a custom form element. -It gets passed `({value, onChange, required, form}, h)` where `value` is the current value of the meta field, `required` is a boolean that's true if the field `id` is in the `restrictedMetaFields` restriction, `form` is the `id` of the associated `` element, and `onChange: (newVal) => void` is a function saving the new value and `h` is the `createElement` function from [preact](https://preactjs.com/guide/v10/api-reference#h--createelement). +It gets passed `({value, onChange, required, form}, h)` where `value` is the current value of the meta field, `required` is a boolean that’s true if the field `id` is in the `restrictedMetaFields` restriction, `form` is the `id` of the associated `` element, and `onChange: (newVal) => void` is a function saving the new value and `h` is the `createElement` function from [preact](https://preactjs.com/guide/v10/api-reference#h--createelement). `h` can be useful when using uppy from plain JavaScript, where you cannot write JSX. ```js @@ -287,7 +287,7 @@ uppy.use(Dashboard, { ![](/images/uppy-dashboard-meta-fields.jpg) -Note that this metadata will only be set on a file object if it is entered by the user. If the user doesn't edit a file's metadata, it will not have default values; instead everything will be `undefined`. If you want to set a certain meta field to each file regardless of user actions, set [`meta` in the Uppy constructor options](/docs/uppy/#meta). +Note that this metadata will only be set on a file object if it’s entered by the user. If the user doesn’t edit a file’s metadata, it will not have default values; instead everything will be `undefined`. If you want to set a certain meta field to each file regardless of user actions, set [`meta` in the Uppy constructor options](/docs/uppy/#meta). ### `closeModalOnClickOutside: false` @@ -299,7 +299,7 @@ Set to true to automatically close the modal when all current uploads are comple With this option, the modal is only automatically closed when uploads are complete _and successful_. If some uploads failed, the modal stays open so the user can retry failed uploads or cancel the current batch and upload an entirely different set of files instead. -> Setting [`allowMultipleUploads: false`](/docs/uppy#allowMultipleUploads-true) is **strongly** recommended when using this option. With multiple upload batches, the auto-closing behavior can be very confusing for users. +> Setting [`allowMultipleUploads: false`](/docs/uppy#allowMultipleUploads-true) is **strongly** recommended when using this option. With several upload batches, the auto-closing behavior can be quite confusing for users. ### `disablePageScrollWhenModalOpen: true` @@ -311,13 +311,13 @@ Add light animations when the modal dialog is opened or closed, for a more satis ### `fileManagerSelectionType: 'files'` -Configure the type of selections allowed when browsing your file system via the file manager selection window. May be either 'files', 'folders', or 'both'. Selecting entire folders for upload may not be supported on all [browsers](https://caniuse.com/#feat=input-file-directory). +Configure the type of selections allowed when browsing your file system via the file manager selection window. May be either `'files'`, `'folders'`, or `'both'`. Selecting entire folders for upload may not be supported on all [browsers](https://caniuse.com/#feat=input-file-directory). ### `proudlyDisplayPoweredByUppy: true` Uppy is provided to the world for free by the team behind [Transloadit](https://transloadit.com). In return, we ask that you consider keeping a tiny Uppy logo at the bottom of the Dashboard, so that more people can discover and use Uppy. -This is, of course, entirely optional. Just set this option to false if you do not wish to display the Uppy logo. +Set this option to `false` if you do not wish to display the Uppy logo. ### `disableStatusBar: false` @@ -325,7 +325,7 @@ Dashboard ships with the `StatusBar` plugin that shows upload progress and pause ### `disableInformer: false` -Dashboard ships with the `Informer` plugin that notifies when the browser is offline, or when it is time to say cheese if `Webcam` is taking a picture. If you want, you can disable the Informer and/or provide your own custom solution. +Dashboard ships with the `Informer` plugin that notifies when the browser is offline, or when it’s time to say cheese if `Webcam` is taking a picture. If you want, you can disable the Informer and/or provide your own custom solution. ### `disableThumbnailGenerator: false` @@ -335,7 +335,7 @@ Dashboard ships with the `ThumbnailGenerator` plugin that adds small resized ima Localize text that is shown to the user. -The Dashboard also contains the [`@uppy/status-bar`](/docs/status-bar) plugin by default, which has its own strings. Strings for the Status Bar can also be specified in the Dashboard `locale.strings` option, and will be passed down. They are not all listed below—see the [`@uppy/status-bar`](/docs/status-bar) documentation pages for the full list. +The Dashboard also includes the [`@uppy/status-bar`](/docs/status-bar) plugin by default, which has its own strings. Strings for the Status Bar can also be specified in the Dashboard `locale.strings` option, and will be passed down. They are not all listed below—see the [`@uppy/status-bar`](/docs/status-bar) documentation pages for the full list. The default English strings are: @@ -437,11 +437,11 @@ const strings = { Uppy Dashboard supports “Dark Mode”. You can try it live on [the Dashboard example page](https://uppy.io/examples/dashboard/). -There are three options: +It supports the following values: -- `light` — the default -- `dark` -- `auto` — will respect the user’s system settings and switch automatically +* `light` — the default +* `dark` +* `auto` — will respect the user’s system settings and switch automatically ![Uppy dark mode screenshot](/images/uppy-dashboard-dark-mar-2020.png) @@ -515,7 +515,7 @@ Fired when the Dashboard modal is closed. **Parameters:** -- `file` — The [File Object](https://uppy.io/docs/uppy/#File-Objects) representing the file that was opened for editing. +* `file` — The [File Object](https://uppy.io/docs/uppy/#File-Objects) representing the file that was opened for editing. Fired when the user clicks “edit” icon next to a file in the Dashboard. The FileCard panel is then open with file metadata available for editing. @@ -523,6 +523,6 @@ Fired when the user clicks “edit” icon next to a file in the Dashboard. The **Parameters:** -- `file` — The [File Object](https://uppy.io/docs/uppy/#File-Objects) representing the file that was edited. +* `file` — The [File Object](https://uppy.io/docs/uppy/#File-Objects) representing the file that was edited. Fired when the user finished editing the file metadata. diff --git a/website/src/docs/dragdrop.md b/website/src/docs/dragdrop.md index 6625308995..f28a8f07b7 100644 --- a/website/src/docs/dragdrop.md +++ b/website/src/docs/dragdrop.md @@ -9,7 +9,7 @@ category: "Sources" tagline: "plain and simple drag-and-drop area" --- -The `@uppy/drag-drop` plugin renders a simple drag and drop area for file selection. it can be useful when you only want the local device as a file source, don’t need file previews and a UI for metadata editing, and the [Dashboard](/docs/dashboard/) feels like overkill. +The `@uppy/drag-drop` plugin renders a drag and drop area for file selection. it can be useful when you only want the local device as a file source, don’t need file previews and a UI for metadata editing, and the [Dashboard](/docs/dashboard/) feels like overkill. ```js import DragDrop from '@uppy/drag-drop' @@ -31,7 +31,7 @@ Install from NPM: npm install @uppy/drag-drop ``` -In the [CDN package](/docs/#With-a-script-tag), it is available on the `Uppy` global object: +In the [CDN package](/docs/#With-a-script-tag), the plugin class is available on the `Uppy` global object: ```js const { DragDrop } = Uppy @@ -39,7 +39,7 @@ const { DragDrop } = Uppy ## CSS -The `@uppy/drag-drop` plugin includes some simple styles, like shown in the [example](/examples/dragdrop). You can also choose not to use it and provide your own styles instead. +The `@uppy/drag-drop` plugin includes some basi c styles, like shown in the [example](/examples/dragdrop). You can also choose not to use it and provide your own styles instead. ```js import '@uppy/core/dist/style.css' @@ -66,7 +66,7 @@ uppy.use(DragDrop, { ### `id: 'DragDrop'` -A unique identifier for this plugin. It defaults to `'DragDrop'`. Use this if you need to add multiple DragDrop instances. +A unique identifier for this plugin. It defaults to `'DragDrop'`. Use this if you need to add several DragDrop instances. ### `target: null` @@ -115,5 +115,7 @@ const strings = { [ondragover]: https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/ondragover + [ondragleave]: https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/ondragleave + [ondrop]: https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/ondrop diff --git a/website/src/docs/drop-target.md b/website/src/docs/drop-target.md index 92a7b04f53..73e106533e 100644 --- a/website/src/docs/drop-target.md +++ b/website/src/docs/drop-target.md @@ -33,7 +33,7 @@ Install from NPM: npm install @uppy/drop-target ``` -In the [CDN package](/docs/#With-a-script-tag), it is available on the `Uppy` global object: +In the [CDN package](/docs/#With-a-script-tag), the plugin class is available on the `Uppy` global object: ```js const DragDrop = Uppy.DropTarget @@ -41,7 +41,7 @@ const DragDrop = Uppy.DropTarget ## CSS -The `@uppy/drop-target` plugin includes some simple styles for `uppy-is-drag-over` CSS class name. You can also choose not to use it and provide your own styles instead. +The `@uppy/drop-target` plugin includes some basic styles for `uppy-is-drag-over` CSS class name. You can also choose not to use it and provide your own styles instead. ```js import '@uppy/core/dist/style.css' @@ -82,5 +82,7 @@ Callback for the [`ondragleave`][ondragleave] event handler. [ondragover]: https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/ondragover + [ondragleave]: https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/ondragleave + [ondrop]: https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/ondrop diff --git a/website/src/docs/dropbox.md b/website/src/docs/dropbox.md index 648c8ff390..c4a7b352b4 100644 --- a/website/src/docs/dropbox.md +++ b/website/src/docs/dropbox.md @@ -33,7 +33,7 @@ Install from NPM: npm install @uppy/dropbox ``` -In the [CDN package](/docs/#With-a-script-tag), it is available on the `Uppy` global object: +In the [CDN package](/docs/#With-a-script-tag), the plugin class is available on the `Uppy` global object: ```js const { Dropbox } = Uppy @@ -42,12 +42,14 @@ const { Dropbox } = Uppy ## Setting Up To use the Dropbox provider, you need to configure the Dropbox keys that Companion should use. With the standalone Companion server, specify environment variables: + ```shell export COMPANION_DROPBOX_KEY="Dropbox API key" export COMPANION_DROPBOX_SECRET="Dropbox API secret" ``` When using the Companion Node.js API, configure these options: + ```js companion.app({ providerOptions: { @@ -62,15 +64,15 @@ companion.app({ You can create a Dropbox App on the [Dropbox Developers site](https://www.dropbox.com/developers/apps/create). Things to note: -- Choose the "Dropbox API", not the business variant. -- Typically you'll want "Full Dropbox" access, unless you are very certain that you need the other one. -You'll be redirected to the app page. This page lists the app key and app secret, which you should use to configure Companion as shown above. +* Choose the “Dropbox API”, not the business variant. +* Typically you’ll want “Full Dropbox” access, unless you are absolutely certain that you need the other one. -The app page has a "Redirect URIs" field. Here, add: -``` -https://$YOUR_COMPANION_HOST_NAME/dropbox/redirect -``` +You’ll be redirected to the app page. This page lists the app key and app secret, which you should use to configure Companion as shown above. + +The app page has a “Redirect URIs” field. Here, add: + + https://$YOUR_COMPANION_HOST_NAME/dropbox/redirect You can only use the integration with your own account initially—make sure to apply for production status on the app page before you publish your app, or your users will not be able to sign in! @@ -117,11 +119,11 @@ The valid and authorised URL(s) from which OAuth responses should be accepted. This value can be a `String`, a `Regex` pattern, or an `Array` of both. -This is useful when you have your [Companion](/docs/companion) running on multiple hosts. Otherwise, the default value should do just fine. +This is useful when you have your [Companion](/docs/companion) running on several hosts. Otherwise, the default value should do fine. ### `companionCookiesRule: 'same-origin'` -This option correlates to the [RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials), which tells the plugin whether or not to send cookies to [Companion](/docs/companion). +This option correlates to the [RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials), which tells the plugin whether to send cookies to [Companion](/docs/companion). ### `locale: {}` diff --git a/website/src/docs/facebook.md b/website/src/docs/facebook.md index 099a0043b6..79b9a31a6c 100644 --- a/website/src/docs/facebook.md +++ b/website/src/docs/facebook.md @@ -78,11 +78,11 @@ The valid and authorized URL(s) from which OAuth responses should be accepted. This value can be a `String`, a `Regex` pattern, or an `Array` of both. -This is useful when you have your [Companion](/docs/companion) running on multiple hosts. Otherwise, the default value should be good enough. +This is useful when you have your [Companion](/docs/companion) running on several hosts. Otherwise, the default value should be good enough. ### `companionCookiesRule: 'same-origin'` -This option correlates to the [RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials), which tells the plugin whether or not to send cookies to [Companion](/docs/companion). +This option correlates to the [RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials), which tells the plugin whether to send cookies to [Companion](/docs/companion). ### `locale: {}` diff --git a/website/src/docs/fileinput.md b/website/src/docs/fileinput.md index b70e34610a..21aa49111c 100644 --- a/website/src/docs/fileinput.md +++ b/website/src/docs/fileinput.md @@ -33,7 +33,7 @@ Install from NPM: npm install @uppy/file-input ``` -In the [CDN package](/docs/#With-a-script-tag), it is available on the `Uppy` global object: +In the [CDN package](/docs/#With-a-script-tag), the plugin class is available on the `Uppy` global object: ```js const { FileInput } = Uppy @@ -41,7 +41,7 @@ const { FileInput } = Uppy ## CSS -The `@uppy/file-input` plugin includes some simple styles for use with the [`pretty`](#pretty-true) option, like shown in the [example](/examples/xhrupload). You can also choose not to use it and provide your own styles instead. +The `@uppy/file-input` plugin includes some basic styles for use with the [`pretty`](#pretty-true) option, like shown in the [example](/examples/xhrupload). You can also choose not to use it and provide your own styles instead. ```js import '@uppy/core/dist/style.css' @@ -68,7 +68,7 @@ uppy.use(FileInput, { ### `id: 'FileInput'` -A unique identifier for this plugin. It defaults to `'FileInput'`. Use this if you need to add multiple FileInput instances. +A unique identifier for this plugin. It defaults to `'FileInput'`. Use this if you need to add several `FileInput` instances. ### `target: null` diff --git a/website/src/docs/form.md b/website/src/docs/form.md index 11c7f09e27..8c63fe2bc9 100644 --- a/website/src/docs/form.md +++ b/website/src/docs/form.md @@ -10,8 +10,8 @@ tagline: "collect metadata from <form> right before the Uppy The `@uppy/form` plugin has several features to integrate with HTML `` elements. -- It collects user-specified metadata from form fields, right before Uppy begins uploading/processing files. -- It can append upload results back to the form as a hidden field. Currently the appended result is a stringified version of a [`result`](/docs/uppy/#uppy-upload) returned from `uppy.upload()` or `complete` event. +* It collects user-specified metadata from form fields, right before Uppy begins uploading/processing files. +* It can append upload results back to the form as a hidden field. The appended result is a stringified version of a [`result`](/docs/uppy/#uppy-upload) returned from `uppy.upload()` or `complete` event. ```js import Form from '@uppy/form' @@ -31,7 +31,7 @@ Install from NPM: npm install @uppy/form ``` -In the [CDN package](/docs/#With-a-script-tag), it is available on the `Uppy` global object: +In the [CDN package](/docs/#With-a-script-tag), the plugin class is available on the `Uppy` global object: ```js const { Form } = Uppy @@ -66,19 +66,19 @@ The `name` attribute for the `` where the result will be ad ### `getMetaFromForm: true` -Configures whether or not to extract metadata from the form. When set to true, the `Form` plugin will extract all fields from a `` element before upload begins. Those fields will then be added to global `uppy.state.meta` and each file’s meta, and appended as (meta)data to the upload in an object with `[file input name attribute]` -> `[file input value]` key/values. +Configures whether to extract metadata from the form. When set to true, the `Form` plugin will extract all fields from a `` element before upload begins. Those fields will then be added to global `uppy.state.meta` and each file’s meta, and appended as (meta)data to the upload in an object with `[file input name attribute]` -> `[file input value]` key/values. ### `addResultToForm: true` -Configures whether or not to add upload/encoding results back to the form in an `` element. +Configures whether to add upload/encoding results back to the form in an `` element. ### `triggerUploadOnSubmit: false` -Configures whether or not to start the upload when the form is submitted. When the user presses a submit button, this will prevent form submission, and instead upload files. You can then: +Configures whether to start the upload when the form is submitted. When the user presses a submit button, this will prevent form submission, and instead upload files. You can then: -- use `submitOnSuccess: true` if you need the form to _actually_ be submitted once all files have been uploaded. -- listen for `uppy.on('complete')` to do something else if the file uploads are all you need. For example, if the form is used for file metadata only. +* use `submitOnSuccess: true` if you need the form to _actually_ be submitted once all files have been uploaded. +* listen for `uppy.on('complete')` to do something else if the file uploads are all you need. For example, if the form is used for file metadata only. ### `submitOnSuccess: false` -Configures whether or not to submit the form after Uppy finishes uploading/encoding. +Configures whether to submit the form after Uppy finishes uploading/encoding. diff --git a/website/src/docs/golden-retriever.md b/website/src/docs/golden-retriever.md index 2e84379407..c5929cdae8 100644 --- a/website/src/docs/golden-retriever.md +++ b/website/src/docs/golden-retriever.md @@ -10,7 +10,7 @@ tagline: "restore files and continue uploading after a page refresh or a browser The `@uppy/golden-retriever` plugin saves selected files in your browser cache, so that if the browser crashes, Uppy can restore everything and continue uploading as if nothing happened. You can read more about it [on our blog](https://uppy.io/blog/2017/07/golden-retriever/). -The Golden Retriever uses LocalStorage to store file metadata and Uppy state, and IndexedDB for small files. It also uses a Service Worker for _all_ files because, unlike IndexedDB, a Service Worker can keep very large files. Service Worker storage is _very_ temporary though, and doesn't persist across browser crashes or restarts. It works very well, however, for accidental refreshes or closed tabs. +The Golden Retriever uses LocalStorage to store file metadata and Uppy state, and IndexedDB for small files. It also uses a Service Worker for _all_ files because, unlike IndexedDB, a Service Worker can keep large files. Service Worker storage is _quite_ temporary though, and doesn’t persist across browser crashes or restarts. It works well, however, for accidental refreshes or closed tabs. ## Installation @@ -22,7 +22,7 @@ Install from NPM: npm install @uppy/golden-retriever ``` -In the [CDN package](/docs/#With-a-script-tag), it is available on the `Uppy` global object: +In the [CDN package](/docs/#With-a-script-tag), the plugin class is available on the `Uppy` global object: ```js const { GoldenRetriever } = Uppy @@ -30,7 +30,7 @@ const { GoldenRetriever } = Uppy ## Usage -1\. Bundle your own service worker `sw.js` file with Uppy GoldenRetriever’s service worker. If you are using Browserify, just bundle it separately. For Webpack, there is a plugin [serviceworker-webpack-plugin](https://github.com/oliviertassinari/serviceworker-webpack-plugin). +1\. Bundle your own service worker `sw.js` file with Uppy GoldenRetriever’s service worker. If you are using Browserify, bundle it separately. For Webpack, check out [serviceworker-webpack-plugin](https://github.com/oliviertassinari/serviceworker-webpack-plugin). ```js // sw.js diff --git a/website/src/docs/google-drive.md b/website/src/docs/google-drive.md index b08301ae5e..ab56cfb3cc 100644 --- a/website/src/docs/google-drive.md +++ b/website/src/docs/google-drive.md @@ -33,7 +33,7 @@ Install from NPM: npm install @uppy/google-drive ``` -In the [CDN package](/docs/#With-a-script-tag), it is available on the `Uppy` global object: +In the [CDN package](/docs/#With-a-script-tag), the plugin class is available on the `Uppy` global object: ```js const { GoogleDrive } = Uppy @@ -42,12 +42,14 @@ const { GoogleDrive } = Uppy ## Setting Up To use the Google Drive provider, you need to configure the Google Drive keys that Companion should use. With the standalone Companion server, specify environment variables: + ```shell export COMPANION_GOOGLE_KEY="Google Drive OAuth client ID" export COMPANION_GOOGLE_SECRET="Google Drive OAuth client secret" ``` When using the Companion Node.js API, configure these options: + ```js companion.app({ providerOptions: { @@ -61,12 +63,11 @@ companion.app({ To sign up for API keys, go to the [Google Developer Console](https://console.developers.google.com/). -Create a project for your app if you don't have one yet. -- On the project's dashboard, [enable the Google Drive API](https://developers.google.com/drive/api/v3/enable-drive-api). -- [Set up OAuth authorization](https://developers.google.com/drive/api/v3/about-auth). Use this for an authorized redirect URI: - ``` - https://$YOUR_COMPANION_HOST_NAME/drive/redirect - ``` +Create a project for your app if you don’t have one yet. + +* On the project’s dashboard, [enable the Google Drive API](https://developers.google.com/drive/api/v3/enable-drive-api). +* [Set up OAuth authorization](https://developers.google.com/drive/api/v3/about-auth). Use this for an authorized redirect URI: + https://$YOUR\_COMPANION\_HOST\_NAME/drive/redirect Google will give you an OAuth client ID and client secret. Use them to configure Companion as shown above. @@ -113,11 +114,11 @@ The valid and authorised URL(s) from which OAuth responses should be accepted. This value can be a `String`, a `Regex` pattern, or an `Array` of both. -This is useful when you have your [Companion](/docs/companion) running on multiple hosts. Otherwise, the default value should be good enough. +This is useful when you have your [Companion](/docs/companion) running on several hosts. Otherwise, the default value should be good enough. ### `companionCookiesRule: 'same-origin'` -This option correlates to the [RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials), which tells the plugin whether or not to send cookies to [Companion](/docs/companion). +This option correlates to the [RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials), which tells the plugin whether to send cookies to [Companion](/docs/companion). ### `locale: {}` diff --git a/website/src/docs/index.md b/website/src/docs/index.md index 2c0b7e2694..30ea9c7c2a 100644 --- a/website/src/docs/index.md +++ b/website/src/docs/index.md @@ -7,7 +7,7 @@ order: 0 category: "Docs" --- -Uppy is a sleek and modular file uploader. It fetches files from local disk, Google Drive, Instagram, remote urls, cameras etc, and then uploads them to the final destination. It’s fast, easy to use and lets you worry about more important problems than building a file uploader. +Uppy is a sleek and modular file uploader. It fetches files from local disk, Google Drive, Instagram, remote urls, cameras etc, and then uploads them to the final destination. It’s fast, has a comprehensible API and lets you worry about more important problems than building a file uploader. Uppy consists of a core module and [various plugins](/docs/plugins/) for selecting, manipulating and uploading files. @@ -19,12 +19,12 @@ Here’s the simplest example html page with Uppy (it uses a CDN bundle, while w Uppy - +
- + +```html + ``` 2\. Add CSS to ``: -``` html - + +```html + ``` 3\. Initialize at the bottom of the closing `` tag: -``` html +```html + ``` diff --git a/website/src/docs/informer.md b/website/src/docs/informer.md index ee6e343a6f..7f4e2988d4 100644 --- a/website/src/docs/informer.md +++ b/website/src/docs/informer.md @@ -36,7 +36,7 @@ Install from NPM: npm install @uppy/informer ``` -In the [CDN package](/docs/#With-a-script-tag), it is available on the `Uppy` global object: +In the [CDN package](/docs/#With-a-script-tag), the plugin class is available on the `Uppy` global object: ```js const { Informer } = Uppy @@ -61,7 +61,7 @@ The `@uppy/informer` plugin has the following configurable options: ### `id: 'Informer'` -A unique identifier for this plugin. It defaults to `'Informer'`. Use this if you need multiple Informer instances. +A unique identifier for this plugin. It defaults to `'Informer'`. Use this if you need several `Informer` instances. ### `target: null` diff --git a/website/src/docs/instagram.md b/website/src/docs/instagram.md index 988cf04eb6..c35995f79b 100644 --- a/website/src/docs/instagram.md +++ b/website/src/docs/instagram.md @@ -35,7 +35,7 @@ Install from NPM: npm install @uppy/instagram ``` -In the [CDN package](/docs/#With-a-script-tag), it is available on the `Uppy` global object: +In the [CDN package](/docs/#With-a-script-tag), the plugin class is available on the `Uppy` global object: ```js const { Instagram } = Uppy @@ -84,11 +84,11 @@ The valid and authorised URL(s) from which OAuth responses should be accepted. This value can be a `String`, a `Regex` pattern, or an `Array` of both. -This is useful when you have your [Companion](/docs/companion) running on multiple hosts. Otherwise, the default value should be good enough. +This is useful when you have your [Companion](/docs/companion) running on several hosts. Otherwise, the default value should be good enough. ### `companionCookiesRule: 'same-origin'` -This option correlates to the [RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials), which tells the plugin whether or not to send cookies to [Companion](/docs/companion). +This option correlates to the [RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials), which tells the plugin whether to send cookies to [Companion](/docs/companion). ### `locale: {}` diff --git a/website/src/docs/locales.md b/website/src/docs/locales.md index 9b543bea33..8a445a9cc8 100644 --- a/website/src/docs/locales.md +++ b/website/src/docs/locales.md @@ -7,7 +7,7 @@ category: "Docs" body_class: "page-docs-locales" --- -Uppy speaks multiple languages, English being the default. You can use a locale pack to translate Uppy into your language of choice. +Uppy speaks many languages, English being the default. You can use a locale pack to translate Uppy into your language of choice. [List of our locale packs](#List-of-locale-packs) @@ -34,8 +34,8 @@ const uppy = new Uppy({ Add a ` - + + + - - + + ``` Please note that while you may be able to get 2.0 to work in IE11 this way, we do not officially support it anymore. ### Use `BasePlugin` or `UIPlugin` instead of `Plugin` -[`@uppy/core`][core] provided a `Plugin` class for creating plugins. This was used for any official plugin, but also for users who want to create their own custom plugin. However, `Plugin` always came bundled with Preact, even if the plugin itself didn't add any UI elements. +[`@uppy/core`][core] used to provide a `Plugin` class for creating plugins. This was used for any official plugin, but also for users who want to create their own custom plugin. But, `Plugin` always came bundled with Preact, even if the plugin itself didn’t add any UI elements. `Plugin` has been replaced with `BasePlugin` and `UIPlugin`. `BasePlugin` is the minimum you need to create a plugin and `UIPlugin` adds Preact for rendering user interfaces. @@ -62,7 +62,7 @@ You can import them from [`@uppy/core`][core]: import { BasePlugin, UIPlugin } from '@uppy/core' ``` -**Note:** some bundlers will include `UIPlugin` (and therefore Preact) if you import from `@uppy/core`. To make sure this does not happen, you can import `Uppy` and `BasePlugin` directly: +**Note:** some bundlers will include `UIPlugin` (and thus Preact) if you import from `@uppy/core`. To make sure this does not happen, you can import `Uppy` and `BasePlugin` directly: ```js import Uppy from '@uppy/core/lib/Uppy.js' @@ -115,7 +115,9 @@ const otherUppy = Uppy() // incorrect, will throw. ### Rename `allowMultipleUploads` to `allowMultipleUploadBatches` -[`allowMultipleUploadBatches`](https://uppy.io/docs/uppy/#allowMultipleUploadBatches-true) means allowing multiple calls to [`.upload()`](https://uppy.io/docs/uppy/#uppy-upload), in other words, a user can add more files after already having uploaded some. +[`allowMultipleUploadBatches`](https://uppy.io/docs/uppy/#allowMultipleUploadBatches-true) means allowing several calls to [`.upload()`](https://uppy.io/docs/uppy/#uppy-upload), in other words, a user can add more files after already having uploaded some. + + We have renamed this to be more intention revealing that this is about uploads, and not whether a user can choose multiple files for one upload. @@ -127,7 +129,7 @@ const uppy = new Uppy({ ### New default limits for [`@uppy/xhr-upload`][xhr] and [`@uppy/tus`][tus] -The default limit has been changed from `0` to `5`. Setting this to `0` means there is no limit on concurrent uploads. +The default limit has been changed from `0` to `5`. Setting this to `0` means no limit on concurrent uploads. You can change the limit on the Tus and XHR plugin options. @@ -175,6 +177,7 @@ uppy.use(Tus, { Uppy types are now individual exports and should be imported separately. + ```ts import type { PluginOptions, UIPlugin, PluginTarget } from '@uppy/core' ``` @@ -184,6 +187,7 @@ import type { PluginOptions, UIPlugin, PluginTarget } from '@uppy/core' [`@uppy/core`][core] provides an [`.on`](/docs/uppy/#uppy-on-39-event-39-action) method to listen to [events](/docs/uppy/#Events). The types for these events were loose and allowed for invalid events to be passed, such as `uppy.on('upload-errrOOOoooOOOOOrrrr')`. + ```ts // Before: @@ -214,6 +218,7 @@ uppy.on<'complete', Meta>('complete', (result) => { Plugins that add their own events can merge with existing ones in `@uppy/core` with `declare module '@uppy/core' { ... }`. This is a TypeScript pattern called [module augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation). For instance, when using [`@uppy/dashboard`][dashboard]: + ```ts uppy.on('dashboard:file-edit-state', (file) => { const fileName = file.name @@ -236,16 +241,20 @@ Tus will now by default try to resume uploads if the upload has been started in This also means tus will store some data in localStorage for each upload, which will automatically be removed on success. Making `removeFingerprintOnSuccess` obsolete too. -### That's it! +### That’s it! Uppy 1.0 will continue to receive bug fixes for three more months (until ), security fixes for one more year (until ), but no more new features after today. Exceptions are unlikely, but _can_ be made – to accommodate those with commercial support contracts, for example. -We hope you'll waste no time in taking Uppy 2.0 out for a walk. When you do, please let us know what you thought of it on [Reddit](https://www.reddit.com/r/javascript/comments/penbr7/uppy_file_uploader_20_smaller_and_faster_modular/), [HN](https://news.ycombinator.com/item?id=28359287), ProductHunt, or [Twitter](https://twitter.com/uppy_io/status/1432399270846603264). We're howling at the moon to hear from you! +We hope you’ll waste no time in taking Uppy 2.0 out for a walk. When you do, please let us know what you thought of it on [Reddit](https://www.reddit.com/r/javascript/comments/penbr7/uppy\_file\_uploader\_20\_smaller\_and\_faster\_modular/), [HN](https://news.ycombinator.com/item?id=28359287), ProductHunt, or [Twitter](https://twitter.com/uppy\_io/status/1432399270846603264). We’re howling at the moon to hear from you! [core]: /docs/uppy/ + [xhr]: /docs/xhr-upload/ + [dashboard]: /docs/dashboard/ + [aws-s3-multipart]: /docs/aws-s3-multipart/ + [tus]: /docs/tus/ diff --git a/website/src/docs/onedrive.md b/website/src/docs/onedrive.md index db07a805be..28fe5bc123 100644 --- a/website/src/docs/onedrive.md +++ b/website/src/docs/onedrive.md @@ -78,11 +78,11 @@ The valid and authorised URL(s) from which OAuth responses should be accepted. This value can be a `String`, a `Regex` pattern, or an `Array` of both. -This is useful when you have your [Companion](/docs/companion) running on multiple hosts. Otherwise, the default value should be good enough. +This is useful when you have your [Companion](/docs/companion) running on many hosts. Otherwise, the default value should be good enough. ### `companionCookiesRule: 'same-origin'` -This option correlates to the [RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials), which tells the plugin whether or not to send cookies to [Companion](/docs/companion). +This option correlates to the [RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials), which tells the plugin whether to send cookies to [Companion](/docs/companion). ### `locale: {}` diff --git a/website/src/docs/plugin-common-options.md b/website/src/docs/plugin-common-options.md index c55fe0406c..b84ebf56ae 100644 --- a/website/src/docs/plugin-common-options.md +++ b/website/src/docs/plugin-common-options.md @@ -10,7 +10,7 @@ Each plugin can have any number of options (please see specific plugins for deta ### `id` -A unique string identifying the plugin. By default, the plugin's name is used, so usually it does not need to be configured manually. Use this if you need to add multiple plugins of the same type. +A unique string identifying the plugin. By default, the plugin’s name is used, so usually it does not need to be configured manually. Use this if you need to add several plugins of the same type. ### `target` @@ -70,10 +70,12 @@ uppy.getPlugin('Dashboard').setOptions({ }) ``` -> ⚠️ This should work for most options, except for `limit` and some others related to an upload. This is because some objects/instances are created immediately upon initialization, and not updated later. +> ⚠️ This should work for most options, except for `limit` and some others related to an upload. This is because some objects/instances are created at once upon initialization, and not updated later. + + ## Provider Plugins See the [Provider Plugins](/docs/providers) documentation page for information on provider plugins. diff --git a/website/src/docs/plugins.md b/website/src/docs/plugins.md index eb130de127..5adbf4380f 100644 --- a/website/src/docs/plugins.md +++ b/website/src/docs/plugins.md @@ -9,6 +9,6 @@ order: 3 category: "Docs" --- -Everything in Uppy is a Plugin. This lets us offer a wealth of features, but avoid bloating your JS bundle sizes if you don't need all of them. +Everything in Uppy is a Plugin. This lets us offer a wealth of features, but avoid bloating your JS bundle sizes if you don’t need them all. See [list of packages and sizes](#package-list) below to install what you need. diff --git a/website/src/docs/progressbar.md b/website/src/docs/progressbar.md index 8c254dc6ba..1982bf4e41 100644 --- a/website/src/docs/progressbar.md +++ b/website/src/docs/progressbar.md @@ -9,7 +9,7 @@ category: "UI Elements" tagline: "add a small YouTube-style progress bar at the top of the page" --- -`@uppy/progress-bar` is a minimalist plugin that shows the current upload progress in a thin bar element, similar to the ones used by YouTube and GitHub when navigating between pages. +`@uppy/progress-bar` is a minimalist plugin that shows the current upload progress in a thin bar element, like the ones used by YouTube and GitHub when navigating between pages. ```js import ProgressBar from '@uppy/progress-bar' @@ -33,7 +33,7 @@ Install from NPM: npm install @uppy/progress-bar ``` -In the [CDN package](/docs/#With-a-script-tag), it is available on the `Uppy` global object: +In the [CDN package](/docs/#With-a-script-tag), the plugin class is available on the `Uppy` global object: ```js const { ProgressBar } = Uppy @@ -66,7 +66,7 @@ uppy.use(ProgressBar, { ### `id: 'ProgressBar'` -A unique identifier for this Progress Bar. It defaults to `'ProgressBar'`. Use this if you need to add multiple ProgressBar instances. +A unique identifier for this Progress Bar. It defaults to `'ProgressBar'`. Use this if you need to add many `ProgressBar` instances. ### `target: null` @@ -74,7 +74,7 @@ DOM element, CSS selector, or plugin to mount the progress bar into. ### `fixed: false` -When set to true, show the progress bar at the top of the page with `position: fixed`. When set to false, show the progress bar inline wherever it is mounted. +When set to true, show the progress bar at the top of the page with `position: fixed`. When set to false, show the progress bar inline wherever it’s mounted. ```js uppy.use(ProgressBar, { diff --git a/website/src/docs/providers.md b/website/src/docs/providers.md index 867640142b..47bcf492f3 100644 --- a/website/src/docs/providers.md +++ b/website/src/docs/providers.md @@ -6,15 +6,16 @@ order: 10 category: "Sources" --- -The Provider plugins help you connect to your accounts with remote file providers such as [Dropbox](https://dropbox.com), [Google Drive](https://drive.google.com), [Instagram](https://instagram.com) and remote URLs (importing a file by pasting a direct link to it). Because this requires server-to-server communication, they work tightly with [Companion](https://github.com/transloadit/uppy/tree/master/packages/%40uppy/companion) to manage the server-to-server authorization for your account. Almost all of the communication (file download/upload) is done on the server-to-server end, so this saves you the stress and bills of data consumption on the client. +The Provider plugins help you connect to your accounts with remote file providers such as [Dropbox](https://dropbox.com), [Google Drive](https://drive.google.com), [Instagram](https://instagram.com) and remote URLs (importing a file by pasting a direct link to it). Because this requires server-to-server communication, they work tightly with [Companion](https://github.com/transloadit/uppy/tree/master/packages/%40uppy/companion) to manage the server-to-server authorization for your account. Almost all the communication (file download/upload) is done on the server-to-server end, so this saves you the stress and bills of data consumption on the client. As of now, the supported providers are [**Dropbox**](/docs/dropbox), [**Google Drive**](/docs/google-drive), [**OneDrive**](/docs/onedrive/), [**Box**](/docs/box/), [**Instagram**](/docs/instagram), [**Facebook**](/docs/facebook/), [**Zoom**](/docs/zoom/) and [**URL**](/docs/url). -Usage of the Provider plugins is not that different from any other *acquirer* plugin, except that it takes an extra option `companionUrl`, which specifies the URL to the Companion that you are running. This allows Uppy to know what server to connect to when datacenter operations are required by the provider plugin. +Usage of the Provider plugins is not that different from any other _acquirer_ plugin, except that it takes an extra option `companionUrl`, which specifies the URL to the Companion that you are running. This allows Uppy to know what server to connect to when datacenter operations are required by the provider plugin. -Here's a quick example: +Here’s a quick example: + ```js import Uppy from '@uppy/core' import Dashboard from '@uppy/dashboard' diff --git a/website/src/docs/react-dashboard-modal.md b/website/src/docs/react-dashboard-modal.md index 276077fe7a..ce188dd3ee 100644 --- a/website/src/docs/react-dashboard-modal.md +++ b/website/src/docs/react-dashboard-modal.md @@ -40,13 +40,15 @@ Import general Core styles from `@uppy/core/dist/style.css` first, then add the Styles for Provider plugins, like Google Drive and Instagram, are also bundled with Dashboard styles. Styles for other plugins, such as `@uppy/url` and `@uppy/webcam`, are not included. If you are using those, please see their docs and make sure to include styles for them as well. + + ## Props The `` component supports most [`@uppy/dashboard`][] options as props. It adds two more: - - `open` - Boolean true or false, setting this to `true` opens the modal and setting it to `false` closes it. - - `onRequestClose` - Callback called when the user attempts to close the modal, either by clicking the close button or by clicking outside the modal (if the `closeModalOnClickOutside` prop is set). +* `open` - Boolean true or false, setting this to `true` opens the modal and setting it to `false` closes it. +* `onRequestClose` - Callback called when the user attempts to close the modal, either by clicking the close button or by clicking outside the modal (if the `closeModalOnClickOutside` prop is set). An Uppy instance must be provided in the `uppy={}` prop: see [Initializing Uppy](/docs/react/initializing) for details. @@ -119,4 +121,5 @@ class MusicUploadButton extends React.Component { ``` [`@uppy/dashboard`]: /docs/dashboard/ + [`@uppy/webcam`]: /docs/webcam/ diff --git a/website/src/docs/react-dashboard.md b/website/src/docs/react-dashboard.md index 600cd6145c..76906e5dff 100644 --- a/website/src/docs/react-dashboard.md +++ b/website/src/docs/react-dashboard.md @@ -46,6 +46,7 @@ The `` component supports all [`@uppy/dashboard`][] options as prop > The `` cannot be passed to a `target:` option of a remote provider or plugins such as [`@uppy/webcam`][]. To use other plugins like [`@uppy/webcam`][] (Image Editor, Google Drive, etc) with the `` component, first add them to the Uppy instance, and then specify their `id` in the [`plugins`](/docs/dashboard/#plugins) prop: + ```js import React from 'react' import { Dashboard } from '@uppy/react' @@ -72,4 +73,5 @@ function Uploader () { ``` [`@uppy/dashboard`]: /docs/dashboard/ + [`@uppy/webcam`]: /docs/webcam/ diff --git a/website/src/docs/react-dragdrop.md b/website/src/docs/react-dragdrop.md index 5ca87cfe75..cc5cbaa183 100644 --- a/website/src/docs/react-dragdrop.md +++ b/website/src/docs/react-dragdrop.md @@ -27,7 +27,7 @@ import { DragDrop } from '@uppy/react' ## CSS -The `DragDrop` component includes some simple styles, like shown in the [example](/examples/dragdrop). You can also choose not to use it and provide your own styles instead: +The `DragDrop` component includes some basic styles, like shown in the [example](/examples/dragdrop). You can also choose not to include those and use your own styles instead: ```js import '@uppy/core/dist/style.css' diff --git a/website/src/docs/react-fileinput.md b/website/src/docs/react-fileinput.md index 48cda1dddc..732f270d05 100644 --- a/website/src/docs/react-fileinput.md +++ b/website/src/docs/react-fileinput.md @@ -27,7 +27,7 @@ import { FileInput } from '@uppy/react' ## CSS -The `FileInput` component includes some simple styles. You can also choose not to use it and provide your own styles instead: +The `FileInput` component includes some basic styles. You can also choose not to use it and provide your own styles instead: ```js import '@uppy/core/dist/style.css' diff --git a/website/src/docs/react-initializing.md b/website/src/docs/react-initializing.md index 2775928d6c..dfd36270d8 100644 --- a/website/src/docs/react-initializing.md +++ b/website/src/docs/react-initializing.md @@ -8,13 +8,13 @@ order: 1 category: "React" --- -When using Uppy's React components, an Uppy instance must be passed in to the `uppy={}` prop from the outside. This Uppy instance must be initialized before passing it to the desired component, and be cleaned up using `uppy.close()` when you are done with it. +When using Uppy’s React components, an Uppy instance must be passed in to the `uppy={}` prop from the outside. This Uppy instance must be initialized before passing it to the desired component, and be cleaned up using `uppy.close()` when you are done with it. ## Functional Components -Functional components are re-run on every render. This makes it very easy to accidentally recreate a fresh Uppy instance every time, causing state to be reset and resources to be wasted. +Functional components are re-run on every render. This could lead to accidentally recreate a fresh Uppy instance every time, causing state to be reset and resources to be wasted. -The `@uppy/react` package provides a hook `useUppy()` that can manage an Uppy instance's lifetime for you. It will be created when your component is first rendered, and destroyed when your component unmounts. +The `@uppy/react` package provides a hook `useUppy()` that can manage an Uppy instance’s lifetime for you. It will be created when your component is first rendered, and destroyed when your component unmounts. ```js import Uppy from '@uppy/core' @@ -36,7 +36,7 @@ Importantly, the `useUppy()` hook takes a _function_ that returns an Uppy instan ## Class Components -A simple approach is to create an Uppy instance in your React component's `constructor()` and destroy it in `componentWillUnmount()`. +A common approach is to create an Uppy instance in your React component’s `constructor()` and destroy it in `componentWillUnmount()`. > ⚠ Uppy instances are stateful, so the same instance must be used across different renders. > Do **NOT** initialize Uppy in a `render()` method! diff --git a/website/src/docs/react-native.md b/website/src/docs/react-native.md index 941bfff767..1e0845f62d 100644 --- a/website/src/docs/react-native.md +++ b/website/src/docs/react-native.md @@ -9,7 +9,7 @@ category: "React" ⚠️ In Beta -`@uppy/react-native` is a basic Uppy component for React Native with Expo. It is in Beta, and is not full-featured. You can select local images or videos, take pictures with a camera or add any files from [remote urls](/docs/url) with the help of a server-side component, [Uppy Companion](/docs/companion). +`@uppy/react-native` is a basic Uppy component for React Native with Expo. This plugin is still in development, and is not fully featured. You can select local images or videos, take pictures with a camera or add any files from [remote urls](/docs/url) with the help of a server-side component, [Uppy Companion](/docs/companion). Make sure to check out the example in [examples/react-native-expo](https://github.com/transloadit/uppy/tree/master/examples/react-native-expo). diff --git a/website/src/docs/react.md b/website/src/docs/react.md index e56a42d2e7..5039595901 100644 --- a/website/src/docs/react.md +++ b/website/src/docs/react.md @@ -75,20 +75,30 @@ const AvatarPicker = ({ currentAvatar }) => { The following plugins are available as React component wrappers: - - [<Dashboard />][] - renders an inline [`@uppy/dashboard`][] - - [<DashboardModal />][] - renders a [`@uppy/dashboard`][] modal - - [<DragDrop />][] - renders a [`@uppy/drag-drop`][] area - - [<ProgressBar />][] - renders a [`@uppy/progress-bar`][] - - [<StatusBar />][] - renders a [`@uppy/status-bar`][] +* [\][] - renders an inline [`@uppy/dashboard`][] +* [\][] - renders a [`@uppy/dashboard`][] modal +* [\][] - renders a [`@uppy/drag-drop`][] area +* [\][] - renders a [`@uppy/progress-bar`][] +* [\][] - renders a [`@uppy/status-bar`][] [React]: https://facebook.github.io/react + [Preact]: https://preactjs.com/ -[<Dashboard />]: /docs/react/dashboard -[<DragDrop />]: /docs/react/dragdrop -[<ProgressBar />]: /docs/react/progress-bar -[<StatusBar />]: /docs/react/status-bar -[<DashboardModal />]: /docs/react/dashboard-modal + +[]: /docs/react/dashboard + +[]: /docs/react/dragdrop + +[]: /docs/react/progress-bar + +[]: /docs/react/status-bar + +[]: /docs/react/dashboard-modal + [`@uppy/dashboard`]: /docs/dashboard + [`@uppy/drag-drop`]: /docs/drag-drop + [`@uppy/progress-bar`]: /docs/progress-bar + [`@uppy/status-bar`]: /docs/status-bar diff --git a/website/src/docs/redux.md b/website/src/docs/redux.md index b20f560f3f..7d47837a6e 100644 --- a/website/src/docs/redux.md +++ b/website/src/docs/redux.md @@ -34,7 +34,7 @@ If you’d like to persist your Uppy state — please look into [@uppy/golden-re ## Redux Dev Tools -This is a `ReduxDevTools` plugin that simply syncs with the [redux-devtools](https://github.com/gaearon/redux-devtools) browser or JS extensions, and allows for basic time travel: +This is a `ReduxDevTools` plugin that syncs with the [redux-devtools](https://github.com/gaearon/redux-devtools) browser or JS extensions, and allows for basic time travel: ```js import Uppy from '@uppy/core' @@ -53,4 +53,4 @@ const uppy = new Uppy({ After you `.use(ReduxDevTools)`, you should be able to see Uppy’s state in Redux Dev Tools. -You will likely not need this if you are actually using Redux yourself, as well as Redux Store in Uppy like in the example above, since it will just work automatically in that case. +You will likely not need this if you are actually using Redux yourself, as well as Redux Store in Uppy like in the example above, since it will work automatically in that case. diff --git a/website/src/docs/robodog-dashboard.md b/website/src/docs/robodog-dashboard.md index 3c846bf5ab..91180284ad 100644 --- a/website/src/docs/robodog-dashboard.md +++ b/website/src/docs/robodog-dashboard.md @@ -7,7 +7,7 @@ order: 4 category: "File Processing" --- -Add the [Dashboard UI][dashboard] to your page, all wired up and ready to go! This is a basic wrapper around the [Transloadit][transloadit] and [Dashboard][dashboard] plugins. Unlike the [File Picker][file picker] API, this Dashboard is embedded directly into the page. Users can upload multiple files after another. +Add the [Dashboard UI][dashboard] to your page, all wired up and ready to go! This is a basic wrapper around the [Transloadit][transloadit] and [Dashboard][dashboard] plugins. Unlike the [File Picker][file picker] API, this Dashboard is embedded directly into the page. Users can upload many files after another. ```html
@@ -39,7 +39,7 @@ const uppy = Robodog.dashboard(selector, { ...options }) ## Transloadit -Most options to the [Transloadit][transloadit] plugin are supported with the exception of `id`. +Most options to the [Transloadit][transloadit] plugin are supported except for `id`. ## Restrictions @@ -69,8 +69,10 @@ The minimum number of files that must be selected before the upload. The upload Array of mime type wildcards `image/*`, exact mime types `image/jpeg`, or file extensions `.jpg`: `['image/*', '.jpg', '.jpeg', '.png', '.gif']`. -If provided, the [``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#Limiting_accepted_file_types) attribute will be added to `` fields, so only acceptable files can be selected in the system file dialog. +If provided, the [``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#Limiting\_accepted\_file\_types) attribute will be added to `` fields, so only acceptable files can be selected in the system file dialog. [dashboard]: /docs/dashboard + [transloadit]: /docs/transloadit + [file picker]: /docs/robodog/picker diff --git a/website/src/docs/robodog-form.md b/website/src/docs/robodog-form.md index 0d11ec0390..b6912f0a60 100644 --- a/website/src/docs/robodog-form.md +++ b/website/src/docs/robodog-form.md @@ -7,7 +7,7 @@ order: 2 category: "File Processing" --- -Add resumable uploads and Transloadit's processing to your existing HTML upload forms. Selected files will be uploaded to Transloadit, and the Assembly information will be submitted to your form endpoint. +Add resumable uploads and Transloadit’s processing to your existing HTML upload forms. Selected files will be uploaded to Transloadit, and the Assembly information will be submitted to your form endpoint. ```html @@ -77,7 +77,7 @@ The minimum number of files that must be selected before the upload. The upload Array of mime type wildcards `image/*`, exact mime types `image/jpeg`, or file extensions `.jpg`: `['image/*', '.jpg', '.jpeg', '.png', '.gif']`. -If provided, the [``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#Limiting_accepted_file_types) attribute will be added to `` fields, so only acceptable files can be selected in the system file dialog. +If provided, the [``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#Limiting\_accepted\_file\_types) attribute will be added to `` fields, so only acceptable files can be selected in the system file dialog. ## Progress Reporting @@ -121,7 +121,7 @@ window.Robodog.form('form#upload-form', { We now recommend using Uppy over the jQuery SDK. Uppy is framework- and library-agnostic, and much more extensible. -Like the Transloadit jQuery SDK, this API enhances an existing form. That makes this a good candidate for migration. Most of the jQuery SDK options have a direct equivalent in Robodog. +Like the Transloadit jQuery SDK, this API enhances an existing form. That makes this a good candidate for migration. Most of the jQuery SDK options have a direct replacement in Robodog. First, change your import URLs and initialization code: @@ -134,6 +134,7 @@ $(selector).transloadit({ }) ``` + ```html @@ -146,6 +147,7 @@ window.Robodog.form(selector, { ``` Make sure to also include the Uppy css file in your `` tag in case you want to use the `modal: true` option: + ```html @@ -225,8 +227,6 @@ Notice how the form is submitted to the inexistant `/uploads` route once all tra ``` -The equivalent options are listed below. - ### Options | jQuery SDK option | Robodog option | @@ -242,21 +242,19 @@ The equivalent options are listed below. | `triggerUploadOnFileSelection` | `autoProceed: true` | | `processZeroFiles` | `alwaysRunAssembly` | | `maxNumberOfUploadedFiles` | Use [restrictions](#Restrictions) instead. `restrictions.maxNumberOfFiles`. | -| `locale` | No longer supported, this will be addressed by the equivalent to the `translations` option instead. | -| `translations` | Currently unavailable | -| `exclude` | Currently unavailable | +| `locale` | No longer supported, this will be addressed by the `translations` option instead. | +| `translations` | Not available | +| `exclude` | Not available | | `fields` | `fields`. The CSS selector format is no longer supported. Instead, specify an array of form field names. `['field1']` instead of `'input[name=field1]`. | -| `debug` | Obsolete, as Transloadit's backend has improved error reporting. | +| `debug` | Obsolete, as Transloadit’s backend has improved error reporting. | As for the options that are unavailable: -- `exclude` is intended to exclude certain `` inputs from Transloadit processing. It will likely not be added, but we'll perhaps have a `include` CSS selector option instead. -- `debug` will not be added. +* `exclude` is intended to exclude certain `` inputs from Transloadit processing. It will likely not be added, but we’ll perhaps have a `include` CSS selector option instead. +* `debug` will not be added. ### Events -There are no `on*()` _options_ anymore, but `.on('...')` methods are provided instead on the Uppy object that is returned by `window.Robodog.form()`. - | jQuery SDK option | Robodog Event | |---------------|--------------------------| | `onStart` | `.on('transloadit:assembly-created', (assembly) => {})` | @@ -268,7 +266,7 @@ There are no `on*()` _options_ anymore, but `.on('...')` methods are provided in | `onCancel` | `.on('transloadit:cancel', (assembly) => {}))`
or `.on('file-removed', (file) => {})` for individual files | | `onError` | `.on('error', (error) => {})`

The error object might contain an `.assembly` property with an Assembly status for errors that happened during the execution of the Assembly. | | `onSuccess` | `.on('transloadit:complete', (assembly) => {})` | -| `onDisconnect` | Currently unavailable, use something like [`is-offline`](https://www.npmjs.com/package/is-offline) | -| `onReconnect` | Currently unavailable, use something like [`is-offline`](https://www.npmjs.com/package/is-offline) | +| `onDisconnect` | Not available, use something like [`is-offline`](https://www.npmjs.com/package/is-offline) | +| `onReconnect` | Not available, use something like [`is-offline`](https://www.npmjs.com/package/is-offline) | [transloadit plugin]: https://uppy.io/docs/transloadit/ diff --git a/website/src/docs/robodog-picker.md b/website/src/docs/robodog-picker.md index 344e5ecd2f..c1fb72c6e3 100644 --- a/website/src/docs/robodog-picker.md +++ b/website/src/docs/robodog-picker.md @@ -20,10 +20,10 @@ const resultPromise = Robodog.pick({ `resultPromise` is a [Promise][promise] that resolves with an object: - - `successful` - An array containing data about files that were uploaded successfully - - `failed` - An array containing data about files that failed to upload - - `transloadit` - An array of Assembly statuses - - `results` - An array of results produced by the assembly, if `waitForEncoding` was used +* `successful` - An array containing data about files that were uploaded successfully +* `failed` - An array containing data about files that didn’t upload +* `transloadit` - An array of Assembly statuses +* `results` - An array of results produced by the assembly, if `waitForEncoding` was used ## `options.target` @@ -35,9 +35,9 @@ All the options to the [Transloadit][transloadit] plugin are supported. The Promise resolution value has a `transloadit` and `results` key. -`result.transloadit` contains an array of Assembly statuses. Assembly statuses are objects as described in the [Transloadit documentation][assembly-status]. There may be multiple Assembly statuses if the `getAssemblyOptions` option was used, because different files may be processed by different Assemblies. +`result.transloadit` is an array of Assembly statuses. Assembly statuses are objects as described in the [Transloadit documentation][assembly-status]. There may be several Assembly statuses if the `getAssemblyOptions` option was used, because different files may be processed by different Assemblies. -`result.results` contains an array of results produced by the Assemblies. Each result has an `assemblyId` property containing the string ID of the Assembly that produced it, and a `stepName` property containing the string name of the Assembly step that produced it. +`result.results` is an array of results produced by the Assemblies. Each result has an `assemblyId` property containing the string ID of the Assembly that produced it, and a `stepName` property containing the string name of the Assembly step that produced it. ## Restrictions @@ -57,7 +57,7 @@ Maximum file size in bytes for all the files together. ### `restrictions.maxNumberOfFiles` -The total number of files that can be selected. If this is equal to 1, users can only select a single file in system dialogs; else they can select multiple. +The total number of files that can be selected. If this is equal to 1, users can only select a single file in system dialogs; else they can select several. ### `restrictions.minNumberOfFiles` @@ -67,23 +67,23 @@ The minimum number of files that must be selected before the upload. Array of mime type wildcards `image/*`, exact mime types `image/jpeg`, or file extensions `.jpg`: `['image/*', '.jpg', '.jpeg', '.png', '.gif']`. -If provided, the [``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#Limiting_accepted_file_types) attribute will be used for the internal file input field, so only acceptable files can be selected in the system file dialog. +If provided, the [``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#Limiting\_accepted\_file\_types) attribute will be used for the internal file input field, so only acceptable files can be selected in the system file dialog. ## Providers Providers import files from third party services using [Uppy Companion][companion] or from local sources like the device camera. -By default, the Picker will use Transloadit's [Uppy Companion][companion] servers for imports from third party service. You can self-host your own instances as well. +By default, the Picker will use Transloadit’s [Uppy Companion][companion] servers for imports from third party service. You can self-host your own instances as well. ### `providers: []` Array of providers to use. Each entry is the name of a provider. The available ones are: -- `'dropbox'` – Import files from Dropbox using [Uppy Companion][companion]. -- `'google-drive'` – Import files from Google Drive using [Uppy Companion][companion]. -- `'instagram'` – Import files from Instagram using [Uppy Companion][companion]. -- `'url'` – Import files from public Web URLs using [Uppy Companion][companion]. -- `'webcam'` – Take photos and record videos using thee user's device camera. +* `'dropbox'` – Import files from Dropbox using [Uppy Companion][companion]. +* `'google-drive'` – Import files from Google Drive using [Uppy Companion][companion]. +* `'instagram'` – Import files from Instagram using [Uppy Companion][companion]. +* `'url'` – Import files from public Web URLs using [Uppy Companion][companion]. +* `'webcam'` – Take photos and record videos using the user’s device camera. ### `companionUrl: Transloadit.COMPANION` @@ -95,7 +95,7 @@ The valid and authorised URL(s) from which OAuth responses should be accepted. This value can be a `String`, a `Regex` pattern, or an `Array` of both. -This is useful when you have your [Uppy Companion][companion] running on multiple hosts. Otherwise, the default value should do just fine. +This is useful when you have your [Uppy Companion][companion] running on several hosts. Otherwise, the default value should do fine. ### `companionHeaders: {}` @@ -122,6 +122,9 @@ Specific options for the [URL](/docs/url) provider. Specific options for the [Webcam](/docs/webcam) provider. [companion]: /docs/companion + [transloadit]: /docs/transloadit#options + [assembly-status]: https://transloadit.com/docs/api/#assembly-status-response + [promise]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise diff --git a/website/src/docs/robodog-upload.md b/website/src/docs/robodog-upload.md index e3a77a5bf1..8a3b705946 100644 --- a/website/src/docs/robodog-upload.md +++ b/website/src/docs/robodog-upload.md @@ -7,7 +7,7 @@ order: 3 category: "File Processing" --- -Upload files straight to Transloadit from your own custom UI. Give us an array of files, and we'll give you an array of results! +Upload files straight to Transloadit from your own custom UI. Give us an array of files, and we’ll give you an array of results! ```js const resultPromise = Robodog.upload(files, { @@ -20,9 +20,9 @@ const resultPromise = Robodog.upload(files, { `resultPromise` is a [Promise][promise] that resolves with an object: - - `successful` - An array containing data about files that were uploaded successfully - - `failed` - An array containing data about files that failed to upload - - `transloadit` - An array of Assembly statuses +* `successful` - An array containing data about files that were uploaded successfully +* `failed` - An array containing data about files that didn’t upload +* `transloadit` - An array of Assembly statuses ## `files` @@ -35,6 +35,9 @@ These can also be [Blob][blob]s with a `.name` property. That way you can upload All the options to the [Transloadit][tl-options] plugin are supported. [file]: https://developer.mozilla.org/en-US/docs/Web/API/File + [blob]: https://developer.mozilla.org/en-US/docs/Web/API/Blob + [promise]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise + [tl-options]: /docs/transloadit#options diff --git a/website/src/docs/robodog.md b/website/src/docs/robodog.md index 4acec49d0e..a5148e2820 100644 --- a/website/src/docs/robodog.md +++ b/website/src/docs/robodog.md @@ -11,7 +11,7 @@ tagline: "user friendly abstraction to do file processing with Transloadit" [Transloadit][transloadit] is a service that helps you handle file uploads, resize, crop and watermark your images, make GIFs, transcode your videos, extract thumbnails, generate audio waveforms, and so much more. In short, [Transloadit][transloadit] is the Swiss Army Knife for your files. -Robodog is an Uppy-based library that helps you talk to the Transloadit API. It includes a modal UI file picker with support for imports from third-party services, integration with HTML forms, and more. Because it's based on Uppy, you can add any existing Uppy plugin to add more functionality. +Robodog is an Uppy-based library that helps you talk to the Transloadit API. It includes a modal UI file picker with support for imports from third-party services, integration with HTML forms, and more. Because it’s based on Uppy, you can add any existing Uppy plugin to add more functionality. ## Install @@ -42,7 +42,7 @@ Robodog has several methods for different use cases. If you want to have a modal UI that users can use to select files from their local device or from third party sources like Instagram, use the [File Picker API](#File-Picker). This can be used for one-off uploads _outside_ an HTML form, like profile avatars or images to embed in a blog post. -If you already have an HTML form, you can use the [Form API](#Form) to add Transloadit's encoding capabilities to it. Files will be uploaded to Transloadit, and the form will submit JSON information about the files and encoding results. You can also optionally show upload progress using Uppy's Status Bar UI, or even use the advanced Dashboard UI so users can import files from third party sources as well. +If you already have an HTML form, you can use the [Form API](#Form) to add Transloadit’s encoding capabilities to it. Files will be uploaded to Transloadit, and the form will submit JSON information about the files and encoding results. You can also optionally show upload progress using Uppy’s Status Bar UI, or even use the advanced Dashboard UI so users can import files from third party sources as well. Finally, you can use the [Programmatic Upload API](#Programmatic-Uploads) with your custom UI implementation. @@ -72,7 +72,7 @@ resultPromise.then((bundle) => { ## Form -Add resumable uploads and Transloadit's processing to your existing HTML upload forms. Selected files will be uploaded to Transloadit, and the Assembly information will be submitted to your form endpoint. +Add resumable uploads and Transloadit’s processing to your existing HTML upload forms. Selected files will be uploaded to Transloadit, and the Assembly information will be submitted to your form endpoint. ```html @@ -95,7 +95,7 @@ Robodog.form('form#upload-form', { ## Programmatic Uploads -Upload files straight to Transloadit from your own custom UI. Give us an array of files, and we'll give you an array of results! +Upload files straight to Transloadit from your own custom UI. Give us an array of files, and we’ll give you an array of results! ```js const resultPromise = Robodog.upload(files, { @@ -113,5 +113,7 @@ resultPromise.then((bundle) => { View Documentation [transloadit]: https://transloadit.com/ + [browserify]: https://browserify.org + [webpack]: https://webpack.js.org diff --git a/website/src/docs/statusbar.md b/website/src/docs/statusbar.md index 93295756c3..bffbd7863c 100644 --- a/website/src/docs/statusbar.md +++ b/website/src/docs/statusbar.md @@ -10,7 +10,7 @@ tagline: "advanced upload progress status bar" --- The `@uppy/status-bar` plugin shows upload progress and speed, ETAs, pre- and post-processing information, and allows users to control (pause/resume/cancel) the upload. -It is best used in combination with a simple file source plugin, such as [`@uppy/file-input`][] or [`@uppy/drag-drop`][], or a custom implementation. +This plugin is best used in combination with a basic file source plugin, such as [`@uppy/file-input`][] or [`@uppy/drag-drop`][], or a custom implementation. ```js import StatusBar from '@uppy/status-bar' @@ -34,7 +34,7 @@ Install from NPM: npm install @uppy/status-bar ``` -In the [CDN package](/docs/#With-a-script-tag), it is available on the `Uppy` global object: +In the [CDN package](/docs/#With-a-script-tag), the plugin class is available on the `Uppy` global object: ```js const { StatusBar } = Uppy @@ -74,7 +74,7 @@ uppy.use(StatusBar, { ### `id: 'StatusBar'` -A unique identifier for this Status Bar. It defaults to `'StatusBar'`. Use this if you need to add multiple StatusBar instances. +A unique identifier for this Status Bar. It defaults to `'StatusBar'`. Use this if you need to add several StatusBar instances. ### `target: body` @@ -86,7 +86,7 @@ Hide the Status Bar after the upload is complete. ### `showProgressDetails: false` -By default, progress in the Status Bar is shown as simple percentage. If you would like to also display remaining upload size and time, set this to `true`. +By default, progress in the Status Bar is shown as percentage only. If you would like to also display remaining upload size and time, set this to `true`. `showProgressDetails: false`: Uploading: 45% `showProgressDetails: true`: Uploading: 45%・43 MB of 101 MB・8s left @@ -168,4 +168,5 @@ const strings = { ``` [`@uppy/file-input`]: /docs/file-input + [`@uppy/drag-drop`]: /docs/drag-drop diff --git a/website/src/docs/stores.md b/website/src/docs/stores.md index 974d8efc7b..af366fe68c 100644 --- a/website/src/docs/stores.md +++ b/website/src/docs/stores.md @@ -14,12 +14,12 @@ If your app uses a state management library such as [Redux](https://redux.js.org Uppy comes with two state management solutions (stores): - - `@uppy/store-default`, a simple object-based store. - - `@uppy/store-redux`, a store that uses a key in a Redux store. +* `@uppy/store-default`, a basic object-based store. +* `@uppy/store-redux`, a store that uses a key in a Redux store. -There are also some third-party stores: +You can also use a third-party store: - - [uppy-store-ngrx](https://github.com/rimlin/uppy-store-ngrx/), keeping Uppy state in a key in an [Ngrx](https://github.com/ngrx/platform) store for use with Angular. +* [uppy-store-ngrx](https://github.com/rimlin/uppy-store-ngrx/), keeping Uppy state in a key in an [Ngrx](https://github.com/ngrx/platform) store for use with Angular. ## Using stores @@ -45,7 +45,7 @@ The `ReduxStore` dispatches `uppy/STATE_UPDATE` actions to update state. When the state in Redux changes, it notifies Uppy. This way, you get most of the benefits of Redux, including support for the Redux Devtools and time traveling! -Here is how you can integrate Uppy's `ReduxStore`: +Here is how you can integrate Uppy’s `ReduxStore`: ```js import Uppy from '@uppy/core' @@ -80,7 +80,7 @@ ReduxStore({ #### `opts.selector` -If you'd rather not store the Uppy state under the `state.uppy` key at all, use the `selector` option to the `ReduxStore` constructor to tell it where to find state instead: +If you’d rather not store the Uppy state under the `state.uppy` key at all, use the `selector` option to the `ReduxStore` constructor to tell it where to find state instead: ```js const uppy = new Uppy({ @@ -92,21 +92,21 @@ const uppy = new Uppy({ }) ``` -Note that when specifying a custom selector, you **must** also specify a custom store ID. The store `id` tells the reducer in which property it should put Uppy's state. The selector must then take the state from that property. In the example, we set the ID to `avatarUpload` and take the state from the `[reducer mount path].avatarUpload`. +Note that when specifying a custom selector, you **must** also specify a custom store ID. The store `id` tells the reducer in which property it should put Uppy’s state. The selector must then take the state from that property. In the example, we set the ID to `avatarUpload` and take the state from the `[reducer mount path].avatarUpload`. -If your app uses [`reselect`](https://npmjs.com/package/reselect), its selectors work very well with this! +If your app uses [`reselect`](https://npmjs.com/package/reselect), its selectors work well with this! ## Implementing Stores An Uppy store is an object with three methods. - - `getState()` - Return the current state object. - - `setState(patch)` - Merge the object `patch` into the current state. - - `subscribe(listener)` - Call `listener` whenever the state changes. - `listener` is a function that should receive three parameters: - `(prevState, nextState, patch)` +* `getState()` - Return the current state object. +* `setState(patch)` - Merge the object `patch` into the current state. +* `subscribe(listener)` - Call `listener` whenever the state changes. + `listener` is a function that should receive three parameters: + `(prevState, nextState, patch)` - The `subscribe()` method should return a function that 'unsubscribes' (removes) the `listener`. + The `subscribe()` method should return a function that “unsubscribes” (removes) the `listener`. The default store implementation, for example, looks a bit like this: diff --git a/website/src/docs/svelte.md b/website/src/docs/svelte.md index 53823fe70d..95755a8dc6 100644 --- a/website/src/docs/svelte.md +++ b/website/src/docs/svelte.md @@ -84,17 +84,17 @@ const uppy = new Uppy().use(Webcam); The following plugins are available as Svelte component wrappers: -- `` - renders an inline `@uppy/dashboard` -- `` - renders a `@uppy/dashboard` modal -- `` - renders a `@uppy/drag-drop` area -- `` - renders a `@uppy/progress-bar` -- `` - renders a `@uppy/status-bar` +* `` - renders an inline `@uppy/dashboard` +* `` - renders a `@uppy/dashboard` modal +* `` - renders a `@uppy/drag-drop` area +* `` - renders a `@uppy/progress-bar` +* `` - renders a `@uppy/status-bar` -Each component takes a `props` prop that will be passed to the UI Plugin. Both `@uppy/dashboard` based plugins also take a `plugins` array as a props, make it easy to add your plugins. +Each component takes a `props` prop that will be passed to the UI Plugin. Both `@uppy/dashboard` based plugins also take a `plugins` array as a props, make it easier to add your plugins. ### Initializing Uppy -Due to the way Svelte handles reactivity, you can simply initialize Uppy the same way you would with vanilla JavaScript +Due to the way Svelte handles reactivity, you can initialize Uppy the same way you would with vanilla JavaScript ```js import Uppy from '@uppy/core' @@ -118,12 +118,12 @@ The `Dashboard` component requires the following CSS for styling: ``` -Import general Core styles from `@uppy/core/dist/style.css` first, then add the Dashboard styles from `@uppy/dashboard/dist/style.css`. A minified version is also available as `style.min.css` at the same path. The way to do import depends on your build system. +Import general Core styles from `@uppy/core/dist/style.css` first, then add the Dashboard styles from `@uppy/dashboard/dist/style.css`. A minified version is also available as `style.min.css` at the same path. The way to do import depends on your build system. ⚠️ The `@uppy/dashboard` plugin includes CSS for the Dashboard itself, and the various plugins used by the Dashboard, such as ([`@uppy/status-bar`](/docs/status-bar) and [`@uppy/informer`](/docs/informer)). If you also use the `@uppy/status-bar` or `@uppy/informer` plugin directly, you should not include their CSS files, but instead only use the one from the `@uppy/dashboard` plugin. Styles for Provider plugins, like Google Drive and Instagram, are also bundled with Dashboard styles. Styles for other plugins, such as `@uppy/url` and `@uppy/webcam`, are not included. If you are using those, please see their docs and make sure to include styles for them as well. - + #### Props The `` component supports all `@uppy/dashboard` options to be passed as an object to the `props` prop: @@ -163,13 +163,13 @@ Styles for Provider plugins, like Google Drive and Instagram, are also bundled w The `` component supports all `@uppy/dashboard` options to be passed as an object on the `props` prop. An Uppy instance must be provided in the `uppy={}` prop. -The `` cannot be passed to a `target:` option of a remote provider or plugins such as [`@uppy/webcam`][]. To use other plugins like [`@uppy/webcam`][] with the `` component, first add them to the Uppy instance, and then specify their `id` in the [`plugins`](/docs/dashboard/#plugins) prop: +The `` cannot be passed to a `target:` option of a remote provider or plugins such as \[`@uppy/webcam`]\[@uppy/webcam]. To use other plugins like \[`@uppy/webcam`]\[@uppy/webcam] with the `` component, first add them to the Uppy instance, and then specify their `id` in the [`plugins`](/docs/dashboard/#plugins) prop: ### `` #### CSS -The `DragDrop` component includes some simple styles, like shown in the [example](/examples/dragdrop). You can also choose not to use it and provide your own styles instead: +The `DragDrop` component includes some basic styles, like shown in the [example](/examples/dragdrop). You can also choose not to use it and provide your own styles instead: ```html ``` -Import general Core styles from `@uppy/core/dist/style.css` first, then add the Dashboard styles from `@uppy/dashboard/dist/style.css`. A minified version is also available as `style.min.css` at the same path. The way to do import depends on your build system. With default Vue, you can just add a `style` tag and make the `src` attribute the file you need. +Import general Core styles from `@uppy/core/dist/style.css` first, then add the Dashboard styles from `@uppy/dashboard/dist/style.css`. A minified version is also available as `style.min.css` at the same path. The way to do import depends on your build system. With default Vue, you can add a `style` tag and make the `src` attribute the file you need. ⚠️ The `@uppy/dashboard` plugin includes CSS for the Dashboard itself, and the various plugins used by the Dashboard, such as ([`@uppy/status-bar`](/docs/status-bar) and [`@uppy/informer`](/docs/informer)). If you also use the `@uppy/status-bar` or `@uppy/informer` plugin directly, you should not include their CSS files, but instead only use the one from the `@uppy/dashboard` plugin. @@ -117,12 +118,12 @@ Styles for Provider plugins, like Google Drive and Instagram, are also bundled w #### Props -The `` component supports all `@uppy/dashboard` options to be passed as an object on the `props` prop. An Uppy instance must be provided in the `:uppy=''` prop. +The `` component supports all `@uppy/dashboard` options to be passed as an object on the `props` prop. An Uppy instance must be provided in the `:uppy=''` prop. The `` cannot be passed to a `target:` option of a remote provider or plugins such as [`@uppy/webcam`][]. To use other plugins like [`@uppy/webcam`][] with the `` component, first add them to the Uppy instance, and then specify their `id` in the [`plugins`](/docs/dashboard/#plugins) prop: -### `` - +### `` + #### CSS The `DashboardModal` component requires the following CSS for styling: @@ -132,7 +133,7 @@ The `DashboardModal` component requires the following CSS for styling: ``` -Import general Core styles from `@uppy/core/dist/style.css` first, then add the Dashboard styles from `@uppy/dashboard/dist/style.css`. A minified version is also available as `style.min.css` at the same path. The way to do import depends on your build system. With default Vue, you can just add a `style` tag and make the `src` attribute the file you need. +Import general Core styles from `@uppy/core/dist/style.css` first, then add the Dashboard styles from `@uppy/dashboard/dist/style.css`. A minified version is also available as `style.min.css` at the same path. The way to do import depends on your build system. With default Vue, you can add a `style` tag and make the `src` attribute the file you need. ⚠️ The `@uppy/dashboard` plugin includes CSS for the Dashboard itself, and the various plugins used by the Dashboard, such as ([`@uppy/status-bar`](/docs/status-bar) and [`@uppy/informer`](/docs/informer)). If you also use the `@uppy/status-bar` or `@uppy/informer` plugin directly, you should not include their CSS files, but instead only use the one from the `@uppy/dashboard` plugin. @@ -140,7 +141,7 @@ Styles for Provider plugins, like Google Drive and Instagram, are also bundled w #### Props -The `` component supports all `@uppy/dashboard` options to be passed as an object on the `props` prop. An Uppy instance must be provided in the `:uppy=''` prop. +The `` component supports all `@uppy/dashboard` options to be passed as an object on the `props` prop. An Uppy instance must be provided in the `:uppy=''` prop. The `` cannot be passed to a `target:` option of a remote provider or plugins such as [`@uppy/webcam`][]. To use other plugins like [`@uppy/webcam`][] with the `` component, first add them to the Uppy instance, and then specify their `id` in the [`plugins`](/docs/dashboard/#plugins) prop: @@ -148,7 +149,7 @@ The `` cannot be passed to a `target:` option of a remote pro #### CSS -The `DragDrop` component includes some simple styles, like shown in the [example](/examples/dragdrop). You can also choose not to use it and provide your own styles instead: +The `DragDrop` component includes some basic styles, like shown in the [example](/examples/dragdrop). You can also choose not to include those and use your own styles instead: ```html @@ -159,7 +160,7 @@ Import general Core styles from `@uppy/core/dist/style.css` first, then add the #### Props -The `` component supports all `@uppy/drag-drop` options to be passed as an object on the `props` prop. An Uppy instance must be provided in the `:uppy=''` prop. +The `` component supports all `@uppy/drag-drop` options to be passed as an object on the `props` prop. An Uppy instance must be provided in the `:uppy=''` prop. ### `` @@ -176,7 +177,7 @@ Import general Core styles from `@uppy/core/dist/style.css` first, then add the #### Props -The `` component supports all `@uppy/progress-bar` options to be passed as an object on the `props` prop. An Uppy instance must be provided in the `:uppy=''` prop. +The `` component supports all `@uppy/progress-bar` options to be passed as an object on the `props` prop. An Uppy instance must be provided in the `:uppy=''` prop. ### `` @@ -193,9 +194,10 @@ Import general Core styles from `@uppy/core/dist/style.css` first, then add the #### Props -The `` component supports all `@uppy/status-bar` options to be passed as an object on the `props` prop. An Uppy instance must be provided in the `:uppy=''` prop. +The `` component supports all `@uppy/status-bar` options to be passed as an object on the `props` prop. An Uppy instance must be provided in the `:uppy=''` prop. + +[`@uppy/webcam`]: /docs/webcam/ -[Vue]: https://vuejs.org [Nuxt]: https://nuxtjs.org -[`@uppy/webcam`]: /docs/webcam/ +[Vue]: https://vuejs.org diff --git a/website/src/docs/webcam.md b/website/src/docs/webcam.md index 51ffca4b3b..90d10a26d8 100644 --- a/website/src/docs/webcam.md +++ b/website/src/docs/webcam.md @@ -10,7 +10,7 @@ tagline: "upload selfies or audio / video recordings" The `@uppy/webcam` plugin lets you take photos and record videos with a built-in camera on desktop and mobile devices. -> To use the Webcam plugin in Chrome, [your site must be served over https](https://developers.google.com/web/updates/2015/10/chrome-47-webrtc#public_service_announcements). This restriction does not apply on `localhost`, so you don't have to jump through many hoops during development. +> To use the Webcam plugin in Chrome, [your site must be served over https](https://developers.google.com/web/updates/2015/10/chrome-47-webrtc#public\_service\_announcements). This restriction does not apply on `localhost`, so you don’t have to jump through many hoops during development. ```js import Webcam from '@uppy/webcam' @@ -32,7 +32,7 @@ Install from NPM: npm install @uppy/webcam ``` -In the [CDN package](/docs/#With-a-script-tag), it is available on the `Uppy` global object: +In the [CDN package](/docs/#With-a-script-tag), the plugin class is available on the `Uppy` global object: ```js const { Webcam } = Uppy @@ -90,55 +90,51 @@ DOM element, CSS selector, or plugin to mount Webcam into. ### `countdown: false` -When taking a picture: the amount of seconds to wait before actually taking a snapshot. If set to `false` or 0, the timeout is disabled entirely. This also shows a `Smile!` message through the [Informer](/docs/informer) before the picture is taken. +When taking a picture: the amount of seconds to wait before actually taking a snapshot. If set to `false` or 0, the snapshot is taken right away. This also shows a `Smile!` message through the [Informer](/docs/informer) before the picture is taken. ### `onBeforeSnapshot: () => Promise.resolve()` -A hook function to call before a snapshot is taken. The Webcam plugin will wait for the returned Promise to resolve before taking the snapshot. This can be used to implement variations on the `countdown` option for example. +A hook function to call before a snapshot is taken. The Webcam plugin will wait for the returned Promise to resolve before taking the snapshot. This can be used to carry out variations on the `countdown` option for example. ### `modes: []` The types of recording modes to allow. - - `video-audio` - Record a video file, capturing both audio and video. - - `video-only` - Record a video file with the webcam, but don't record audio. - - `audio-only` - Record an audio file with the user's microphone. - - `picture` - Take a picture with the webcam. +* `video-audio` - Record a video file, capturing both audio and video. +* `video-only` - Record a video file with the webcam, but don’t record audio. +* `audio-only` - Record an audio file with the user’s microphone. +* `picture` - Take a picture with the webcam. By default, all modes are allowed, and the Webcam plugin will show controls for recording video as well as taking pictures. ### `mirror: true` -Configures whether or not to mirror preview image from the camera. This option is useful when taking a selfie with a front camera: when you wave your right hand, you will see your hand on the right on the preview screen, like in the mirror. But when you actually take a picture, it will not be mirrored. This is how smartphone selfie cameras behave. +Configures whether to mirror preview image from the camera. This option is useful when taking a selfie with a front camera: when you wave your right hand, you will see your hand on the right on the preview screen, like in the mirror. But when you actually take a picture, it will not be mirrored. This is how smartphone selfie cameras behave. ### `videoConstraints: {}` Configure the kind of video stream you would like to record. Takes an object with properties from the [MediaTrackConstraints][] interface. -You can specify acceptable ranges for the resolution of the video stream using the [`aspectRatio`][], [`width`][], and [`height`][] properties. Each property takes an object with `{ min, ideal, max }` properties. For example, use `width: { min: 720, max: 1920, ideal: 1920 }` to allow any width between 720 and 1920 pixels wide, while preferring the highest resolution. +You can specify acceptable ranges for the resolution of the video stream using the \[`aspectRatio`]\[aspectRatio], \[`width`]\[width], and \[`height`]\[height] properties. Each property takes an object with `{ min, ideal, max }` properties. For example, use `width: { min: 720, max: 1920, ideal: 1920 }` to allow any width between 720 and 1920 pixels wide, while preferring the highest resolution. -Devices sometimes have multiple cameras, front and back, for example. [`facingMode`][] lets you specify which should be used: +Devices sometimes have several cameras, front and back, for example. \[`facingMode`]\[facingMode] lets you specify which should be used: -- `user`: The video source is facing toward the user; this includes, for example, the front-facing camera on a smartphone. -- `environment`: The video source is facing away from the user, thereby viewing their environment. This is the back camera on a smartphone. -- `left`: The video source is facing toward the user but to their left, such as a camera aimed toward the user but over their left shoulder. -- `right`: The video source is facing toward the user but to their right, such as a camera aimed toward the user but over their right shoulder. +* `user`: The video source is facing toward the user; this includes, for example, the front-facing camera on a smartphone. +* `environment`: The video source is facing away from the user, thereby viewing their environment. This is the back camera on a smartphone. +* `left`: The video source is facing toward the user but to their left, such as a camera aimed toward the user but over their left shoulder. +* `right`: The video source is facing toward the user but to their right, such as a camera aimed toward the user but over their right shoulder. -For a full list of available properties, see MDN's [MediaTrackConstraints][] documentation. +For a full list of available properties, check out MDN documentation for [MediaTrackConstraints][]. [MediaTrackConstraints]: https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints#Properties_of_video_tracks -[`aspectRatio`]: https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints/aspectRatio -[`width`]: https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints/width -[`height`]: https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints/height -[`facingMode`]: https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints/facingMode ### `showVideoSourceDropdown: false` -Configures whether or not to show a dropdown which enables to choose the video device to use. This option will have priority over `facingMode` if enabled. The default is `false`. +Configures whether to show a dropdown which enables to choose the video device to use. This option will have priority over `facingMode` if enabled. The default is `false`. ### `showRecordingLength: false` -Configures whether or not to show the length of the recording while the recording is in progress. The default is `false`. +Configures whether to show the length of the recording while the recording is in progress. The default is `false`. ### `preferredVideoMimeType: null` diff --git a/website/src/docs/writing-plugins.md b/website/src/docs/writing-plugins.md index 5aa9422311..b03ede4b1c 100644 --- a/website/src/docs/writing-plugins.md +++ b/website/src/docs/writing-plugins.md @@ -6,20 +6,20 @@ order: 8 category: "Contributing" --- -There are already a few useful Uppy plugins out there, but there might come a time when you will want to build your own. Plugins can hook into the upload process or render a custom UI, typically to: +You can find already a few useful Uppy plugins out there, but there might come a time when you will want to build your own. Plugins can hook into the upload process or render a custom UI, typically to: - - Render some custom UI element, e.g., [StatusBar](/docs/statusbar) or [Dashboard](/docs/dashboard). - - Do the actual uploading, e.g., [XHRUpload](/docs/xhrupload) or [Tus](/docs/tus). - - Do work before the upload, like compressing an image or calling external API. - - Interact with a third-party service to process uploads correctly, e.g., [Transloadit](/docs/transloadit) or [AwsS3](/docs/aws-s3). +* Render some custom UI element, e.g., [StatusBar](/docs/statusbar) or [Dashboard](/docs/dashboard). +* Do the actual uploading, e.g., [XHRUpload](/docs/xhrupload) or [Tus](/docs/tus). +* Do work before the upload, like compressing an image or calling external API. +* Interact with a third-party service to process uploads correctly, e.g., [Transloadit](/docs/transloadit) or [AwsS3](/docs/aws-s3). See a [full example of a plugin](#Example-of-a-custom-plugin) below. ## Creating A Plugin -Uppy has two classes to create plugins with. `BasePlugin` for plugins that don't require an user interface, and `UIPlugin` for onces that do. +Uppy has two classes to create plugins with. `BasePlugin` for plugins that don’t need a user interface, and `UIPlugin` for onces that do. Each plugin has an `id` and a `type`. `id`s are used to uniquely identify plugins. -A `type` can be anything—some plugins use `type`s to determine whether to do something to some other plugin. +A `type` can be anything—some plugins use `type`s to decide whether to do something to some other plugin. For example, when targeting plugins at the built-in `Dashboard` plugin, the Dashboard uses the `type` to figure out where to mount different UI elements. `'acquirer'`-type plugins are mounted into the tab bar, while `'progressindicator'`-type plugins are mounted into the progress bar area. @@ -39,9 +39,9 @@ export default class MyPlugin extends BasePlugin { ## Methods -Plugins can implement methods in order to execute certain tasks. The most important method is `install()`, which is called when a plugin is `.use`d. +Plugins can define methods to execute certain tasks. The most important method is `install()`, which is called when a plugin is `.use`d. -All of the below methods are optional! Only implement the methods you need. +All the below methods are optional! Only define the methods you need. ### `BasePlugin` @@ -61,7 +61,7 @@ export default class MyPlugin extends UIPlugin { #### `uninstall()` -Called when the plugin is removed, or the Uppy instance is closed. This should undo all of the work done in the `install()` method. +Called when the plugin is removed, or the Uppy instance is closed. This should undo all the work done in the `install()` method. ```js export default class MyPlugin extends UIPlugin { @@ -79,7 +79,7 @@ Called after every state update with a debounce, after everything has mounted. #### `addTarget()` -Use this to add your plugin to another plugin's target. This is what `@uppy/dashboard` uses to add other plugins to its UI. +Use this to add your plugin to another plugin’s target. This is what `@uppy/dashboard` uses to add other plugins to its UI. ### `UIPlugin` @@ -93,26 +93,26 @@ This method can be overridden to support for different render engines. #### `render()` -Render this plugin's UI. Uppy uses [Preact](https://preactjs.com) as its view engine, so `render()` should return a Preact element. +Render this plugin’s UI. Uppy uses [Preact](https://preactjs.com) as its view engine, so `render()` should return a Preact element. `render` is automatically called by Uppy on each state change. #### `onMount()` -Called after Preact has rendered the components of the plugin. Can be used to perform additional side-effects. +Called after Preact has rendered the components of the plugin. #### `update(state)` -Called on each state update. You will rarely need to use this, it is mostly handy if you want to build a UI plugin using something other than Preact. +Called on each state update. You will rarely need to use this, unless if you want to build a UI plugin using something other than Preact. #### `onUnmount()` -Called after the elements have been removed from the DOM. Can be used to perform additional (clean up) side-effects. +Called after the elements have been removed from the DOM. Can be used to do some clean up or other side-effects. ## Upload Hooks When creating an upload, Uppy runs files through an upload pipeline. The pipeline consists of three parts, each of which can be hooked into: Preprocessing, Uploading, and Postprocessing. Preprocessors can be used to configure uploader plugins, encrypt files, resize images, etc., before uploading them. Uploaders do the actual uploading work, such as creating an XMLHttpRequest object and sending the file. Postprocessors do their work after files have been uploaded completely. This could be anything from waiting for a file to propagate across a CDN, to sending another request to relate some metadata to the file. -Each hook is a function that receives an array containing the file IDs that are being uploaded, and returns a Promise to signal completion. Hooks are added and removed through `Uppy` methods: `addPreProcessor`, `addUploader`, `addPostProcessor`, and their `remove*` counterparts. Normally, hooks should be added during the plugin's `install()` method, and removed during the `uninstall()` method. +Each hook is a function that receives an array containing the file IDs that are being uploaded, and returns a Promise to signal completion. Hooks are added and removed through `Uppy` methods: `addPreProcessor`, `addUploader`, `addPostProcessor`, and their `remove*` counterparts. Normally, hooks should be added during the plugin `install()` method, and removed during the `uninstall()` method. Additionally, upload hooks can fire events to signal progress. @@ -142,65 +142,89 @@ class MyPlugin extends BasePlugin { } ``` +Or you can define the method as a class field: + +```js +class MyPlugin extends UIPlugin { + constructor (uppy, opts) { + super(uppy, opts) + this.id = opts.id || 'MyPlugin' + this.type = 'example' + } + + prepareUpload = (fileIDs) => { // ← this! + console.log(this) // `this` refers to the `MyPlugin` instance. + return Promise.resolve() + } + + install () { + this.uppy.addPreProcessor(this.prepareUpload) + } + + uninstall () { + this.uppy.removePreProcessor(this.prepareUpload) + } +} +``` + ### `addPreProcessor(fn)` Add a preprocessing function. `fn` gets called with a list of file IDs before an upload starts. `fn` should return a Promise. Its resolution value is ignored. To change file data and such, use Uppy state updates, for example using [`setFileState`][core.setfilestate]. ### `addUploader(fn)` -Add an uploader function. `fn` gets called with a list of file IDs when an upload should start. Uploader functions should do the actual uploading work, such as creating and sending an XMLHttpRequest or calling into some upload service's SDK. `fn` should return a Promise that resolves once all files have been uploaded. +Add an uploader function. `fn` gets called with a list of file IDs when an upload should start. Uploader functions should do the actual uploading work, such as creating and sending an XMLHttpRequest or calling into some upload service SDK. `fn` should return a Promise that resolves once all files have been uploaded. You may choose to still resolve the Promise if some file uploads fail. This way, any postprocessing will still run on the files that were uploaded successfully, while uploads that failed will be retried when `uppy.retryAll` is called. ### `addPostProcessor(fn)` -Add a postprocessing function. `fn` is called with a list of file IDs when an upload has finished. `fn` should return a Promise that resolves when the processing work is complete. Again, the resolution value of the Promise is ignored. This hook can be used to do any finishing work. For example, you could wait for file encoding or CDN propagation to complete, or you could do an HTTP API call to create an album containing all images that were just uploaded. +Add a postprocessing function. `fn` is called with a list of file IDs when an upload has finished. `fn` should return a Promise that resolves when the processing work is complete. Again, the resolution value of the Promise is ignored. This hook can be used to do any finishing work. For example, you could wait for file encoding or CDN propagation to complete, or you could do an HTTP API call to create an album containing all images that were uploaded. ### `removePreProcessor/removeUploader/removePostProcessor(fn)` -Remove a processor or uploader function that was added previously. Normally, this should be done in the `uninstall()` method. +Remove a processor or uploader function that was added before. Normally, this should be done in the `uninstall()` method. ## Progress events Progress events can be fired for individual files to show feedback to the user. For upload progress events, only emitting how many bytes are expected and how many have been uploaded is enough. Uppy will handle calculating progress percentages, upload speed, etc. -Preprocessing and postprocessing progress events are plugin-dependent and can refer to anything, so Uppy doesn't try to be smart about them. There are two types of processing progress events: determinate and indeterminate. Some processing does not have meaningful progress beyond "not done" and "done". For example, sending a request to initialize a server-side resource that will serve as the upload destination. In those situations, indeterminate progress is suitable. Other processing does have meaningful progress. For example, encrypting a large file. In those situations, determinate progress is suitable. +Preprocessing and postprocessing progress events are plugin-dependent and can refer to anything, so Uppy doesn’t try to be smart about them. Processing progress events can be of two types: determinate or indeterminate. Some processing does not have meaningful progress beyond “not done” and “done”. For example, sending a request to initialize a server-side resource that will serve as the upload destination. In those situations, indeterminate progress is suitable. Other processing does have meaningful progress. For example, encrypting a large file. In those situations, determinate progress is suitable. ### `preprocess-progress(fileID, progress)` `progress` is an object with properties: - - `mode` - Either `'determinate'` or `'indeterminate'`. - - `message` - A message to show to the user. Something like `'Preparing upload...'`, but be more specific if possible. +* `mode` - Either `'determinate'` or `'indeterminate'`. +* `message` - A message to show to the user. Something like `'Preparing upload...'`, but be more specific if possible. When `mode` is `'determinate'`, also add the `value` property: - - `value` - A progress value between 0 and 1. +* `value` - A progress value between 0 and 1. ### `upload-progress(progress)` `progress` is an object with properties: - - `uploader` - The uploader plugin that fired the event (`this`). - - `id` - The file ID. - - `bytesTotal` - The full amount of bytes to be uploaded. - - `bytesUploaded` - The amount of bytes that have been uploaded so far. +* `uploader` - The uploader plugin that fired the event (`this`). +* `id` - The file ID. +* `bytesTotal` - The full amount of bytes to be uploaded. +* `bytesUploaded` - The amount of bytes that have been uploaded so far. ### `postprocess-progress(fileID, progress)` `progress` is an object with properties: - - `mode` - Either `'determinate'` or `'indeterminate'`. - - `message` - A message to show to the user. Something like `'Preparing upload...'`, but be more specific if possible. +* `mode` - Either `'determinate'` or `'indeterminate'`. +* `message` - A message to show to the user. Something like `'Preparing upload...'`, but be more specific if possible. When `mode` is `'determinate'`, also add the `value` property: - - `value` - A progress value between 0 and 1. +* `value` - A progress value between 0 and 1. - ### `error(err\[, fileID\]) - - `err` is an `Error` object. `fileID` can optionally which file fails to inform the user. +### `error(err[, fileID])` +`err` is an `Error` object. `fileID` can optionally which file fails to inform the user. ### JSX @@ -210,6 +234,7 @@ You have to import the Preact `h` function and tell Babel to use it by adding a See the Preact [Getting Started Guide](https://preactjs.com/guide/getting-started) for more on Babel and JSX. + ```js /** @jsx h */ import { UIPlugin } from '@uppy/core' @@ -254,6 +279,7 @@ This allows them to be overridden by Locale Packs, or directly when users pass ` Below is a full example of a [small plugin](https://github.com/arturi/uppy-plugin-image-compressor) that compresses images before uploading them. You can replace `compressorjs` method with any other work you need to do. This works especially well for async stuff, like calling an external API. + ```js import { UIPlugin } from '@uppy/core' import Translator from '@uppy/utils/lib/Translator' diff --git a/website/src/docs/xhrupload.md b/website/src/docs/xhrupload.md index d7921a0412..8bacab1f11 100644 --- a/website/src/docs/xhrupload.md +++ b/website/src/docs/xhrupload.md @@ -32,7 +32,7 @@ Install from NPM: npm install @uppy/xhr-upload ``` -In the [CDN package](/docs/#With-a-script-tag), it is available on the `Uppy` global object: +In the [CDN package](/docs/#With-a-script-tag), the plugin class is available on the `Uppy` global object: ```js const { XHRUpload } = Uppy @@ -56,7 +56,7 @@ Configures which HTTP method to use for the upload. ### `formData: true` -Configures whether or not to use a multipart form upload, using [FormData][]. +Configures whether to use a multipart form upload, using [FormData][]. This works similarly to using a `` element with an `` for uploads. When set to `true`, file metadata is also sent to the endpoint as separate form fields. When set to `false`, only the file contents are sent. @@ -72,10 +72,10 @@ is set to `true`, otherwise it defaults to `'file'`. Pass an array of field names to limit the metadata fields that will be sent to the endpoint as form fields. * Set this to `['name']` to only send the `name` field. -* Set this to `null` (the default) to send *all* metadata fields. +* Set this to `null` (the default) to send _all_ metadata fields. * Set this to an empty array `[]` to not send any fields. -If the [`formData`](#formData-true) option is set to false, `metaFields` has no effect. +If the [`formData`](#formData-true) option is set to false, `metaFields` is ignored. ### `headers: {}` @@ -89,6 +89,7 @@ const headers = { ``` Header values can also be derived from file data by providing a function. The function receives a [File Object][File Objects] and must return an object where the keys are header names, and values are header values. + ```js const headers = (file) => { return { @@ -98,7 +99,7 @@ const headers = (file) => { } ``` -> ⚠️ The function syntax is not available when the [`bundle: true`](#bundle-false) option is set. `bundle` is disabled by default. +> ⚠️ The function syntax is not available when the [`bundle: true`](#bundle-false) option is set. ### `bundle: false` @@ -121,7 +122,7 @@ uppy.setFileState(otherFileID, { ### `validateStatus(statusCode, responseText, response)` -> This option is only used for **local** uploads at this time. Uploads from remote providers like Google Drive or Instagram do not support this and will always use the default. +> This option is only used for **local** uploads. Uploads from remote providers like Google Drive or Instagram do not support this and will always use the default. Check if the response from the upload endpoint indicates that the upload was successful. By default, responses with a 2xx HTTP status code are considered successful. @@ -141,7 +142,7 @@ The `responseText` is the XHR endpoint response as a string. ### `getResponseData(responseText, response)` -When an upload has completed, Uppy will extract response data from the upload endpoint. This response data will be available on the file's `.response` property, and be emitted in the [`upload-success`][uppy.upload-success] event: +When an upload has completed, Uppy will extract response data from the upload endpoint. This response data will be available on the file’s `.response` property, and be emitted in the [`upload-success`][uppy.upload-success] event: ```js const responseData = uppy.getFile(fileID).response @@ -181,14 +182,14 @@ function getResponseData (responseText, response) { The `responseText` is the XHR endpoint response as a string. -For uploads from the user's device, `response` is the [XMLHttpRequest][] object. +For uploads from the user’s device, `response` is the [XMLHttpRequest][] object. -When uploading files from remote providers such as Dropbox or Instagram, Companion sends upload response data to the client. This is made available in the `getResponseData()` function as well. The `response` object from Companion contains some properties named after their [XMLHttpRequest][] counterparts: +When uploading files from remote providers such as Dropbox or Instagram, Companion sends upload response data to the client. This is made available in the `getResponseData()` function as well. The `response` object from Companion has some properties named after their [XMLHttpRequest][] counterparts: - - `response.responseText` - the XHR endpoint response as a string; - - `response.status` - the HTTP status code; - - `response.statusText` - the HTTP status text; - - `response.headers` - an object mapping lowercase header names to their values. +* `response.responseText` - the XHR endpoint response as a string; +* `response.status` - the HTTP status code; +* `response.statusText` - the HTTP status text; +* `response.headers` - an object mapping lowercase header names to their values. ### `getResponseError(responseText, response)` @@ -218,15 +219,15 @@ The default for the timeout is 30 seconds. ### `limit: 5` -Limit the amount of uploads going on at the same time. Setting this to `0` means there is no limit on concurrent uploads. +Limit the amount of uploads going on at the same time. Setting this option to `0` means no limit on concurrent uploads. ### `responseType: ''` -The response type expected from the server, determining how the `xhr.response` property should be filled. The `xhr.response` property can be accessed in a custom [`getResponseData()`](#getResponseData-responseText-response) callback. This option sets the [`XMLHttpRequest.responseType`][XHR.responseType] property. Only '', 'text', 'arraybuffer', 'blob' and 'document' are widely supported by browsers, so it's recommended to use one of those. The default is the empty string, which is equivalent to 'text' for the `xhr.response` property. +The response type expected from the server, determining how the `xhr.response` property should be filled. The `xhr.response` property can be accessed in a custom [`getResponseData()`](#getResponseData-responseText-response) callback. This option sets the [`XMLHttpRequest.responseType`][XHR.responseType] property. Only `''`, `'text'`, `'arraybuffer'`, `'blob'` and `'document'` are widely supported by browsers, so it’s recommended to use one of those. The default is the empty string, which is equivalent to `'text'` for the `xhr.response` property. ### `withCredentials: false` -Indicates whether or not cross-site Access-Control requests should be made using credentials. +Indicates whether cross-site Access-Control requests should be made using credentials. ### `locale: {}` @@ -257,7 +258,7 @@ uppy.on('file-added', (file) => { Now, a form field named `size` will be sent along to the [`endpoint`](#endpoint-39-39) once the upload starts. -By default, all metadata is sent, including Uppy's default `name` and `type` metadata. If you do not want the `name` and `type` metadata properties to be sent to your upload endpoint, you can use the [`metaFields`](#metaFields-null) option to restrict the field names that should be sent. +By default, all metadata is sent, including Uppy’s default `name` and `type` metadata. If you do not want the `name` and `type` metadata properties to be sent to your upload endpoint, you can use the [`metaFields`](#metaFields-null) option to restrict the field names that should be sent. ```js uppy.use(XHRUpload, { @@ -270,6 +271,8 @@ uppy.use(XHRUpload, { The XHRUpload plugin works similarly to a `` upload. You can use the `$_FILES` variable on the server to work with uploaded files. See the PHP documentation on [Handling file uploads][PHP.file-upload]. + + The default form field for file uploads is `files[]`, which means you have to access the `$_FILES` array as described in [Uploading multiple files][PHP.multiple]: ```php @@ -281,7 +284,7 @@ $file_name = $_POST['name']; // desired name of the file move_uploaded_file($file_path, './img/' . basename($file_name)); // save the file in `img/` ``` -Note how we are using `$_POST['name']` instead of `$my_file['name']`. `$my_file['name']` contains the original name of the file on the user's device. `$_POST['name']` contains the `name` metadata value for the uploaded file, which can be edited by the user using the [Dashboard](/docs/dashboard). +Note how we are using `$_POST['name']` instead of `$my_file['name']`. `$my_file['name']` has the original name of the file on the user’s device. `$_POST['name']` has the `name` metadata value for the uploaded file, which can be edited by the user using the [Dashboard](/docs/dashboard). Set a custom `fieldName` to make working with the `$_FILES` array a bit less convoluted: @@ -303,10 +306,17 @@ move_uploaded_file($file_path, $_SERVER['DOCUMENT_ROOT'] . '/img/' . basename($f ``` [FormData]: https://developer.mozilla.org/en-US/docs/Web/API/FormData + [XMLHttpRequest]: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest + [XHR.timeout]: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/timeout + [XHR.responseType]: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType + [uppy.upload-success]: /docs/uppy/#upload-success + [File Objects]: /docs/uppy/#File-Objects + [PHP.file-upload]: https://secure.php.net/manual/en/features.file-upload.php + [PHP.multiple]: https://secure.php.net/manual/en/features.file-upload.multiple.php diff --git a/website/src/docs/zoom.md b/website/src/docs/zoom.md index 046161be8f..e2726138a0 100644 --- a/website/src/docs/zoom.md +++ b/website/src/docs/zoom.md @@ -33,7 +33,7 @@ Install from NPM: npm install @uppy/zoom ``` -In the [CDN package](/docs/#With-a-script-tag), it is available on the `Uppy` global object: +In the [CDN package](/docs/#With-a-script-tag), the plugin class is available on the `Uppy` global object: ```js const { Zoom } = Uppy @@ -82,11 +82,11 @@ The valid and authorised URL(s) from which OAuth responses should be accepted. This value can be a `String`, a `Regex` pattern, or an `Array` of both. -This is useful when you have your [Companion](/docs/companion) running on multiple hosts. Otherwise, the default value should be good enough. +This is useful when you have your [Companion](/docs/companion) running on more than one server. Otherwise, the default value should be good enough. ### `companionCookiesRule: 'same-origin'` -This option correlates to the [RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials), which tells the plugin whether or not to send cookies to [Companion](/docs/companion). +This option correlates to the [RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials), which tells the plugin whether to send cookies to [Companion](/docs/companion). ### `locale: {}` @@ -106,7 +106,7 @@ If you are a Zoom account owner and you are looking to enable the Transloadit Ad ### Install Transloadit Zoom Add-on -To enable the Transloadit Add-on on your Zoom account please visit the Transloadit App on the [Zoom Marketplace](https://marketplace.zoom.us/apps/oBMBQjN6SSakyh7OiLZMdA) and click the "Install" button. +To enable the Transloadit Add-on on your Zoom account please visit the Transloadit App on the [Zoom Marketplace](https://marketplace.zoom.us/apps/oBMBQjN6SSakyh7OiLZMdA) and click the “Install” button. ### Uninstall via Marketplace diff --git a/website/src/examples/dashboard/app.es6 b/website/src/examples/dashboard/app.es6 index 285a63b45b..3a48910fdd 100644 --- a/website/src/examples/dashboard/app.es6 +++ b/website/src/examples/dashboard/app.es6 @@ -213,7 +213,7 @@ function loadLocaleFromCDN (localeName) { const head = document.getElementsByTagName('head')[0] const js = document.createElement('script') js.type = 'text/javascript' - js.src = `https://releases.transloadit.com/uppy/locales/v2.0.2/${localeName}.min.js` + js.src = `https://releases.transloadit.com/uppy/locales/v2.0.3/${localeName}.min.js` head.appendChild(js) } diff --git a/website/src/examples/i18n/app.html b/website/src/examples/i18n/app.html index cef51b8b4c..2a571ba68f 100644 --- a/website/src/examples/i18n/app.html +++ b/website/src/examples/i18n/app.html @@ -1,7 +1,7 @@ - +
@@ -12,8 +12,8 @@
Uploaded files:
- - + + + +