diff --git a/.all-contributorsrc b/.all-contributorsrc
index 77967d7..2c38b22 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -28,6 +28,18 @@
"code",
"ideas"
]
+ },
+ {
+ "login": "simon300000",
+ "name": "simon3000",
+ "avatar_url": "https://avatars1.githubusercontent.com/u/12656264?v=4",
+ "profile": "https://github.com/simon300000",
+ "contributions": [
+ "code",
+ "ideas",
+ "translation"
+ ]
}
- ]
+ ],
+ "repoType": "github"
}
diff --git a/.eslintrc b/.eslintrc
index 9971537..b6ba07b 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -7,10 +7,17 @@
"mocha": true
},
"extends": ["kotori"],
+ "plugins": ["prettier"],
"globals": {
"autobind": true
},
"rules": {
- "new-cap": 0
+ "new-cap": 0,
+ "prettier/prettier": [1, {
+ "singleQuote": true,
+ "trailingComma": "none",
+ "bracketSpacing": true,
+ "jsxBracketSameLine": true
+ }]
}
}
diff --git a/README.md b/README.md
index 0a33a30..ac76cab 100644
--- a/README.md
+++ b/README.md
@@ -20,6 +20,7 @@ Table of Contents
* [Dev](#dev)
* [Commands](#commands)
* [API](#api)
+ * [Localization](#localization)
* [Contribute](#contribute)
* [Contributors](#contributors)
* [License](#license)
@@ -63,12 +64,12 @@ A: Pixiv change the `REFRESH TOKEN` auth method, so re-login with refresh_token
# Start for development
$ git clone https://github.com/LoveLiveSunshine/pixiv.moe
$ cd pixiv.moe
-$ npm install
+$ yarn
$ npm start
```
### Commands
-- Install dependencies: `npm install`
+- Install dependencies: `yarn`
- Run: `npm start`
- Test: `npm test`
- Build: `npm run dist`
@@ -539,16 +540,24 @@ curl 'https://api.pixiv.moe/v1/favourite/46453302' \
```
+## Localization
+
+App will auto detect your browser language and use the localization. You can set language manually in drawer.
+Now the app supports Japanese and English.
+Help us if you can translate this app. Please follow the guide in `src/locale`.
+
## Contribute
-Feel free to contribute (PR-s and issues welcomed).
+Feel free to contribute (PR-s and issues welcomed).
+Only `1.x-dev` branch is accepted.
## Contributors
Thanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds/all-contributors#emoji-key)):
-| [
そら](http://kokororin.github.io)
[💻](https://github.com/LoveLiveSunshine/pixiv.moe/commits?author=kokororin "Code") [📖](https://github.com/LoveLiveSunshine/pixiv.moe/commits?author=kokororin "Documentation") [🎨](#design-kokororin "Design") [⚠️](https://github.com/LoveLiveSunshine/pixiv.moe/commits?author=kokororin "Tests") | [
吟夢ちゃん](https://kirainmoe.com/)
[💻](https://github.com/LoveLiveSunshine/pixiv.moe/commits?author=kirainmoe "Code") [🤔](#ideas-kirainmoe "Ideas, Planning, & Feedback") |
-| :---: | :---: |
+
+| [
そら](http://kokororin.github.io)
[💻](https://github.com/LoveLiveSunshine/pixiv.moe/commits?author=kokororin "Code") [📖](https://github.com/LoveLiveSunshine/pixiv.moe/commits?author=kokororin "Documentation") [🎨](#design-kokororin "Design") [⚠️](https://github.com/LoveLiveSunshine/pixiv.moe/commits?author=kokororin "Tests") | [
吟夢ちゃん](https://kirainmoe.com/)
[💻](https://github.com/LoveLiveSunshine/pixiv.moe/commits?author=kirainmoe "Code") [🤔](#ideas-kirainmoe "Ideas, Planning, & Feedback") | [
simon3000](https://github.com/simon300000)
[💻](https://github.com/LoveLiveSunshine/pixiv.moe/commits?author=simon300000 "Code") [🤔](#ideas-simon300000 "Ideas, Planning, & Feedback") [🌍](#translation-simon300000 "Translation") |
+| :---: | :---: | :---: |
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
diff --git a/package.json b/package.json
index 3f61ecf..3df5590 100644
--- a/package.json
+++ b/package.json
@@ -1,11 +1,10 @@
{
"name": "pixiv.moe",
- "version": "1.2.6",
+ "version": "1.3.0",
"description": "Source code of https://pixiv.moe",
"scripts": {
"clean": "rimraf dist/*",
- "copy": "copyfiles -f ./src/index.html ./dist",
- "predist": "npm run clean && npm run copy",
+ "predist": "npm run clean",
"dist": "cross-env NODE_ENV=production webpack --config build/webpack.config.js",
"postdist": "copyfiles -f ./src/icons/*.ico ./src/icons/*.png ./dist/assets && copyfiles -f ./src/manifest.json ./dist",
"archive": "cd dist && tar -czvf dist.tar.gz * --exclude=*.gz",
@@ -35,11 +34,12 @@
"devDependencies": {
"autoprefixer": "^7.1.2",
"babel-core": "^6.26.0",
+ "babel-eslint": "^8.2.3",
"babel-loader": "^7.1.2",
- "babel-plugin-minify-dead-code-elimination": "^0.2.0",
- "babel-plugin-minify-guarded-expressions": "^0.2.0",
+ "babel-plugin-minify-dead-code-elimination": "^0.4.3",
+ "babel-plugin-minify-guarded-expressions": "^0.4.3",
"babel-plugin-transform-async-to-generator": "^6.16.0",
- "babel-plugin-transform-decorators-legacy": "^1.3.4",
+ "babel-plugin-transform-decorators-legacy": "^1.3.5",
"babel-plugin-transform-object-assign": "^6.8.0",
"babel-plugin-transform-react-remove-prop-types": "^0.4.8",
"babel-polyfill": "^6.26.0",
@@ -53,8 +53,9 @@
"cross-env": "^5.0.5",
"css-loader": "^0.28.5",
"eslint": "^4.5.0",
- "eslint-config-kotori": "^0.1.6",
+ "eslint-config-kotori": "^0.2.3",
"eslint-loader": "^1.9.0",
+ "eslint-plugin-prettier": "^2.6.0",
"fetch-mock": "^5.12.2",
"file-loader": "^0.11.2",
"glob": "^7.1.2",
@@ -78,6 +79,7 @@
"open-browser-webpack-plugin": "^0.0.5",
"optimize-js-plugin": "^0.0.4",
"postcss-loader": "^2.0.6",
+ "prettier": "^1.13.5",
"puppeteer": "^0.11.0",
"react-hot-loader": "next",
"react-test-renderer": "^16.3.2",
@@ -103,13 +105,14 @@
"moment": "^2.16.0",
"namespaced-types": "^0.1.2",
"prop-types": "^15.5.10",
- "react": "^16.3.2",
+ "react": "^16.4.1",
"react-css-modules": "^4.7.1",
"react-document-title": "^2.0.3",
- "react-dom": "^16.3.2",
+ "react-dom": "^16.4.1",
"react-ga": "^2.1.2",
"react-image": "^1.0.1",
- "react-masonry-component": "^6.2.0",
+ "react-intl": "^2.4.0",
+ "react-masonry-component": "^6.2.1",
"react-mdl": "^1.10.3",
"react-modal": "^3.3.1",
"react-redux": "^5.0.6",
diff --git a/src/actions/gallery.js b/src/actions/gallery.js
index 4e53c80..d72e268 100644
--- a/src/actions/gallery.js
+++ b/src/actions/gallery.js
@@ -1,7 +1,7 @@
import namespacedTypes from 'namespaced-types';
import config from '@/config';
-import { cachedFetch } from '@/utils';
+import cachedFetch from '@/utils/cachedFetch';
export const types = namespacedTypes('gallery', [
'SET_ITEMS',
diff --git a/src/actions/illust.js b/src/actions/illust.js
index ab81b36..f86fbcf 100644
--- a/src/actions/illust.js
+++ b/src/actions/illust.js
@@ -1,7 +1,8 @@
import namespacedTypes from 'namespaced-types';
import config from '@/config';
-import { cachedFetch, getImagesFromZip } from '@/utils';
+import cachedFetch from '@/utils/cachedFetch';
+import getImagesFromZip from '@/utils/getImagesFromZip';
export const types = namespacedTypes('illust', [
'SET_ITEM',
diff --git a/src/actions/index.js b/src/actions/index.js
deleted file mode 100644
index f1c0082..0000000
--- a/src/actions/index.js
+++ /dev/null
@@ -1,2 +0,0 @@
-export * as GalleryActions from '@/actions/gallery';
-export * as IllustActions from '@/actions/illust';
diff --git a/src/actions/locale.js b/src/actions/locale.js
new file mode 100644
index 0000000..b14367e
--- /dev/null
+++ b/src/actions/locale.js
@@ -0,0 +1,10 @@
+import namespacedTypes from 'namespaced-types';
+
+export const types = namespacedTypes('locale', ['SET_LOCALE']);
+
+export function setLocale(data) {
+ return {
+ type: types.SET_LOCALE,
+ payload: data
+ };
+}
diff --git a/src/components/Comment.js b/src/components/Comment.js
index 918b793..7e49374 100644
--- a/src/components/Comment.js
+++ b/src/components/Comment.js
@@ -6,7 +6,7 @@ import CSSModules from 'react-css-modules';
import Img from 'react-image';
import ListItem from 'react-mdl/lib/List/ListItem';
import ListItemContent from 'react-mdl/lib/List/ListItemContent';
-import { EmojiParser } from '@/utils';
+import EmojiParser from '@/utils/EmojiParser';
const Comment = ({ item }) => {
for (const badWord of Comment.badWords) {
@@ -60,4 +60,5 @@ Comment.propTypes = {
item: PropTypes.object
};
+// eslint-disable-next-line babel/new-cap
export default CSSModules(Comment, styles, { allowMultiple: true });
diff --git a/src/components/ConnectedIntlProvider.js b/src/components/ConnectedIntlProvider.js
new file mode 100644
index 0000000..e5576c4
--- /dev/null
+++ b/src/components/ConnectedIntlProvider.js
@@ -0,0 +1,7 @@
+import { connect } from 'react-redux';
+import { IntlProvider } from 'react-intl';
+
+export default connect(state => ({
+ locale: state.locale.lang,
+ messages: state.locale.messages
+}))(IntlProvider);
diff --git a/src/components/InfiniteScroll.js b/src/components/InfiniteScroll.js
index ae91986..54df23d 100644
--- a/src/components/InfiniteScroll.js
+++ b/src/components/InfiniteScroll.js
@@ -2,6 +2,8 @@ import React from 'react';
import PropTypes from 'prop-types';
export default class InfiniteScroll extends React.Component {
+ static scrollingClassName = 'mdl-layout__content';
+
static propTypes = {
distance: PropTypes.number.isRequired,
onLoadMore: PropTypes.func.isRequired,
@@ -9,8 +11,6 @@ export default class InfiniteScroll extends React.Component {
isLoading: PropTypes.bool.isRequired
};
- static scrollingClassName = 'mdl-layout__content';
-
constructor(props) {
super(props);
}
diff --git a/src/components/Item.js b/src/components/Item.js
index 1701f73..1643b49 100644
--- a/src/components/Item.js
+++ b/src/components/Item.js
@@ -4,6 +4,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import CSSModules from 'react-css-modules';
import { Link } from 'react-router-dom';
+import { FormattedMessage } from 'react-intl';
import Icon from 'react-mdl/lib/Icon';
@CSSModules(styles, { allowMultiple: true })
@@ -18,10 +19,6 @@ export default class Item extends React.Component {
super(props);
}
- shouldComponentUpdate() {
- return false;
- }
-
onImageMouseMove(event) {
event = event.nativeEvent;
const target = event.target;
@@ -39,7 +36,11 @@ export default class Item extends React.Component {
renderRankText() {
if (this.props.item.previous_rank === 0) {
- return 初登场;
+ return (
+
+
+
+ );
}
let icon;
if (this.props.item.previous_rank < this.props.item.rank) {
@@ -49,7 +50,11 @@ export default class Item extends React.Component {
}
return (
- {icon} {'前日 ' + this.props.item.previous_rank + '位'}
+ {icon}
+
);
}
@@ -69,7 +74,12 @@ export default class Item extends React.Component {
{this.props.item.work.title}
- {`${this.props.item.rank}位`}
+
+
+
{this.renderRankText()}
diff --git a/src/components/List.js b/src/components/List.js
index 90ae8d3..b34d8a7 100644
--- a/src/components/List.js
+++ b/src/components/List.js
@@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import Masonry from 'react-masonry-component';
-import { Item } from '@/components';
+import Item from '@/components/Item';
export default class List extends React.Component {
static propTypes = {
diff --git a/src/components/Loading.js b/src/components/Loading.js
index eb840c9..c292e58 100644
--- a/src/components/Loading.js
+++ b/src/components/Loading.js
@@ -6,7 +6,6 @@ import CSSModules from 'react-css-modules';
import Spinner from 'react-mdl/lib/Spinner';
const Loading = ({ isHidden }) => {
- // it means ローディング
return isHidden ? null : (
@@ -18,4 +17,5 @@ Loading.propTypes = {
isHidden: PropTypes.bool
};
+// eslint-disable-next-line babel/new-cap
export default CSSModules(Loading, styles, { allowMultiple: true });
diff --git a/src/components/Login.js b/src/components/Login.js
index c8cc372..fa1fa2a 100644
--- a/src/components/Login.js
+++ b/src/components/Login.js
@@ -9,10 +9,12 @@ import classNames from 'classnames';
import Button from 'react-mdl/lib/Button';
import Textfield from 'react-mdl/lib/Textfield';
import Icon from 'react-mdl/lib/Icon';
-import { moment, Storage } from '@/utils';
+import { FormattedMessage, injectIntl } from 'react-intl';
+import moment from '@/utils/moment';
+import Storage from '@/utils/Storage';
+import withRef from '@/utils/withRef';
-@CSSModules(styles, { allowMultiple: true })
-export default class Login extends React.Component {
+class Login extends React.Component {
static propTypes = {
onLogoutClick: PropTypes.func,
onLogoutClick: PropTypes.func,
@@ -87,12 +89,14 @@ export default class Login extends React.Component {
- ニックネーム 「{this.props.authData.user.name}」
+ 「{
+ this.props.authData.user.name
+ }」
@@ -103,7 +107,9 @@ export default class Login extends React.Component {
this.setUsername(event.target.value)}
value={this.getUsername()}
- label="メールアドレス / pixiv ID"
+ label={this.props.intl.formatMessage({
+ id: 'Email Address / pixiv ID'
+ })}
spellCheck={false}
floatingLabel
style={{ width: '100%' }}
@@ -112,7 +118,9 @@ export default class Login extends React.Component {
type="password"
onChange={event => this.setPassword(event.target.value)}
value={this.getPassword()}
- label="パスワード"
+ label={this.props.intl.formatMessage({
+ id: 'Password'
+ })}
floatingLabel
style={{ width: '100%' }}
/>
@@ -126,7 +134,9 @@ export default class Login extends React.Component {
raised
accent
ripple>
- {this.props.isSubmitting ? 'ちょっとまって' : 'ログイン'}
+
@@ -151,3 +161,9 @@ export default class Login extends React.Component {
);
}
}
+
+export default withRef(
+ // eslint-disable-next-line babel/new-cap
+ CSSModules(Login, styles, { allowMultiple: true }),
+ injectIntl
+);
diff --git a/src/components/Message.js b/src/components/Message.js
index bb92b63..cabdac9 100644
--- a/src/components/Message.js
+++ b/src/components/Message.js
@@ -3,19 +3,19 @@ import styles from '@/styles/Message.scss';
import React from 'react';
import PropTypes from 'prop-types';
import CSSModules from 'react-css-modules';
+import { FormattedMessage } from 'react-intl';
@CSSModules(styles, { allowMultiple: true })
export default class Message extends React.Component {
- static defaultProps = {
- isHidden: false,
- text: 'エラーが発生しました。URLを確認するか、しばらく時間を置いて再度アクセスしてください。'
- };
-
static propTypes = {
isHidden: PropTypes.bool,
text: PropTypes.string
};
+ static defaultProps = {
+ isHidden: false
+ };
+
constructor(props) {
super(props);
}
@@ -23,7 +23,13 @@ export default class Message extends React.Component {
render() {
return this.props.isHidden ? null : (
-
{this.props.text}
+
+ {this.props.text ? (
+ this.props.text
+ ) : (
+
+ )}
+
);
}
diff --git a/src/components/Refresh.js b/src/components/Refresh.js
index d39b31d..ff8647d 100644
--- a/src/components/Refresh.js
+++ b/src/components/Refresh.js
@@ -19,4 +19,5 @@ Refresh.propTypes = {
onClick: PropTypes.func
};
+// eslint-disable-next-line babel/new-cap
export default CSSModules(Refresh, styles, { allowMultiple: true });
diff --git a/src/components/TrackPageView.js b/src/components/TrackPageView.js
index ef6c1ba..a5ec842 100644
--- a/src/components/TrackPageView.js
+++ b/src/components/TrackPageView.js
@@ -3,7 +3,8 @@ import ReactGA from 'react-ga';
import { Route } from 'react-router-dom';
import config from '@/config';
-import { Piwik, cachedFetch } from '@/utils';
+import Piwik from '@/utils/Piwik';
+import cachedFetch from '@/utils/cachedFetch';
export default class TrackPageView extends React.Component {
constructor(props) {
diff --git a/src/components/index.js b/src/components/index.js
deleted file mode 100644
index 7bbee24..0000000
--- a/src/components/index.js
+++ /dev/null
@@ -1,12 +0,0 @@
-export Alert from '@/components/Alert';
-export Comment from '@/components/Comment';
-export GifPlayer from '@/components/GifPlayer';
-export InfiniteScroll from '@/components/InfiniteScroll';
-export Item from '@/components/Item';
-export List from '@/components/List';
-export Login from '@/components/Login';
-export Loading from '@/components/Loading';
-export Message from '@/components/Message';
-export Refresh from '@/components/Refresh';
-export ScrollContext from '@/components/ScrollContext';
-export TrackPageView from '@/components/TrackPageView';
diff --git a/src/config/index.js b/src/config/index.js
index ba950ab..3c5231c 100644
--- a/src/config/index.js
+++ b/src/config/index.js
@@ -13,6 +13,16 @@ export default {
piwikSiteId: '2PMEnB',
projectLink: 'https://github.com/LoveLiveSunshine/pixiv.moe',
siteTitle: 'pixivギャラリー',
+ languages: [
+ {
+ name: '日本語',
+ value: 'ja'
+ },
+ {
+ name: 'English',
+ value: 'en'
+ }
+ ],
keywords: [
{
en: 'ranking',
diff --git a/src/containers/AppContainer.js b/src/containers/AppContainer.js
index b8eac1e..2494827 100644
--- a/src/containers/AppContainer.js
+++ b/src/containers/AppContainer.js
@@ -7,13 +7,13 @@ import '@/styles/Base.scss';
import '@/styles/Reset.scss';
import { history } from '@/stores';
-import {
- GalleryContainer,
- IllustContainer,
- RedirectContainer,
- NotFoundContainer
-} from '@/containers';
-import { ScrollContext, TrackPageView } from '@/components';
+import GalleryContainer from '@/containers/GalleryContainer';
+import IllustContainer from '@/containers/IllustContainer';
+import RedirectContainer from '@/containers/RedirectContainer';
+import NotFoundContainer from '@/containers/NotFoundContainer';
+
+import ScrollContext from '@/components/ScrollContext';
+import TrackPageView from '@/components/TrackPageView';
const AppContainer = () => (
diff --git a/src/containers/GalleryContainer.js b/src/containers/GalleryContainer.js
index 05e2595..1efa9a6 100644
--- a/src/containers/GalleryContainer.js
+++ b/src/containers/GalleryContainer.js
@@ -11,14 +11,25 @@ import Content from 'react-mdl/lib/Layout/Content';
import Icon from 'react-mdl/lib/Icon';
import shortid from 'shortid';
import DocumentTitle from 'react-document-title';
+import { FormattedMessage, injectIntl } from 'react-intl';
+import classNames from 'classnames';
import config from '@/config';
-import { GalleryActions } from '@/actions';
-import { InfiniteScroll, List, Loading, Refresh, Message } from '@/components';
-import { scrollTo, Storage } from '@/utils';
+import * as GalleryActions from '@/actions/gallery';
+import InfiniteScroll from '@/components/InfiniteScroll';
+import List from '@/components/List';
+import Loading from '@/components/Loading';
+import Refresh from '@/components/Refresh';
+import Message from '@/components/Message';
+import scrollTo from '@/utils/scrollTo';
+import Storage from '@/utils/Storage';
-export class GalleryContainerWithoutStore extends React.Component {
+import chooseLocale from '@/locale/chooseLocale';
+
+@connect(state => ({ gallery: state.gallery }))
+@injectIntl
+export default class GalleryContainer extends React.Component {
constructor(props) {
super(props);
}
@@ -102,45 +113,70 @@ export class GalleryContainerWithoutStore extends React.Component {
document.body.removeChild(temp);
}
+ @autobind
+ onLanguageClick(event) {
+ event.preventDefault();
+
+ this.layoutDOMNode.MaterialLayout.toggleDrawer();
+ const value = event.target.dataset.value;
+ Storage.set('lang', value);
+ chooseLocale(value, this.props.dispatch);
+ }
+
@autobind
onKeywordClick(event) {
- event.nativeEvent.preventDefault();
+ event.preventDefault();
this.layoutDOMNode.MaterialLayout.toggleDrawer();
- const tag = event.nativeEvent.target.dataset.tag;
+ const tag = event.target.dataset.tag;
this.props.dispatch(GalleryActions.setTag(tag));
this.reRenderContent(false);
Storage.set('tag', tag);
}
+ renderLanguages() {
+ const languages = config.languages;
+
+ return languages.map(elem => {
+ const lang = Storage.get('lang');
+ const highlight = elem.value === lang;
+
+ return (
+
+ {highlight && }
+ {elem.name}
+
+ );
+ });
+ }
+
renderKeywords() {
const keywords = config.keywords;
return keywords.map(elem => {
- let linkStyle = null,
- iconStyle = {
- display: 'none'
- };
- if (elem.en === this.props.gallery.tag) {
- linkStyle = {
- fontWeight: 'bold',
- fontSize: '16px'
- };
- iconStyle = {
- color: '#4caf50',
- display: 'inline-block'
- };
- }
+ const highlight = elem.en === this.props.gallery.tag;
+
return (
-
- {elem.jp}
+ className={classNames({
+ [`nav-link__${elem.en}`]: true,
+ 'nav-link__highlight': highlight
+ })}>
+ {highlight && }
+ {elem.en === 'ranking'
+ ? this.props.intl.formatMessage({ id: 'Ranking' })
+ : elem.jp}
);
});
@@ -148,9 +184,9 @@ export class GalleryContainerWithoutStore extends React.Component {
@autobind
onHeaderClick(event) {
- const target = event.nativeEvent.target,
+ const target = event.target,
tagName = target.tagName.toLowerCase(),
- classList = event.nativeEvent.target.classList;
+ classList = event.target.classList;
if (
!classList.contains('material-icons') &&
@@ -178,8 +214,20 @@ export class GalleryContainerWithoutStore extends React.Component {
-
- {this.renderKeywords()}
+
+
+
+
+
+ {this.renderLanguages()}
+
+
+
+
+
+
+ {this.renderKeywords()}
+
(this.errorRef = ref)}
- text="読み込みに失敗しました"
+ text={this.props.intl.formatMessage({ id: 'Failed to Load' })}
isHidden={!this.props.gallery.isError}
/>
({ gallery: state.gallery }))(
- GalleryContainerWithoutStore
-);
diff --git a/src/containers/IllustContainer.js b/src/containers/IllustContainer.js
index fb6e816..6d6c02c 100644
--- a/src/containers/IllustContainer.js
+++ b/src/containers/IllustContainer.js
@@ -14,23 +14,26 @@ import { List } from 'react-mdl/lib/List';
import shortid from 'shortid';
import Img from 'react-image';
import DocumentTitle from 'react-document-title';
+import { FormattedMessage, injectIntl } from 'react-intl';
import config from '@/config';
-import { IllustActions } from '@/actions';
-import {
- Alert,
- Comment,
- GifPlayer,
- InfiniteScroll,
- Loading,
- Message
-} from '@/components';
-import { LoginContainer } from '@/containers';
-import { cachedFetch, moment, Storage } from '@/utils';
+import * as IllustActions from '@/actions/illust';
+import Alert from '@/components/Alert';
+import Comment from '@/components/Comment';
+import GifPlayer from '@/components/GifPlayer';
+import InfiniteScroll from '@/components/InfiniteScroll';
+import Loading from '@/components/Loading';
+import Message from '@/components/Message';
+import LoginContainer from '@/containers/LoginContainer';
+import cachedFetch from '@/utils/cachedFetch';
+import moment from '@/utils/moment';
+import Storage from '@/utils/Storage';
+@connect(state => ({ illust: state.illust }))
+@injectIntl
@CSSModules(styles, { allowMultiple: true })
-export class IllustContainerWithoutStore extends React.Component {
+export default class IllustContainer extends React.Component {
constructor(props) {
super(props);
@@ -94,9 +97,9 @@ export class IllustContainerWithoutStore extends React.Component {
onFavouriteClick(event) {
const authData = Storage.get('auth');
if (authData === null || authData.expires_at < moment().unix()) {
- return this.loginRef.open();
+ return this.loginRef.getRef().open();
}
- const target = event.nativeEvent.target,
+ const target = event.target,
body = document.body;
if (target.classList.contains('fn-wait')) {
return;
@@ -121,8 +124,9 @@ export class IllustContainerWithoutStore extends React.Component {
.catch(() => {
target.classList.remove('fn-wait');
body.classList.remove('fn-wait');
- // text from SIF
- this.alertRef.setContent('通信エラーが発生しました');
+ this.alertRef.setContent(
+ this.props.intl.formatMessage({ id: 'Communication Error Occurred' })
+ );
});
}
@@ -196,7 +200,12 @@ export class IllustContainerWithoutStore extends React.Component {
return ;
}
if (this.props.illust.isError) {
- return ;
+ return (
+
+ );
}
try {
return (
@@ -230,13 +239,13 @@ export class IllustContainerWithoutStore extends React.Component {
@@ -252,8 +261,9 @@ export class IllustContainerWithoutStore extends React.Component {
{`${moment(this.item.created_time).format('LLL')}(JST)`}
-
{`${this.item.width}x${this.item
- .height}`}
+
{`${this.item.width}x${
+ this.item.height
+ }`}
{Array.isArray(this.item.tools) && (
- pixivにリダイレクトする
+
- this.props.dispatch(IllustActions.fetchComments(this.illustId))}
+ this.props.dispatch(IllustActions.fetchComments(this.illustId))
+ }
isLoading={this.props.illust.isFetchingComments}
hasMore={!this.props.illust.isCommentsEnd}>
- {this.props.illust.comments.length === 0 ? (
-
コメントはありません
- ) : (
- コメント
- )}
+
+
+
{this.props.illust.comments.map(elem => {
return ;
@@ -297,7 +312,12 @@ export class IllustContainerWithoutStore extends React.Component {
);
} catch (e) {
- return ;
+ return (
+
+ );
}
}
@@ -313,7 +333,3 @@ export class IllustContainerWithoutStore extends React.Component {
);
}
}
-
-export default connect(state => ({ illust: state.illust }))(
- IllustContainerWithoutStore
-);
diff --git a/src/containers/LoginContainer.js b/src/containers/LoginContainer.js
index 366a528..d3b1885 100644
--- a/src/containers/LoginContainer.js
+++ b/src/containers/LoginContainer.js
@@ -1,11 +1,16 @@
import React from 'react';
+import { injectIntl } from 'react-intl';
-import { Alert, Login } from '@/components';
-import { cachedFetch, moment, Storage } from '@/utils';
+import Alert from '@/components/Alert';
+import Login from '@/components/Login';
+import cachedFetch from '@/utils/cachedFetch';
+import moment from '@/utils/moment';
+import Storage from '@/utils/Storage';
+import withRef from '@/utils/withRef';
import config from '@/config';
-export default class LoginContainer extends React.Component {
+class LoginContainer extends React.Component {
constructor(props) {
super(props);
@@ -30,22 +35,25 @@ export default class LoginContainer extends React.Component {
@autobind
onKeydown(event) {
if (event.keyCode === 27) {
- this.loginRef.close();
+ this.loginRef.getRef().close();
}
- if (this.loginRef.state.isHidden === false && event.keyCode === 13) {
+ if (
+ this.loginRef.getRef().state.isHidden === false &&
+ event.keyCode === 13
+ ) {
this.onLoginClick();
}
}
@autobind
open() {
- this.loginRef.open();
+ this.loginRef.getRef().open();
}
@autobind
close() {
- this.loginRef.close();
+ this.loginRef.getRef().close();
}
@autobind
@@ -55,18 +63,28 @@ export default class LoginContainer extends React.Component {
}
if (!Storage.isSupport()) {
- return this.alertRef.setContent('localStorageをサポートしていないブラウザ');
+ return this.alertRef.setContent(
+ this.props.intl.formatMessage({
+ id: 'Web Browser does not support localStorage'
+ })
+ );
}
- const username = this.loginRef.getUsername();
- const password = this.loginRef.getPassword();
+ const username = this.loginRef.getRef().getUsername();
+ const password = this.loginRef.getRef().getPassword();
if (username === '') {
- return this.alertRef.setContent('pixiv ID、またはメールアドレスが未記入です');
+ return this.alertRef.setContent(
+ this.props.intl.formatMessage({
+ id: 'pixiv ID or Email Address is Blank'
+ })
+ );
}
if (password === '') {
- return this.alertRef.setContent('パスワードが未記入です');
+ return this.alertRef.setContent(
+ this.props.intl.formatMessage({ id: 'Password is Blank' })
+ );
}
this.setState({
@@ -97,8 +115,8 @@ export default class LoginContainer extends React.Component {
});
setTimeout(() => {
this.close();
- this.loginRef.setUsername('');
- this.loginRef.setPassword('');
+ this.loginRef.getRef().setUsername('');
+ this.loginRef.getRef().setPassword('');
}, 1500);
} else {
this.alertRef.setContent(data.message);
@@ -113,8 +131,9 @@ export default class LoginContainer extends React.Component {
this.setState({
isSubmitting: false
});
- // text from SIF
- this.alertRef.setContent('通信エラーが発生しました');
+ this.alertRef.setContent(
+ this.props.intl.formatMessage({ id: 'Communication Error Occurred' })
+ );
});
}
@@ -141,3 +160,5 @@ export default class LoginContainer extends React.Component {
);
}
}
+
+export default withRef(LoginContainer, injectIntl);
diff --git a/src/containers/NotFoundContainer.js b/src/containers/NotFoundContainer.js
index a1d907a..e9fceb5 100644
--- a/src/containers/NotFoundContainer.js
+++ b/src/containers/NotFoundContainer.js
@@ -1,6 +1,6 @@
import React from 'react';
-import { Message } from '@/components';
+import Message from '@/components/Message';
const NotFoundContainer = () => ;
diff --git a/src/containers/RedirectContainer.js b/src/containers/RedirectContainer.js
index 5d4f669..50ee595 100644
--- a/src/containers/RedirectContainer.js
+++ b/src/containers/RedirectContainer.js
@@ -1,8 +1,10 @@
import React from 'react';
import PropTypes from 'prop-types';
+import { injectIntl } from 'react-intl';
-import { Message } from '@/components';
+import Message from '@/components/Message';
+@injectIntl
export default class RedirectContainer extends React.Component {
static propTypes = {
illustId: PropTypes.string
@@ -38,7 +40,11 @@ export default class RedirectContainer extends React.Component {
{this.state.isError ? (
) : (
-
+
)}
);
diff --git a/src/containers/index.js b/src/containers/index.js
deleted file mode 100644
index 2d44b3c..0000000
--- a/src/containers/index.js
+++ /dev/null
@@ -1,10 +0,0 @@
-export AppContainer from '@/containers/AppContainer';
-export GalleryContainer, {
- GalleryContainerWithoutStore
-} from '@/containers/GalleryContainer';
-export IllustContainer, {
- IllustContainerWithoutStore
-} from '@/containers/IllustContainer';
-export LoginContainer from '@/containers/LoginContainer';
-export NotFoundContainer from '@/containers/NotFoundContainer';
-export RedirectContainer from '@/containers/RedirectContainer';
diff --git a/src/icons/convert.sh b/src/icons/convert.sh
old mode 100755
new mode 100644
diff --git a/src/index.ejs b/src/index.ejs
index 2f068b0..f7a059a 100644
--- a/src/index.ejs
+++ b/src/index.ejs
@@ -1,5 +1,5 @@
-
+
diff --git a/src/index.js b/src/index.js
index 88a0ff3..35408a8 100644
--- a/src/index.js
+++ b/src/index.js
@@ -6,15 +6,22 @@ import { Provider } from 'react-redux';
import { configureStore } from '@/stores';
import AppContainer from '@/containers/AppContainer';
+import ConnectedIntlProvider from '@/components/ConnectedIntlProvider';
+import chooseLocale from '@/locale/chooseLocale';
+
const store = configureStore();
+chooseLocale(navigator.language, store.dispatch);
+
// Render the main component into the dom
const render = Component => {
ReactDOM.render(
-
-
-
+
+
+
+
+
,
document.getElementById('app')
);
diff --git a/src/locale/chooseLocale.js b/src/locale/chooseLocale.js
new file mode 100644
index 0000000..6843d0d
--- /dev/null
+++ b/src/locale/chooseLocale.js
@@ -0,0 +1,42 @@
+import { addLocaleData } from 'react-intl';
+import jaLocaleData from 'react-intl/locale-data/ja';
+import ja from '@/locale/ja';
+import enLocaleData from 'react-intl/locale-data/en';
+import en from '@/locale/en';
+import Storage from '@/utils/Storage';
+import * as LocaleActions from '@/actions/locale';
+
+const chooseLocale = (language, dispatch) => {
+ const cachedLang = Storage.get('lang');
+ let lang;
+ let messages;
+
+ if (!cachedLang) {
+ lang = language.split('-')[0];
+ } else {
+ lang = cachedLang;
+ }
+
+ switch (lang) {
+ case 'en':
+ addLocaleData(enLocaleData);
+ lang = 'en';
+ messages = en;
+ break;
+ default:
+ addLocaleData(jaLocaleData);
+ lang = 'ja';
+ messages = ja;
+ }
+
+ Storage.set('lang', lang);
+
+ dispatch(
+ LocaleActions.setLocale({
+ lang,
+ messages
+ })
+ );
+};
+
+export default chooseLocale;
diff --git a/src/locale/en.js b/src/locale/en.js
new file mode 100644
index 0000000..685e51c
--- /dev/null
+++ b/src/locale/en.js
@@ -0,0 +1,32 @@
+const en = {
+ Debut: 'Debut',
+ 'Yesterday x rank': 'Yesterday #{rank}',
+ 'x rank': '#{rank}',
+ 'Redirect to pixiv': 'Redirect to pixiv',
+ 'Add to Bookmarks': 'Add to Bookmarks',
+ Download: 'Download',
+ Tweet: 'Tweet',
+ Comments: 'Comments',
+ 'No Comments': 'No Comments',
+ 'An Error Occurred': 'An Error Occurred',
+ 'Communication Error Occurred': 'Communication Error Occurred',
+ 'Web Browser does not support localStorage':
+ 'Web Browser does not support localStorage',
+ 'pixiv ID or Email Address is Blank': 'pixiv ID or Email Address is Blank',
+ 'Password is Blank': 'Password is Blank',
+ 'Wait a Moment': 'Wait a Moment',
+ Login: 'Login',
+ Logout: 'Logout',
+ 'Email Address / pixiv ID': 'Email Address / pixiv ID',
+ Password: 'Password',
+ Nickname: 'Nickname',
+ 'An error occurred. Check the URL or wait for a while and access again.':
+ 'An error occurred. Check the URL or wait for a while and access again.',
+ 'Failed to Load': 'Failed to Load',
+ Tags: 'Tags',
+ 'Redirecting to pixiv.net': 'Redirecting to pixiv.net',
+ Language: 'Language',
+ Ranking: 'Ranking'
+};
+
+export default en;
diff --git a/src/locale/ja.js b/src/locale/ja.js
new file mode 100644
index 0000000..da34727
--- /dev/null
+++ b/src/locale/ja.js
@@ -0,0 +1,33 @@
+const ja = {
+ Debut: '初登场',
+ 'Yesterday x rank': '前日 {rank}位',
+ 'x rank': '{rank}位',
+ 'Redirect to pixiv': 'pixivにリダイレクトする',
+ 'Add to Bookmarks': 'ブックマークに追加',
+ Download: 'ダウンロード',
+ Tweet: 'ツイート',
+ Comments: 'コメント',
+ 'No Comments': 'コメントはありません',
+ 'An Error Occurred': 'エラーが発生しました',
+ 'Communication Error Occurred': '通信エラーが発生しました',
+ 'Web Browser does not support localStorage':
+ 'localStorageをサポートしていないブラウザ',
+ 'pixiv ID or Email Address is Blank':
+ 'pixiv ID、またはメールアドレスが未記入です',
+ 'Password is Blank': 'パスワードが未記入です',
+ 'Wait a Moment': 'ちょっとまって',
+ Login: 'ログイン',
+ Logout: 'ログアウト',
+ 'Email Address / pixiv ID': 'メールアドレス / pixiv ID',
+ Password: 'パスワード',
+ Nickname: 'ニックネーム',
+ 'An error occurred. Check the URL or wait for a while and access again.':
+ 'エラーが発生しました。URLを確認するか、しばらく時間を置いて再度アクセスしてください。',
+ 'Failed to Load': '読み込みに失敗しました',
+ Tags: 'タグ',
+ 'Redirecting to pixiv.net': 'あなたはpixiv.netへリダイレクトしています',
+ Language: '言語',
+ Ranking: 'ランキング'
+};
+
+export default ja;
diff --git a/src/reducers/gallery.js b/src/reducers/gallery.js
index 217cb72..45c7e67 100644
--- a/src/reducers/gallery.js
+++ b/src/reducers/gallery.js
@@ -1,4 +1,4 @@
-import { GalleryActions } from '@/actions';
+import * as GalleryActions from '@/actions/gallery';
const types = GalleryActions.types;
diff --git a/src/reducers/illust.js b/src/reducers/illust.js
index c228a81..30bde94 100644
--- a/src/reducers/illust.js
+++ b/src/reducers/illust.js
@@ -1,4 +1,4 @@
-import { IllustActions } from '@/actions';
+import * as IllustActions from '@/actions/illust';
const types = IllustActions.types;
diff --git a/src/reducers/index.js b/src/reducers/index.js
index afe1420..07f38f9 100644
--- a/src/reducers/index.js
+++ b/src/reducers/index.js
@@ -2,10 +2,12 @@ import { combineReducers } from 'redux';
import gallery from '@/reducers/gallery';
import illust from '@/reducers/illust';
+import locale from '@/reducers/locale';
const reducers = combineReducers({
gallery,
- illust
+ illust,
+ locale
});
export default reducers;
diff --git a/src/reducers/locale.js b/src/reducers/locale.js
new file mode 100644
index 0000000..8518af5
--- /dev/null
+++ b/src/reducers/locale.js
@@ -0,0 +1,23 @@
+import * as LocaleActions from '@/actions/locale';
+
+const types = LocaleActions.types;
+
+export default function locale(
+ state = {
+ lang: '',
+ messages: {}
+ },
+ action
+) {
+ switch (action.type) {
+ case types.SET_LOCALE:
+ return {
+ ...state,
+ lang: action.payload.lang,
+ messages: action.payload.messages
+ };
+
+ default:
+ return state;
+ }
+}
diff --git a/src/styles/Reset.scss b/src/styles/Reset.scss
index a08a5b0..d55c0a6 100644
--- a/src/styles/Reset.scss
+++ b/src/styles/Reset.scss
@@ -26,6 +26,14 @@
.nav-link__sunshine {
border-top: 1px solid rgba(0, 0, 0, 0.12);
}
+ .nav-link__highlight {
+ font-weight: bold;
+ font-size: 16px;
+ .material-icons {
+ color: #4caf50;
+ display: inline-block;
+ }
+ }
}
.mdl-list__item-avatar {
diff --git a/src/utils/EmojiParser.js b/src/utils/EmojiParser.js
index 830b5cc..ff11254 100644
--- a/src/utils/EmojiParser.js
+++ b/src/utils/EmojiParser.js
@@ -161,9 +161,11 @@ export default class EmojiParser {
let replaceStr = '';
for (const series of EmojiParser.emojiSeries) {
if (match === `(${series.name})`) {
- replaceStr += ``;
+ replaceStr += ``;
}
}
return replaceStr === '' ? match : replaceStr;
diff --git a/src/utils/Piwik.js b/src/utils/Piwik.js
index f18893a..1898afa 100644
--- a/src/utils/Piwik.js
+++ b/src/utils/Piwik.js
@@ -109,7 +109,7 @@ export default class Piwik {
}
connectToHistory(history) {
- this.unlistenFromHistory = history.listen(function(loc) {
+ this.unlistenFromHistory = history.listen(loc => {
this.track(loc);
});
diff --git a/src/utils/cachedFetch.js b/src/utils/cachedFetch.js
index 3333e15..68a9400 100644
--- a/src/utils/cachedFetch.js
+++ b/src/utils/cachedFetch.js
@@ -1,5 +1,7 @@
// modify from https://www.sitepoint.com/cache-fetched-ajax-requests/
-import { hashStr, moment, Storage } from '@/utils';
+import hashStr from '@/utils/hashStr';
+import moment from '@/utils/moment';
+import Storage from '@/utils/Storage';
function buildURL(url, params) {
if (!params) {
diff --git a/src/utils/getImagesFromZip.js b/src/utils/getImagesFromZip.js
index c8a46bd..93d0957 100644
--- a/src/utils/getImagesFromZip.js
+++ b/src/utils/getImagesFromZip.js
@@ -1,5 +1,5 @@
import JSZip from 'jszip';
-import { cachedFetch } from '@/utils';
+import cachedFetch from '@/utils/cachedFetch';
export default function getImagesFromZip(zipURL) {
return new Promise(resolve => {
diff --git a/src/utils/index.js b/src/utils/index.js
deleted file mode 100644
index acc6e16..0000000
--- a/src/utils/index.js
+++ /dev/null
@@ -1,8 +0,0 @@
-export cachedFetch from '@/utils/cachedFetch';
-export hashStr from '@/utils/hashStr';
-export EmojiParser from '@/utils/EmojiParser';
-export getImagesFromZip from '@/utils/getImagesFromZip';
-export moment from '@/utils/moment';
-export Piwik from '@/utils/Piwik';
-export scrollTo from '@/utils/scrollTo';
-export Storage from '@/utils/Storage';
diff --git a/src/utils/withRef.js b/src/utils/withRef.js
new file mode 100644
index 0000000..db37799
--- /dev/null
+++ b/src/utils/withRef.js
@@ -0,0 +1,75 @@
+import React from 'react';
+import shortid from 'shortid';
+
+export function refComponentHoc(ChildComponent, refer) {
+ return class RefComponent extends React.Component {
+ constructor(props) {
+ super(props);
+ }
+
+ @autobind
+ setRef(childComponentInstance) {
+ if (refer) {
+ refer.ref = childComponentInstance;
+ }
+ this[ChildComponent.name] = childComponentInstance;
+ }
+
+ render() {
+ const props = { ...this.props, ref: this.setRef };
+ return ;
+ }
+ };
+}
+
+export default function withRef(wrappedComponent, ...decorators) {
+ const refer = new Proxy(
+ { id: '' },
+ {
+ get(target, key) {
+ if (key === 'id') {
+ const value = target.id;
+ target.id = '';
+ return value;
+ }
+ return target[key];
+ },
+ set(target, key, value) {
+ key = shortid.generate();
+ target.id = key;
+ target[key] = value;
+ return true;
+ }
+ }
+ );
+
+ const refComponent = refComponentHoc(wrappedComponent, refer);
+ const ResultComponent = decorators.reduce((prev, next) => {
+ return next(prev);
+ }, refComponent);
+
+ return class RefComponentWrapper extends React.Component {
+ constructor(props) {
+ super(props);
+ }
+
+ componentDidMount() {
+ !this._refId && (this._refId = refer.id);
+ }
+
+ componentWillUnmount() {
+ refer[this._refId] = null;
+ this._refId = null;
+ }
+
+ @autobind
+ getRef() {
+ return refer[this._refId];
+ }
+
+ render() {
+ const props = { ...this.props };
+ return ;
+ }
+ };
+}
diff --git a/test/actions/galleryTest.js b/test/actions/galleryTest.js
index e9f8f36..78fdcfc 100644
--- a/test/actions/galleryTest.js
+++ b/test/actions/galleryTest.js
@@ -2,7 +2,7 @@ import nock from 'nock';
import mockStore from '../helpers/mockStoreHelper';
import config from '@/config';
-import { GalleryActions } from '@/actions';
+import * as GalleryActions from '@/actions/gallery';
describe('GalleryActions', () => {
afterEach(() => {
@@ -10,7 +10,9 @@ describe('GalleryActions', () => {
});
it('fire SET_FETCH_ERROR when fetching sources has been done', done => {
- nock(config.baseURL).get(`${config.galleryURI}?tag=nico`).reply(200);
+ nock(config.baseURL)
+ .get(`${config.galleryURI}?tag=nico`)
+ .reply(200);
const expectedActions = [
{
diff --git a/test/containers/GalleryContainerTest.js b/test/containers/GalleryContainerTest.js
deleted file mode 100644
index 398583f..0000000
--- a/test/containers/GalleryContainerTest.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import { expect } from 'chai';
-import createComponent from '../helpers/shallowRenderHelper';
-
-import { GalleryContainerWithoutStore } from '@/containers';
-import config from '@/config';
-
-describe('GalleryContainer', () => {
- let galleryContainer;
-
- beforeEach(() => {
- galleryContainer = createComponent(GalleryContainerWithoutStore, {
- gallery: []
- });
- });
-
- it('GalleryContainerの has a title', () => {
- expect(galleryContainer.props.title).to.equal(config.siteTitle);
- });
-});
diff --git a/test/containers/NotFoundContainerTest.js b/test/containers/NotFoundContainerTest.js
deleted file mode 100644
index cf781c1..0000000
--- a/test/containers/NotFoundContainerTest.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import { expect } from 'chai';
-import createComponent from '../helpers/shallowRenderHelper';
-
-import { NotFoundContainer } from '@/containers';
-
-describe('NotFoundContainer', () => {
- let notFoundContainer;
-
- beforeEach(() => {
- notFoundContainer = createComponent(NotFoundContainer);
- });
-
- it('NotFoundContainer has a correct message', () => {
- expect(notFoundContainer.props.text).to.equal(
- 'エラーが発生しました。URLを確認するか、しばらく時間を置いて再度アクセスしてください。'
- );
- });
-});
diff --git a/test/containers/RedirectContainerTest.js b/test/containers/RedirectContainerTest.js
deleted file mode 100644
index edc56f4..0000000
--- a/test/containers/RedirectContainerTest.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import { expect } from 'chai';
-import createComponent from '../helpers/shallowRenderHelper';
-
-import { RedirectContainer } from '@/containers';
-
-describe('RedirectContainer', () => {
- let redirectContainer;
-
- beforeEach(() => {
- redirectContainer = createComponent(RedirectContainer, {
- illustId: '45944782'
- });
- });
-
- it('RedirectContainer has a correct message', () => {
- expect(redirectContainer.props.children.props.text).to.equal(
- 'あなたはpixiv.netへリダイレクトしています'
- );
- });
-});
diff --git a/test/utils/EmojiParserTest.js b/test/utils/EmojiParserTest.js
index 447b7be..6badba9 100644
--- a/test/utils/EmojiParserTest.js
+++ b/test/utils/EmojiParserTest.js
@@ -1,5 +1,5 @@
import { expect } from 'chai';
-import { EmojiParser } from '@/utils';
+import EmojiParser from '@/utils/EmojiParser';
describe('EmojiParser', () => {
it('should parse out with a ', () => {
diff --git a/test/utils/StorageTest.js b/test/utils/StorageTest.js
index 747032a..b0b586a 100644
--- a/test/utils/StorageTest.js
+++ b/test/utils/StorageTest.js
@@ -1,5 +1,5 @@
import { expect } from 'chai';
-import { Storage } from '@/utils';
+import Storage from '@/utils/Storage';
describe('Storage', () => {
it('set and get storage should work', () => {
diff --git a/test/utils/cachedFetchTest.js b/test/utils/cachedFetchTest.js
index 79621c6..7f7d169 100644
--- a/test/utils/cachedFetchTest.js
+++ b/test/utils/cachedFetchTest.js
@@ -1,6 +1,6 @@
import { expect } from 'chai';
import fetchMock from 'fetch-mock';
-import { cachedFetch } from '@/utils';
+import cachedFetch from '@/utils/cachedFetch';
describe('cachedFetch', () => {
afterEach(() => {
diff --git a/test/utils/hashStrTest.js b/test/utils/hashStrTest.js
index a651af9..a69ce0a 100644
--- a/test/utils/hashStrTest.js
+++ b/test/utils/hashStrTest.js
@@ -1,5 +1,5 @@
import { expect } from 'chai';
-import { hashStr } from '@/utils';
+import hashStr from '@/utils/hashStr';
describe('hashStr', () => {
it('hashStr of `kotori` should be -1125571242', () => {
diff --git a/test/utils/momentTest.js b/test/utils/momentTest.js
index e43d27f..e27ea02 100644
--- a/test/utils/momentTest.js
+++ b/test/utils/momentTest.js
@@ -1,5 +1,5 @@
import { expect } from 'chai';
-import { moment } from '@/utils';
+import moment from '@/utils/moment';
describe('moment', () => {
it('convert YYYY-MM-DD H:i:s to JST', () => {
diff --git a/yarn.lock b/yarn.lock
index 9b35891..1391c79 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,70 +2,77 @@
# yarn lockfile v1
-"@babel/code-frame@7.0.0-beta.40", "@babel/code-frame@^7.0.0-beta.40":
- version "7.0.0-beta.40"
- resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.40.tgz#37e2b0cf7c56026b4b21d3927cadf81adec32ac6"
+"@babel/code-frame@7.0.0-beta.44":
+ version "7.0.0-beta.44"
+ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.44.tgz#2a02643368de80916162be70865c97774f3adbd9"
dependencies:
- "@babel/highlight" "7.0.0-beta.40"
+ "@babel/highlight" "7.0.0-beta.44"
-"@babel/generator@7.0.0-beta.40":
- version "7.0.0-beta.40"
- resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.0.0-beta.40.tgz#ab61f9556f4f71dbd1138949c795bb9a21e302ea"
+"@babel/generator@7.0.0-beta.44":
+ version "7.0.0-beta.44"
+ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.0.0-beta.44.tgz#c7e67b9b5284afcf69b309b50d7d37f3e5033d42"
dependencies:
- "@babel/types" "7.0.0-beta.40"
+ "@babel/types" "7.0.0-beta.44"
jsesc "^2.5.1"
lodash "^4.2.0"
source-map "^0.5.0"
trim-right "^1.0.1"
-"@babel/helper-function-name@7.0.0-beta.40":
- version "7.0.0-beta.40"
- resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.40.tgz#9d033341ab16517f40d43a73f2d81fc431ccd7b6"
+"@babel/helper-function-name@7.0.0-beta.44":
+ version "7.0.0-beta.44"
+ resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.44.tgz#e18552aaae2231100a6e485e03854bc3532d44dd"
dependencies:
- "@babel/helper-get-function-arity" "7.0.0-beta.40"
- "@babel/template" "7.0.0-beta.40"
- "@babel/types" "7.0.0-beta.40"
+ "@babel/helper-get-function-arity" "7.0.0-beta.44"
+ "@babel/template" "7.0.0-beta.44"
+ "@babel/types" "7.0.0-beta.44"
-"@babel/helper-get-function-arity@7.0.0-beta.40":
- version "7.0.0-beta.40"
- resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.40.tgz#ac0419cf067b0ec16453e1274f03878195791c6e"
+"@babel/helper-get-function-arity@7.0.0-beta.44":
+ version "7.0.0-beta.44"
+ resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.44.tgz#d03ca6dd2b9f7b0b1e6b32c56c72836140db3a15"
dependencies:
- "@babel/types" "7.0.0-beta.40"
+ "@babel/types" "7.0.0-beta.44"
-"@babel/highlight@7.0.0-beta.40":
- version "7.0.0-beta.40"
- resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0-beta.40.tgz#b43d67d76bf46e1d10d227f68cddcd263786b255"
+"@babel/helper-split-export-declaration@7.0.0-beta.44":
+ version "7.0.0-beta.44"
+ resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.44.tgz#c0b351735e0fbcb3822c8ad8db4e583b05ebd9dc"
+ dependencies:
+ "@babel/types" "7.0.0-beta.44"
+
+"@babel/highlight@7.0.0-beta.44":
+ version "7.0.0-beta.44"
+ resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0-beta.44.tgz#18c94ce543916a80553edcdcf681890b200747d5"
dependencies:
chalk "^2.0.0"
esutils "^2.0.2"
js-tokens "^3.0.0"
-"@babel/template@7.0.0-beta.40":
- version "7.0.0-beta.40"
- resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.40.tgz#034988c6424eb5c3268fe6a608626de1f4410fc8"
+"@babel/template@7.0.0-beta.44":
+ version "7.0.0-beta.44"
+ resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.44.tgz#f8832f4fdcee5d59bf515e595fc5106c529b394f"
dependencies:
- "@babel/code-frame" "7.0.0-beta.40"
- "@babel/types" "7.0.0-beta.40"
- babylon "7.0.0-beta.40"
+ "@babel/code-frame" "7.0.0-beta.44"
+ "@babel/types" "7.0.0-beta.44"
+ babylon "7.0.0-beta.44"
lodash "^4.2.0"
-"@babel/traverse@^7.0.0-beta.40":
- version "7.0.0-beta.40"
- resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0-beta.40.tgz#d140e449b2e093ef9fe1a2eecc28421ffb4e521e"
+"@babel/traverse@7.0.0-beta.44":
+ version "7.0.0-beta.44"
+ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0-beta.44.tgz#a970a2c45477ad18017e2e465a0606feee0d2966"
dependencies:
- "@babel/code-frame" "7.0.0-beta.40"
- "@babel/generator" "7.0.0-beta.40"
- "@babel/helper-function-name" "7.0.0-beta.40"
- "@babel/types" "7.0.0-beta.40"
- babylon "7.0.0-beta.40"
- debug "^3.0.1"
+ "@babel/code-frame" "7.0.0-beta.44"
+ "@babel/generator" "7.0.0-beta.44"
+ "@babel/helper-function-name" "7.0.0-beta.44"
+ "@babel/helper-split-export-declaration" "7.0.0-beta.44"
+ "@babel/types" "7.0.0-beta.44"
+ babylon "7.0.0-beta.44"
+ debug "^3.1.0"
globals "^11.1.0"
invariant "^2.2.0"
lodash "^4.2.0"
-"@babel/types@7.0.0-beta.40", "@babel/types@^7.0.0-beta.40":
- version "7.0.0-beta.40"
- resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.40.tgz#25c3d7aae14126abe05fcb098c65a66b6d6b8c14"
+"@babel/types@7.0.0-beta.44":
+ version "7.0.0-beta.44"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.44.tgz#6b1b164591f77dec0a0342aca995f2d046b3a757"
dependencies:
esutils "^2.0.2"
lodash "^4.2.0"
@@ -447,14 +454,14 @@ babel-core@^6.26.0:
slash "^1.0.0"
source-map "^0.5.7"
-babel-eslint@^8.0.2:
- version "8.2.2"
- resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-8.2.2.tgz#1102273354c6f0b29b4ea28a65f97d122296b68b"
+babel-eslint@^8.2.3:
+ version "8.2.3"
+ resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-8.2.3.tgz#1a2e6681cc9bc4473c32899e59915e19cd6733cf"
dependencies:
- "@babel/code-frame" "^7.0.0-beta.40"
- "@babel/traverse" "^7.0.0-beta.40"
- "@babel/types" "^7.0.0-beta.40"
- babylon "^7.0.0-beta.40"
+ "@babel/code-frame" "7.0.0-beta.44"
+ "@babel/traverse" "7.0.0-beta.44"
+ "@babel/types" "7.0.0-beta.44"
+ babylon "7.0.0-beta.44"
eslint-scope "~3.7.1"
eslint-visitor-keys "^1.0.0"
@@ -513,9 +520,9 @@ babel-helper-define-map@^6.24.1:
babel-types "^6.26.0"
lodash "^4.17.4"
-babel-helper-evaluate-path@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/babel-helper-evaluate-path/-/babel-helper-evaluate-path-0.2.0.tgz#0bb2eb01996c0cef53c5e8405e999fe4a0244c08"
+babel-helper-evaluate-path@^0.4.3:
+ version "0.4.3"
+ resolved "https://registry.yarnpkg.com/babel-helper-evaluate-path/-/babel-helper-evaluate-path-0.4.3.tgz#0a89af702c06b217027fa371908dd4989d3e633f"
babel-helper-explode-assignable-expression@^6.24.1:
version "6.24.1"
@@ -534,9 +541,9 @@ babel-helper-explode-class@^6.24.1:
babel-traverse "^6.24.1"
babel-types "^6.24.1"
-babel-helper-flip-expressions@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/babel-helper-flip-expressions/-/babel-helper-flip-expressions-0.2.0.tgz#160d2090a3d9f9c64a750905321a0bc218f884ec"
+babel-helper-flip-expressions@^0.4.3:
+ version "0.4.3"
+ resolved "https://registry.yarnpkg.com/babel-helper-flip-expressions/-/babel-helper-flip-expressions-0.4.3.tgz#3696736a128ac18bc25254b5f40a22ceb3c1d3fd"
babel-helper-function-name@^6.24.1:
version "6.24.1"
@@ -562,9 +569,9 @@ babel-helper-hoist-variables@^6.24.1:
babel-runtime "^6.22.0"
babel-types "^6.24.1"
-babel-helper-mark-eval-scopes@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.2.0.tgz#7648aaf2ec92aae9b09a20ad91e8df5e1fcc94b2"
+babel-helper-mark-eval-scopes@^0.4.3:
+ version "0.4.3"
+ resolved "https://registry.yarnpkg.com/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.4.3.tgz#d244a3bef9844872603ffb46e22ce8acdf551562"
babel-helper-optimise-call-expression@^6.24.1:
version "6.24.1"
@@ -591,9 +598,9 @@ babel-helper-remap-async-to-generator@^6.24.1:
babel-traverse "^6.24.1"
babel-types "^6.24.1"
-babel-helper-remove-or-void@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/babel-helper-remove-or-void/-/babel-helper-remove-or-void-0.2.0.tgz#8e46ad5b30560d57d7510b3fd93f332ee7c67386"
+babel-helper-remove-or-void@^0.4.3:
+ version "0.4.3"
+ resolved "https://registry.yarnpkg.com/babel-helper-remove-or-void/-/babel-helper-remove-or-void-0.4.3.tgz#a4f03b40077a0ffe88e45d07010dee241ff5ae60"
babel-helper-replace-supers@^6.24.1:
version "6.24.1"
@@ -633,20 +640,20 @@ babel-plugin-check-es2015-constants@^6.22.0:
dependencies:
babel-runtime "^6.22.0"
-babel-plugin-minify-dead-code-elimination@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-minify-dead-code-elimination/-/babel-plugin-minify-dead-code-elimination-0.2.0.tgz#e8025ee10a1e5e4f202633a6928ce892c33747e3"
+babel-plugin-minify-dead-code-elimination@^0.4.3:
+ version "0.4.3"
+ resolved "https://registry.yarnpkg.com/babel-plugin-minify-dead-code-elimination/-/babel-plugin-minify-dead-code-elimination-0.4.3.tgz#73628265864f9008d0027506f58abeb3c1d02d98"
dependencies:
- babel-helper-evaluate-path "^0.2.0"
- babel-helper-mark-eval-scopes "^0.2.0"
- babel-helper-remove-or-void "^0.2.0"
+ babel-helper-evaluate-path "^0.4.3"
+ babel-helper-mark-eval-scopes "^0.4.3"
+ babel-helper-remove-or-void "^0.4.3"
lodash.some "^4.6.0"
-babel-plugin-minify-guarded-expressions@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-minify-guarded-expressions/-/babel-plugin-minify-guarded-expressions-0.2.0.tgz#8a8c950040fce3e258a12e6eb21eab94ad7235ab"
+babel-plugin-minify-guarded-expressions@^0.4.3:
+ version "0.4.3"
+ resolved "https://registry.yarnpkg.com/babel-plugin-minify-guarded-expressions/-/babel-plugin-minify-guarded-expressions-0.4.3.tgz#cc709b4453fd21b1f302877444c89f88427ce397"
dependencies:
- babel-helper-flip-expressions "^0.2.0"
+ babel-helper-flip-expressions "^0.4.3"
babel-plugin-syntax-async-functions@^6.8.0:
version "6.13.0"
@@ -737,9 +744,9 @@ babel-plugin-transform-class-properties@^6.24.1:
babel-runtime "^6.22.0"
babel-template "^6.24.1"
-babel-plugin-transform-decorators-legacy@^1.3.4:
- version "1.3.4"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators-legacy/-/babel-plugin-transform-decorators-legacy-1.3.4.tgz#741b58f6c5bce9e6027e0882d9c994f04f366925"
+babel-plugin-transform-decorators-legacy@^1.3.5:
+ version "1.3.5"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators-legacy/-/babel-plugin-transform-decorators-legacy-1.3.5.tgz#0e492dffa0edd70529072887f8aa86d4dd8b40a1"
dependencies:
babel-plugin-syntax-decorators "^6.1.18"
babel-runtime "^6.2.0"
@@ -1181,9 +1188,9 @@ babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26
lodash "^4.17.4"
to-fast-properties "^1.0.3"
-babylon@7.0.0-beta.40, babylon@^7.0.0-beta.40:
- version "7.0.0-beta.40"
- resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.40.tgz#91fc8cd56d5eb98b28e6fde41045f2957779940a"
+babylon@7.0.0-beta.44:
+ version "7.0.0-beta.44"
+ resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.44.tgz#89159e15e6e30c5096e22d738d8c0af8a0e8ca1d"
babylon@^6.11.0, babylon@^6.17.4, babylon@^6.18.0:
version "6.18.0"
@@ -2320,7 +2327,7 @@ debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.4.1, debug@^2.6.
dependencies:
ms "2.0.0"
-debug@^3.0.1, debug@^3.1.0:
+debug@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
dependencies:
@@ -2495,7 +2502,7 @@ dns-txt@^2.0.2:
dependencies:
buffer-indexof "^1.0.0"
-doctrine@^2.0.2, doctrine@^2.1.0:
+doctrine@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
dependencies:
@@ -2822,12 +2829,12 @@ escope@^3.6.0:
esrecurse "^4.1.0"
estraverse "^4.1.1"
-eslint-config-kotori@^0.1.6:
- version "0.1.6"
- resolved "https://registry.yarnpkg.com/eslint-config-kotori/-/eslint-config-kotori-0.1.6.tgz#556c527515ba6eff8fe4c5063d04bc05c2bbee5e"
+eslint-config-kotori@^0.2.3:
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/eslint-config-kotori/-/eslint-config-kotori-0.2.3.tgz#330a0b38d7135f02272d03acd399e84676c3edfa"
dependencies:
- babel-eslint "^8.0.2"
- eslint-plugin-react "^7.3.0"
+ eslint-plugin-babel ">=5.0.0"
+ eslint-plugin-react ">=7.0.0"
eslint-loader@^1.9.0:
version "1.9.0"
@@ -2839,14 +2846,31 @@ eslint-loader@^1.9.0:
object-hash "^1.1.4"
rimraf "^2.6.1"
-eslint-plugin-react@^7.3.0:
- version "7.7.0"
- resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.7.0.tgz#f606c719dbd8a1a2b3d25c16299813878cca0160"
+eslint-plugin-babel@>=5.0.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-babel/-/eslint-plugin-babel-5.1.0.tgz#9c76e476162041e50b6ba69aa4eae3bdd6a4e1c3"
+ dependencies:
+ eslint-rule-composer "^0.3.0"
+
+eslint-plugin-prettier@^2.6.0:
+ version "2.6.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-2.6.0.tgz#33e4e228bdb06142d03c560ce04ec23f6c767dd7"
dependencies:
- doctrine "^2.0.2"
- has "^1.0.1"
+ fast-diff "^1.1.1"
+ jest-docblock "^21.0.0"
+
+eslint-plugin-react@>=7.0.0:
+ version "7.9.1"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.9.1.tgz#101aadd15e7c7b431ed025303ac7b421a8e3dc15"
+ dependencies:
+ doctrine "^2.1.0"
+ has "^1.0.2"
jsx-ast-utils "^2.0.1"
- prop-types "^15.6.0"
+ prop-types "^15.6.1"
+
+eslint-rule-composer@^0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz#79320c927b0c5c0d3d3d2b76c8b4a488f25bbaf9"
eslint-scope@^3.7.1, eslint-scope@~3.7.1:
version "3.7.1"
@@ -3143,6 +3167,10 @@ fast-deep-equal@^2.0.1:
version "2.0.1"
resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
+fast-diff@^1.1.1:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154"
+
fast-json-stable-stringify@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
@@ -3560,10 +3588,14 @@ global@^4.3.0:
min-document "^2.19.0"
process "~0.5.1"
-globals@^11.0.1, globals@^11.1.0:
+globals@^11.0.1:
version "11.3.0"
resolved "https://registry.yarnpkg.com/globals/-/globals-11.3.0.tgz#e04fdb7b9796d8adac9c8f64c14837b2313378b0"
+globals@^11.1.0:
+ version "11.5.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-11.5.0.tgz#6bc840de6771173b191f13d3a9c94d441ee92642"
+
globals@^9.18.0:
version "9.18.0"
resolved "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
@@ -3731,6 +3763,12 @@ has@^1.0.1:
dependencies:
function-bind "^1.0.2"
+has@^1.0.2:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
+ dependencies:
+ function-bind "^1.1.1"
+
hash-base@^3.0.0:
version "3.0.4"
resolved "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918"
@@ -4079,21 +4117,41 @@ interpret@^1.0.0:
version "1.1.0"
resolved "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614"
-invariant@^2.0.0, invariant@^2.2.0:
+intl-format-cache@^2.0.5:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/intl-format-cache/-/intl-format-cache-2.1.0.tgz#04a369fecbfad6da6005bae1f14333332dcf9316"
+
+intl-messageformat-parser@1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/intl-messageformat-parser/-/intl-messageformat-parser-1.4.0.tgz#b43d45a97468cadbe44331d74bb1e8dea44fc075"
+
+intl-messageformat@^2.0.0, intl-messageformat@^2.1.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-2.2.0.tgz#345bcd46de630b7683330c2e52177ff5eab484fc"
+ dependencies:
+ intl-messageformat-parser "1.4.0"
+
+intl-relativeformat@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/intl-relativeformat/-/intl-relativeformat-2.1.0.tgz#010f1105802251f40ac47d0e3e1a201348a255df"
+ dependencies:
+ intl-messageformat "^2.0.0"
+
+invariant@^2.0.0:
version "2.2.3"
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.3.tgz#1a827dfde7dcbd7c323f0ca826be8fa7c5e9d688"
dependencies:
loose-envify "^1.0.0"
-invariant@^2.2.1:
- version "2.2.2"
- resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360"
+invariant@^2.1.1, invariant@^2.2.0, invariant@^2.2.2:
+ version "2.2.4"
+ resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
dependencies:
loose-envify "^1.0.0"
-invariant@^2.2.2:
- version "2.2.4"
- resolved "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
+invariant@^2.2.1:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360"
dependencies:
loose-envify "^1.0.0"
@@ -4515,6 +4573,10 @@ istanbul-reports@^1.3.0:
dependencies:
handlebars "^4.0.3"
+jest-docblock@^21.0.0:
+ version "21.2.0"
+ resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414"
+
js-base64@^2.1.8:
version "2.4.3"
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.3.tgz#2e545ec2b0f2957f41356510205214e98fad6582"
@@ -6275,6 +6337,10 @@ preserve@^0.2.0:
version "0.2.0"
resolved "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
+prettier@^1.13.5:
+ version "1.13.5"
+ resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.13.5.tgz#7ae2076998c8edce79d63834e9b7b09fead6bfd0"
+
pretty-bytes@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-4.0.2.tgz#b2bf82e7350d65c6c33aa95aaa5a4f6327f61cd9"
@@ -6331,7 +6397,7 @@ prop-types@^15.5.0, prop-types@^15.5.4:
fbjs "^0.8.9"
loose-envify "^1.3.1"
-prop-types@^15.5.10:
+prop-types@^15.5.10, prop-types@^15.6.1:
version "15.6.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.1.tgz#36644453564255ddda391191fb3a125cbdf654ca"
dependencies:
@@ -6506,9 +6572,9 @@ react-document-title@^2.0.3:
prop-types "^15.5.6"
react-side-effect "^1.0.2"
-react-dom@^16.3.2:
- version "16.3.2"
- resolved "https://registry.npmjs.org/react-dom/-/react-dom-16.3.2.tgz#cb90f107e09536d683d84ed5d4888e9640e0e4df"
+react-dom@^16.4.1:
+ version "16.4.1"
+ resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.4.1.tgz#7f8b0223b3a5fbe205116c56deb85de32685dad6"
dependencies:
fbjs "^0.8.16"
loose-envify "^1.1.0"
@@ -6538,13 +6604,22 @@ react-image@^1.0.1:
dependencies:
prop-types "15.6.0"
+react-intl@^2.4.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/react-intl/-/react-intl-2.4.0.tgz#66c14dc9df9a73b2fbbfbd6021726e80a613eb15"
+ dependencies:
+ intl-format-cache "^2.0.5"
+ intl-messageformat "^2.1.0"
+ intl-relativeformat "^2.0.0"
+ invariant "^2.1.1"
+
react-is@^16.3.2:
version "16.3.2"
resolved "https://registry.npmjs.org/react-is/-/react-is-16.3.2.tgz#f4d3d0e2f5fbb6ac46450641eb2e25bf05d36b22"
-react-masonry-component@^6.2.0:
- version "6.2.0"
- resolved "https://registry.npmjs.org/react-masonry-component/-/react-masonry-component-6.2.0.tgz#e0689ff2b819da34785a8d8604ea52ff9e1caae6"
+react-masonry-component@^6.2.1:
+ version "6.2.1"
+ resolved "https://registry.yarnpkg.com/react-masonry-component/-/react-masonry-component-6.2.1.tgz#dd23b3129d6b922852b160472e6c9a6256fcdb8a"
dependencies:
create-react-class "^15.6.2"
element-resize-detector "^1.1.9"
@@ -6626,9 +6701,9 @@ react-test-renderer@^16.3.2:
prop-types "^15.6.0"
react-is "^16.3.2"
-react@^16.3.2:
- version "16.3.2"
- resolved "https://registry.npmjs.org/react/-/react-16.3.2.tgz#fdc8420398533a1e58872f59091b272ce2f91ea9"
+react@^16.4.1:
+ version "16.4.1"
+ resolved "https://registry.yarnpkg.com/react/-/react-16.4.1.tgz#de51ba5764b5dbcd1f9079037b862bd26b82fe32"
dependencies:
fbjs "^0.8.16"
loose-envify "^1.1.0"