Merge pull request #33 from abisz/linting

Linting
This commit is contained in:
Alexander S 2017-03-08 22:49:29 +02:00 committed by GitHub
commit c8e68a2138
16 changed files with 413 additions and 400 deletions

19
.eslintrc Normal file
View File

@ -0,0 +1,19 @@
{
"extends": "airbnb",
"plugins": [
"react",
"jsx-a11y",
"import"
],
"rules": {
"global-require": [0],
"react/jsx-filename-extension": [0],
"react/prefer-es6-class": [0],
"react/prefer-stateless-function": [0],
"react/forbid-prop-types": [0],
/* to allow importing 'gatsby-helpers' */
"import/no-extraneous-dependencies": [0],
"import/no-unresolved": [0],
"import/extensions": [0]
}
}

4
.gitignore vendored
View File

@ -1,4 +1,8 @@
node_modules/ node_modules/
npm-debug.log
.eslintcache
public public
.gatsby-context.js .gatsby-context.js

View File

@ -1,44 +1,48 @@
import React from 'react' import React from 'react';
import { Link } from 'react-router' import { Link } from 'react-router';
import { prune, include as includes } from 'underscore.string' import { include as includes } from 'underscore.string';
import find from 'lodash/find' import find from 'lodash/find';
import './style.css' import './style.css';
class ReadNext extends React.Component { class ReadNext extends React.Component {
render() { render() {
const {post} = this.props const { post } = this.props;
const {pages} = this.props.route const { pages } = this.props.route;
const {readNext} = post const { readNext } = post;
let nextPost let nextPost;
if (readNext) { if (readNext) {
nextPost = find(pages, (page) => includes(page.path, readNext) nextPost = find(pages, page => includes(page.path, readNext));
)
} }
if (!nextPost) { if (!nextPost) {
return React.createElement('noscript', null) return React.createElement('noscript', null);
} else { }
nextPost = find(pages, (page) => includes(page.path, readNext.slice(1, -1))
) nextPost = find(pages, page => includes(page.path, readNext.slice(1, -1)));
const description = nextPost.data.description const description = nextPost.data.description;
return ( return (
<div> <div>
<h6 style={ { fontSize: '16px', margin: '20px 0 0'} }>READ THIS NEXT:</h6> <h6 style={{ fontSize: '16px', margin: '20px 0 0' }}>READ THIS NEXT:</h6>
<h3 style={ { margin: '5px 0 0'} }><Link to={ nextPost.path } query={ { readNext: true} } > { nextPost.data.title } </Link></h3> <h3 style={{ margin: '5px 0 0' }}>
<p className='description'> <Link to={nextPost.path} query={{ readNext: true }}>
{ description } {nextPost.data.title}
</Link>
</h3>
<p className="description">
{description}
</p> </p>
</div> </div>
); );
} }
}
} }
ReadNext.propTypes = { ReadNext.propTypes = {
post: React.PropTypes.object.isRequired, post: React.PropTypes.object.isRequired,
pages: React.PropTypes.array, pages: React.PropTypes.array,
} route: React.PropTypes.object,
};
export default ReadNext;
export default ReadNext

View File

@ -1,13 +1,10 @@
import React from 'react' import React from 'react';
import { RouteHandler, Link } from 'react-router' import { config } from 'config';
import { prefixLink } from 'gatsby-helpers' import './style.css';
import { config } from 'config' import '../../static/fonts/fontawesome/style.css';
import './style.css'
import '../../static/fonts/fontawesome/style.css'
class SiteLinks extends React.Component { class SiteLinks extends React.Component {
render () { render() {
return ( return (
<div className="blog-links"> <div className="blog-links">
<ul> <ul>
@ -55,8 +52,8 @@ class SiteLinks extends React.Component {
)} )}
</ul> </ul>
</div> </div>
) );
} }
} }
export default SiteLinks export default SiteLinks;

View File

