commit ed5dfa9f4bf2a870092596eb26c760f6b8701df5
parent 02877714b77962cc72ea78489b89bdb4c0d468ff
Author: Vladimir Kutepov <frenzzy.man@gmail.com>
Date: Fri, 10 Feb 2017 18:33:45 +0300
Reenable ESLint rules in accordance to Airbnb style guide (#1126)
Diffstat:
15 files changed, 88 insertions(+), 56 deletions(-)
diff --git a/package.json b/package.json
@@ -162,17 +162,10 @@
"browser": true
},
"rules": {
- "arrow-parens": "off",
- "generator-star-spacing": "off",
"import/extensions": "off",
"import/no-extraneous-dependencies": "off",
- "react/forbid-prop-types": "off",
"react/jsx-filename-extension": "off",
- "react/no-array-index-key": "off",
- "react/no-danger": "off",
- "react/no-unused-prop-types": "off",
- "react/prefer-stateless-function": "off",
- "react/require-default-props": "off"
+ "react/prefer-stateless-function": "off"
}
},
"stylelint": {
diff --git a/src/components/Header/Header.js b/src/components/Header/Header.js
@@ -20,7 +20,7 @@ class Header extends React.Component {
return (
<div className={s.root}>
<div className={s.container}>
- <Navigation className={s.nav} />
+ <Navigation />
<Link className={s.brand} to="/">
<img src={logoUrl} srcSet={`${logoUrl2x} 2x`} width="38" height="38" alt="React" />
<span className={s.brandTxt}>Your Company</span>
diff --git a/src/components/Html.js b/src/components/Html.js
@@ -14,13 +14,21 @@ class Html extends React.Component {
static propTypes = {
title: PropTypes.string.isRequired,
description: PropTypes.string.isRequired,
- style: PropTypes.string,
+ styles: PropTypes.arrayOf(PropTypes.shape({
+ id: PropTypes.string.isRequired,
+ cssText: PropTypes.string.isRequired,
+ }).isRequired),
scripts: PropTypes.arrayOf(PropTypes.string.isRequired),
- children: PropTypes.string,
+ children: PropTypes.string.isRequired,
+ };
+
+ static defaultProps = {
+ styles: [],
+ scripts: [],
};
render() {
- const { title, description, style, scripts, children } = this.props;
+ const { title, description, styles, scripts, children } = this.props;
return (
<html className="no-js" lang="en">
<head>
@@ -30,13 +38,25 @@ class Html extends React.Component {
<meta name="description" content={description} />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="apple-touch-icon" href="apple-touch-icon.png" />
- {style && <style id="css" dangerouslySetInnerHTML={{ __html: style }} />}
+ {styles.map(style =>
+ <style
+ key={style.id}
+ id={style.id}
+ // eslint-disable-next-line react/no-danger
+ dangerouslySetInnerHTML={{ __html: style.cssText }}
+ />,
+ )}
</head>
<body>
- <div id="app" dangerouslySetInnerHTML={{ __html: children }} />
- {scripts && scripts.map(script => <script key={script} src={script} />)}
+ <div
+ id="app"
+ // eslint-disable-next-line react/no-danger
+ dangerouslySetInnerHTML={{ __html: children }}
+ />
+ {scripts.map(script => <script key={script} src={script} />)}
{analytics.google.trackingId &&
<script
+ // eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html:
'window.ga=function(){ga.q.push(arguments)};ga.q=[];ga.l=+new Date;' +
`ga('create','${analytics.google.trackingId}','auto');ga('send','pageview')` }}
diff --git a/src/components/Link/Link.js b/src/components/Link/Link.js
@@ -21,10 +21,14 @@ function isModifiedEvent(event) {
class Link extends React.Component {
static propTypes = {
to: PropTypes.string.isRequired,
- children: PropTypes.node,
+ children: PropTypes.node.isRequired,
onClick: PropTypes.func,
};
+ static defaultProps = {
+ onClick: null,
+ };
+
handleClick = (event) => {
if (this.props.onClick) {
this.props.onClick(event);
diff --git a/src/components/Navigation/Navigation.css b/src/components/Navigation/Navigation.css
@@ -8,7 +8,8 @@
*/
.root {
- margin: 0;
+ float: right;
+ margin: 6px 0 0;
}
.link {
diff --git a/src/components/Navigation/Navigation.js b/src/components/Navigation/Navigation.js
@@ -7,20 +7,16 @@
* LICENSE.txt file in the root directory of this source tree.
*/
-import React, { PropTypes } from 'react';
+import React from 'react';
import cx from 'classnames';
import withStyles from 'isomorphic-style-loader/lib/withStyles';
import s from './Navigation.css';
import Link from '../Link';
class Navigation extends React.Component {
- static propTypes = {
- className: PropTypes.string,
- };
-
render() {
return (
- <div className={cx(s.root, this.props.className)} role="navigation">
+ <div className={s.root} role="navigation">
<Link className={s.link} to="/about">About</Link>
<Link className={s.link} to="/contact">Contact</Link>
<span className={s.spacer}> | </span>
diff --git a/src/components/Page/Page.js b/src/components/Page/Page.js
@@ -13,7 +13,7 @@ import s from './Page.css';
class Page extends React.Component {
static propTypes = {
- title: PropTypes.string,
+ title: PropTypes.string.isRequired,
html: PropTypes.string.isRequired,
};
@@ -22,8 +22,11 @@ class Page extends React.Component {
return (
<div className={s.root}>
<div className={s.container}>
- {title && <h1>{title}</h1>}
- <div dangerouslySetInnerHTML={{ __html: html }} />
+ <h1>{title}</h1>
+ <div
+ // eslint-disable-next-line react/no-danger
+ dangerouslySetInnerHTML={{ __html: html }}
+ />
</div>
</div>
);
diff --git a/src/data/queries/news.js b/src/data/queries/news.js
@@ -30,7 +30,7 @@ const news = {
lastFetchTime = new Date();
lastFetchTask = fetch(url)
.then(response => response.json())
- .then(data => {
+ .then((data) => {
if (data.status === 'ok') {
items = data.items;
}
diff --git a/src/routes/error/ErrorPage.js b/src/routes/error/ErrorPage.js
@@ -13,7 +13,11 @@ import s from './ErrorPage.css';
class ErrorPage extends React.Component {
static propTypes = {
- error: PropTypes.object.isRequired,
+ error: PropTypes.shape({
+ name: PropTypes.string.isRequired,
+ message: PropTypes.string.isRequired,
+ stack: PropTypes.string.isRequired,
+ }).isRequired,
};
render() {
diff --git a/src/routes/home/Home.css b/src/routes/home/Home.css
@@ -20,20 +20,30 @@
max-width: var(--max-content-width);
}
-.news {
- padding: 0;
-}
-
.newsItem {
- list-style-type: none;
- padding-bottom: 6px;
+ margin: 0 0 2rem;
}
.newsTitle {
- font-size: 1.125em;
+ font-size: 1.5rem;
}
-.newsTitle,
.newsDesc {
- display: block;
+ h1,
+ h2,
+ h3,
+ h4,
+ h5,
+ h6 {
+ font-size: 1.125rem;
+ }
+
+ pre {
+ white-space: pre-wrap;
+ font-size: 0.875rem;
+ }
+
+ img {
+ max-width: 100%;
+ }
}
diff --git a/src/routes/home/Home.js b/src/routes/home/Home.js
@@ -25,17 +25,16 @@ class Home extends React.Component {
<div className={s.root}>
<div className={s.container}>
<h1>React.js News</h1>
- <ul className={s.news}>
- {this.props.news.map((item, index) => (
- <li key={index} className={s.newsItem}>
- <a href={item.link} className={s.newsTitle}>{item.title}</a>
- <span
- className={s.newsDesc}
- dangerouslySetInnerHTML={{ __html: item.content.substring(0, 100) }}
- />
- </li>
- ))}
- </ul>
+ {this.props.news.map(item => (
+ <article key={item.link} className={s.newsItem}>
+ <h1 className={s.newsTitle}><a href={item.link}>{item.title}</a></h1>
+ <div
+ className={s.newsDesc}
+ // eslint-disable-next-line react/no-danger
+ dangerouslySetInnerHTML={{ __html: item.content }}
+ />
+ </article>
+ ))}
</div>
</div>
);
diff --git a/src/server.js b/src/server.js
@@ -112,7 +112,9 @@ app.get('*', async (req, res, next) => {
const data = { ...route };
data.children = ReactDOM.renderToString(<App context={context}>{route.component}</App>);
- data.style = [...css].join('');
+ data.styles = [
+ { id: 'css', cssText: [...css].join('') },
+ ];
data.scripts = [
assets.vendor.js,
assets.client.js,
@@ -142,7 +144,7 @@ app.use((err, req, res, next) => { // eslint-disable-line no-unused-vars
<Html
title="Internal Server Error"
description={err.message}
- style={errorPageStyle._getCss()} // eslint-disable-line no-underscore-dangle
+ styles={[{ id: 'css', cssText: errorPageStyle._getCss() }]} // eslint-disable-line no-underscore-dangle
>
{ReactDOM.renderToString(<ErrorPageWithoutStyle error={err} />)}
</Html>,
diff --git a/tools/lib/fs.js b/tools/lib/fs.js
@@ -13,7 +13,7 @@ import glob from 'glob';
import mkdirp from 'mkdirp';
import rimraf from 'rimraf';
-export const readFile = (file) => new Promise((resolve, reject) => {
+export const readFile = file => new Promise((resolve, reject) => {
fs.readFile(file, 'utf8', (err, data) => (err ? reject(err) : resolve(data)));
});
@@ -46,7 +46,7 @@ export const readDir = (pattern, options) => new Promise((resolve, reject) =>
glob(pattern, options, (err, result) => (err ? reject(err) : resolve(result))),
);
-export const makeDir = (name) => new Promise((resolve, reject) => {
+export const makeDir = name => new Promise((resolve, reject) => {
mkdirp(name, err => (err ? reject(err) : resolve()));
});
@@ -56,7 +56,7 @@ export const copyDir = async (source, target) => {
nosort: true,
dot: true,
});
- await Promise.all(dirs.map(async dir => {
+ await Promise.all(dirs.map(async (dir) => {
const from = path.resolve(source, dir);
const to = path.resolve(target, dir);
await makeDir(path.dirname(to));
diff --git a/tools/run.js b/tools/run.js
@@ -17,7 +17,7 @@ function run(fn, options) {
console.log(
`[${format(start)}] Starting '${task.name}${options ? ` (${options})` : ''}'...`,
);
- return task(options).then(resolution => {
+ return task(options).then((resolution) => {
const end = new Date();
const time = end.getTime() - start.getTime();
console.log(
@@ -30,7 +30,7 @@ function run(fn, options) {
if (require.main === module && process.argv.length > 2) {
delete require.cache[__filename]; // eslint-disable-line no-underscore-dangle
const module = require(`./${process.argv[2]}.js`).default; // eslint-disable-line import/no-dynamic-require
- run(module).catch(err => { console.error(err.stack); process.exit(1); });
+ run(module).catch((err) => { console.error(err.stack); process.exit(1); });
}
export default run;
diff --git a/tools/runServer.js b/tools/runServer.js
@@ -21,7 +21,7 @@ const serverPath = path.join(output.path, output.filename);
// Launch or restart the Node.js server
function runServer() {
- return new Promise(resolve => {
+ return new Promise((resolve) => {
function onStdOut(data) {
const time = new Date().toTimeString();
const match = data.toString('utf8').match(RUNNING_REGEXP);