From 64a3d26cca07c2ecedfb2c4044a0824a351c423a Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Thu, 17 Nov 2016 10:58:40 -0500 Subject: [PATCH] Updating eslint --- webapp/.eslintrc.json | 26 +++++++++++-------- webapp/client/web_client.jsx | 8 +++--- webapp/client/webrtc_session.jsx | 6 ++--- .../admin_console/cluster_settings.jsx | 4 +-- .../admin_console/cluster_table.jsx | 2 +- .../admin_console/cluster_table_container.jsx | 6 ++--- .../admin_console/file_upload_setting.jsx | 2 +- webapp/components/channel_header.jsx | 8 +++--- webapp/components/login/login_controller.jsx | 1 - webapp/components/navbar.jsx | 8 +++--- .../suggestion/at_mention_provider.jsx | 2 +- .../user_settings/user_settings_modal.jsx | 2 -- webapp/components/youtube_video.jsx | 2 +- webapp/package.json | 6 ++--- webapp/utils/emoticons.jsx | 4 +-- webapp/utils/markdown.jsx | 2 +- webapp/utils/text_formatting.jsx | 4 +-- webapp/utils/utils.jsx | 16 +++++------- 18 files changed, 53 insertions(+), 56 deletions(-) diff --git a/webapp/.eslintrc.json b/webapp/.eslintrc.json index 2762483ef964f..183df2017b7a7 100644 --- a/webapp/.eslintrc.json +++ b/webapp/.eslintrc.json @@ -1,12 +1,13 @@ { "extends": "eslint:recommended", "parserOptions": { - "ecmaVersion": 6, + "ecmaVersion": 8, "sourceType": "module", "ecmaFeatures": { "jsx": true, "impliedStrict": true, - "modules": true + "modules": true, + "experimentalObjectRestSpread": true } }, "parser": "babel-eslint", @@ -50,6 +51,7 @@ "dot-notation": 2, "eqeqeq": [2, "smart"], "func-call-spacing": [2, "never"], + "func-name-matching": 0, "func-names": 2, "func-style": [2, "declaration"], "generator-star-spacing": [2, {"before": false, "after": true}], @@ -136,6 +138,7 @@ "no-proto": 2, "no-redeclare": 2, "no-return-assign": [2, "always"], + "no-return-await": 2, "no-script-url": 2, "no-self-assign": [2, {"props": true}], "no-self-compare": 2, @@ -166,6 +169,7 @@ "no-useless-constructor": 2, "no-useless-escape": 2, "no-useless-rename": 2, + "no-useless-return": 2, "no-var": 0, "no-void": 2, "no-warning-comments": 1, @@ -182,7 +186,6 @@ "prefer-arrow-callback": 2, "prefer-const": 2, "prefer-numeric-literals": 2, - "prefer-reflect": 2, "prefer-rest-params": 2, "prefer-spread": 2, "prefer-template": 0, @@ -190,6 +193,7 @@ "quotes": [2, "single", "avoid-escape"], "radix": 2, "react/display-name": [2, { "ignoreTranspilerName": false }], + "react/forbid-component-props": 0, "react/jsx-boolean-value": [2, "always"], "react/jsx-closing-bracket-location": [2, { "location": "tag-aligned" }], "react/jsx-curly-spacing": [2, "never"], @@ -202,26 +206,33 @@ "react/jsx-key": 2, "react/jsx-max-props-per-line": [2, { "maximum": 1 }], "react/jsx-no-bind": 0, + "react/jsx-no-comment-textnodes": 2, "react/jsx-no-duplicate-props": [2, { "ignoreCase": false }], "react/jsx-no-literals": 2, "react/jsx-no-target-blank": 2, "react/jsx-no-undef": 2, "react/jsx-pascal-case": 2, "react/jsx-space-before-closing": [2, "never"], + "react/jsx-tag-spacing": [2, { "closingSlash": "never", "beforeSelfClosing": "never", "afterOpening": "never" }], "react/jsx-uses-react": 2, "react/jsx-uses-vars": 2, - "react/jsx-no-comment-textnodes": 2, + "react/jsx-wrap-multilines": 2, + "react/no-children-prop": 2, "react/no-danger": 0, + "react/no-danger-with-children": 2, "react/no-deprecated": 2, "react/no-did-mount-set-state": 2, "react/no-did-update-set-state": 2, "react/no-direct-mutation-state": 2, + "react/no-find-dom-node": 1, "react/no-is-mounted": 2, "react/no-multi-comp": [2, { "ignoreStateless": true }], "react/no-render-return-value": 2, "react/no-set-state": 0, "react/no-string-refs": 0, + "react/no-unescaped-entities": 2, "react/no-unknown-property": 2, + "react/no-unused-prop-types": [1, {"skipShapeProps": true}], "react/prefer-es6-class": 2, "react/prefer-stateless-function": 0, "react/prop-types": 2, @@ -229,14 +240,7 @@ "react/require-render-return": 2, "react/self-closing-comp": 2, "react/sort-comp": 0, - "react/jsx-wrap-multilines": 2, - "react/no-find-dom-node": 1, - "react/forbid-component-props": 0, - "react/no-danger-with-children": 2, - "react/no-unused-prop-types": [1, {"skipShapeProps": true}], "react/style-prop-object": 2, - "react/no-children-prop": 2, - "react/no-unescaped-entities": 2, "require-yield": 2, "rest-spread-spacing": [2, "never"], "semi": [2, "always"], diff --git a/webapp/client/web_client.jsx b/webapp/client/web_client.jsx index 5d2696c37c896..c5d704d8c1dcc 100644 --- a/webapp/client/web_client.jsx +++ b/webapp/client/web_client.jsx @@ -17,23 +17,23 @@ class WebClientClass extends Client { TeamStore.addChangeListener(this.onTeamStoreChanged); } - onTeamStoreChanged = () => { + onTeamStoreChanged() { this.setTeamId(TeamStore.getCurrentId()); } - track = (category, action, label, property, value) => { + track(category, action, label, property, value) { if (global.window && global.window.analytics) { global.window.analytics.track(action, {category, label, property, value}); } } - trackPage = () => { + trackPage() { if (global.window && global.window.analytics) { global.window.analytics.page(); } } - handleError = (err, res) => { // eslint-disable-line no-unused-vars + handleError(err, res) { if (err.status === HTTP_UNAUTHORIZED && res.req.url !== '/api/v3/users/login') { GlobalActions.emitUserLoggedOutEvent('/login'); } diff --git a/webapp/client/webrtc_session.jsx b/webapp/client/webrtc_session.jsx index 9ee7fcd5a0f44..df60a1053210c 100644 --- a/webapp/client/webrtc_session.jsx +++ b/webapp/client/webrtc_session.jsx @@ -1951,7 +1951,7 @@ export default class WebrtcSession { return (trickle === true); } - unbindWebSocket = (onUnbindMessage, onUnbindError) => { + unbindWebSocket(onUnbindMessage, onUnbindError) { for (var eventName in this.wsHandlers) { if (this.wsHandlers.hasOwnProperty(eventName)) { this.ws.removeEventListener(eventName, this.wsHandlers[eventName]); @@ -1962,5 +1962,5 @@ export default class WebrtcSession { if (this.wsKeepaliveTimeoutId) { clearTimeout(this.wsKeepaliveTimeoutId); } - }; -} \ No newline at end of file + } +} diff --git a/webapp/components/admin_console/cluster_settings.jsx b/webapp/components/admin_console/cluster_settings.jsx index 8aab905e44e6a..bbd135e507e75 100644 --- a/webapp/components/admin_console/cluster_settings.jsx +++ b/webapp/components/admin_console/cluster_settings.jsx @@ -60,7 +60,7 @@ export default class ClusterSettings extends AdminSettings { ); } - overrideHandleChange = (id, value) => { + overrideHandleChange(id, value) { this.setState({ showWarning: true }); @@ -185,4 +185,4 @@ export default class ClusterSettings extends AdminSettings { ); } -} \ No newline at end of file +} diff --git a/webapp/components/admin_console/cluster_table.jsx b/webapp/components/admin_console/cluster_table.jsx index 4aca796a0c93f..0a2755c4aa130 100644 --- a/webapp/components/admin_console/cluster_table.jsx +++ b/webapp/components/admin_console/cluster_table.jsx @@ -176,4 +176,4 @@ export default class ClusterTable extends React.Component { ); } -} \ No newline at end of file +} diff --git a/webapp/components/admin_console/cluster_table_container.jsx b/webapp/components/admin_console/cluster_table_container.jsx index 5dad56469373b..aad5753b7b88f 100644 --- a/webapp/components/admin_console/cluster_table_container.jsx +++ b/webapp/components/admin_console/cluster_table_container.jsx @@ -18,7 +18,7 @@ export default class ClusterTableContainer extends React.Component { }; } - load = () => { + load() { Client.getClusterStatus( (data) => { this.setState({ @@ -44,7 +44,7 @@ export default class ClusterTableContainer extends React.Component { } } - reload = (e) => { + reload(e) { if (e) { e.preventDefault(); } @@ -68,4 +68,4 @@ export default class ClusterTableContainer extends React.Component { /> ); } -} \ No newline at end of file +} diff --git a/webapp/components/admin_console/file_upload_setting.jsx b/webapp/components/admin_console/file_upload_setting.jsx index a7df16c0af6ed..0c1efc168a8e4 100644 --- a/webapp/components/admin_console/file_upload_setting.jsx +++ b/webapp/components/admin_console/file_upload_setting.jsx @@ -108,7 +108,7 @@ export default class FileUploadSetting extends Setting { disabled={!this.state.fileSelected} onClick={this.handleSubmit} ref='upload_button' - data-loading-text={` ${this.props.uploadingText}`} + data-loading-text={` ${this.props.uploadingText}`} > : - } + } ); const toggleFavorite = ( diff --git a/webapp/components/login/login_controller.jsx b/webapp/components/login/login_controller.jsx index fd5413c17a129..603ec40d6ac24 100644 --- a/webapp/components/login/login_controller.jsx +++ b/webapp/components/login/login_controller.jsx @@ -167,7 +167,6 @@ export default class LoginController extends React.Component { (err) => { if (err.id === 'api.user.login.not_verified.app_error') { browserHistory.push('/should_verify_email?&email=' + encodeURIComponent(loginId)); - return; } else if (err.id === 'store.sql_user.get_for_login.app_error' || err.id === 'ent.ldap.do_login.user_not_registered.app_error') { this.setState({ diff --git a/webapp/components/navbar.jsx b/webapp/components/navbar.jsx index d71fec9457231..0a5f04394c7b5 100644 --- a/webapp/components/navbar.jsx +++ b/webapp/components/navbar.jsx @@ -501,10 +501,10 @@ export default class Navbar extends React.Component { id='channelHeader.removeFromFavorites' defaultMessage='Remove from Favorites' /> : - } + } ); diff --git a/webapp/components/suggestion/at_mention_provider.jsx b/webapp/components/suggestion/at_mention_provider.jsx index d1a03deb5c57a..13b9344adb593 100644 --- a/webapp/components/suggestion/at_mention_provider.jsx +++ b/webapp/components/suggestion/at_mention_provider.jsx @@ -112,7 +112,7 @@ export default class AtMentionProvider { handlePretextChanged(suggestionId, pretext) { clearTimeout(this.timeoutId); - const captured = (/(?:^|\W)@([a-z0-9\-\._]*)$/i).exec(pretext.toLowerCase()); + const captured = (/(?:^|\W)@([a-z0-9\-._]*)$/i).exec(pretext.toLowerCase()); if (captured) { const prefix = captured[1]; diff --git a/webapp/components/user_settings/user_settings_modal.jsx b/webapp/components/user_settings/user_settings_modal.jsx index 9112f87110480..c1194ed787465 100644 --- a/webapp/components/user_settings/user_settings_modal.jsx +++ b/webapp/components/user_settings/user_settings_modal.jsx @@ -104,7 +104,6 @@ class UserSettingsModal extends React.Component { } this.props.onModalDismissed(); - return; } // called after the dialog is fully hidden and faded out @@ -251,7 +250,6 @@ class UserSettingsModal extends React.Component { setRequireConfirm={ (requireConfirm) => { this.requireConfirm = requireConfirm; - return; } } /> diff --git a/webapp/components/youtube_video.jsx b/webapp/components/youtube_video.jsx index 93ea4f9466de6..908a2c74eab5c 100644 --- a/webapp/components/youtube_video.jsx +++ b/webapp/components/youtube_video.jsx @@ -5,7 +5,7 @@ import ChannelStore from 'stores/channel_store.jsx'; import WebClient from 'client/web_client.jsx'; import * as Utils from 'utils/utils.jsx'; -const ytRegex = /(?:http|https):\/\/(?:www\.|m\.)?(?:(?:youtube\.com\/(?:(?:v\/)|(?:(?:watch|embed\/watch)(?:\/|.*v=))|(?:embed\/)|(?:user\/[^\/]+\/u\/[0-9]\/)))|(?:youtu\.be\/))([^#&\?]*)/; +const ytRegex = /(?:http|https):\/\/(?:www\.|m\.)?(?:(?:youtube\.com\/(?:(?:v\/)|(?:(?:watch|embed\/watch)(?:\/|.*v=))|(?:embed\/)|(?:user\/[^/]+\/u\/[0-9]\/)))|(?:youtu\.be\/))([^#&?]*)/; import React from 'react'; diff --git a/webapp/package.json b/webapp/package.json index 818050cc28582..46838718a987a 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -38,7 +38,7 @@ }, "devDependencies": { "babel-core": "6.18.2", - "babel-eslint": "6.1.2", + "babel-eslint": "7.1.0", "babel-loader": "6.2.7", "babel-plugin-transform-runtime": "6.15.0", "babel-polyfill": "6.16.0", @@ -48,8 +48,8 @@ "copy-webpack-plugin": "4.0.1", "cross-env": "3.1.3", "css-loader": "0.25.0", - "eslint": "3.5.0", - "eslint-plugin-react": "6.3.0", + "eslint": "3.10.2", + "eslint-plugin-react": "6.7.1", "exports-loader": "0.6.3", "extract-text-webpack-plugin": "1.0.1", "file-loader": "0.9.0", diff --git a/webapp/utils/emoticons.jsx b/webapp/utils/emoticons.jsx index ba54d8cb3a0c2..7280ef88b4a16 100644 --- a/webapp/utils/emoticons.jsx +++ b/webapp/utils/emoticons.jsx @@ -12,7 +12,7 @@ export const emoticonPatterns = { smile: /(^|\s)(:-?d)(?=$|\s)/gi, // :D stuck_out_tongue_closed_eyes: /(^|\s)(x-d)(?=$|\s)/gi, // x-d stuck_out_tongue: /(^|\s)(:-?p)(?=$|\s)/gi, // :p - rage: /(^|\s)(:-?[\[@])(?=$|\s)/g, // :@ + rage: /(^|\s)(:-?[[@])(?=$|\s)/g, // :@ slightly_frowning_face: /(^|\s)(:-?\()(?=$|\s)/g, // :( cry: /(^|\s)(:['’]-?\(|:'\(|:'\()(?=$|\s)/g, // :`( confused: /(^|\s)(:-?\/)(?=$|\s)/g, // :/ @@ -23,7 +23,7 @@ export const emoticonPatterns = { heart: /(^|\s)(<3|<3)(?=$|\s)/g, // <3 broken_heart: /(^|\s)(<\/3|</3)(?=$|\s)/g, // +\(\)~@]/).filter((term) => Boolean(term))); + terms.push(...captured[0].split(/[ <>+()~@]/).filter((term) => Boolean(term))); continue; } diff --git a/webapp/utils/utils.jsx b/webapp/utils/utils.jsx index 7a609a2d1de42..248fabd9a8ed8 100644 --- a/webapp/utils/utils.jsx +++ b/webapp/utils/utils.jsx @@ -30,8 +30,8 @@ export function isEmail(email) { export function cleanUpUrlable(input) { var cleaned = input.trim().replace(/-/g, ' ').replace(/[^\w\s]/gi, '').toLowerCase().replace(/\s/g, '-'); cleaned = cleaned.replace(/-{2,}/, '-'); - cleaned = cleaned.replace(/^\-+/, ''); - cleaned = cleaned.replace(/\-+$/, ''); + cleaned = cleaned.replace(/^-+/, ''); + cleaned = cleaned.replace(/-+$/, ''); return cleaned; } @@ -135,7 +135,6 @@ export function ding() { canDing = false; setTimeout(() => { canDing = true; - return; }, 3000); } } @@ -194,14 +193,14 @@ export function getTimestamp() { // extracts links not styled by Markdown export function extractFirstLink(text) { - const pattern = /(^|[\s\n]|)((?:https?|ftp):\/\/[\-A-Z0-9+\u0026\u2019@#\/%?=()~_|!:,.;]*[\-A-Z0-9+\u0026@#\/%=~()_|])/i; + const pattern = /(^|[\s\n]|)((?:https?|ftp):\/\/[-A-Z0-9+\u0026\u2019@#/%?=()~_|!:,.;]*[-A-Z0-9+\u0026@#/%=~()_|])/i; let inText = text; // strip out code blocks inText = inText.replace(/`[^`]*`/g, ''); // strip out inline markdown images - inText = inText.replace(/!\[[^\]]*\]\([^\)]*\)/g, ''); + inText = inText.replace(/!\[[^\]]*]\([^)]*\)/g, ''); const match = pattern.exec(inText); if (match) { @@ -212,7 +211,7 @@ export function extractFirstLink(text) { } export function escapeRegExp(string) { - return string.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1'); + return string.replace(/([.*+?^=!:${}()|[\]/\\])/g, '\\$1'); } // Taken from http://stackoverflow.com/questions/1068834/object-comparison-in-javascript and modified slightly @@ -708,7 +707,6 @@ export function updateCodeTheme(userTheme) { element.themes.forEach((theme) => { if (userTheme === theme.id) { cssPath = theme.cssURL; - return; } }); } @@ -736,8 +734,6 @@ export function placeCaretAtEnd(el) { el.focus(); el.selectionStart = el.value.length; el.selectionEnd = el.value.length; - - return; } export function getCaretPosition(el) { @@ -799,7 +795,7 @@ export function isValidUsername(name) { error = 'This field is required'; } else if (name.length < Constants.MIN_USERNAME_LENGTH || name.length > Constants.MAX_USERNAME_LENGTH) { error = 'Must be between ' + Constants.MIN_USERNAME_LENGTH + ' and ' + Constants.MAX_USERNAME_LENGTH + ' characters'; - } else if (!(/^[a-z0-9\.\-_]+$/).test(name)) { + } else if (!(/^[a-z0-9.\-_]+$/).test(name)) { error = "Must contain only letters, numbers, and the symbols '.', '-', and '_'."; } else if (!(/[a-z]/).test(name.charAt(0))) { //eslint-disable-line no-negated-condition error = 'First character must be a letter.';