diff --git a/.eslintrc b/.eslintrc index 1122f7e2e2..bc716af7d6 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,5 +1,5 @@ { - "extends": "airbnb", + "extends": ["airbnb", "prettier"], "parser": "babel-eslint", "env": { "browser": true, @@ -16,12 +16,12 @@ "import/no-unresolved": 0, "import/no-named-as-default": 2, "comma-dangle": 0, // not sure why airbnb turned this on. gross! - "indent": [2, 2, {"SwitchCase": 1}], + "indent": 0, "no-console": 0, "no-alert": 0, "no-underscore-dangle": 0, "max-len": [1, 120, 2, {"ignoreComments": true, "ignoreTemplateLiterals": true}], - "quote-props": [1, "consistent-as-needed"], + "quote-props": [1, "as-needed"], "no-unused-vars": [1, {"vars": "local", "args": "none"}], "consistent-return": ["error", { "treatUndefinedAsUnspecified": true }], "no-param-reassign": [2, { "props": false }], @@ -60,10 +60,13 @@ }, "allowChildren": false } + ], + "prettier/prettier": [ + "error" ] }, "plugins": [ - "react", "jsx-a11y", "import" + "react", "jsx-a11y", "import", "prettier" ], "settings": { "import/parser": "babel-eslint", diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000000..be8ed7938d --- /dev/null +++ b/.prettierrc @@ -0,0 +1,18 @@ +{ + "arrowParens": "always", + "bracketSpacing": true, + "htmlWhitespaceSensitivity": "css", + "insertPragma": false, + "jsxBracketSameLine": false, + "jsxSingleQuote": false, + "parser": "babel", + "printWidth": 80, + "proseWrap": "never", + "requirePragma": false, + "semi": true, + "singleQuote": true, + "tabWidth": 2, + "trailingComma": "none", + "useTabs": false, + "quoteProps": "as-needed" +} \ No newline at end of file diff --git a/client/common/Button.jsx b/client/common/Button.jsx index 20bd9c2537..3009ab338b 100644 --- a/client/common/Button.jsx +++ b/client/common/Button.jsx @@ -8,7 +8,7 @@ import { remSize, prop } from '../theme'; const kinds = { block: 'block', icon: 'icon', - inline: 'inline', + inline: 'inline' }; // The '&&&' will increase the specificity of the @@ -34,7 +34,7 @@ const StyledButton = styled.button` svg * { fill: ${prop('Button.default.foreground')}; } - + &:hover:not(:disabled) { color: ${prop('Button.hover.foreground')}; background-color: ${prop('Button.hover.background')}; @@ -115,7 +115,7 @@ const StyledIconButton = styled.button` border-radius: 50%; padding: ${remSize(8)} ${remSize(25)}; line-height: 1; - + &:hover:not(:disabled) { color: ${prop('Button.hover.foreground')}; background-color: ${prop('Button.hover.background')}; @@ -150,10 +150,24 @@ const StyledIconButton = styled.button` * A Button performs an primary action */ const Button = ({ - children, href, kind, iconBefore, iconAfter, 'aria-label': ariaLabel, to, type, ...props + children, + href, + kind, + iconBefore, + iconAfter, + 'aria-label': ariaLabel, + to, + type, + ...props }) => { const hasChildren = React.Children.count(children) > 0; - const content = <>{iconBefore}{hasChildren && {children}}{iconAfter}; + const content = ( + <> + {iconBefore} + {hasChildren && {children}} + {iconAfter} + + ); let StyledComponent = StyledButton; if (kind === kinds.inline) { @@ -177,22 +191,36 @@ const Button = ({ } if (to) { - return {content}; + return ( + + {content} + + ); } - return {content}; + return ( + + {content} + + ); }; Button.defaultProps = { - 'children': null, - 'disabled': false, - 'iconAfter': null, - 'iconBefore': null, - 'kind': kinds.block, - 'href': null, + children: null, + disabled: false, + iconAfter: null, + iconBefore: null, + kind: kinds.block, + href: null, 'aria-label': null, - 'to': null, - 'type': 'button', + to: null, + type: 'button' }; Button.kinds = kinds; @@ -202,27 +230,27 @@ Button.propTypes = { * The visible part of the button, telling the user what * the action is */ - 'children': PropTypes.element, + children: PropTypes.element, /** If the button can be activated or not */ - 'disabled': PropTypes.bool, + disabled: PropTypes.bool, /** * SVG icon to place after child content */ - 'iconAfter': PropTypes.element, + iconAfter: PropTypes.element, /** * SVG icon to place before child content */ - 'iconBefore': PropTypes.element, + iconBefore: PropTypes.element, /** * The kind of button - determines how it appears visually */ - 'kind': PropTypes.oneOf(Object.values(kinds)), + kind: PropTypes.oneOf(Object.values(kinds)), /** * Specifying an href will use an to link to the URL */ - 'href': PropTypes.string, + href: PropTypes.string, /* * An ARIA Label used for accessibility */ @@ -230,11 +258,11 @@ Button.propTypes = { /** * Specifying a to URL will use a react-router Link */ - 'to': PropTypes.string, + to: PropTypes.string, /** * If using a button, then type is defines the type of button */ - 'type': PropTypes.oneOf(['button', 'submit']), + type: PropTypes.oneOf(['button', 'submit']) }; export default Button; diff --git a/client/common/Button.stories.jsx b/client/common/Button.stories.jsx index bf1a02c8ac..a583d8b46d 100644 --- a/client/common/Button.stories.jsx +++ b/client/common/Button.stories.jsx @@ -21,42 +21,45 @@ export const AllFeatures = () => ( ); export const SubmitButton = () => ( - + ); -export const DefaultTypeButton = () => ; +export const DefaultTypeButton = () => ( + +); -export const DisabledButton = () => ; +export const DisabledButton = () => ( + +); export const AnchorButton = () => ( - + ); export const ReactRouterLink = () => ( - + ); export const ButtonWithIconBefore = () => ( - + ); export const ButtonWithIconAfter = () => ( - + ); export const InlineButtonWithIconAfter = () => ( - ); diff --git a/client/common/icons.jsx b/client/common/icons.jsx index d4a458bca8..e4bb1d2de1 100644 --- a/client/common/icons.jsx +++ b/client/common/icons.jsx @@ -23,7 +23,6 @@ import CircleTerminal from '../images/circle-terminal.svg'; import CircleFolder from '../images/circle-folder.svg'; import CircleInfo from '../images/circle-info.svg'; - // HOC that adds the right web accessibility props // https://www.scottohara.me/blog/2019/05/22/contextual-images-svgs-and-a11y.html @@ -34,13 +33,17 @@ function withLabel(SvgComponent) { const StyledIcon = styled(SvgComponent)` &&& { color: ${prop('Icon.default')}; - & g, & path, & polygon { + & g, + & path, + & polygon { opacity: 1; fill: ${prop('Icon.default')}; } &:hover { color: ${prop('Icon.hover')}; - & g, & path, & polygon { + & g, + & path, + & polygon { opacity: 1; fill: ${prop('Icon.hover')}; } @@ -50,18 +53,16 @@ function withLabel(SvgComponent) { const { 'aria-label': ariaLabel } = props; if (ariaLabel) { - return (); + return ( + + ); } - return (); + return ; }; Icon.propTypes = { diff --git a/client/common/icons.stories.jsx b/client/common/icons.stories.jsx index 3c3307ab47..3df22e3196 100644 --- a/client/common/icons.stories.jsx +++ b/client/common/icons.stories.jsx @@ -12,7 +12,5 @@ export const AllIcons = () => { const names = Object.keys(icons); const SelectedIcon = icons[select('name', names, names[0])]; - return ( - - ); + return ; }; diff --git a/client/components/AddRemoveButton.jsx b/client/components/AddRemoveButton.jsx index ea600cf91d..23fb9082f5 100644 --- a/client/components/AddRemoveButton.jsx +++ b/client/components/AddRemoveButton.jsx @@ -2,12 +2,14 @@ import React from 'react'; import PropTypes from 'prop-types'; import { withTranslation } from 'react-i18next'; - import AddIcon from '../images/plus.svg'; import RemoveIcon from '../images/minus.svg'; const AddRemoveButton = ({ type, onClick, t }) => { - const alt = type === 'add' ? t('AddRemoveButton.AltAddARIA') : t('AddRemoveButton.AltRemoveARIA'); + const alt = + type === 'add' + ? t('AddRemoveButton.AltAddARIA') + : t('AddRemoveButton.AltRemoveARIA'); const Icon = type === 'add' ? AddIcon : RemoveIcon; return ( diff --git a/client/components/Dropdown.jsx b/client/components/Dropdown.jsx index 0cd29574ec..1bf7f5d0e4 100644 --- a/client/components/Dropdown.jsx +++ b/client/components/Dropdown.jsx @@ -13,11 +13,11 @@ const DropdownWrapper = styled.ul` color: ${prop('primaryTextColor')}; position: absolute; - right: ${props => (props.right ? 0 : 'initial')}; - left: ${props => (props.left ? 0 : 'initial')}; + right: ${(props) => (props.right ? 0 : 'initial')}; + left: ${(props) => (props.left ? 0 : 'initial')}; - ${props => (props.align === 'right' && 'right: 0;')} - ${props => (props.align === 'left' && 'left: 0;')} + ${(props) => props.align === 'right' && 'right: 0;'} + ${(props) => props.align === 'left' && 'left: 0;'} text-align: left; @@ -28,15 +28,20 @@ const DropdownWrapper = styled.ul` z-index: 2; border-radius: ${remSize(6)}; - & li:first-child { border-radius: ${remSize(5)} ${remSize(5)} 0 0; } - & li:last-child { border-radius: 0 0 ${remSize(5)} ${remSize(5)}; } + & li:first-child { + border-radius: ${remSize(5)} ${remSize(5)} 0 0; + } + & li:last-child { + border-radius: 0 0 ${remSize(5)} ${remSize(5)}; + } & li:hover { - background-color: ${prop('Button.hover.background')}; color: ${prop('Button.hover.foreground')}; - * { color: ${prop('Button.hover.foreground')}; } + * { + color: ${prop('Button.hover.foreground')}; + } } li { @@ -60,7 +65,9 @@ const DropdownWrapper = styled.ul` justify-content: flex-start; } - & button span { padding: 0px } + & button span { + padding: 0px; + } } `; @@ -68,32 +75,32 @@ const DropdownWrapper = styled.ul` // const MaybeIcon = (Element, label) => Element && ; const Dropdown = ({ items, align }) => ( - + {/* className="nav__items-left" */} - {items && items.map(({ - title, icon, href, action - }) => ( -
  • - {/* {MaybeIcon(icon, `Navigate to ${title}`)} */} - {href - ? {title} - : action()}>{title}} - -
  • - )) - } + {items && + items.map(({ title, icon, href, action }) => ( +
  • + {/* {MaybeIcon(icon, `Navigate to ${title}`)} */} + {href ? ( + {title} + ) : ( + action()}>{title} + )} +
  • + ))}
    ); - Dropdown.propTypes = { align: PropTypes.oneOf(['left', 'right']), - items: PropTypes.arrayOf(PropTypes.shape({ - action: PropTypes.func, - icon: PropTypes.func, - href: PropTypes.string, - title: PropTypes.string - })), + items: PropTypes.arrayOf( + PropTypes.shape({ + action: PropTypes.func, + icon: PropTypes.func, + href: PropTypes.string, + title: PropTypes.string + }) + ) }; Dropdown.defaultProps = { diff --git a/client/components/Nav.jsx b/client/components/Nav.jsx index 993a9ff828..9ad07edec3 100644 --- a/client/components/Nav.jsx +++ b/client/components/Nav.jsx @@ -9,7 +9,10 @@ import { languageKeyToLabel } from '../i18n'; import * as IDEActions from '../modules/IDE/actions/ide'; import * as toastActions from '../modules/IDE/actions/toast'; import * as projectActions from '../modules/IDE/actions/project'; -import { setAllAccessibleOutput, setLanguage } from '../modules/IDE/actions/preferences'; +import { + setAllAccessibleOutput, + setLanguage +} from '../modules/IDE/actions/preferences'; import { logoutUser } from '../modules/User/actions'; import getConfig from '../utils/getConfig'; @@ -200,7 +203,11 @@ class Nav extends React.PureComponent { handleShare() { const { username } = this.props.params; - this.props.showShareModal(this.props.project.id, this.props.project.name, username); + this.props.showShareModal( + this.props.project.id, + this.props.project.name, + username + ); this.setDropdown('none'); } @@ -242,11 +249,20 @@ class Nav extends React.PureComponent { return (