diff --git a/.eslintrc.js b/.eslintrc.js
index 342e74be95..f928f0c33d 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -213,6 +213,7 @@ module.exports = {
'packages/@uppy/progress-bar/src/**/*.js',
'packages/@uppy/svelte/src/**/*.js',
'packages/@uppy/svelte/rollup.config.js',
+ 'packages/@uppy/url/src/**/*.js',
'packages/@uppy/vue/src/**/*.js',
'packages/@uppy/webcam/src/**/*.js',
],
diff --git a/packages/@uppy/url/package.json b/packages/@uppy/url/package.json
index 93094eee78..9091f42d8b 100644
--- a/packages/@uppy/url/package.json
+++ b/packages/@uppy/url/package.json
@@ -6,6 +6,7 @@
"main": "lib/index.js",
"style": "dist/style.min.css",
"types": "types/index.d.ts",
+ "type": "module",
"keywords": [
"file uploader",
"url",
diff --git a/packages/@uppy/url/src/Url.jsx b/packages/@uppy/url/src/Url.jsx
new file mode 100644
index 0000000000..c5551123f6
--- /dev/null
+++ b/packages/@uppy/url/src/Url.jsx
@@ -0,0 +1,192 @@
+import { h } from 'preact'
+import { UIPlugin } from '@uppy/core'
+import { RequestClient } from '@uppy/companion-client'
+import toArray from '@uppy/utils/lib/toArray'
+import UrlUI from './UrlUI.jsx'
+import forEachDroppedOrPastedUrl from './utils/forEachDroppedOrPastedUrl.js'
+
+import packageJson from '../package.json'
+import locale from './locale.js'
+
+function UrlIcon () {
+ return (
+
+ )
+}
+
+function addProtocolToURL (url) {
+ const protocolRegex = /^[a-z0-9]+:\/\//
+ const defaultProtocol = 'http://'
+ if (protocolRegex.test(url)) {
+ return url
+ }
+
+ return defaultProtocol + url
+}
+
+function canHandleRootDrop (e) {
+ const items = toArray(e.dataTransfer.items)
+ const urls = items.filter((item) => item.kind === 'string'
+ && item.type === 'text/uri-list')
+ return urls.length > 0
+}
+
+function checkIfCorrectURL (url) {
+ if (!url) return false
+
+ const protocol = url.match(/^([a-z0-9]+):\/\//)[1]
+ if (protocol !== 'http' && protocol !== 'https') {
+ return false
+ }
+
+ return true
+}
+
+function getFileNameFromUrl (url) {
+ return url.substring(url.lastIndexOf('/') + 1)
+}
+/**
+ * Url
+ *
+ */
+export default class Url extends UIPlugin {
+ static VERSION = packageJson.version
+
+ constructor (uppy, opts) {
+ super(uppy, opts)
+ this.id = this.opts.id || 'Url'
+ this.title = this.opts.title || 'Link'
+ this.type = 'acquirer'
+ this.icon = () =>
+
+ // Set default options and locale
+ this.defaultLocale = locale
+
+ const defaultOptions = {}
+
+ this.opts = { ...defaultOptions, ...opts }
+
+ this.i18nInit()
+
+ this.hostname = this.opts.companionUrl
+
+ if (!this.hostname) {
+ throw new Error('Companion hostname is required, please consult https://uppy.io/docs/companion')
+ }
+
+ // Bind all event handlers for referencability
+ this.getMeta = this.getMeta.bind(this)
+ this.addFile = this.addFile.bind(this)
+ this.handleRootDrop = this.handleRootDrop.bind(this)
+ this.handleRootPaste = this.handleRootPaste.bind(this)
+
+ this.client = new RequestClient(uppy, {
+ companionUrl: this.opts.companionUrl,
+ companionHeaders: this.opts.companionHeaders,
+ companionCookiesRule: this.opts.companionCookiesRule,
+ })
+ }
+
+ getMeta (url) {
+ return this.client.post('url/meta', { url })
+ .then((res) => {
+ if (res.error) {
+ this.uppy.log('[URL] Error:')
+ this.uppy.log(res.error)
+ throw new Error('Failed to fetch the file')
+ }
+ return res
+ })
+ }
+
+ async addFile (protocollessUrl) {
+ const url = this.addProtocolToURL(protocollessUrl)
+ if (!this.checkIfCorrectURL(url)) {
+ this.uppy.log(`[URL] Incorrect URL entered: ${url}`)
+ this.uppy.info(this.i18n('enterCorrectUrl'), 'error', 4000)
+ return undefined
+ }
+
+ try {
+ const meta = await this.getMeta(url)
+
+ const tagFile = {
+ source: this.id,
+ name: this.getFileNameFromUrl(url),
+ type: meta.type,
+ data: {
+ size: meta.size,
+ },
+ isRemote: true,
+ body: {
+ url,
+ },
+ remote: {
+ companionUrl: this.opts.companionUrl,
+ url: `${this.hostname}/url/get`,
+ body: {
+ fileId: url,
+ url,
+ },
+ providerOptions: this.client.opts,
+ },
+ }
+ this.uppy.log('[Url] Adding remote file')
+ try {
+ return this.uppy.addFile(tagFile)
+ } catch (err) {
+ if (!err.isRestriction) {
+ this.uppy.log(err)
+ }
+ return err
+ }
+ } catch (err) {
+ this.uppy.log(err)
+ this.uppy.info({
+ message: this.i18n('failedToFetch'),
+ details: err,
+ }, 'error', 4000)
+ return err
+ }
+ }
+
+ handleRootDrop (e) {
+ forEachDroppedOrPastedUrl(e.dataTransfer, 'drop', (url) => {
+ this.uppy.log(`[URL] Adding file from dropped url: ${url}`)
+ this.addFile(url)
+ })
+ }
+
+ handleRootPaste (e) {
+ forEachDroppedOrPastedUrl(e.clipboardData, 'paste', (url) => {
+ this.uppy.log(`[URL] Adding file from pasted url: ${url}`)
+ this.addFile(url)
+ })
+ }
+
+ render () {
+ return
+ }
+
+ install () {
+ const { target } = this.opts
+ if (target) {
+ this.mount(target, this)
+ }
+ }
+
+ uninstall () {
+ this.unmount()
+ }
+}
+
+// TODO: remove from prototype in the next major.
+Url.prototype.addProtocolToURL = addProtocolToURL
+Url.prototype.canHandleRootDrop = canHandleRootDrop
+Url.prototype.checkIfCorrectURL = checkIfCorrectURL
+Url.prototype.getFileNameFromUrl = getFileNameFromUrl
diff --git a/packages/@uppy/url/src/UrlUI.js b/packages/@uppy/url/src/UrlUI.jsx
similarity index 71%
rename from packages/@uppy/url/src/UrlUI.js
rename to packages/@uppy/url/src/UrlUI.jsx
index 99d21f239b..e387faa03b 100644
--- a/packages/@uppy/url/src/UrlUI.js
+++ b/packages/@uppy/url/src/UrlUI.jsx
@@ -1,4 +1,4 @@
-const { h, Component } = require('preact')
+import { h, Component } from 'preact'
class UrlUI extends Component {
constructor (props) {
@@ -12,23 +12,26 @@ class UrlUI extends Component {
}
handleKeyPress (ev) {
+ const { addFile } = this.props
if (ev.keyCode === 13) {
- this.props.addFile(this.input.value)
+ addFile(this.input.value)
}
}
handleClick () {
- this.props.addFile(this.input.value)
+ const { addFile } = this.props
+ addFile(this.input.value)
}
render () {
+ const { i18n } = this.props
return (
{ this.input = input }}
data-uppy-super-focusable
@@ -38,11 +41,11 @@ class UrlUI extends Component {
type="button"
onClick={this.handleClick}
>
- {this.props.i18n('import')}
+ {i18n('import')}
)
}
}
-module.exports = UrlUI
+export default UrlUI
diff --git a/packages/@uppy/url/src/index.js b/packages/@uppy/url/src/index.js
index 1568e89b9e..a427b2b25e 100644
--- a/packages/@uppy/url/src/index.js
+++ b/packages/@uppy/url/src/index.js
@@ -1,189 +1 @@
-const { UIPlugin } = require('@uppy/core')
-const { h } = require('preact')
-const { RequestClient } = require('@uppy/companion-client')
-const toArray = require('@uppy/utils/lib/toArray')
-const UrlUI = require('./UrlUI.js')
-const forEachDroppedOrPastedUrl = require('./utils/forEachDroppedOrPastedUrl')
-
-const locale = require('./locale')
-
-function UrlIcon () {
- return (
-
- )
-}
-
-/**
- * Url
- *
- */
-module.exports = class Url extends UIPlugin {
- static VERSION = require('../package.json').version
-
- constructor (uppy, opts) {
- super(uppy, opts)
- this.id = this.opts.id || 'Url'
- this.title = this.opts.title || 'Link'
- this.type = 'acquirer'
- this.icon = () =>
-
- // Set default options and locale
- this.defaultLocale = locale
-
- const defaultOptions = {}
-
- this.opts = { ...defaultOptions, ...opts }
-
- this.i18nInit()
-
- this.hostname = this.opts.companionUrl
-
- if (!this.hostname) {
- throw new Error('Companion hostname is required, please consult https://uppy.io/docs/companion')
- }
-
- // Bind all event handlers for referencability
- this.getMeta = this.getMeta.bind(this)
- this.addFile = this.addFile.bind(this)
- this.handleRootDrop = this.handleRootDrop.bind(this)
- this.handleRootPaste = this.handleRootPaste.bind(this)
-
- this.client = new RequestClient(uppy, {
- companionUrl: this.opts.companionUrl,
- companionHeaders: this.opts.companionHeaders,
- companionCookiesRule: this.opts.companionCookiesRule,
- })
- }
-
- getFileNameFromUrl (url) {
- return url.substring(url.lastIndexOf('/') + 1)
- }
-
- checkIfCorrectURL (url) {
- if (!url) return false
-
- const protocol = url.match(/^([a-z0-9]+):\/\//)[1]
- if (protocol !== 'http' && protocol !== 'https') {
- return false
- }
-
- return true
- }
-
- addProtocolToURL (url) {
- const protocolRegex = /^[a-z0-9]+:\/\//
- const defaultProtocol = 'http://'
- if (protocolRegex.test(url)) {
- return url
- }
-
- return defaultProtocol + url
- }
-
- getMeta (url) {
- return this.client.post('url/meta', { url })
- .then((res) => {
- if (res.error) {
- this.uppy.log('[URL] Error:')
- this.uppy.log(res.error)
- throw new Error('Failed to fetch the file')
- }
- return res
- })
- }
-
- addFile (url) {
- url = this.addProtocolToURL(url)
- if (!this.checkIfCorrectURL(url)) {
- this.uppy.log(`[URL] Incorrect URL entered: ${url}`)
- this.uppy.info(this.i18n('enterCorrectUrl'), 'error', 4000)
- return
- }
-
- return this.getMeta(url)
- .then((meta) => {
- const tagFile = {
- source: this.id,
- name: this.getFileNameFromUrl(url),
- type: meta.type,
- data: {
- size: meta.size,
- },
- isRemote: true,
- body: {
- url,
- },
- remote: {
- companionUrl: this.opts.companionUrl,
- url: `${this.hostname}/url/get`,
- body: {
- fileId: url,
- url,
- },
- providerOptions: this.client.opts,
- },
- }
- return tagFile
- })
- .then((tagFile) => {
- this.uppy.log('[Url] Adding remote file')
- try {
- return this.uppy.addFile(tagFile)
- } catch (err) {
- if (!err.isRestriction) {
- this.uppy.log(err)
- }
- return err
- }
- })
- .catch((err) => {
- this.uppy.log(err)
- this.uppy.info({
- message: this.i18n('failedToFetch'),
- details: err,
- }, 'error', 4000)
- return err
- })
- }
-
- canHandleRootDrop (e) {
- const items = toArray(e.dataTransfer.items)
- const urls = items.filter((item) => item.kind === 'string'
- && item.type === 'text/uri-list')
- return urls.length > 0
- }
-
- handleRootDrop (e) {
- forEachDroppedOrPastedUrl(e.dataTransfer, 'drop', (url) => {
- this.uppy.log(`[URL] Adding file from dropped url: ${url}`)
- this.addFile(url)
- })
- }
-
- handleRootPaste (e) {
- forEachDroppedOrPastedUrl(e.clipboardData, 'paste', (url) => {
- this.uppy.log(`[URL] Adding file from pasted url: ${url}`)
- this.addFile(url)
- })
- }
-
- render () {
- return
- }
-
- install () {
- const { target } = this.opts
- if (target) {
- this.mount(target, this)
- }
- }
-
- uninstall () {
- this.unmount()
- }
-}
+export { default } from './Url.jsx'
diff --git a/packages/@uppy/url/src/locale.js b/packages/@uppy/url/src/locale.js
index df90c44af0..79350e25aa 100644
--- a/packages/@uppy/url/src/locale.js
+++ b/packages/@uppy/url/src/locale.js
@@ -1,4 +1,4 @@
-module.exports = {
+export default {
strings: {
// Label for the "Import" button.
import: 'Import',
diff --git a/packages/@uppy/url/src/utils/forEachDroppedOrPastedUrl.js b/packages/@uppy/url/src/utils/forEachDroppedOrPastedUrl.js
index d02f8fc081..a0c700a1a2 100644
--- a/packages/@uppy/url/src/utils/forEachDroppedOrPastedUrl.js
+++ b/packages/@uppy/url/src/utils/forEachDroppedOrPastedUrl.js
@@ -1,4 +1,4 @@
-const toArray = require('@uppy/utils/lib/toArray')
+import toArray from '@uppy/utils/lib/toArray'
/*
SITUATION
@@ -58,7 +58,7 @@ const toArray = require('@uppy/utils/lib/toArray')
* @param {string} isDropOrPaste - either 'drop' or 'paste'
* @param {Function} callback - (urlString) => {}
*/
-module.exports = function forEachDroppedOrPastedUrl (dataTransfer, isDropOrPaste, callback) {
+export default function forEachDroppedOrPastedUrl (dataTransfer, isDropOrPaste, callback) {
const items = toArray(dataTransfer.items)
let urlItems
diff --git a/website/src/docs/url.md b/website/src/docs/url.md
index a2853e493a..025774f0d7 100644
--- a/website/src/docs/url.md
+++ b/website/src/docs/url.md
@@ -87,7 +87,7 @@ This option correlates to the [RequestCredentials value](https://developer.mozil
```js
-module.exports = {
+export default {
strings: {
// Label for the "Import" button.
import: 'Import',