* Add quotes ESLint rule * Add jsx-quotes ESlint rule * Sort ESLint rulesmaster
@@ -21,22 +21,10 @@ parserOptions: | |||||
rules: | rules: | ||||
no-cond-assign: error | |||||
no-console: warn | |||||
no-irregular-whitespace: error | |||||
no-unreachable: error | |||||
valid-typeof: error | |||||
consistent-return: error | |||||
dot-notation: error | |||||
eqeqeq: error | |||||
no-fallthrough: error | |||||
no-unused-expressions: error | |||||
strict: off | |||||
no-catch-shadow: error | |||||
indent: | |||||
- warn | |||||
- 2 | |||||
brace-style: warn | brace-style: warn | ||||
comma-dangle: | |||||
- error | |||||
- always-multiline | |||||
comma-spacing: | comma-spacing: | ||||
- warn | - warn | ||||
- before: false | - before: false | ||||
@@ -44,25 +32,43 @@ rules: | |||||
comma-style: | comma-style: | ||||
- warn | - warn | ||||
- last | - last | ||||
consistent-return: error | |||||
dot-notation: error | |||||
eqeqeq: error | |||||
indent: | |||||
- warn | |||||
- 2 | |||||
jsx-quotes: | |||||
- error | |||||
- prefer-single | |||||
no-catch-shadow: error | |||||
no-cond-assign: error | |||||
no-console: warn | |||||
no-fallthrough: error | |||||
no-irregular-whitespace: error | |||||
no-mixed-spaces-and-tabs: warn | no-mixed-spaces-and-tabs: warn | ||||
no-nested-ternary: warn | no-nested-ternary: warn | ||||
no-trailing-spaces: warn | no-trailing-spaces: warn | ||||
semi: error | |||||
no-unreachable: error | |||||
no-unused-expressions: error | |||||
object-curly-spacing: | |||||
- error | |||||
- always | |||||
padded-blocks: | padded-blocks: | ||||
- error | - error | ||||
- classes: always | - classes: always | ||||
comma-dangle: | |||||
quotes: | |||||
- error | - error | ||||
- always-multiline | |||||
object-curly-spacing: | |||||
- error | |||||
- always | |||||
- single | |||||
semi: error | |||||
strict: off | |||||
valid-typeof: error | |||||
react/jsx-wrap-multilines: error | |||||
react/jsx-no-bind: error | react/jsx-no-bind: error | ||||
react/self-closing-comp: error | |||||
react/prop-types: error | |||||
react/jsx-wrap-multilines: error | |||||
react/no-multi-comp: off | react/no-multi-comp: off | ||||
react/prop-types: error | |||||
react/self-closing-comp: error | |||||
jsx-a11y/accessible-emoji: warn | jsx-a11y/accessible-emoji: warn | ||||
jsx-a11y/anchor-has-content: warn | jsx-a11y/anchor-has-content: warn | ||||
@@ -21,8 +21,8 @@ class AvatarOverlay extends React.PureComponent { | |||||
return ( | return ( | ||||
<div className='account__avatar-overlay'> | <div className='account__avatar-overlay'> | ||||
<div className="account__avatar-overlay-base" style={baseStyle} /> | |||||
<div className="account__avatar-overlay-overlay" style={overlayStyle} /> | |||||
<div className='account__avatar-overlay-base' style={baseStyle} /> | |||||
<div className='account__avatar-overlay-overlay' style={overlayStyle} /> | |||||
</div> | </div> | ||||
); | ); | ||||
} | } | ||||
@@ -17,7 +17,7 @@ class DropdownMenu extends React.PureComponent { | |||||
}; | }; | ||||
static defaultProps = { | static defaultProps = { | ||||
ariaLabel: "Menu", | |||||
ariaLabel: 'Menu', | |||||
}; | }; | ||||
state = { | state = { | ||||
@@ -70,7 +70,7 @@ class DropdownMenu extends React.PureComponent { | |||||
render () { | render () { | ||||
const { icon, items, size, direction, ariaLabel } = this.props; | const { icon, items, size, direction, ariaLabel } = this.props; | ||||
const { expanded } = this.state; | const { expanded } = this.state; | ||||
const directionClass = (direction === "left") ? "dropdown__left" : "dropdown__right"; | |||||
const directionClass = (direction === 'left') ? 'dropdown__left' : 'dropdown__right'; | |||||
const dropdownItems = expanded && ( | const dropdownItems = expanded && ( | ||||
<ul className='dropdown__content-list'> | <ul className='dropdown__content-list'> | ||||
@@ -128,10 +128,10 @@ class StatusActionBar extends ImmutablePureComponent { | |||||
} | } | ||||
if (status.get('in_reply_to_id', null) === null) { | if (status.get('in_reply_to_id', null) === null) { | ||||
replyIcon = "reply"; | |||||
replyIcon = 'reply'; | |||||
replyTitle = intl.formatMessage(messages.reply); | replyTitle = intl.formatMessage(messages.reply); | ||||
} else { | } else { | ||||
replyIcon = "reply-all"; | |||||
replyIcon = 'reply-all'; | |||||
replyTitle = intl.formatMessage(messages.replyAll); | replyTitle = intl.formatMessage(messages.replyAll); | ||||
} | } | ||||
@@ -142,7 +142,7 @@ class StatusActionBar extends ImmutablePureComponent { | |||||
<IconButton className='status__action-bar-button star-icon' animate={true} active={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' onClick={this.handleFavouriteClick} /> | <IconButton className='status__action-bar-button star-icon' animate={true} active={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' onClick={this.handleFavouriteClick} /> | ||||
<div className='status__action-bar-dropdown'> | <div className='status__action-bar-dropdown'> | ||||
<DropdownMenu items={menu} icon='ellipsis-h' size={18} direction="right" ariaLabel="More"/> | |||||
<DropdownMenu items={menu} icon='ellipsis-h' size={18} direction='right' ariaLabel='More'/> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
); | ); | ||||
@@ -49,7 +49,7 @@ const { localeData, messages } = getLocale(); | |||||
addLocaleData(localeData); | addLocaleData(localeData); | ||||
const store = configureStore(); | const store = configureStore(); | ||||
const initialState = JSON.parse(document.getElementById("initial-state").textContent); | |||||
const initialState = JSON.parse(document.getElementById('initial-state').textContent); | |||||
store.dispatch(hydrateStore(initialState)); | store.dispatch(hydrateStore(initialState)); | ||||
const browserHistory = useRouterHistory(createBrowserHistory)({ | const browserHistory = useRouterHistory(createBrowserHistory)({ | ||||
@@ -81,7 +81,7 @@ class ActionBar extends React.PureComponent { | |||||
return ( | return ( | ||||
<div className='account__action-bar'> | <div className='account__action-bar'> | ||||
<div className='account__action-bar-dropdown'> | <div className='account__action-bar-dropdown'> | ||||
<DropdownMenu items={menu} icon='bars' size={24} direction="right" /> | |||||
<DropdownMenu items={menu} icon='bars' size={24} direction='right' /> | |||||
</div> | </div> | ||||
<div className='account__action-bar-links'> | <div className='account__action-bar-links'> | ||||
@@ -151,8 +151,8 @@ class ComposeForm extends ImmutablePureComponent { | |||||
return ( | return ( | ||||
<div className='compose-form'> | <div className='compose-form'> | ||||
<Collapsable isVisible={this.props.spoiler} fullHeight={50}> | <Collapsable isVisible={this.props.spoiler} fullHeight={50}> | ||||
<div className="spoiler-input"> | |||||
<input placeholder={intl.formatMessage(messages.spoiler_placeholder)} value={this.props.spoiler_text} onChange={this.handleChangeSpoilerText} onKeyDown={this.handleKeyDown} type="text" className="spoiler-input__input" id='cw-spoiler-input'/> | |||||
<div className='spoiler-input'> | |||||
<input placeholder={intl.formatMessage(messages.spoiler_placeholder)} value={this.props.spoiler_text} onChange={this.handleChangeSpoilerText} onKeyDown={this.handleKeyDown} type='text' className='spoiler-input__input' id='cw-spoiler-input'/> | |||||
</div> | </div> | ||||
</Collapsable> | </Collapsable> | ||||
@@ -193,7 +193,7 @@ class ComposeForm extends ImmutablePureComponent { | |||||
<div className='compose-form__publish'> | <div className='compose-form__publish'> | ||||
<div className='character-counter__wrapper'><CharacterCounter max={500} text={text} /></div> | <div className='character-counter__wrapper'><CharacterCounter max={500} text={text} /></div> | ||||
<div className='compose-form__publish-button-wrapper'><Button text={publishText} onClick={this.handleSubmit} disabled={disabled || this.props.is_uploading || text.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, "_").length > 500 || (text.length !==0 && text.trim().length === 0)} block /></div> | |||||
<div className='compose-form__publish-button-wrapper'><Button text={publishText} onClick={this.handleSubmit} disabled={disabled || this.props.is_uploading || text.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, '_').length > 500 || (text.length !==0 && text.trim().length === 0)} block /></div> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -106,9 +106,9 @@ class EmojiPickerDropdown extends React.PureComponent { | |||||
return ( | return ( | ||||
<Dropdown ref={this.setRef} className='emoji-picker__dropdown' onShow={this.onShowDropdown} onHide={this.onHideDropdown}> | <Dropdown ref={this.setRef} className='emoji-picker__dropdown' onShow={this.onShowDropdown} onHide={this.onHideDropdown}> | ||||
<DropdownTrigger className='emoji-button' title={intl.formatMessage(messages.emoji)}> | <DropdownTrigger className='emoji-button' title={intl.formatMessage(messages.emoji)}> | ||||
<img draggable="false" | |||||
className={`emojione ${active && loading ? "pulse-loading" : ''}`} | |||||
alt="🙂" src="/emoji/1f602.svg" /> | |||||
<img draggable='false' | |||||
className={`emojione ${active && loading ? 'pulse-loading' : ''}`} | |||||
alt='🙂' src='/emoji/1f602.svg' /> | |||||
</DropdownTrigger> | </DropdownTrigger> | ||||
<DropdownContent className='dropdown__left'> | <DropdownContent className='dropdown__left'> | ||||
{ | { | ||||
@@ -49,11 +49,11 @@ class Compose extends React.PureComponent { | |||||
if (multiColumn) { | if (multiColumn) { | ||||
header = ( | header = ( | ||||
<div className='drawer__header'> | <div className='drawer__header'> | ||||
<Link to='/getting-started' className='drawer__tab' title={intl.formatMessage(messages.start)}><i role="img" aria-label={intl.formatMessage(messages.start)} className='fa fa-fw fa-asterisk' /></Link> | |||||
<Link to='/timelines/public/local' className='drawer__tab' title={intl.formatMessage(messages.community)}><i role="img" aria-label={intl.formatMessage(messages.community)} className='fa fa-fw fa-users' /></Link> | |||||
<Link to='/timelines/public' className='drawer__tab' title={intl.formatMessage(messages.public)}><i role="img" aria-label={intl.formatMessage(messages.public)} className='fa fa-fw fa-globe' /></Link> | |||||
<a href='/settings/preferences' className='drawer__tab' title={intl.formatMessage(messages.preferences)}><i role="img" aria-label={intl.formatMessage(messages.preferences)} className='fa fa-fw fa-cog' /></a> | |||||
<a href='/auth/sign_out' className='drawer__tab' data-method='delete' title={intl.formatMessage(messages.logout)}><i role="img" aria-label={intl.formatMessage(messages.logout)} className='fa fa-fw fa-sign-out' /></a> | |||||
<Link to='/getting-started' className='drawer__tab' title={intl.formatMessage(messages.start)}><i role='img' aria-label={intl.formatMessage(messages.start)} className='fa fa-fw fa-asterisk' /></Link> | |||||
<Link to='/timelines/public/local' className='drawer__tab' title={intl.formatMessage(messages.community)}><i role='img' aria-label={intl.formatMessage(messages.community)} className='fa fa-fw fa-users' /></Link> | |||||
<Link to='/timelines/public' className='drawer__tab' title={intl.formatMessage(messages.public)}><i role='img' aria-label={intl.formatMessage(messages.public)} className='fa fa-fw fa-globe' /></Link> | |||||
<a href='/settings/preferences' className='drawer__tab' title={intl.formatMessage(messages.preferences)}><i role='img' aria-label={intl.formatMessage(messages.preferences)} className='fa fa-fw fa-cog' /></a> | |||||
<a href='/auth/sign_out' className='drawer__tab' data-method='delete' title={intl.formatMessage(messages.logout)}><i role='img' aria-label={intl.formatMessage(messages.logout)} className='fa fa-fw fa-sign-out' /></a> | |||||
</div> | </div> | ||||
); | ); | ||||
} | } | ||||
@@ -94,9 +94,9 @@ class GettingStarted extends ImmutablePureComponent { | |||||
id='getting_started.support' | id='getting_started.support' | ||||
defaultMessage='{faq} • {userguide} • {apps}' | defaultMessage='{faq} • {userguide} • {apps}' | ||||
values={{ | values={{ | ||||
faq: <a href="https://github.com/tootsuite/documentation/blob/master/Using-Mastodon/FAQ.md" rel="noopener" target="_blank"><FormattedMessage id='getting_started.faq' defaultMessage='FAQ' /></a>, | |||||
userguide: <a href="https://github.com/tootsuite/documentation/blob/master/Using-Mastodon/User-guide.md" rel="noopener" target="_blank"><FormattedMessage id='getting_started.userguide' defaultMessage='User Guide' /></a>, | |||||
apps: <a href="https://github.com/tootsuite/documentation/blob/master/Using-Mastodon/Apps.md" rel="noopener" target="_blank"><FormattedMessage id='getting_started.appsshort' defaultMessage='Apps' /></a>, | |||||
faq: <a href='https://github.com/tootsuite/documentation/blob/master/Using-Mastodon/FAQ.md' rel='noopener' target='_blank'><FormattedMessage id='getting_started.faq' defaultMessage='FAQ' /></a>, | |||||
userguide: <a href='https://github.com/tootsuite/documentation/blob/master/Using-Mastodon/User-guide.md' rel='noopener' target='_blank'><FormattedMessage id='getting_started.userguide' defaultMessage='User Guide' /></a>, | |||||
apps: <a href='https://github.com/tootsuite/documentation/blob/master/Using-Mastodon/Apps.md' rel='noopener' target='_blank'><FormattedMessage id='getting_started.appsshort' defaultMessage='Apps' /></a>, | |||||
}} | }} | ||||
/> | /> | ||||
</p> | </p> | ||||
@@ -104,7 +104,7 @@ class GettingStarted extends ImmutablePureComponent { | |||||
<FormattedMessage | <FormattedMessage | ||||
id='getting_started.open_source_notice' | id='getting_started.open_source_notice' | ||||
defaultMessage='Mastodon is open source software. You can contribute or report issues on GitHub at {github}.' | defaultMessage='Mastodon is open source software. You can contribute or report issues on GitHub at {github}.' | ||||
values={{ github: <a href="https://github.com/tootsuite/mastodon" rel="noopener" target="_blank">tootsuite/mastodon</a> }} | |||||
values={{ github: <a href='https://github.com/tootsuite/mastodon' rel='noopener' target='_blank'>tootsuite/mastodon</a> }} | |||||
/> | /> | ||||
</p> | </p> | ||||
</div> | </div> | ||||
@@ -59,7 +59,7 @@ class HomeTimeline extends React.PureComponent { | |||||
let emptyMessage; | let emptyMessage; | ||||
if (hasFollows) { | if (hasFollows) { | ||||
emptyMessage = <FormattedMessage id='empty_column.home.inactivity' defaultMessage="Your home feed is empty. If you have been inactive for a while, it will be regenerated for you soon." />; | |||||
emptyMessage = <FormattedMessage id='empty_column.home.inactivity' defaultMessage='Your home feed is empty. If you have been inactive for a while, it will be regenerated for you soon.' />; | |||||
} else { | } else { | ||||
emptyMessage = <FormattedMessage id='empty_column.home' defaultMessage="You aren't following anyone yet. Visit {public} or use search to get started and meet other users." values={{ public: <Link to='/timelines/public'><FormattedMessage id='empty_column.home.public_timeline' defaultMessage='the public timeline' /></Link> }} />; | emptyMessage = <FormattedMessage id='empty_column.home' defaultMessage="You aren't following anyone yet. Visit {public} or use search to get started and meet other users." values={{ public: <Link to='/timelines/public'><FormattedMessage id='empty_column.home.public_timeline' defaultMessage='the public timeline' /></Link> }} />; | ||||
} | } | ||||
@@ -84,7 +84,7 @@ class ActionBar extends React.PureComponent { | |||||
<div className='detailed-status__button'><IconButton animate={true} active={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' onClick={this.handleFavouriteClick} activeStyle={{ color: '#ca8f04' }} /></div> | <div className='detailed-status__button'><IconButton animate={true} active={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' onClick={this.handleFavouriteClick} activeStyle={{ color: '#ca8f04' }} /></div> | ||||
<div className='detailed-status__action-bar-dropdown'> | <div className='detailed-status__action-bar-dropdown'> | ||||
<DropdownMenu size={18} icon='ellipsis-h' items={menu} direction="left" ariaLabel="More" /> | |||||
<DropdownMenu size={18} icon='ellipsis-h' items={menu} direction='left' ariaLabel='More' /> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
); | ); | ||||
@@ -121,7 +121,7 @@ class UI extends React.PureComponent { | |||||
<TabsBar /> | <TabsBar /> | ||||
<ColumnsAreaContainer singleColumn={isMobile(width)}>{children}</ColumnsAreaContainer> | <ColumnsAreaContainer singleColumn={isMobile(width)}>{children}</ColumnsAreaContainer> | ||||
<NotificationsContainer /> | <NotificationsContainer /> | ||||
<LoadingBarContainer className="loading-bar" /> | |||||
<LoadingBarContainer className='loading-bar' /> | |||||
<ModalContainer /> | <ModalContainer /> | ||||
<UploadArea active={draggingOver} onClose={this.closeUploadModal} /> | <UploadArea active={draggingOver} onClose={this.closeUploadModal} /> | ||||
</div> | </div> | ||||
@@ -1,5 +1,6 @@ | |||||
/*eslint eqeqeq: "off"*/ | /*eslint eqeqeq: "off"*/ | ||||
/*eslint no-nested-ternary: "off"*/ | /*eslint no-nested-ternary: "off"*/ | ||||
/*eslint quotes: "off"*/ | |||||
export default [{ | export default [{ | ||||
locale: "oc", | locale: "oc", | ||||
@@ -10,7 +10,7 @@ module.exports = merge(devConfig, { | |||||
devServer: { | devServer: { | ||||
host: env.LOCAL_DOMAIN ? '0.0.0.0' : devServer.host, | host: env.LOCAL_DOMAIN ? '0.0.0.0' : devServer.host, | ||||
port: devServer.port, | port: devServer.port, | ||||
headers: { "Access-Control-Allow-Origin": "*" }, | |||||
headers: { 'Access-Control-Allow-Origin': '*' }, | |||||
compress: true, | compress: true, | ||||
historyApiFallback: true, | historyApiFallback: true, | ||||
contentBase: resolve(paths.output, paths.entry), | contentBase: resolve(paths.output, paths.entry), | ||||
@@ -30,7 +30,7 @@ locales.forEach(locale => { | |||||
// then check locales/locale-data | // then check locales/locale-data | ||||
`../../app/javascript/mastodon/locales/locale-data/${baseLocale}.js`, | `../../app/javascript/mastodon/locales/locale-data/${baseLocale}.js`, | ||||
// fall back to English (this is what react-intl does anyway) | // fall back to English (this is what react-intl does anyway) | ||||
`../../node_modules/react-intl/locale-data/en.js`, | |||||
'../../node_modules/react-intl/locale-data/en.js', | |||||
].filter(filename => fs.existsSync(path.join(outPath, filename))) | ].filter(filename => fs.existsSync(path.join(outPath, filename))) | ||||
.map(filename => filename.replace(/..\/..\/node_modules\//, ''))[0]; | .map(filename => filename.replace(/..\/..\/node_modules\//, ''))[0]; | ||||
@@ -34,11 +34,11 @@ const validateLanguages = function (languages, validators) { | |||||
}, []); | }, []); | ||||
if (invalidLanguages.length > 0) { | if (invalidLanguages.length > 0) { | ||||
console.log(`\nError: Specified invalid LANGUAGES:`); | |||||
console.log('\nError: Specified invalid LANGUAGES:'); | |||||
for (let { language, error } of invalidLanguages) { | for (let { language, error } of invalidLanguages) { | ||||
console.error(`* ${language}: ${error}`); | console.error(`* ${language}: ${error}`); | ||||
} | } | ||||
console.log(`\nUse yarn "manage:translations -- --help" for usage information\n`); | |||||
console.log('\nUse yarn "manage:translations -- --help" for usage information\n'); | |||||
process.exit(1); | process.exit(1); | ||||
} | } | ||||
}; | }; | ||||
@@ -95,7 +95,7 @@ if (argv.help) { | |||||
// check if message directory exists | // check if message directory exists | ||||
if (!fs.existsSync(`${process.cwd()}/${messagesDirectory}`)) { | if (!fs.existsSync(`${process.cwd()}/${messagesDirectory}`)) { | ||||
console.error(`\nError: messageDirectory not exists\n(${process.cwd()}/${messagesDirectory})\n`); | console.error(`\nError: messageDirectory not exists\n(${process.cwd()}/${messagesDirectory})\n`); | ||||
console.error(`Try to run "yarn build:development" first`); | |||||
console.error('Try to run "yarn build:development" first'); | |||||
process.exit(1); | process.exit(1); | ||||
} | } | ||||
@@ -13,8 +13,8 @@ describe('<Column />', () => { | |||||
it('runs the scroll animation if the column contains scrollable content', () => { | it('runs the scroll animation if the column contains scrollable content', () => { | ||||
const wrapper = mount( | const wrapper = mount( | ||||
<Column heading="notifications"> | |||||
<div className="scrollable" /> | |||||
<Column heading='notifications'> | |||||
<div className='scrollable' /> | |||||
</Column> | </Column> | ||||
); | ); | ||||
wrapper.find(ColumnHeader).simulate('click'); | wrapper.find(ColumnHeader).simulate('click'); | ||||
@@ -22,7 +22,7 @@ describe('<Column />', () => { | |||||
}); | }); | ||||
it('does not try to scroll if there is no scrollable content', () => { | it('does not try to scroll if there is no scrollable content', () => { | ||||
const wrapper = mount(<Column heading="notifications" />); | |||||
const wrapper = mount(<Column heading='notifications' />); | |||||
wrapper.find(ColumnHeader).simulate('click'); | wrapper.find(ColumnHeader).simulate('click'); | ||||
expect(global.requestAnimationFrame.called).to.equal(false); | expect(global.requestAnimationFrame.called).to.equal(false); | ||||
}); | }); | ||||