From d7f8076fb3dfb16dd9c3ef72fcfbe11892ec51c8 Mon Sep 17 00:00:00 2001 From: Andrew Kachnic Date: Thu, 30 Jul 2020 08:34:53 -0400 Subject: [PATCH] Allowed HTML Attributes to be passed via props This fix still needs some work, as certain attributes could be passed to Uppy or as an HTML attribute, such as target When this is fixed, this will resolve #2403 --- packages/@uppy/react/src/Dashboard.js | 9 +- packages/@uppy/react/src/DashboardModal.js | 9 +- packages/@uppy/react/src/DragDrop.js | 9 +- packages/@uppy/react/src/ProgressBar.js | 9 +- packages/@uppy/react/src/StatusBar.js | 9 +- packages/@uppy/react/src/common.js | 166 +++++++++++++++++++++ 6 files changed, 206 insertions(+), 5 deletions(-) create mode 100644 packages/@uppy/react/src/common.js diff --git a/packages/@uppy/react/src/Dashboard.js b/packages/@uppy/react/src/Dashboard.js index bad915ec7..041661db1 100644 --- a/packages/@uppy/react/src/Dashboard.js +++ b/packages/@uppy/react/src/Dashboard.js @@ -1,6 +1,7 @@ const React = require('react') const DashboardPlugin = require('@uppy/dashboard') const basePropTypes = require('./propTypes').dashboard +const { findValidProps } = require('./common') const h = React.createElement @@ -10,6 +11,11 @@ const h = React.createElement */ class Dashboard extends React.Component { + constructor (props) { + super(props) + this.validProps = findValidProps(props) + } + componentDidMount () { this.installPlugin() } @@ -48,7 +54,8 @@ class Dashboard extends React.Component { return h('div', { ref: (container) => { this.container = container - } + }, + ...this.validProps }) } } diff --git a/packages/@uppy/react/src/DashboardModal.js b/packages/@uppy/react/src/DashboardModal.js index 8ab5eee2f..db08fad8f 100644 --- a/packages/@uppy/react/src/DashboardModal.js +++ b/packages/@uppy/react/src/DashboardModal.js @@ -2,6 +2,7 @@ const React = require('react') const PropTypes = require('prop-types') const DashboardPlugin = require('@uppy/dashboard') const basePropTypes = require('./propTypes').dashboard +const { findValidProps } = require('./common') const h = React.createElement @@ -11,6 +12,11 @@ const h = React.createElement */ class DashboardModal extends React.Component { + constructor (props) { + super(props) + this.validProps = findValidProps(props) + } + componentDidMount () { this.installPlugin() } @@ -64,7 +70,8 @@ class DashboardModal extends React.Component { return h('div', { ref: (container) => { this.container = container - } + }, + ...this.validProps }) } } diff --git a/packages/@uppy/react/src/DragDrop.js b/packages/@uppy/react/src/DragDrop.js index a0ba1fb86..b4ca1c76d 100644 --- a/packages/@uppy/react/src/DragDrop.js +++ b/packages/@uppy/react/src/DragDrop.js @@ -1,6 +1,7 @@ const React = require('react') const DragDropPlugin = require('@uppy/drag-drop') const propTypes = require('./propTypes') +const { findValidProps } = require('./common') const h = React.createElement @@ -10,6 +11,11 @@ const h = React.createElement */ class DragDrop extends React.Component { + constructor (props) { + super(props) + this.validProps = findValidProps(props) + } + componentDidMount () { this.installPlugin() } @@ -49,7 +55,8 @@ class DragDrop extends React.Component { return h('div', { ref: (container) => { this.container = container - } + }, + ...this.validProps }) } } diff --git a/packages/@uppy/react/src/ProgressBar.js b/packages/@uppy/react/src/ProgressBar.js index 89e7660a1..f64bf476f 100644 --- a/packages/@uppy/react/src/ProgressBar.js +++ b/packages/@uppy/react/src/ProgressBar.js @@ -2,6 +2,7 @@ const React = require('react') const PropTypes = require('prop-types') const ProgressBarPlugin = require('@uppy/progress-bar') const uppyPropType = require('./propTypes').uppy +const { findValidProps } = require('./common') const h = React.createElement @@ -10,6 +11,11 @@ const h = React.createElement */ class ProgressBar extends React.Component { + constructor (props) { + super(props) + this.validProps = findValidProps(props) + } + componentDidMount () { this.installPlugin() } @@ -49,7 +55,8 @@ class ProgressBar extends React.Component { return h('div', { ref: (container) => { this.container = container - } + }, + ...this.validProps }) } } diff --git a/packages/@uppy/react/src/StatusBar.js b/packages/@uppy/react/src/StatusBar.js index edea5bb56..3f7dd1724 100644 --- a/packages/@uppy/react/src/StatusBar.js +++ b/packages/@uppy/react/src/StatusBar.js @@ -2,6 +2,7 @@ const React = require('react') const PropTypes = require('prop-types') const StatusBarPlugin = require('@uppy/status-bar') const uppyPropType = require('./propTypes').uppy +const { findValidProps } = require('./common') const h = React.createElement @@ -11,6 +12,11 @@ const h = React.createElement */ class StatusBar extends React.Component { + constructor (props) { + super(props) + this.validProps = findValidProps(props) + } + componentDidMount () { this.installPlugin() } @@ -50,7 +56,8 @@ class StatusBar extends React.Component { return h('div', { ref: (container) => { this.container = container - } + }, + ...this.validProps }) } } diff --git a/packages/@uppy/react/src/common.js b/packages/@uppy/react/src/common.js new file mode 100644 index 000000000..fe9ee21a7 --- /dev/null +++ b/packages/@uppy/react/src/common.js @@ -0,0 +1,166 @@ +const possibleStandardNames = { + accept: 'accept', + acceptcharset: 'acceptCharset', + 'accept-charset': 'acceptCharset', + accesskey: 'accessKey', + action: 'action', + allowfullscreen: 'allowFullScreen', + alt: 'alt', + as: 'as', + async: 'async', + autocapitalize: 'autoCapitalize', + autocomplete: 'autoComplete', + autocorrect: 'autoCorrect', + autofocus: 'autoFocus', + autoplay: 'autoPlay', + autosave: 'autoSave', + capture: 'capture', + cellpadding: 'cellPadding', + cellspacing: 'cellSpacing', + challenge: 'challenge', + charset: 'charSet', + checked: 'checked', + children: 'children', + cite: 'cite', + class: 'className', + classid: 'classID', + classname: 'className', + cols: 'cols', + colspan: 'colSpan', + content: 'content', + contenteditable: 'contentEditable', + contextmenu: 'contextMenu', + controls: 'controls', + controlslist: 'controlsList', + coords: 'coords', + crossorigin: 'crossOrigin', + dangerouslysetinnerhtml: 'dangerouslySetInnerHTML', + data: 'data', + datetime: 'dateTime', + default: 'default', + defaultchecked: 'defaultChecked', + defaultvalue: 'defaultValue', + defer: 'defer', + dir: 'dir', + disabled: 'disabled', + disablepictureinpicture: 'disablePictureInPicture', + disableremoteplayback: 'disableRemotePlayback', + download: 'download', + draggable: 'draggable', + enctype: 'encType', + enterkeyhint: 'enterKeyHint', + for: 'htmlFor', + form: 'form', + formmethod: 'formMethod', + formaction: 'formAction', + formenctype: 'formEncType', + formnovalidate: 'formNoValidate', + formtarget: 'formTarget', + frameborder: 'frameBorder', + headers: 'headers', + height: 'height', + hidden: 'hidden', + high: 'high', + href: 'href', + hreflang: 'hrefLang', + htmlfor: 'htmlFor', + httpequiv: 'httpEquiv', + 'http-equiv': 'httpEquiv', + icon: 'icon', + id: 'id', + innerhtml: 'innerHTML', + inputmode: 'inputMode', + integrity: 'integrity', + is: 'is', + itemid: 'itemID', + itemprop: 'itemProp', + itemref: 'itemRef', + itemscope: 'itemScope', + itemtype: 'itemType', + keyparams: 'keyParams', + keytype: 'keyType', + kind: 'kind', + label: 'label', + lang: 'lang', + list: 'list', + loop: 'loop', + low: 'low', + manifest: 'manifest', + marginwidth: 'marginWidth', + marginheight: 'marginHeight', + max: 'max', + maxlength: 'maxLength', + media: 'media', + mediagroup: 'mediaGroup', + method: 'method', + min: 'min', + minlength: 'minLength', + multiple: 'multiple', + muted: 'muted', + name: 'name', + nomodule: 'noModule', + nonce: 'nonce', + novalidate: 'noValidate', + open: 'open', + optimum: 'optimum', + pattern: 'pattern', + placeholder: 'placeholder', + playsinline: 'playsInline', + poster: 'poster', + preload: 'preload', + profile: 'profile', + radiogroup: 'radioGroup', + readonly: 'readOnly', + referrerpolicy: 'referrerPolicy', + rel: 'rel', + required: 'required', + reversed: 'reversed', + role: 'role', + rows: 'rows', + rowspan: 'rowSpan', + sandbox: 'sandbox', + scope: 'scope', + scoped: 'scoped', + scrolling: 'scrolling', + seamless: 'seamless', + selected: 'selected', + shape: 'shape', + size: 'size', + sizes: 'sizes', + span: 'span', + spellcheck: 'spellCheck', + src: 'src', + srcdoc: 'srcDoc', + srclang: 'srcLang', + srcset: 'srcSet', + start: 'start', + step: 'step', + style: 'style', + summary: 'summary', + tabindex: 'tabIndex', + target: 'target', + title: 'title', + type: 'type', + usemap: 'useMap', + value: 'value', + width: 'width', + wmode: 'wmode', + wrap: 'wrap' +} +const getEntries = (object) => { + // eslint-disable-next-line compat/compat + return Object.entries ? Object.entries : Object.keys(object).map(key => [key, object[key]]) +} +const getValues = (object) => { + // eslint-disable-next-line compat/compat + return Object.values ? Object.values : Object.keys(object).map(key => object[key]) +} +const findValidProps = (props) => { + const validReactHTMLAttributes = getValues(possibleStandardNames) + const reducer = (acc, [key, value]) => validReactHTMLAttributes.includes(key) ? { ...acc, [key]: value } : acc + return getEntries(props).reduce(reducer, {}) +} + +module.exports = { + findValidProps +}