about summary refs log tree commit diff
path: root/app
diff options
context:
space:
mode:
authorZac Anger <zac@zacanger.com>2017-04-15 05:27:27 -0600
committerEugen <eugen@zeonfederated.com>2017-04-15 13:27:27 +0200
commitf4045ba3d962105ae4a7c0ee785a83c678ca2f8a (patch)
tree89eedfbe31105593e77a78014e3dd94c658f0156 /app
parentdf4ff9a8e13d776e1670c232655db0275a353a0f (diff)
Add eslint-plugin-jsx-a11y (#1651)
* Add eslint-plugin-jsx-a11y.

* Fix npm script.

* Adjust npm scripts so test also runs lint.

* Fix existing lint errors.

* Don't break on a11y issues.

* Add role and tabIndex.

* Add vim and Mac files to .gitignore and .dockerignore.

* Handle htmlFor (partially), a that's actually a button.

* Fix missing tabIndex.

* Add cursor:pointer to load-more

* Revert change to load_more.

* Fixes based on review.

* Update yarn.lock.

* Don't try to install fsevents on Linux (hides warning noise).
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/components/components/autosuggest_textarea.jsx7
-rw-r--r--app/assets/javascripts/components/components/button.jsx1
-rw-r--r--app/assets/javascripts/components/components/column_back_button.jsx4
-rw-r--r--app/assets/javascripts/components/components/column_back_button_slim.jsx2
-rw-r--r--app/assets/javascripts/components/components/column_collapsable.jsx4
-rw-r--r--app/assets/javascripts/components/components/load_more.jsx2
-rw-r--r--app/assets/javascripts/components/components/media_gallery.jsx2
-rw-r--r--app/assets/javascripts/components/components/permalink.jsx3
-rw-r--r--app/assets/javascripts/components/components/status_content.jsx2
-rw-r--r--app/assets/javascripts/components/components/video_player.jsx8
-rw-r--r--app/assets/javascripts/components/features/account/components/header.jsx11
-rw-r--r--app/assets/javascripts/components/features/compose/components/privacy_dropdown.jsx2
-rw-r--r--app/assets/javascripts/components/features/compose/components/search.jsx8
-rw-r--r--app/assets/javascripts/components/features/notifications/components/clear_column_button.jsx2
-rw-r--r--app/assets/javascripts/components/features/notifications/components/column_settings.jsx4
-rw-r--r--app/assets/javascripts/components/features/notifications/components/notification.jsx2
-rw-r--r--app/assets/javascripts/components/features/notifications/components/setting_toggle.jsx7
-rw-r--r--app/assets/javascripts/components/features/ui/components/column_header.jsx2
-rw-r--r--app/assets/javascripts/components/features/ui/components/column_link.jsx3
-rw-r--r--app/assets/javascripts/components/features/ui/components/media_modal.jsx4
-rw-r--r--app/assets/javascripts/components/features/ui/components/modal_root.jsx2
-rw-r--r--app/assets/javascripts/components/link_header.jsx2
-rw-r--r--app/assets/javascripts/components/locales/es.jsx2
-rw-r--r--app/assets/javascripts/components/locales/ru.jsx2
-rw-r--r--app/assets/javascripts/components/middleware/errors.jsx2
-rw-r--r--app/assets/javascripts/components/reducers/alerts.jsx24
26 files changed, 70 insertions, 44 deletions
diff --git a/app/assets/javascripts/components/components/autosuggest_textarea.jsx b/app/assets/javascripts/components/components/autosuggest_textarea.jsx
index 744424661..04328aae8 100644
--- a/app/assets/javascripts/components/components/autosuggest_textarea.jsx
+++ b/app/assets/javascripts/components/components/autosuggest_textarea.jsx
@@ -178,7 +178,12 @@ const AutosuggestTextarea = React.createClass({
 
         <div style={{ display: (suggestions.size > 0 && !suggestionsHidden) ? 'block' : 'none' }} className='autosuggest-textarea__suggestions'>
           {suggestions.map((suggestion, i) => (
-            <div key={suggestion} className={`autosuggest-textarea__suggestions__item ${i === selectedSuggestion ? 'selected' : ''}`} onClick={this.onSuggestionClick.bind(this, suggestion)}>
+            <div
+              role='button'
+              tabIndex='0'
+              key={suggestion}
+              className={`autosuggest-textarea__suggestions__item ${i === selectedSuggestion ? 'selected' : ''}`}
+              onClick={this.onSuggestionClick.bind(this, suggestion)}>
               <AutosuggestAccountContainer id={suggestion} />
             </div>
           ))}
diff --git a/app/assets/javascripts/components/components/button.jsx b/app/assets/javascripts/components/components/button.jsx
index babc6b259..c3e184024 100644
--- a/app/assets/javascripts/components/components/button.jsx
+++ b/app/assets/javascripts/components/components/button.jsx
@@ -9,6 +9,7 @@ const Button = React.createClass({
     block: React.PropTypes.bool,
     secondary: React.PropTypes.bool,
     size: React.PropTypes.number,
+    style: React.PropTypes.object,
     children: React.PropTypes.node
   },
 
diff --git a/app/assets/javascripts/components/components/column_back_button.jsx b/app/assets/javascripts/components/components/column_back_button.jsx
index 6b5ffee53..91c3b92be 100644
--- a/app/assets/javascripts/components/components/column_back_button.jsx
+++ b/app/assets/javascripts/components/components/column_back_button.jsx
@@ -15,13 +15,13 @@ const ColumnBackButton = React.createClass({
   mixins: [PureRenderMixin],
 
   handleClick () {
-    if (window.history && window.history.length == 1) this.context.router.push("/");
+    if (window.history && window.history.length === 1) this.context.router.push("/");
     else this.context.router.goBack();
   },
 
   render () {
     return (
-      <div onClick={this.handleClick} className='column-back-button'>
+      <div role='button' tabIndex='0' onClick={this.handleClick} className='column-back-button'>
         <i className='fa fa-fw fa-chevron-left' style={iconStyle} />
         <FormattedMessage id='column_back_button.label' defaultMessage='Back' />
       </div>
diff --git a/app/assets/javascripts/components/components/column_back_button_slim.jsx b/app/assets/javascripts/components/components/column_back_button_slim.jsx
index 780e3b182..536964b01 100644
--- a/app/assets/javascripts/components/components/column_back_button_slim.jsx
+++ b/app/assets/javascripts/components/components/column_back_button_slim.jsx
@@ -31,7 +31,7 @@ const ColumnBackButtonSlim = React.createClass({
   render () {
     return (
       <div style={{ position: 'relative' }}>
-        <div style={outerStyle} onClick={this.handleClick} className='column-back-button'>
+        <div role='button' tabIndex='0' style={outerStyle} onClick={this.handleClick} className='column-back-button'>
           <i className='fa fa-fw fa-chevron-left' style={iconStyle} />
           <FormattedMessage id='column_back_button.label' defaultMessage='Back' />
         </div>
diff --git a/app/assets/javascripts/components/components/column_collapsable.jsx b/app/assets/javascripts/components/components/column_collapsable.jsx
index 85ce63835..75dfc8a4e 100644
--- a/app/assets/javascripts/components/components/column_collapsable.jsx
+++ b/app/assets/javascripts/components/components/column_collapsable.jsx
@@ -46,7 +46,9 @@ const ColumnCollapsable = React.createClass({
 
     return (
       <div style={{ position: 'relative' }}>
-        <div title={`${title}`} style={{...iconStyle }} className={`column-icon ${collapsedClassName}`} onClick={this.handleToggleCollapsed}><i className={`fa fa-${icon}`} /></div>
+        <div role='button' tabIndex='0' title={`${title}`} style={{...iconStyle }} className={`column-icon ${collapsedClassName}`} onClick={this.handleToggleCollapsed}>
+          <i className={`fa fa-${icon}`} />
+        </div>
 
         <Motion defaultStyle={{ opacity: 0, height: 0 }} style={{ opacity: spring(collapsed ? 0 : 100), height: spring(collapsed ? 0 : fullHeight, collapsed ? undefined : { stiffness: 150, damping: 9 }) }}>
           {({ opacity, height }) =>
diff --git a/app/assets/javascripts/components/components/load_more.jsx b/app/assets/javascripts/components/components/load_more.jsx
index 2cb9b09a8..b4bc8b711 100644
--- a/app/assets/javascripts/components/components/load_more.jsx
+++ b/app/assets/javascripts/components/components/load_more.jsx
@@ -1,7 +1,7 @@
 import { FormattedMessage } from 'react-intl';
 
 const LoadMore = ({ onClick }) => (
-  <a href='#' className='load-more' onClick={onClick}>
+  <a href="#" className='load-more' role='button' onClick={onClick}>
     <FormattedMessage id='status.load_more' defaultMessage='Load more' />
   </a>
 );
diff --git a/app/assets/javascripts/components/components/media_gallery.jsx b/app/assets/javascripts/components/components/media_gallery.jsx
index 10b7d525b..325fd8157 100644
--- a/app/assets/javascripts/components/components/media_gallery.jsx
+++ b/app/assets/javascripts/components/components/media_gallery.jsx
@@ -220,7 +220,7 @@ const MediaGallery = React.createClass({
       }
 
       children = (
-        <div style={spoilerStyle} className='media-spoiler' onClick={this.handleOpen}>
+        <div role='button' tabIndex='0' style={spoilerStyle} className='media-spoiler' onClick={this.handleOpen}>
           <span style={spoilerSpanStyle}>{warning}</span>
           <span style={spoilerSubSpanStyle}><FormattedMessage id='status.sensitive_toggle' defaultMessage='Click to view' /></span>
         </div>
diff --git a/app/assets/javascripts/components/components/permalink.jsx b/app/assets/javascripts/components/components/permalink.jsx
index ae2fb0d29..ebfa63cbc 100644
--- a/app/assets/javascripts/components/components/permalink.jsx
+++ b/app/assets/javascripts/components/components/permalink.jsx
@@ -6,7 +6,8 @@ const Permalink = React.createClass({
 
   propTypes: {
     href: React.PropTypes.string.isRequired,
-    to: React.PropTypes.string.isRequired
+    to: React.PropTypes.string.isRequired,
+    children: React.PropTypes.node.isRequired
   },
 
   handleClick (e) {
diff --git a/app/assets/javascripts/components/components/status_content.jsx b/app/assets/javascripts/components/components/status_content.jsx
index 33e407e43..ce8ead41e 100644
--- a/app/assets/javascripts/components/components/status_content.jsx
+++ b/app/assets/javascripts/components/components/status_content.jsx
@@ -119,7 +119,7 @@ const StatusContent = React.createClass({
       return (
         <div className='status__content' style={{ cursor: 'pointer' }} onMouseDown={this.handleMouseDown} onMouseUp={this.handleMouseUp}>
           <p style={{ marginBottom: hidden && status.get('mentions').size === 0 ? '0px' : '' }} >
-            <span dangerouslySetInnerHTML={spoilerContent} />  <a className='status__content__spoiler-link' onClick={this.handleSpoilerClick}>{toggleText}</a>
+            <span dangerouslySetInnerHTML={spoilerContent} />  <a tabIndex='0' className='status__content__spoiler-link' role='button' onClick={this.handleSpoilerClick}>{toggleText}</a>
           </p>
 
           {mentionsPlaceholder}
diff --git a/app/assets/javascripts/components/components/video_player.jsx b/app/assets/javascripts/components/components/video_player.jsx
index dce276c75..e9e860e39 100644
--- a/app/assets/javascripts/components/components/video_player.jsx
+++ b/app/assets/javascripts/components/components/video_player.jsx
@@ -194,7 +194,7 @@ const VideoPlayer = React.createClass({
     if (!this.state.visible) {
       if (sensitive) {
         return (
-          <div style={{...spoilerStyle, width: `${width}px`, height: `${height}px` }} className='media-spoiler' onClick={this.handleVisibility}>
+          <div role='button' tabIndex='0' style={{...spoilerStyle, width: `${width}px`, height: `${height}px` }} className='media-spoiler' onClick={this.handleVisibility}>
             {spoilerButton}
             <span style={spoilerSpanStyle}><FormattedMessage id='status.sensitive_warning' defaultMessage='Sensitive content' /></span>
             <span style={spoilerSubSpanStyle}><FormattedMessage id='status.sensitive_toggle' defaultMessage='Click to view' /></span>
@@ -202,7 +202,7 @@ const VideoPlayer = React.createClass({
         );
       } else {
         return (
-          <div style={{...spoilerStyle, width: `${width}px`, height: `${height}px` }} className='media-spoiler' onClick={this.handleVisibility}>
+          <div role='button' tabIndex='0' style={{...spoilerStyle, width: `${width}px`, height: `${height}px` }} className='media-spoiler' onClick={this.handleVisibility}>
             {spoilerButton}
             <span style={spoilerSpanStyle}><FormattedMessage id='status.media_hidden' defaultMessage='Media hidden' /></span>
             <span style={spoilerSubSpanStyle}><FormattedMessage id='status.sensitive_toggle' defaultMessage='Click to view' /></span>
@@ -213,7 +213,7 @@ const VideoPlayer = React.createClass({
 
     if (this.state.preview && !autoplay) {
       return (
-        <div style={{ cursor: 'pointer', position: 'relative', marginTop: '8px', width: `${width}px`, height: `${height}px`, background: `url(${media.get('preview_url')}) no-repeat center`, backgroundSize: 'cover' }} onClick={this.handleOpen}>
+        <div role='button' tabIndex='0' style={{ cursor: 'pointer', position: 'relative', marginTop: '8px', width: `${width}px`, height: `${height}px`, background: `url(${media.get('preview_url')}) no-repeat center`, backgroundSize: 'cover' }} onClick={this.handleOpen}>
           {spoilerButton}
           <div style={{ position: 'absolute', top: '50%', left: '50%', fontSize: '36px', transform: 'translate(-50%, -50%)', padding: '5px', borderRadius: '100px', color: 'rgba(255, 255, 255, 0.8)' }}><i className='fa fa-play' /></div>
         </div>
@@ -225,7 +225,7 @@ const VideoPlayer = React.createClass({
         {spoilerButton}
         {muteButton}
         {expandButton}
-        <video ref={this.setRef} src={media.get('url')} autoPlay={!isIOS()} loop={true} muted={this.state.muted} style={videoStyle} onClick={this.handleVideoClick} />
+        <video role='button' tabIndex='0' ref={this.setRef} src={media.get('url')} autoPlay={!isIOS()} loop={true} muted={this.state.muted} style={videoStyle} onClick={this.handleVideoClick} />
       </div>
     );
   }
diff --git a/app/assets/javascripts/components/features/account/components/header.jsx b/app/assets/javascripts/components/features/account/components/header.jsx
index a359963c4..c4619a3c7 100644
--- a/app/assets/javascripts/components/features/account/components/header.jsx
+++ b/app/assets/javascripts/components/features/account/components/header.jsx
@@ -43,7 +43,16 @@ const Avatar = React.createClass({
     return (
       <Motion defaultStyle={{ radius: 90 }} style={{ radius: spring(isHovered ? 30 : 90, { stiffness: 180, damping: 12 }) }}>
         {({ radius }) =>
-          <a href={account.get('url')} className='account__header__avatar' target='_blank' rel='noopener' style={{ display: 'block', width: '90px', height: '90px', margin: '0 auto', marginBottom: '10px', borderRadius: `${radius}px`, overflow: 'hidden' }} onMouseOver={this.handleMouseOver} onMouseOut={this.handleMouseOut}>
+          <a
+            href={account.get('url')}
+            className='account__header__avatar'
+            target='_blank'
+            rel='noopener'
+            style={{ display: 'block', width: '90px', height: '90px', margin: '0 auto', marginBottom: '10px', borderRadius: `${radius}px`, overflow: 'hidden' }}
+            onMouseOver={this.handleMouseOver}
+            onMouseOut={this.handleMouseOut}
+            onFocus={this.handleMouseOver}
+            onBlur={this.handleMouseOut}>
             <img src={account.get('avatar')} alt={account.get('acct')} style={{ display: 'block', width: '90px', height: '90px' }} />
           </a>
         }
diff --git a/app/assets/javascripts/components/features/compose/components/privacy_dropdown.jsx b/app/assets/javascripts/components/features/compose/components/privacy_dropdown.jsx
index e54fa4d28..de8942d4d 100644
--- a/app/assets/javascripts/components/features/compose/components/privacy_dropdown.jsx
+++ b/app/assets/javascripts/components/features/compose/components/privacy_dropdown.jsx
@@ -83,7 +83,7 @@ const PrivacyDropdown = React.createClass({
         <div className='privacy-dropdown__value'><IconButton icon={valueOption.icon} title={intl.formatMessage(messages.change_privacy)} size={18} active={open} inverted onClick={this.handleToggle} style={iconStyle} /></div>
         <div className='privacy-dropdown__dropdown'>
           {options.map(item =>
-            <div key={item.value} onClick={this.handleClick.bind(this, item.value)} className={`privacy-dropdown__option ${item.value === value ? 'active' : ''}`}>
+            <div role='button' tabIndex='0' key={item.value} onClick={this.handleClick.bind(this, item.value)} className={`privacy-dropdown__option ${item.value === value ? 'active' : ''}`}>
               <div className='privacy-dropdown__option__icon'><i className={`fa fa-fw fa-${item.icon}`} /></div>
               <div className='privacy-dropdown__option__content'>
                 <strong>{item.shortText}</strong>
diff --git a/app/assets/javascripts/components/features/compose/components/search.jsx b/app/assets/javascripts/components/features/compose/components/search.jsx
index 936e003f2..9ca1f5dc5 100644
--- a/app/assets/javascripts/components/features/compose/components/search.jsx
+++ b/app/assets/javascripts/components/features/compose/components/search.jsx
@@ -36,6 +36,10 @@ const Search = React.createClass({
     }
   },
 
+  noop () {
+
+  },
+
   handleFocus () {
     this.props.onShow();
   },
@@ -56,9 +60,9 @@ const Search = React.createClass({
           onFocus={this.handleFocus}
         />
 
-        <div className='search__icon'>
+        <div role='button' tabIndex='0' className='search__icon' onClick={hasValue ? this.handleClear : this.noop}>
           <i className={`fa fa-search ${hasValue ? '' : 'active'}`} />
-          <i className={`fa fa-times-circle ${hasValue ? 'active' : ''}`} onClick={this.handleClear} />
+          <i aria-label="Clear search" className={`fa fa-times-circle ${hasValue ? 'active' : ''}`} />
         </div>
       </div>
     );
diff --git a/app/assets/javascripts/components/features/notifications/components/clear_column_button.jsx b/app/assets/javascripts/components/features/notifications/components/clear_column_button.jsx
index debbfd01f..63fe86af6 100644
--- a/app/assets/javascripts/components/features/notifications/components/clear_column_button.jsx
+++ b/app/assets/javascripts/components/features/notifications/components/clear_column_button.jsx
@@ -15,7 +15,7 @@ const ClearColumnButton = React.createClass({
     const { intl } = this.props;
 
     return (
-      <div title={intl.formatMessage(messages.clear)} className='column-icon column-icon-clear' tabIndex='0' onClick={this.props.onClick}>
+      <div role='button' title={intl.formatMessage(messages.clear)} className='column-icon column-icon-clear' tabIndex='0' onClick={this.props.onClick}>
         <i className='fa fa-eraser' />
       </div>
     );
diff --git a/app/assets/javascripts/components/features/notifications/components/column_settings.jsx b/app/assets/javascripts/components/features/notifications/components/column_settings.jsx
index 2edf98292..03bfaa653 100644
--- a/app/assets/javascripts/components/features/notifications/components/column_settings.jsx
+++ b/app/assets/javascripts/components/features/notifications/components/column_settings.jsx
@@ -27,9 +27,11 @@ const ColumnSettings = React.createClass({
 
   propTypes: {
     settings: ImmutablePropTypes.map.isRequired,
-    intl: React.PropTypes.object.isRequired,
     onChange: React.PropTypes.func.isRequired,
     onSave: React.PropTypes.func.isRequired,
+    intl: React.PropTypes.shape({
+      formatMessage: React.PropTypes.func.isRequired
+    }).isRequired
   },
 
   mixins: [PureRenderMixin],
diff --git a/app/assets/javascripts/components/features/notifications/components/notification.jsx b/app/assets/javascripts/components/features/notifications/components/notification.jsx
index fdebe4bb5..2a9f2d076 100644
--- a/app/assets/javascripts/components/features/notifications/components/notification.jsx
+++ b/app/assets/javascripts/components/features/notifications/components/notification.jsx
@@ -71,7 +71,7 @@ const Notification = React.createClass({
     );
   },
 
-  render () {
+  render () { // eslint-disable-line consistent-return
     const { notification } = this.props;
     const account          = notification.get('account');
     const displayName      = account.get('display_name').length > 0 ? account.get('display_name') : account.get('username');
diff --git a/app/assets/javascripts/components/features/notifications/components/setting_toggle.jsx b/app/assets/javascripts/components/features/notifications/components/setting_toggle.jsx
index eae3c2be2..c4bfad5cd 100644
--- a/app/assets/javascripts/components/features/notifications/components/setting_toggle.jsx
+++ b/app/assets/javascripts/components/features/notifications/components/setting_toggle.jsx
@@ -14,8 +14,8 @@ const labelSpanStyle = {
   marginLeft: '8px'
 };
 
-const SettingToggle = ({ settings, settingKey, label, onChange }) => (
-  <label style={labelStyle}>
+const SettingToggle = ({ settings, settingKey, label, onChange, htmlFor = '' }) => (
+  <label htmlFor={htmlFor} style={labelStyle}>
     <Toggle checked={settings.getIn(settingKey)} onChange={(e) => onChange(settingKey, e.target.checked)} />
     <span className='setting-toggle' style={labelSpanStyle}>{label}</span>
   </label>
@@ -25,7 +25,8 @@ SettingToggle.propTypes = {
   settings: ImmutablePropTypes.map.isRequired,
   settingKey: React.PropTypes.array.isRequired,
   label: React.PropTypes.node.isRequired,
-  onChange: React.PropTypes.func.isRequired
+  onChange: React.PropTypes.func.isRequired,
+  htmlFor: React.PropTypes.string
 };
 
 export default SettingToggle;
diff --git a/app/assets/javascripts/components/features/ui/components/column_header.jsx b/app/assets/javascripts/components/features/ui/components/column_header.jsx
index b7052ffaf..1df0b3da9 100644
--- a/app/assets/javascripts/components/features/ui/components/column_header.jsx
+++ b/app/assets/javascripts/components/features/ui/components/column_header.jsx
@@ -25,7 +25,7 @@ const ColumnHeader = React.createClass({
     }
 
     return (
-      <div aria-label={type} className={`column-header ${active ? 'active' : ''}`} onClick={this.handleClick}>
+      <div role='button' tabIndex='0' aria-label={type} className={`column-header ${active ? 'active' : ''}`} onClick={this.handleClick}>
         {icon}
         {type}
       </div>
diff --git a/app/assets/javascripts/components/features/ui/components/column_link.jsx b/app/assets/javascripts/components/features/ui/components/column_link.jsx
index 2bd1e1017..fb253bbbd 100644
--- a/app/assets/javascripts/components/features/ui/components/column_link.jsx
+++ b/app/assets/javascripts/components/features/ui/components/column_link.jsx
@@ -34,7 +34,8 @@ ColumnLink.propTypes = {
   icon: React.PropTypes.string.isRequired,
   text: React.PropTypes.string.isRequired,
   to: React.PropTypes.string,
-  href: React.PropTypes.string
+  href: React.PropTypes.string,
+  method: React.PropTypes.string
 };
 
 export default ColumnLink;
diff --git a/app/assets/javascripts/components/features/ui/components/media_modal.jsx b/app/assets/javascripts/components/features/ui/components/media_modal.jsx
index 130f48b46..786b08152 100644
--- a/app/assets/javascripts/components/features/ui/components/media_modal.jsx
+++ b/app/assets/javascripts/components/features/ui/components/media_modal.jsx
@@ -104,8 +104,8 @@ const MediaModal = React.createClass({
     leftNav = rightNav = content = '';
 
     if (media.size > 1) {
-      leftNav  = <div style={leftNavStyle} className='modal-container__nav' onClick={this.handlePrevClick}><i className='fa fa-fw fa-chevron-left' /></div>;
-      rightNav = <div style={rightNavStyle} className='modal-container__nav' onClick={this.handleNextClick}><i className='fa fa-fw fa-chevron-right' /></div>;
+      leftNav  = <div role='button' tabIndex='0' style={leftNavStyle} className='modal-container__nav' onClick={this.handlePrevClick}><i className='fa fa-fw fa-chevron-left' /></div>;
+      rightNav = <div role='button' tabIndex='0' style={rightNavStyle} className='modal-container__nav' onClick={this.handleNextClick}><i className='fa fa-fw fa-chevron-right' /></div>;
     }
 
     if (attachment.get('type') === 'image') {
diff --git a/app/assets/javascripts/components/features/ui/components/modal_root.jsx b/app/assets/javascripts/components/features/ui/components/modal_root.jsx
index 74eb50039..a1ed8fd88 100644
--- a/app/assets/javascripts/components/features/ui/components/modal_root.jsx
+++ b/app/assets/javascripts/components/features/ui/components/modal_root.jsx
@@ -66,7 +66,7 @@ const ModalRoot = React.createClass({
 
               return (
                 <div key={key}>
-                  <div className='modal-root__overlay' style={{ opacity: style.opacity, transform: `translateZ(0px)` }} onClick={onClose} />
+                  <div role='presentation' className='modal-root__overlay' style={{ opacity: style.opacity, transform: `translateZ(0px)` }} onClick={onClose} />
                   <div className='modal-root__container' style={{ opacity: style.opacity, transform: `translateZ(0px) scale(${style.scale})` }}>
                     <SpecificComponent {...props} onClose={onClose} />
                   </div>
diff --git a/app/assets/javascripts/components/link_header.jsx b/app/assets/javascripts/components/link_header.jsx
index 9a9ff7e7a..b872dc24a 100644
--- a/app/assets/javascripts/components/link_header.jsx
+++ b/app/assets/javascripts/components/link_header.jsx
@@ -14,7 +14,7 @@ Link.parseAttrs = (link, parts) => {
     link  = Link.parseParams(link, uriAttrs[1])
   }
 
-  while(match = Link.attrPattern.exec(attrs)) {
+  while(match = Link.attrPattern.exec(attrs)) { // eslint-disable-line no-cond-assign
     attr  = match[1].toLowerCase()
     value = match[4] || match[3] || match[2]
 
diff --git a/app/assets/javascripts/components/locales/es.jsx b/app/assets/javascripts/components/locales/es.jsx
index 7e9c0dc2c..b118def8b 100644
--- a/app/assets/javascripts/components/locales/es.jsx
+++ b/app/assets/javascripts/components/locales/es.jsx
@@ -73,7 +73,7 @@ const es = {
   "notifications.column_settings.mention": "Menciones:",
   "notifications.column_settings.reblog": "Retoots:",
   "emoji_button.label": "Insertar emoji",
-  "privacy.public.short": "Público", 
+  "privacy.public.short": "Público",
   "privacy.public.long": "Mostrar en la historia federada",
   "privacy.unlisted.short": "Sin federar",
   "privacy.unlisted.long": "No mostrar en la historia federada",
diff --git a/app/assets/javascripts/components/locales/ru.jsx b/app/assets/javascripts/components/locales/ru.jsx
index 95ed52656..5d84527b6 100644
--- a/app/assets/javascripts/components/locales/ru.jsx
+++ b/app/assets/javascripts/components/locales/ru.jsx
@@ -16,7 +16,7 @@ const ru = {
   "status.show_less": "Свернуть",
   "status.open": "Развернуть статус",
   "status.report": "Пожаловаться",
-  "status.load_more": "Показать еще", 
+  "status.load_more": "Показать еще",
   "video_player.toggle_sound": "Вкл./выкл. звук",
   "video_player.toggle_visible": "Показать/скрыть",
   "account.disclaimer": "Это пользователь с другого узла. Число может быть больше.",
diff --git a/app/assets/javascripts/components/middleware/errors.jsx b/app/assets/javascripts/components/middleware/errors.jsx
index 4aca75f1e..9a51257cb 100644
--- a/app/assets/javascripts/components/middleware/errors.jsx
+++ b/app/assets/javascripts/components/middleware/errors.jsx
@@ -22,7 +22,7 @@ export default function errorsMiddleware() {
 
           dispatch(showAlert(title, message));
         } else {
-          console.error(action.error);
+          console.error(action.error); // eslint-disable-line no-console
           dispatch(showAlert('Oops!', 'An unexpected error occurred.'));
         }
       }
diff --git a/app/assets/javascripts/components/reducers/alerts.jsx b/app/assets/javascripts/components/reducers/alerts.jsx
index 42987f649..dc0145824 100644
--- a/app/assets/javascripts/components/reducers/alerts.jsx
+++ b/app/assets/javascripts/components/reducers/alerts.jsx
@@ -9,17 +9,17 @@ const initialState = Immutable.List([]);
 
 export default function alerts(state = initialState, action) {
   switch(action.type) {
-    case ALERT_SHOW:
-      return state.push(Immutable.Map({
-        key: state.size > 0 ? state.last().get('key') + 1 : 0,
-        title: action.title,
-        message: action.message
-      }));
-    case ALERT_DISMISS:
-      return state.filterNot(item => item.get('key') === action.alert.key);
-    case ALERT_CLEAR:
-      return state.clear();
-    default:
-      return state;
+  case ALERT_SHOW:
+    return state.push(Immutable.Map({
+      key: state.size > 0 ? state.last().get('key') + 1 : 0,
+      title: action.title,
+      message: action.message
+    }));
+  case ALERT_DISMISS:
+    return state.filterNot(item => item.get('key') === action.alert.key);
+  case ALERT_CLEAR:
+    return state.clear();
+  default:
+    return state;
   }
 };