@ -1,24 +1,23 @@
import React from 'react' import React from 'react';
import { RouteHandler, Link } from 'react-router' import { Link } from 'react-router';
import { prefixLink } from 'gatsby-helpers' import { prefixLink } from 'gatsby-helpers';
import './style.css' import './style.css';
class SiteNav extends React.Component { class SiteNav extends React.Component {
render() { render() {
const {location} = this.props
return ( return (
<nav className='blog-nav'> <nav className="blog-nav">
<ul> <ul>
<li> <li>
<Link to={ prefixLink('/')} activeClassName="current" onlyActiveOnIndex> Articles <Link to={prefixLink('/')} activeClassName="current" onlyActiveOnIndex> Articles
</Link> </Link>
</li> </li>
<li> <li>
<Link to={ prefixLink('/about/')} activeClassName="current"> About me <Link to={prefixLink('/about/')} activeClassName="current"> About me
</Link> </Link>
</li> </li>
<li> <li>
<Link to={ prefixLink('/contact/')} activeClassName="current"> Contact me <Link to={prefixLink('/contact/')} activeClassName="current"> Contact me
</Link> </Link>
</li> </li>
</ul> </ul>
@ -27,8 +26,4 @@ class SiteNav extends React.Component {
} }
} }
SiteNav.propTypes = { export default SiteNav;
location: React.PropTypes.object,
}
export default SiteNav

View File

@ -1,27 +1,22 @@
import React from 'react' import React from 'react';
import moment from 'moment' import SiteSidebar from '../SiteSidebar';
import { RouteHandler, Link } from 'react-router'
import { prefixLink } from 'gatsby-helpers'
import access from 'safe-access'
import { config } from 'config'
import SiteSidebar from '../SiteSidebar'
import './style.css'; import './style.css';
class SitePage extends React.Component { class SitePage extends React.Component {
render() { render() {
const {route} = this.props const { route } = this.props;
const post = route.page.data const post = route.page.data;
return ( return (
<div> <div>
<SiteSidebar {...this.props}/> <SiteSidebar {...this.props} />
<div className='content'> <div className="content">
<div className='main'> <div className="main">
<div className='main-inner'> <div className="main-inner">
<div className='blog-page'> <div className="blog-page">
<div className='text'> <div className="text">
<h1>{ post.title }</h1> <h1>{post.title}</h1>
<div dangerouslySetInnerHTML={ { __html: post.body} } /> <div dangerouslySetInnerHTML={{ __html: post.body }} />
</div> </div>
</div> </div>
</div> </div>
@ -34,6 +29,6 @@ class SitePage extends React.Component {
SitePage.propTypes = { SitePage.propTypes = {
route: React.PropTypes.object.isRequired, route: React.PropTypes.object.isRequired,
} };
export default SitePage export default SitePage;

View File

@ -1,42 +1,41 @@
import React from 'react' import React from 'react';
import moment from 'moment' import moment from 'moment';
import { RouteHandler, Link } from 'react-router' import { Link } from 'react-router';
import { prefixLink } from 'gatsby-helpers' import { prefixLink } from 'gatsby-helpers';
import access from 'safe-access' import { config } from 'config';
import { config } from 'config' import ReadNext from '../ReadNext';
import ReadNext from '../ReadNext' import './style.css';
import './style.css' import '../../static/css/highlight.css';
import '../../static/css/highlight.css'
class SitePost extends React.Component { class SitePost extends React.Component {
render() { render() {
const {route} = this.props const { route } = this.props;
const post = route.page.data const post = route.page.data;
const home = ( const home = (
<div> <div>
<Link className='gohome' to={ prefixLink('/') }> All Articles <Link className="gohome" to={prefixLink('/')}>All Articles</Link>
</Link>
</div> </div>
) );
return ( return (
<div> <div>
{ home } {home}
<div className='blog-single'> <div className="blog-single">
<div className='text'> <div className="text">
<h1>{ post.title }</h1> <h1>{post.title}</h1>
<div dangerouslySetInnerHTML={ { __html: post.body} } /> <div dangerouslySetInnerHTML={{ __html: post.body }} />
<div className='date-published'> <div className="date-published">
<em>Published { moment(post.date).format('D MMM YYYY') }</em> <em>Published {moment(post.date).format('D MMM YYYY')}</em>
</div> </div>
</div> </div>
<div className='footer'> <div className="footer">
<ReadNext post={ post } {...this.props}/> <ReadNext post={post} {...this.props} />
<hr></hr> <hr />
<p> <p>
{ config.siteDescr } {config.siteDescr}
<a href={ config.siteTwitterUrl }> <a href={config.siteTwitterUrl}>
<br></br> <strong>{ config.siteAuthor }</strong> on Twitter</a> <br /> <strong>{config.siteAuthor}</strong> on Twitter
</a>
</p> </p>
</div> </div>
</div> </div>
@ -46,7 +45,7 @@ class SitePost extends React.Component {
} }
SitePost.propTypes = { SitePost.propTypes = {
route: React.PropTypes.object.isRequired route: React.PropTypes.object.isRequired,
} };
export default SitePost export default SitePost;

View File

@ -1,45 +1,51 @@
import React from 'react' import React from 'react';
import { RouteHandler, Link } from 'react-router' import { Link } from 'react-router';
import { prefixLink } from 'gatsby-helpers' import { prefixLink } from 'gatsby-helpers';
import { config } from 'config' import { config } from 'config';
import SiteNav from '../SiteNav' import SiteNav from '../SiteNav';
import SiteLinks from '../SiteLinks' import SiteLinks from '../SiteLinks';
import './style.css' import './style.css';
import profilePic from '../../pages/photo.jpg' import profilePic from '../../pages/photo.jpg';
class SiteSidebar extends React.Component { class SiteSidebar extends React.Component {
render() { render() {
const {location, children} = this.props const { location } = this.props;
const isHome = location.pathname === prefixLink('/') const isHome = location.pathname === prefixLink('/');
let header = ( /* eslint-disable jsx-a11y/img-redundant-alt*/
const header = (
<header> <header>
<Link style={ { textDecoration: 'none', borderBottom: 'none', outline: 'none'} } to={ prefixLink('/') }> <Link style={{ textDecoration: 'none', borderBottom: 'none', outline: 'none' }} to={prefixLink('/')}>
<img src={profilePic} width='75' height='75' /> <img
src={profilePic}
width="75" height="75"
alt="Profile picture of the author"
/>
</Link> </Link>
{ isHome ? ( { isHome ? (
<h1><Link style={ { textDecoration: 'none', borderBottom: 'none', color: 'inherit'} } to={ prefixLink('/') }> { config.siteAuthor } </Link></h1> <h1><Link style={{ textDecoration: 'none', borderBottom: 'none', color: 'inherit' }} to={prefixLink('/')}> {config.siteAuthor}</Link></h1>
) : ) :
<h2><Link style={ { textDecoration: 'none', borderBottom: 'none', color: 'inherit'} } to={ prefixLink('/') }> { config.siteAuthor } </Link></h2> } <h2><Link style={{ textDecoration: 'none', borderBottom: 'none', color: 'inherit' }} to={prefixLink('/')}> {config.siteAuthor}</Link></h2> }
<p> <p>
{ config.siteDescr } {config.siteDescr}
</p> </p>
</header> </header>
) );
/* eslint-enable jsx-a11y/img-redundant-alt*/
return ( return (
<div className='sidebar'> <div className="sidebar">
<div className='sidebar-inner'> <div className="sidebar-inner">
<div className='blog-details'> <div className="blog-details">
<header> <header>
{ header } {header}
</header> </header>
</div> </div>
<div className='blog-options'> <div className="blog-options">
<SiteNav {...this.props}/> <SiteNav {...this.props} />
<footer> <footer>
<SiteLinks {...this.props}/> <SiteLinks {...this.props} />
<p className='copyright'> <p className="copyright">
&copy; All rights reserved. &copy; All rights reserved.
</p> </p>
</footer> </footer>
@ -51,8 +57,8 @@ class SiteSidebar extends React.Component {
} }
SiteSidebar.propTypes = { SiteSidebar.propTypes = {
children: React.PropTypes.any,
location: React.PropTypes.object, location: React.PropTypes.object,
} };
export default SiteSidebar;
export default SiteSidebar

View File

@ -1,8 +1,8 @@
import ReactGA from 'react-ga' import ReactGA from 'react-ga';
import {config} from 'config' import { config } from 'config';
ReactGA.initialize(config.googleAnalyticsId); ReactGA.initialize(config.googleAnalyticsId);
exports.onRouteUpdate = (state, page, pages) => { exports.onRouteUpdate = (state) => {
ReactGA.pageview(state.pathname); ReactGA.pageview(state.pathname);
}; };

View File

@ -1,22 +1,22 @@
var rucksack = require('rucksack-css') const rucksack = require('rucksack-css');
var lost = require("lost") const lost = require('lost');
var cssnext = require("postcss-cssnext") const cssnext = require('postcss-cssnext');
exports.modifyWebpackConfig = function(config, env) { exports.modifyWebpackConfig = function (config) {
config.merge({ config.merge({
postcss: [ postcss: [
lost(), lost(),
rucksack(), rucksack(),
cssnext({ cssnext({
browsers: ['>1%', 'last 2 versions'] browsers: ['>1%', 'last 2 versions'],
}) }),
] ],
}) });
config.loader('svg', { config.loader('svg', {
test: /\.(svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, test: /\.(svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: 'file-loader', loader: 'file-loader',
}) });
return config return config;
}; };

27
html.js
View File

@ -1,8 +1,8 @@
import React from 'react' import React from 'react';
import Helmet from 'react-helmet' import Helmet from 'react-helmet';
import { prefixLink } from 'gatsby-helpers' import { prefixLink } from 'gatsby-helpers';
const BUILD_TIME = new Date().getTime() const BUILD_TIME = new Date().getTime();
module.exports = React.createClass({ module.exports = React.createClass({
displayName: 'HTML', displayName: 'HTML',
@ -10,12 +10,13 @@ module.exports = React.createClass({
body: React.PropTypes.string, body: React.PropTypes.string,
}, },
render() { render() {
const {body, route} = this.props const { body } = this.props;
const {title} = Helmet.rewind() const { title } = Helmet.rewind();
const font = <link href='https://fonts.googleapis.com/css?family=Roboto:400,400italic,500,700&subset=latin,cyrillic' rel='stylesheet' type='text/css' /> const font = <link href="https://fonts.googleapis.com/css?family=Roboto:400,400italic,500,700&subset=latin,cyrillic" rel="stylesheet" type="text/css" />;
let css let css;
if (process.env.NODE_ENV === 'production') { if (process.env.NODE_ENV === 'production') {
css = <style dangerouslySetInnerHTML={ { __html: require('!raw!./public/styles.css')} } /> // eslint-disable-next-line import/no-webpack-loader-syntax
css = <style dangerouslySetInnerHTML={{ __html: require('!raw!./public/styles.css') }} />;
} }
return ( return (
@ -29,10 +30,10 @@ module.exports = React.createClass({
{ css } { css }
</head> </head>
<body> <body>
<div id="react-mount" dangerouslySetInnerHTML={ { __html: this.props.body} } /> <div id="react-mount" dangerouslySetInnerHTML={{ __html: this.props.body }} />
<script src={ prefixLink(`/bundle.js?t=${BUILD_TIME}`) } /> <script src={prefixLink(`/bundle.js?t=${BUILD_TIME}`)} />
</body> </body>
</html> </html>
) );
}, },
}) });

View File

@ -10,7 +10,7 @@
"clean": "npm run clean:public", "clean": "npm run clean:public",
"copy:files": "find ./pages -maxdepth 1 -type f -regextype posix-extended -regex '.+\\.(pdf|txt|png|jpg|jpeg|gif)$' -exec cp -v {} ./public ';'", "copy:files": "find ./pages -maxdepth 1 -type f -regextype posix-extended -regex '.+\\.(pdf|txt|png|jpg|jpeg|gif)$' -exec cp -v {} ./public ';'",
"copy": "npm run copy:files", "copy": "npm run copy:files",
"lint": "./node_modules/.bin/eslint --ext .js,.jsx --ignore-pattern public .", "lint": "./node_modules/.bin/eslint --cache --ext .js,.jsx --ignore-pattern public .",
"test": "echo \"Error: no test specified\" && exit 1", "test": "echo \"Error: no test specified\" && exit 1",
"deploy": "gatsby build --prefix-links && gh-pages -d public" "deploy": "gatsby build --prefix-links && gh-pages -d public"
}, },

View File

@ -1,19 +1,16 @@
import React from 'react' import React from 'react';
import { Link } from 'react-router'
import { prefixLink } from 'gatsby-helpers'
import { config } from 'config'
import '../static/css/reset.css' import '../static/css/reset.css';
import '../static/css/typography.css' import '../static/css/typography.css';
import '../static/css/base.css' import '../static/css/base.css';
class Template extends React.Component { class Template extends React.Component {
render() { render() {
const {location, children} = this.props const { children } = this.props;
return ( return (
<div className='wrapper'> <div className="wrapper">
{ children } {children}
</div> </div>
); );
} }
@ -21,8 +18,6 @@ class Template extends React.Component {
Template.propTypes = { Template.propTypes = {
children: React.PropTypes.any, children: React.PropTypes.any,
location: React.PropTypes.object, };
route: React.PropTypes.object,
}
export default Template export default Template;

View File

@ -3,6 +3,7 @@ title: My Second Post!
date: "2015-05-06T23:46:37.121Z" date: "2015-05-06T23:46:37.121Z"
layout: post layout: post
path: "/my-second-post/" path: "/my-second-post/"
readNext: "/hi-folks/"
category: "FrontEnd" category: "FrontEnd"
description: "Civil society; save lives pathway to a better life public-private partnerships solution, tackle, protect UNHCR social movement Jane Addams sustainable campaign respond equality." description: "Civil society; save lives pathway to a better life public-private partnerships solution, tackle, protect UNHCR social movement Jane Addams sustainable campaign respond equality."
--- ---

View File

@ -1,61 +1,58 @@
import React from 'react' import React from 'react';
import { Link } from 'react-router' import { Link } from 'react-router';
import sortBy from 'lodash/sortBy' import sortBy from 'lodash/sortBy';
import moment from 'moment' import moment from 'moment';
import Helmet from 'react-helmet' import Helmet from 'react-helmet';
import { prefixLink } from 'gatsby-helpers' import { prefixLink } from 'gatsby-helpers';
import access from 'safe-access' import access from 'safe-access';
import { config } from 'config' import { config } from 'config';
import SitePost from '../components/SitePost' import SiteSidebar from '../components/SiteSidebar';
import SiteSidebar from '../components/SiteSidebar'
class SiteIndex extends React.Component { class SiteIndex extends React.Component {
render() { render() {
const pageLinks = [] const pageLinks = [];
// Sort pages. // Sort pages.
const sortedPages = sortBy(this.props.route.pages, (page) => access(page, 'data.date') const sortedPages = sortBy(this.props.route.pages, page => access(page, 'data.date')).reverse();
).reverse()
sortedPages.forEach((page) => { sortedPages.forEach((page) => {
if (access(page, 'file.ext') === 'md' && access(page, 'data.layout') === 'post') { if (access(page, 'file.ext') === 'md' && access(page, 'data.layout') === 'post') {
const title = access(page, 'data.title') || page.path const title = access(page, 'data.title') || page.path;
const description = access(page, 'data.description') const description = access(page, 'data.description');
const datePublished = access(page, 'data.date') const datePublished = access(page, 'data.date');
const category = access(page, 'data.category') const category = access(page, 'data.category');
pageLinks.push( pageLinks.push((
<div className='blog-post' key={ title }> <div className="blog-post" key={title}>
<time dateTime={ moment(datePublished).format('MMMM D, YYYY') }> <time dateTime={moment(datePublished).format('MMMM D, YYYY')}>
{ moment(datePublished).format('MMMM YYYY') } {moment(datePublished).format('MMMM YYYY')}
</time> </time>
<span style={ { padding: '5px'} }></span> <span style={{ padding: '5px' }} />
<span className='blog-category'>{ category }</span> <span className="blog-category">{category}</span>
<h2><Link style={ { borderBottom: 'none',} } to={ prefixLink(page.path) } > { title } </Link></h2> <h2><Link style={{ borderBottom: 'none' }} to={prefixLink(page.path)}>{title}</Link></h2>
<p dangerouslySetInnerHTML={ { __html: description} } /> <p dangerouslySetInnerHTML={{ __html: description }} />
<Link className='readmore' to={ prefixLink(page.path) }> Read <Link className="readmore" to={prefixLink(page.path)}>Read</Link>
</Link>
</div> </div>
) ));
} }
}) });
return ( return (
<div> <div>
<Helmet title={ config.siteTitle }/> <Helmet title={config.siteTitle} />
<SiteSidebar {...this.props}/> <SiteSidebar {...this.props} />
<div className='content'> <div className="content">
<div className='main'> <div className="main">
<div className='main-inner'> <div className="main-inner">
{ pageLinks } {pageLinks}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
) );
} }
} }
SiteIndex.propTypes = { SiteIndex.propTypes = {
route: React.PropTypes.object, route: React.PropTypes.object,
} };
export default SiteIndex export default SiteIndex;

View File

@ -1,27 +1,27 @@
import React from 'react' import React from 'react';
import Helmet from 'react-helmet' import Helmet from 'react-helmet';
import SitePost from '../components/SitePost' import { config } from 'config';
import SitePage from '../components/SitePage'
import { config } from 'config' import SitePost from '../components/SitePost';
import SitePage from '../components/SitePage';
class MarkdownWrapper extends React.Component { class MarkdownWrapper extends React.Component {
render() { render() {
const {route} = this.props const { route } = this.props;
const post = route.page.data const post = route.page.data;
let layout, template const layout = post.layout;
let template;
layout = post.layout if (layout !== 'page') {
template = <SitePost {...this.props} />;
if (layout != 'page') {
template = <SitePost {...this.props}/>
} else { } else {
template = <SitePage {...this.props}/> template = <SitePage {...this.props} />;
} }
return ( return (
<div> <div>
<Helmet title={ `${post.title} - ${config.siteTitle}` }/> <Helmet title={`${post.title} - ${config.siteTitle}`} />
{ template } {template}
</div> </div>
); );
} }
@ -29,6 +29,6 @@ class MarkdownWrapper extends React.Component {
MarkdownWrapper.propTypes = { MarkdownWrapper.propTypes = {
route: React.PropTypes.object, route: React.PropTypes.object,
} };
export default MarkdownWrapper export default MarkdownWrapper;