Add support for i18n dates (fix #1395)
Also makes our existing date output in AddonDetails pretty.
This commit is contained in:
Родитель
6b957ac8ff
Коммит
3ee7a60853
|
@ -1,3 +1,4 @@
|
|||
server.babel.js
|
||||
dist
|
||||
coverage
|
||||
src/locale
|
||||
|
|
|
@ -12,6 +12,7 @@ const po2json = require('po2json');
|
|||
const glob = require('glob');
|
||||
const shelljs = require('shelljs');
|
||||
const chalk = require('chalk');
|
||||
const toSource = require('tosource');
|
||||
|
||||
const appName = config.get('appName');
|
||||
|
||||
|
@ -30,7 +31,7 @@ poFiles.forEach((pofile) => {
|
|||
const subdir = path.dirname(dir);
|
||||
const locale = path.basename(subdir);
|
||||
const stem = path.basename(pofile, '.po');
|
||||
const jsonfile = path.join(dest, locale, `${stem}.json`);
|
||||
const jsonfile = path.join(dest, locale, `${stem}.js`);
|
||||
shelljs.mkdir('-p', path.join(dest, locale));
|
||||
|
||||
const json = po2json.parseFileSync(pofile, {
|
||||
|
@ -39,5 +40,35 @@ poFiles.forEach((pofile) => {
|
|||
format: 'jed1.x',
|
||||
fuzzy: config.get('po2jsonFuzzyOutput'),
|
||||
});
|
||||
fs.writeFileSync(jsonfile, json);
|
||||
const localeObject = JSON.parse(json);
|
||||
|
||||
// Add the moment locale JS into our locale file, if one is available and
|
||||
// we're building for AMO (which is the only app that uses moment right
|
||||
// now).
|
||||
if (appName === 'amo') {
|
||||
var defineLocale = null;
|
||||
try {
|
||||
const momentLocale = locale.replace('_', '-').toLowerCase();
|
||||
// We're using `new Function()` here to create a function out of the
|
||||
// raw code in this file; this function won't be executed but will be
|
||||
// written out by `toSource()` so that it can be used later (at runtime,
|
||||
// by moment).
|
||||
defineLocale = new Function(
|
||||
fs.readFileSync(
|
||||
`./node_modules/moment/locale/${momentLocale}.js`, 'utf8'
|
||||
)
|
||||
);
|
||||
} catch (e) {
|
||||
// We ignore missing locale errors for en_US as its moment's default
|
||||
// locale so we don't need to provide a translation.
|
||||
if (locale !== 'en_US') {
|
||||
console.info(oneLine`No moment i18n available for ${locale};
|
||||
consider adding one or creating a mapping.`);
|
||||
}
|
||||
}
|
||||
|
||||
localeObject._momentDefineLocale = defineLocale;
|
||||
}
|
||||
|
||||
fs.writeFileSync(jsonfile, `module.exports = ${toSource(localeObject)}`);
|
||||
});
|
||||
|
|
|
@ -170,6 +170,7 @@
|
|||
"isomorphic-fetch": "2.2.1",
|
||||
"jed": "1.1.1",
|
||||
"jsdom": "9.9.1",
|
||||
"moment": "2.17.1",
|
||||
"mozilla-tabzilla": "0.5.1",
|
||||
"normalize.css": "5.0.0",
|
||||
"normalizr": "2.3.0",
|
||||
|
@ -254,6 +255,7 @@
|
|||
"supertest": "2.0.1",
|
||||
"supertest-as-promised": "4.0.2",
|
||||
"svg-url-loader": "1.1.0",
|
||||
"tosource": "1.0.0",
|
||||
"webpack": "1.14.0",
|
||||
"webpack-dev-middleware": "1.9.0",
|
||||
"webpack-dev-server": "1.16.2",
|
||||
|
|
|
@ -32,7 +32,16 @@ export class AddonMoreInfoBase extends React.Component {
|
|||
{addon.current_version.version}
|
||||
</dd>
|
||||
<dt>{i18n.gettext('Last updated')}</dt>
|
||||
<dd>{addon.last_updated}</dd>
|
||||
<dd>
|
||||
{i18n.sprintf(
|
||||
// L10n: This will output, in English:
|
||||
// "2 months ago (Dec 12 2016)"
|
||||
i18n.gettext('%(timeFromNow)s (%(date)s)'), {
|
||||
timeFromNow: i18n.moment(addon.last_updated).fromNow(),
|
||||
date: i18n.moment(addon.last_updated).format('ll'),
|
||||
}
|
||||
)}
|
||||
</dd>
|
||||
{addon.current_version.license ? (
|
||||
<dt ref={(ref) => { this.licenseHeader = ref; }}>
|
||||
{i18n.gettext('License')}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
import 'babel-polyfill';
|
||||
import config from 'config';
|
||||
import Jed from 'jed';
|
||||
import React from 'react';
|
||||
import { render } from 'react-dom';
|
||||
import { Provider } from 'react-redux';
|
||||
|
@ -10,7 +9,7 @@ import { applyRouterMiddleware, Router, browserHistory } from 'react-router';
|
|||
import { ReduxAsyncConnect } from 'redux-connect';
|
||||
import useScroll from 'react-router-scroll/lib/useScroll';
|
||||
|
||||
import { langToLocale, sanitizeLanguage } from 'core/i18n/utils';
|
||||
import { langToLocale, makeI18n, sanitizeLanguage } from 'core/i18n/utils';
|
||||
import I18nProvider from 'core/i18n/Provider';
|
||||
import log from 'core/logger';
|
||||
|
||||
|
@ -24,8 +23,8 @@ export default function makeClient(routes, createStore) {
|
|||
const locale = langToLocale(lang);
|
||||
const appName = config.get('appName');
|
||||
|
||||
function renderApp(jedData) {
|
||||
const i18n = new Jed(jedData);
|
||||
function renderApp(i18nData) {
|
||||
const i18n = makeI18n(i18nData);
|
||||
|
||||
if (initialStateContainer) {
|
||||
try {
|
||||
|
@ -44,7 +43,10 @@ export default function makeClient(routes, createStore) {
|
|||
),
|
||||
});
|
||||
|
||||
const middleware = applyRouterMiddleware(useScroll(), useReduxAsyncConnect());
|
||||
const middleware = applyRouterMiddleware(
|
||||
useScroll(),
|
||||
useReduxAsyncConnect(),
|
||||
);
|
||||
|
||||
render(
|
||||
<I18nProvider i18n={i18n}>
|
||||
|
@ -62,7 +64,7 @@ export default function makeClient(routes, createStore) {
|
|||
try {
|
||||
if (locale !== langToLocale(config.get('defaultLang'))) {
|
||||
// eslint-disable-next-line max-len, global-require, import/no-dynamic-require
|
||||
require(`bundle?name=[name]-i18n-[folder]!json!../../locale/${locale}/${appName}.json`)(renderApp);
|
||||
require(`bundle?name=[name]-i18n-[folder]!../../locale/${locale}/${appName}.js`)(renderApp);
|
||||
} else {
|
||||
renderApp({});
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ function getDisplayName(component) {
|
|||
return component.displayName || component.name || 'Component';
|
||||
}
|
||||
|
||||
|
||||
export default function translate(options = {}) {
|
||||
const { withRef = false } = options;
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import config from 'config';
|
||||
import Jed from 'jed';
|
||||
import moment from 'moment';
|
||||
|
||||
import log from 'core/logger';
|
||||
|
||||
|
@ -173,3 +175,26 @@ export function getLanguage({ lang, acceptLanguage } = {}) {
|
|||
// - normalization e.g: en-us -> en-US.
|
||||
return { lang: sanitizeLanguage(userLang), isLangFromHeader };
|
||||
}
|
||||
|
||||
// moment uses locales like "en-gb" whereas we use "en_GB".
|
||||
export function makeMomentLocale(locale) {
|
||||
return locale.replace('_', '-').toLowerCase();
|
||||
}
|
||||
|
||||
// Create an i18n object with a translated moment object available we can
|
||||
// use for translated dates across the app.
|
||||
export function makeI18n(i18nData, _Jed = Jed) {
|
||||
const i18n = new _Jed(i18nData);
|
||||
|
||||
// This adds the correct moment locale for the active locale so we can get
|
||||
// localised dates, times, etc.
|
||||
if (i18n.options && typeof i18n.options._momentDefineLocale === 'function') {
|
||||
i18n.options._momentDefineLocale();
|
||||
moment.locale(makeMomentLocale(i18n.options.locale_data.messages[''].lang));
|
||||
}
|
||||
|
||||
// We add a translated "moment" property to our `i18n` object
|
||||
// to make translated date/time/etc. easy.
|
||||
i18n.moment = moment;
|
||||
return i18n;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import 'babel-polyfill';
|
|||
import config from 'config';
|
||||
import Express from 'express';
|
||||
import helmet from 'helmet';
|
||||
import Jed from 'jed';
|
||||
import cookie from 'react-cookie';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/server';
|
||||
|
@ -19,7 +18,12 @@ import { prefixMiddleWare } from 'core/middleware';
|
|||
import { convertBoolean } from 'core/utils';
|
||||
import { setClientApp, setLang, setJWT } from 'core/actions';
|
||||
import log from 'core/logger';
|
||||
import { getDirection, isValidLang, langToLocale } from 'core/i18n/utils';
|
||||
import {
|
||||
getDirection,
|
||||
isValidLang,
|
||||
langToLocale,
|
||||
makeI18n,
|
||||
} from 'core/i18n/utils';
|
||||
import I18nProvider from 'core/i18n/Provider';
|
||||
|
||||
import WebpackIsomorphicToolsConfig from './webpack-isomorphic-tools-config';
|
||||
|
@ -121,7 +125,9 @@ function baseServer(routes, createStore, { appInstanceName = appName } = {}) {
|
|||
webpackIsomorphicTools.refresh();
|
||||
}
|
||||
|
||||
match({ routes, location: req.url }, (err, redirectLocation, renderProps) => {
|
||||
match({ location: req.url, routes }, (
|
||||
err, redirectLocation, renderProps
|
||||
) => {
|
||||
cookie.plugToRequest(req, res);
|
||||
|
||||
if (err) {
|
||||
|
@ -182,17 +188,19 @@ function baseServer(routes, createStore, { appInstanceName = appName } = {}) {
|
|||
return loadOnServer({ ...renderProps, store })
|
||||
.then(() => {
|
||||
// eslint-disable-next-line global-require
|
||||
let jedData = {};
|
||||
let i18nData = {};
|
||||
try {
|
||||
if (locale !== langToLocale(config.get('defaultLang'))) {
|
||||
// eslint-disable-next-line global-require, import/no-dynamic-require
|
||||
jedData = require(`json!../../locale/${locale}/${appInstanceName}.json`);
|
||||
i18nData = require(
|
||||
`../../locale/${locale}/${appInstanceName}.js`);
|
||||
}
|
||||
} catch (e) {
|
||||
log.info(`Locale JSON not found or required for locale: "${locale}"`);
|
||||
log.info(`Falling back to default lang: "${config.get('defaultLang')}".`);
|
||||
}
|
||||
const i18n = new Jed(jedData);
|
||||
const i18n = makeI18n(i18nData);
|
||||
|
||||
const InitialComponent = (
|
||||
<I18nProvider i18n={i18n}>
|
||||
<Provider store={store} key="provider">
|
||||
|
|
|
@ -5,8 +5,9 @@ require('./tests/client/init');
|
|||
|
||||
const testsContext = require.context('./tests/client/', true, /\.js$/);
|
||||
const componentsContext = require.context(
|
||||
// This regex excludes server.js or server/*.js
|
||||
'./src/', true, /^(?:(?!server|config|client).)*\.js$/);
|
||||
// This regex excludes everything in locale/**/*.js, server.js, and
|
||||
// server/*.js
|
||||
'./src/', true, /^(?:(?!locale\/[A-Za-z_]{2,5}\/|server|config|client).)*\.js$/);
|
||||
|
||||
testsContext.keys().forEach(testsContext);
|
||||
componentsContext.keys().forEach(componentsContext);
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import config from 'config';
|
||||
import moment from 'moment';
|
||||
|
||||
import * as utils from 'core/i18n/utils';
|
||||
|
||||
|
||||
const defaultLang = config.get('defaultLang');
|
||||
|
||||
|
||||
|
@ -387,4 +389,54 @@ describe('i18n utils', () => {
|
|||
assert.equal(result, undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('makeI18n', () => {
|
||||
let FakeJed;
|
||||
|
||||
before(() => {
|
||||
FakeJed = class {
|
||||
constructor(i18nData) {
|
||||
return i18nData;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
// FIXME: Our moment is not immutable so we reset it before each test.
|
||||
// This is annoying to work around because of the locale `require()`s
|
||||
// and it only affects tests so it'd be nice to fix but doesn't break
|
||||
// anything.
|
||||
moment.locale('en');
|
||||
});
|
||||
|
||||
it('adds a localised moment to the i18n object', () => {
|
||||
const i18nData = {};
|
||||
const i18n = utils.makeI18n(i18nData, FakeJed);
|
||||
assert.ok(i18n.moment);
|
||||
assert.typeOf(i18n.moment, 'function');
|
||||
});
|
||||
|
||||
it('tries to localise moment', () => {
|
||||
const i18nData = {
|
||||
options: {
|
||||
_momentDefineLocale: sinon.stub(),
|
||||
locale_data: { messages: { '': { lang: 'fr' } } },
|
||||
},
|
||||
};
|
||||
const i18n = utils.makeI18n(i18nData, FakeJed);
|
||||
assert.equal(i18n.moment.locale(), 'fr');
|
||||
});
|
||||
|
||||
it('does not localise if _momentDefineLocale is not a function', () => {
|
||||
const i18nData = {
|
||||
options: {
|
||||
_momentDefineLocale: null,
|
||||
locale_data: { messages: { '': { lang: 'fr' } } },
|
||||
},
|
||||
};
|
||||
|
||||
const i18n = utils.makeI18n(i18nData, FakeJed);
|
||||
assert.equal(i18n.moment.locale(), 'en');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import base64url from 'base64url';
|
||||
import { sprintf } from 'jed';
|
||||
import moment from 'moment';
|
||||
import React from 'react';
|
||||
import { createRenderer } from 'react-addons-test-utils';
|
||||
|
||||
|
@ -77,6 +78,7 @@ export function getFakeI18nInst() {
|
|||
npgettext: sinon.stub(),
|
||||
dnpgettext: sinon.stub(),
|
||||
sprintf: sinon.spy(sprintf),
|
||||
moment,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -107,10 +107,12 @@ export default Object.assign({}, webpackConfig, {
|
|||
}),
|
||||
// Replaces server config module with the subset clientConfig object.
|
||||
new webpack.NormalModuleReplacementPlugin(/config$/, 'core/client/config.js'),
|
||||
// Prevent locales with moment require calls from crashing
|
||||
new webpack.NormalModuleReplacementPlugin(/\.\.\/moment$/, 'moment'),
|
||||
// This allow us to exclude locales for other apps being built.
|
||||
new webpack.ContextReplacementPlugin(
|
||||
/locale$/,
|
||||
new RegExp(`^\\.\\/.*?\\/${appName}\\.json$`)
|
||||
new RegExp(`^\\.\\/.*?\\/${appName}\\.js$`)
|
||||
),
|
||||
// Substitutes client only config.
|
||||
new webpack.NormalModuleReplacementPlugin(/core\/logger$/, 'core/client/logger.js'),
|
||||
|
|
|
@ -78,6 +78,8 @@ const settings = {
|
|||
}),
|
||||
// Replaces server config module with the subset clientConfig object.
|
||||
new webpack.NormalModuleReplacementPlugin(/config$/, 'core/client/config.js'),
|
||||
// Prevent locales with moment require calls from crashing
|
||||
new webpack.NormalModuleReplacementPlugin(/\.\.\/moment$/, 'moment'),
|
||||
// Substitutes client only config.
|
||||
new webpack.NormalModuleReplacementPlugin(/core\/logger$/, 'core/client/logger.js'),
|
||||
// Use the browser's window for window.
|
||||
|
@ -85,7 +87,7 @@ const settings = {
|
|||
// This allow us to exclude locales for other apps being built.
|
||||
new webpack.ContextReplacementPlugin(
|
||||
/locale$/,
|
||||
new RegExp(`^\\.\\/.*?\\/${appName}\\.json$`)
|
||||
new RegExp(`^\\.\\/.*?\\/${appName}\\.js$`)
|
||||
),
|
||||
new ExtractTextPlugin('[name]-[contenthash].css', { allChunks: true }),
|
||||
new SriStatsPlugin({
|
||||
|
|
184
yarn.lock
184
yarn.lock
|
@ -280,19 +280,19 @@ babel-code-frame@^6.11.0, babel-code-frame@^6.16.0, babel-code-frame@^6.20.0:
|
|||
esutils "^2.0.2"
|
||||
js-tokens "^2.0.0"
|
||||
|
||||
babel-core@6.20.0, babel-core@^6.18.0:
|
||||
version "6.20.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.20.0.tgz#ab0d7176d9dea434e66badadaf92237865eab1ec"
|
||||
babel-core@6.21.0, babel-core@^6.18.0:
|
||||
version "6.21.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.21.0.tgz#75525480c21c803f826ef3867d22c19f080a3724"
|
||||
dependencies:
|
||||
babel-code-frame "^6.20.0"
|
||||
babel-generator "^6.20.0"
|
||||
babel-generator "^6.21.0"
|
||||
babel-helpers "^6.16.0"
|
||||
babel-messages "^6.8.0"
|
||||
babel-register "^6.18.0"
|
||||
babel-runtime "^6.20.0"
|
||||
babel-template "^6.16.0"
|
||||
babel-traverse "^6.20.0"
|
||||
babel-types "^6.20.0"
|
||||
babel-traverse "^6.21.0"
|
||||
babel-types "^6.21.0"
|
||||
babylon "^6.11.0"
|
||||
convert-source-map "^1.1.0"
|
||||
debug "^2.1.1"
|
||||
|
@ -313,13 +313,13 @@ babel-eslint@7.1.0:
|
|||
babylon "^6.11.2"
|
||||
lodash.pickby "^4.6.0"
|
||||
|
||||
babel-generator@^6.18.0, babel-generator@^6.20.0:
|
||||
version "6.20.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.20.0.tgz#fee63614e0449390103b3097f3f6a118016c6766"
|
||||
babel-generator@^6.18.0, babel-generator@^6.21.0:
|
||||
version "6.21.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.21.0.tgz#605f1269c489a1c75deeca7ea16d43d4656c8494"
|
||||
dependencies:
|
||||
babel-messages "^6.8.0"
|
||||
babel-runtime "^6.20.0"
|
||||
babel-types "^6.20.0"
|
||||
babel-types "^6.21.0"
|
||||
detect-indent "^4.0.0"
|
||||
jsesc "^1.3.0"
|
||||
lodash "^4.2.0"
|
||||
|
@ -919,23 +919,23 @@ babel-template@^6.14.0, babel-template@^6.15.0, babel-template@^6.16.0, babel-te
|
|||
babylon "^6.11.0"
|
||||
lodash "^4.2.0"
|
||||
|
||||
babel-traverse@^6.15.0, babel-traverse@^6.16.0, babel-traverse@^6.18.0, babel-traverse@^6.20.0:
|
||||
version "6.20.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.20.0.tgz#5378d1a743e3d856e6a52289994100bbdfd9872a"
|
||||
babel-traverse@^6.15.0, babel-traverse@^6.16.0, babel-traverse@^6.18.0, babel-traverse@^6.21.0:
|
||||
version "6.21.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.21.0.tgz#69c6365804f1a4f69eb1213f85b00a818b8c21ad"
|
||||
dependencies:
|
||||
babel-code-frame "^6.20.0"
|
||||
babel-messages "^6.8.0"
|
||||
babel-runtime "^6.20.0"
|
||||
babel-types "^6.20.0"
|
||||
babel-types "^6.21.0"
|
||||
babylon "^6.11.0"
|
||||
debug "^2.2.0"
|
||||
globals "^9.0.0"
|
||||
invariant "^2.2.0"
|
||||
lodash "^4.2.0"
|
||||
|
||||
babel-types@^6.13.0, babel-types@^6.15.0, babel-types@^6.16.0, babel-types@^6.18.0, babel-types@^6.20.0, babel-types@^6.8.0, babel-types@^6.9.0:
|
||||
version "6.20.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.20.0.tgz#3869ecb98459533b37df809886b3f7f3b08d2baa"
|
||||
babel-types@^6.13.0, babel-types@^6.15.0, babel-types@^6.16.0, babel-types@^6.18.0, babel-types@^6.21.0, babel-types@^6.8.0, babel-types@^6.9.0:
|
||||
version "6.21.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.21.0.tgz#314b92168891ef6d3806b7f7a917fdf87c11a4b2"
|
||||
dependencies:
|
||||
babel-runtime "^6.20.0"
|
||||
esutils "^2.0.2"
|
||||
|
@ -1278,7 +1278,7 @@ clap@^1.0.9:
|
|||
dependencies:
|
||||
chalk "^1.1.3"
|
||||
|
||||
classnames@2.2.5:
|
||||
classnames@2.2.5, classnames@^2.2.3:
|
||||
version "2.2.5"
|
||||
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.5.tgz#fb3801d453467649ef3603c7d61a02bd129bde6d"
|
||||
|
||||
|
@ -1569,7 +1569,7 @@ core-util-is@1.0.2, core-util-is@~1.0.0:
|
|||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||
|
||||
cosmiconfig@^2.0.0, cosmiconfig@^2.1.0, cosmiconfig@^2.1.1:
|
||||
cosmiconfig@^2.1.0, cosmiconfig@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-2.1.1.tgz#817f2c2039347a1e9bf7d090c0923e53f749ca82"
|
||||
dependencies:
|
||||
|
@ -2438,11 +2438,13 @@ fbjs@^0.8.1, fbjs@^0.8.4:
|
|||
promise "^7.1.1"
|
||||
ua-parser-js "^0.7.9"
|
||||
|
||||
fetch-mock@5.6.0:
|
||||
version "5.6.0"
|
||||
resolved "https://registry.yarnpkg.com/fetch-mock/-/fetch-mock-5.6.0.tgz#afdde7c5ef0d95e71cc35803e325d23d471d1cab"
|
||||
fetch-mock@5.8.0:
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/fetch-mock/-/fetch-mock-5.8.0.tgz#1e80df8be828afc6879621ef662da70172790a08"
|
||||
dependencies:
|
||||
glob-to-regexp "^0.3.0"
|
||||
node-fetch "^1.3.3"
|
||||
path-to-regexp "^1.7.0"
|
||||
|
||||
figures@^1.3.5:
|
||||
version "1.7.0"
|
||||
|
@ -2718,6 +2720,10 @@ glob-parent@^2.0.0:
|
|||
dependencies:
|
||||
is-glob "^2.0.0"
|
||||
|
||||
glob-to-regexp@^0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab"
|
||||
|
||||
glob@7.0.5:
|
||||
version "7.0.5"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.5.tgz#b4202a69099bbb4d292a7c1b95b6682b67ebdc95"
|
||||
|
@ -3036,14 +3042,10 @@ https-browserify@0.0.1:
|
|||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-0.0.1.tgz#3f91365cabe60b77ed0ebba24b454e3e09d95a82"
|
||||
|
||||
iconv-lite@0.4.13:
|
||||
iconv-lite@0.4.13, iconv-lite@^0.4.13, iconv-lite@~0.4.13:
|
||||
version "0.4.13"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.13.tgz#1f88aba4ab0b1508e8312acc39345f36e992e2f2"
|
||||
|
||||
iconv-lite@^0.4.13, iconv-lite@~0.4.13:
|
||||
version "0.4.15"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb"
|
||||
|
||||
icss-replace-symbols@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.0.2.tgz#cb0b6054eb3af6edc9ab1d62d01933e2d4c8bfa5"
|
||||
|
@ -3406,9 +3408,9 @@ jsbn@~0.1.0:
|
|||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.0.tgz#650987da0dd74f4ebf5a11377a2aa2d273e97dfd"
|
||||
|
||||
jsdom@9.8.3:
|
||||
version "9.8.3"
|
||||
resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-9.8.3.tgz#fde29c109c32a1131e0b6c65914e64198f97c370"
|
||||
jsdom@9.9.1:
|
||||
version "9.9.1"
|
||||
resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-9.9.1.tgz#84f3972ad394ab963233af8725211bce4d01bfd5"
|
||||
dependencies:
|
||||
abab "^1.0.0"
|
||||
acorn "^2.4.0"
|
||||
|
@ -3420,7 +3422,7 @@ jsdom@9.8.3:
|
|||
escodegen "^1.6.1"
|
||||
html-encoding-sniffer "^1.0.1"
|
||||
iconv-lite "^0.4.13"
|
||||
nwmatcher ">= 1.3.7 < 2.0.0"
|
||||
nwmatcher ">= 1.3.9 < 2.0.0"
|
||||
parse5 "^1.5.1"
|
||||
request "^2.55.0"
|
||||
sax "^1.1.4"
|
||||
|
@ -3428,7 +3430,7 @@ jsdom@9.8.3:
|
|||
tough-cookie "^2.3.1"
|
||||
webidl-conversions "^3.0.1"
|
||||
whatwg-encoding "^1.0.1"
|
||||
whatwg-url "^3.0.0"
|
||||
whatwg-url "^4.1.0"
|
||||
xml-name-validator ">= 2.0.1 < 3.0.0"
|
||||
|
||||
jsesc@^1.3.0:
|
||||
|
@ -3615,9 +3617,9 @@ klaw@^1.0.0:
|
|||
optionalDependencies:
|
||||
graceful-fs "^4.1.9"
|
||||
|
||||
known-css-properties@^0.0.5:
|
||||
version "0.0.5"
|
||||
resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.0.5.tgz#33de5b8279010a72db917d33119e4c27c078490a"
|
||||
known-css-properties@^0.0.6:
|
||||
version "0.0.6"
|
||||
resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.0.6.tgz#71a0b8fde1b6e3431c471efbc3d9733faebbcfbf"
|
||||
|
||||
lazy-cache@^1.0.3:
|
||||
version "1.0.4"
|
||||
|
@ -3675,7 +3677,7 @@ loader-utils@0.2.x, loader-utils@^0.2.11, loader-utils@^0.2.15, loader-utils@^0.
|
|||
json5 "^0.5.0"
|
||||
object-assign "^4.0.1"
|
||||
|
||||
lodash-es@^4.2.0, lodash-es@^4.2.1:
|
||||
lodash-es@^4.2.1:
|
||||
version "4.17.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.2.tgz#59011b585166e613eb9dd5fc256b2cd1a30f3712"
|
||||
|
||||
|
@ -3778,6 +3780,10 @@ lodash.merge@^4.4.0:
|
|||
version "4.6.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.0.tgz#69884ba144ac33fe699737a6086deffadd0f89c5"
|
||||
|
||||
lodash.mergewith@^4.6.0:
|
||||
version "4.6.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.0.tgz#150cf0a16791f5903b8891eab154609274bdea55"
|
||||
|
||||
lodash.pick@^4.2.1:
|
||||
version "4.4.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3"
|
||||
|
@ -4131,9 +4137,9 @@ node-pre-gyp@^0.6.29:
|
|||
tar "~2.2.1"
|
||||
tar-pack "~3.3.0"
|
||||
|
||||
node-sass@3.13.1:
|
||||
version "3.13.1"
|
||||
resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-3.13.1.tgz#7240fbbff2396304b4223527ed3020589c004fc2"
|
||||
node-sass@4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.1.1.tgz#dc3e27d25bd827b6276ea243be357c7c7cd07111"
|
||||
dependencies:
|
||||
async-foreach "^0.1.3"
|
||||
chalk "^1.1.1"
|
||||
|
@ -4144,6 +4150,7 @@ node-sass@3.13.1:
|
|||
in-publish "^2.0.0"
|
||||
lodash.assign "^4.2.0"
|
||||
lodash.clonedeep "^4.3.2"
|
||||
lodash.mergewith "^4.6.0"
|
||||
meow "^3.7.0"
|
||||
mkdirp "^0.5.1"
|
||||
nan "^2.3.2"
|
||||
|
@ -4151,6 +4158,7 @@ node-sass@3.13.1:
|
|||
npmlog "^4.0.0"
|
||||
request "^2.61.0"
|
||||
sass-graph "^2.1.1"
|
||||
stdout-stream "^1.4.0"
|
||||
|
||||
node-uuid@~1.4.7:
|
||||
version "1.4.7"
|
||||
|
@ -4241,7 +4249,7 @@ number-is-nan@^1.0.0:
|
|||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
|
||||
|
||||
"nwmatcher@>= 1.3.7 < 2.0.0":
|
||||
"nwmatcher@>= 1.3.9 < 2.0.0":
|
||||
version "1.3.9"
|
||||
resolved "https://registry.yarnpkg.com/nwmatcher/-/nwmatcher-1.3.9.tgz#8bab486ff7fa3dfd086656bbe8b17116d3692d2a"
|
||||
|
||||
|
@ -4424,6 +4432,12 @@ path-to-regexp@0.1.7:
|
|||
version "0.1.7"
|
||||
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
|
||||
|
||||
path-to-regexp@^1.7.0:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d"
|
||||
dependencies:
|
||||
isarray "0.0.1"
|
||||
|
||||
path-type@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
|
||||
|
@ -4436,6 +4450,10 @@ pbkdf2-compat@2.0.1:
|
|||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/pbkdf2-compat/-/pbkdf2-compat-2.0.1.tgz#b6e0c8fa99494d94e0511575802a59a5c142f288"
|
||||
|
||||
photoswipe@^4.1.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/photoswipe/-/photoswipe-4.1.1.tgz#41b756a2387e220c286598945503014bf622bba9"
|
||||
|
||||
pify@^2.0.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
|
||||
|
@ -4737,9 +4755,9 @@ postcss-reporter@^1.2.1, postcss-reporter@^1.3.3:
|
|||
log-symbols "^1.0.2"
|
||||
postcss "^5.0.0"
|
||||
|
||||
postcss-reporter@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/postcss-reporter/-/postcss-reporter-2.0.0.tgz#d25e74ba7fce911e2aa72ec1ae592fade6ec3671"
|
||||
postcss-reporter@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/postcss-reporter/-/postcss-reporter-3.0.0.tgz#09ea0f37a444c5693878606e09b018ebeff7cf8f"
|
||||
dependencies:
|
||||
chalk "^1.0.0"
|
||||
lodash "^4.1.0"
|
||||
|
@ -4984,6 +5002,14 @@ react-onclickoutside@5.7.1:
|
|||
dependencies:
|
||||
object-assign "^4.0.1"
|
||||
|
||||
react-photoswipe@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react-photoswipe/-/react-photoswipe-1.2.0.tgz#e296e1150ed153bb2ddbc7222165291c13fe4e8c"
|
||||
dependencies:
|
||||
classnames "^2.2.3"
|
||||
lodash.pick "^4.2.1"
|
||||
photoswipe "^4.1.0"
|
||||
|
||||
react-proxy@^1.1.7:
|
||||
version "1.1.8"
|
||||
resolved "https://registry.yarnpkg.com/react-proxy/-/react-proxy-1.1.8.tgz#9dbfd9d927528c3aa9f444e4558c37830ab8c26a"
|
||||
|
@ -4991,17 +5017,7 @@ react-proxy@^1.1.7:
|
|||
lodash "^4.6.1"
|
||||
react-deep-force-update "^1.0.0"
|
||||
|
||||
react-redux@5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.0.tgz#2693227b19876b6e0047f4b94eb4910f43b677ca"
|
||||
dependencies:
|
||||
hoist-non-react-statics "^1.0.3"
|
||||
invariant "^2.0.0"
|
||||
lodash "^4.2.0"
|
||||
lodash-es "^4.2.0"
|
||||
loose-envify "^1.1.0"
|
||||
|
||||
react-redux@^4.0.0:
|
||||
react-redux@4.4.6, react-redux@^4.0.0:
|
||||
version "4.4.6"
|
||||
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-4.4.6.tgz#4b9d32985307a11096a2dd61561980044fcc6209"
|
||||
dependencies:
|
||||
|
@ -5430,9 +5446,9 @@ sass-graph@^2.1.1:
|
|||
lodash "^4.0.0"
|
||||
yargs "^4.7.1"
|
||||
|
||||
sass-loader@4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-4.1.0.tgz#fd8604c5bf90001b173bb27540e8f2f5ed64602b"
|
||||
sass-loader@4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-4.1.1.tgz#79ef9468cf0bf646c29529e1f2cba6bd6e51c7bc"
|
||||
dependencies:
|
||||
async "^2.0.1"
|
||||
loader-utils "^0.2.15"
|
||||
|
@ -5722,6 +5738,12 @@ sshpk@^1.7.0:
|
|||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e"
|
||||
|
||||
stdout-stream@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.0.tgz#a2c7c8587e54d9427ea9edb3ac3f2cd522df378b"
|
||||
dependencies:
|
||||
readable-stream "^2.0.1"
|
||||
|
||||
stream-browserify@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db"
|
||||
|
@ -5839,19 +5861,19 @@ stylehacks@^2.3.0:
|
|||
text-table "^0.2.0"
|
||||
write-file-stdout "0.0.2"
|
||||
|
||||
stylelint-config-standard@14.0.0:
|
||||
version "14.0.0"
|
||||
resolved "https://registry.yarnpkg.com/stylelint-config-standard/-/stylelint-config-standard-14.0.0.tgz#1164b79c3a1dd924ace1b756ad8ec00cbccb8132"
|
||||
stylelint-config-standard@15.0.1:
|
||||
version "15.0.1"
|
||||
resolved "https://registry.yarnpkg.com/stylelint-config-standard/-/stylelint-config-standard-15.0.1.tgz#f588e036bca6bb52391ea784198e773a9ca70efe"
|
||||
|
||||
stylelint@7.6.0:
|
||||
version "7.6.0"
|
||||
resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-7.6.0.tgz#ddeb06ccc95f72c119fcde5e85439fb7e9cde4df"
|
||||
stylelint@7.7.0:
|
||||
version "7.7.0"
|
||||
resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-7.7.0.tgz#bf222c2a202c0b02d7834ad321fe0883d33cfde0"
|
||||
dependencies:
|
||||
autoprefixer "^6.0.0"
|
||||
balanced-match "^0.4.0"
|
||||
chalk "^1.1.1"
|
||||
colorguard "^1.2.0"
|
||||
cosmiconfig "^2.0.0"
|
||||
cosmiconfig "^2.1.1"
|
||||
doiuse "^2.4.1"
|
||||
execall "^1.0.0"
|
||||
get-stdin "^5.0.0"
|
||||
|
@ -5859,7 +5881,7 @@ stylelint@7.6.0:
|
|||
globjoin "^0.1.4"
|
||||
html-tags "^1.1.1"
|
||||
ignore "^3.2.0"
|
||||
known-css-properties "^0.0.5"
|
||||
known-css-properties "^0.0.6"
|
||||
lodash "^4.0.0"
|
||||
log-symbols "^1.0.2"
|
||||
meow "^3.3.0"
|
||||
|
@ -5868,7 +5890,7 @@ stylelint@7.6.0:
|
|||
postcss "^5.0.20"
|
||||
postcss-less "^0.14.0"
|
||||
postcss-media-query-parser "^0.2.0"
|
||||
postcss-reporter "^2.0.0"
|
||||
postcss-reporter "^3.0.0"
|
||||
postcss-resolve-nested-selector "^0.1.1"
|
||||
postcss-scss "^0.4.0"
|
||||
postcss-selector-parser "^2.1.1"
|
||||
|
@ -5880,7 +5902,7 @@ stylelint@7.6.0:
|
|||
stylehacks "^2.3.0"
|
||||
sugarss "^0.2.0"
|
||||
svg-tags "^1.0.0"
|
||||
table "^3.7.8"
|
||||
table "^4.0.1"
|
||||
|
||||
sugarss@^0.2.0:
|
||||
version "0.2.0"
|
||||
|
@ -5991,6 +6013,17 @@ table@^3.7.8:
|
|||
slice-ansi "0.0.4"
|
||||
string-width "^2.0.0"
|
||||
|
||||
table@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/table/-/table-4.0.1.tgz#a8116c133fac2c61f4a420ab6cdf5c4d61f0e435"
|
||||
dependencies:
|
||||
ajv "^4.7.0"
|
||||
ajv-keywords "^1.0.0"
|
||||
chalk "^1.1.1"
|
||||
lodash "^4.0.0"
|
||||
slice-ansi "0.0.4"
|
||||
string-width "^2.0.0"
|
||||
|
||||
tapable@^0.1.8, tapable@~0.1.8:
|
||||
version "0.1.10"
|
||||
resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.1.10.tgz#29c35707c2b70e50d07482b5d202e8ed446dafd4"
|
||||
|
@ -6320,7 +6353,7 @@ webpack-custom-stats-patch@^0.3.0:
|
|||
dependencies:
|
||||
lodash.merge "^4.4.0"
|
||||
|
||||
webpack-dev-middleware@1.9.0:
|
||||
webpack-dev-middleware@1.9.0, webpack-dev-middleware@^1.0.11, webpack-dev-middleware@^1.4.0:
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-1.9.0.tgz#a1c67a3dfd8a5c5d62740aa0babe61758b4c84aa"
|
||||
dependencies:
|
||||
|
@ -6329,15 +6362,6 @@ webpack-dev-middleware@1.9.0:
|
|||
path-is-absolute "^1.0.0"
|
||||
range-parser "^1.0.3"
|
||||
|
||||
webpack-dev-middleware@^1.0.11, webpack-dev-middleware@^1.4.0:
|
||||
version "1.8.4"
|
||||
resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-1.8.4.tgz#e8765c9122887ce9e3abd4cc9c3eb31b61e0948d"
|
||||
dependencies:
|
||||
memory-fs "~0.3.0"
|
||||
mime "^1.3.4"
|
||||
path-is-absolute "^1.0.0"
|
||||
range-parser "^1.0.3"
|
||||
|
||||
webpack-dev-server@1.16.2:
|
||||
version "1.16.2"
|
||||
resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-1.16.2.tgz#8bebc2c4ce1c45a15c72dd769d9ba08db306a793"
|
||||
|
@ -6427,9 +6451,9 @@ whatwg-fetch@^0.9.0:
|
|||
version "0.9.0"
|
||||
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-0.9.0.tgz#0e3684c6cb9995b43efc9df03e4c365d95fd9cc0"
|
||||
|
||||
whatwg-url@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-3.1.0.tgz#7bdcae490f921aef6451fb6739ec6bbd8e907bf6"
|
||||
whatwg-url@^4.1.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-4.1.1.tgz#567074923352de781e3500d64a86aa92a971b4a4"
|
||||
dependencies:
|
||||
tr46 "~0.0.3"
|
||||
webidl-conversions "^3.0.0"
|
||||
|
|
Загрузка…
Ссылка в новой задаче