diff --git a/.babelrc b/.babelrc index 005e78a..fd23462 100644 --- a/.babelrc +++ b/.babelrc @@ -1,4 +1,5 @@ { + "plugins": ["transform-class-properties"], "presets": [ "stage-0", "es2015", diff --git a/.eslintrc b/.eslintrc index 0cf4c3d..75f7a6f 100644 --- a/.eslintrc +++ b/.eslintrc @@ -34,9 +34,8 @@ "react/react-in-jsx-scope": 2, "react/no-unknown-property": [2], "react/prop-types": 2, - "react/require-extension": [2, { "extensions": [".js", ".jsx"] }], "react/self-closing-comp": [2], - "react/wrap-multilines": [2], + "react/jsx-wrap-multilines": [2], "semi": [2, "always"], "keyword-spacing": [2, { "before": true, "after": true }], "space-before-blocks": 2, diff --git a/package.json b/package.json index cd32a30..af3f6fa 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "dependencies": { "babel-cli": "^6.4.0", "babel-eslint": "^7.2.1", + "babel-plugin-transform-class-properties": "^6.24.1", "babel-polyfill": "^6.3.14", "babel-preset-es2015": "^6.3.13", "babel-preset-react": "^6.3.13", @@ -44,9 +45,9 @@ "isomorphic-fetch": "^2.2.0", "lodash.debounce": "^4.0.3", "minifyify": "^7.1.0", + "prop-types": "^15.5.9", "react": "^15.0.2", "react-dom": "^15.0.2", - "react-pure-render": "^1.0.2", "remark": "^7.0.0", "remark-html": "^6.0.0", "remark-slug": "^4.1.0", diff --git a/src/components/app.js b/src/components/app.js index c6421a8..00ec793 100644 --- a/src/components/app.js +++ b/src/components/app.js @@ -1,8 +1,8 @@ import React from 'react'; import Navigation from './navigation'; +import PropTypes from 'prop-types'; import Content from './content'; import RoundedToggle from './rounded_toggle'; -import PureRenderMixin from 'react-pure-render/mixin'; import GithubSlugger from 'github-slugger'; import debounce from 'lodash.debounce'; import { brandNames, brandClasses } from '../custom'; @@ -41,13 +41,13 @@ let debouncedReplaceState = debounce(hash => { window.history.replaceState('', '', hash); }, 100); -var App = React.createClass({ - mixins: [PureRenderMixin], - propTypes: { - content: React.PropTypes.string.isRequired, - ast: React.PropTypes.object.isRequired - }, - getInitialState() { +export default class App extends React.PureComponent { + static propTypes = { + content: PropTypes.string.isRequired, + ast: PropTypes.object.isRequired + } + constructor(props) { + super(props); var active = 'Introduction'; if (process.browser) { @@ -70,7 +70,7 @@ var App = React.createClass({ active = headingForHash.children[0].value; } } - return { + this.state = { // media queryMatches mqls: mqls, // object of currently matched queries, like { desktop: true } @@ -82,7 +82,7 @@ var App = React.createClass({ showNav: false }; } else { - return { + this.state = { mqls: { }, queryMatches: { desktop: true @@ -92,17 +92,17 @@ var App = React.createClass({ showNav: false }; } - }, + } toggleNav() { this.setState({ showNav: !this.state.showNav }); - }, + } componentDidMount() { this.mediaQueryChanged(); this.onScroll = debounce(this.onScrollImmediate, 100); document.addEventListener('scroll', this.onScroll); this.onScrollImmediate(); - }, - onScrollImmediate() { + } + onScrollImmediate = () => { var sections = document.querySelectorAll('div.section'); if (!sections.length) return; for (var i = 0; i < sections.length; i++) { @@ -114,7 +114,7 @@ var App = React.createClass({ return; } } - }, + } mediaQueryChanged() { this.setState({ queryMatches: this.state.mqls.reduce((memo, q) => { @@ -122,19 +122,19 @@ var App = React.createClass({ return memo; }, {}) }); - }, + } componentWillUnmount() { this.state.mqls.forEach(q => q.removeListener(this.mediaQueryChanged)); document.body.removeEventListener('scroll', this.onScroll); - }, - onChangeLanguage(language) { + } + onChangeLanguage = (language) => { this.setState({ language }, () => { if (window.history) { window.history.pushState(null, null, `?${qs.stringify({ language: language.title })}${window.location.hash}`); } }); - }, + } componentDidUpdate(_, prevState) { if (prevState.activeSection !== this.state.activeSection) { // when the section changes, replace the hash @@ -144,7 +144,7 @@ var App = React.createClass({ // when the language changes, use the hash to set scroll window.location.hash = window.location.hash; } - }, + } navigationItemClicked(activeSection) { setTimeout(() => { this.setState({ activeSection }); @@ -152,12 +152,12 @@ var App = React.createClass({ if (!this.state.queryMatches.desktop) { this.toggleNav(); } - }, + } toggleColumnMode() { this.setState({ columnMode: this.state.columnMode === 1 ? 2 : 1 }); - }, + } render() { let ast = JSON.parse(JSON.stringify(this.props.ast)); let { activeSection, queryMatches, showNav, columnMode } = this.state; @@ -237,6 +237,4 @@ var App = React.createClass({ ); } -}); - -module.exports = App; +} diff --git a/src/components/content.js b/src/components/content.js index 93d6178..6c6195c 100644 --- a/src/components/content.js +++ b/src/components/content.js @@ -1,14 +1,14 @@ import React from 'react'; +import PropTypes from 'prop-types'; import Section from './section'; -import PureRenderMixin from 'react-pure-render/mixin'; import GithubSlugger from 'github-slugger'; import { transformURL } from '../custom'; let slugger = new GithubSlugger(); let slug = title => { slugger.reset(); return slugger.slug(title); }; -var roundedToggleOptionType = React.PropTypes.shape({ - title: React.PropTypes.string, - value: React.PropTypes.string +var roundedToggleOptionType = PropTypes.shape({ + title: PropTypes.string, + value: PropTypes.string }); function chunkifyAST(ast, language) { @@ -71,24 +71,21 @@ function chunkifyAST(ast, language) { }); } -var Content = React.createClass({ - mixins: [PureRenderMixin], - propTypes: { - ast: React.PropTypes.object.isRequired, +export default class Content extends React.PureComponent { + static propTypes = { + ast: PropTypes.object.isRequired, language: roundedToggleOptionType, - leftClassname: React.PropTypes.string.isRequired, - rightClassname: React.PropTypes.string.isRequired - }, + leftClassname: PropTypes.string.isRequired, + rightClassname: PropTypes.string.isRequired + } render() { let { ast, language, leftClassname, rightClassname } = this.props; return (