feat: Use prettier-eslint to format code

This commit is contained in:
Bouncey
2019-02-18 19:32:49 +00:00
committed by mrugesh mohapatra
parent 1ba67c4e2b
commit b13e5fb41a
82 changed files with 1767 additions and 1017 deletions

View File

@ -2,11 +2,8 @@ import { Observable } from 'rx';
export default function(Block) {
Block.on('dataSourceAttached', () => {
Block.findOne$ =
Observable.fromNodeCallback(Block.findOne, Block);
Block.findById$ =
Observable.fromNodeCallback(Block.findById, Block);
Block.find$ =
Observable.fromNodeCallback(Block.find, Block);
Block.findOne$ = Observable.fromNodeCallback(Block.findOne, Block);
Block.findById$ = Observable.fromNodeCallback(Block.findById, Block);
Block.find$ = Observable.fromNodeCallback(Block.find, Block);
});
}

View File

@ -1,10 +1,8 @@
import _ from 'lodash';
export const alertTypes = _.keyBy([
'success',
'info',
'warning',
'danger'
], _.identity);
export const alertTypes = _.keyBy(
['success', 'info', 'warning', 'danger'],
_.identity
);
export const normalizeAlertType = alertType => alertTypes[alertType] || 'info';

View File

@ -1,15 +1,9 @@
import emptyProtector from './empty-protector';
export function checkMapData(
{
entities: {
challenge,
block,
superBlock
},
export function checkMapData({
entities: { challenge, block, superBlock },
result: { superBlocks }
}
) {
}) {
if (
!challenge ||
!block ||
@ -17,9 +11,7 @@ export function checkMapData(
!superBlocks ||
!superBlocks.length
) {
throw new Error(
'entities not found, db may not be properly seeded'
);
throw new Error('entities not found, db may not be properly seeded');
}
}
// getFirstChallenge(
@ -33,11 +25,8 @@ export function getFirstChallenge({
result: { superBlocks }
}) {
return challenge[
emptyProtector(block[
emptyProtector(superBlock[
superBlocks[0]
]).blocks[0]
]).challenges[0]
emptyProtector(block[emptyProtector(superBlock[superBlocks[0]]).blocks[0]])
.challenges[0]
];
}
@ -52,10 +41,8 @@ export function getFirstChallenge({
// };
export function createNameIdMap({ challenge }) {
return {
challengeIdToName: Object.keys(challenge)
.reduce((map, challengeName) => {
map[challenge[challengeName].id] =
challenge[challengeName].dashedName;
challengeIdToName: Object.keys(challenge).reduce((map, challengeName) => {
map[challenge[challengeName].id] = challenge[challengeName].dashedName;
return map;
}, {})
};

View File

@ -3,14 +3,11 @@ import invariant from 'invariant';
import { Observable } from 'rx';
import castToObservable from '../../server/utils/cast-to-observable';
// createFileStream(
// files: [...PolyVinyl]
// ) => Observable[...Observable[...PolyVinyl]]
export function createFileStream(files = []) {
return Observable.of(
Observable.from(files)
);
return Observable.of(Observable.from(files));
}
// Observable::pipe(
@ -20,8 +17,8 @@ export function createFileStream(files = []) {
// ) => Observable[...Observable[...PolyVinyl]]
export function pipe(project) {
const source = this;
return source.map(
files => files.flatMap(file => castToObservable(project(file)))
return source.map(files =>
files.flatMap(file => castToObservable(project(file)))
);
}
@ -44,24 +41,10 @@ export function pipe(project) {
// contents: String,
// history?: [...String],
// }) => PolyVinyl, throws
export function createPoly({
name,
ext,
contents,
history,
...rest
} = {}) {
invariant(
typeof name === 'string',
'name must be a string but got %s',
name
);
export function createPoly({ name, ext, contents, history, ...rest } = {}) {
invariant(typeof name === 'string', 'name must be a string but got %s', name);
invariant(
typeof ext === 'string',
'ext must be a string, but was %s',
ext
);
invariant(typeof ext === 'string', 'ext must be a string, but was %s', ext);
invariant(
typeof contents === 'string',
@ -71,7 +54,7 @@ export function createPoly({
return {
...rest,
history: Array.isArray(history) ? history : [ name + ext ],
history: Array.isArray(history) ? history : [name + ext],
name,
ext,
path: name + '.' + ext,
@ -83,11 +66,13 @@ export function createPoly({
// isPoly(poly: Any) => Boolean
export function isPoly(poly) {
return poly &&
return (
poly &&
typeof poly.contents === 'string' &&
typeof poly.name === 'string' &&
typeof poly.ext === 'string' &&
Array.isArray(poly.history);
Array.isArray(poly.history)
);
}
// checkPoly(poly: Any) => Void, throws
@ -125,7 +110,7 @@ export function setExt(ext, poly) {
path: poly.name + '.' + ext,
key: poly.name + ext
};
newPoly.history = [ ...poly.history, newPoly.path ];
newPoly.history = [...poly.history, newPoly.path];
return newPoly;
}
@ -138,7 +123,7 @@ export function setName(name, poly) {
path: name + '.' + poly.ext,
key: name + poly.ext
};
newPoly.history = [ ...poly.history, newPoly.path ];
newPoly.history = [...poly.history, newPoly.path];
return newPoly;
}
@ -177,10 +162,12 @@ export function appendToTail(tail, poly) {
// compileHeadTail(padding: String, poly: PolyVinyl) => PolyVinyl
export function compileHeadTail(padding = '', poly) {
return clearHeadTail(transformContents(
() => [ poly.head, poly.contents, poly.tail ].join(padding),
return clearHeadTail(
transformContents(
() => [poly.head, poly.contents, poly.tail].join(padding),
poly
));
)
);
}
// transformContents(
@ -192,10 +179,7 @@ export function compileHeadTail(padding = '', poly) {
// already contains a source, this version will continue as
// the source property
export function transformContents(wrap, poly) {
const newPoly = setContent(
wrap(poly.contents),
poly
);
const newPoly = setContent(wrap(poly.contents), poly);
// if no source exist, set the original contents as source
newPoly.source = poly.source || poly.contents;
return newPoly;
@ -207,10 +191,7 @@ export function transformContents(wrap, poly) {
// ) => PolyVinyl
export function transformHeadTailAndContents(wrap, poly) {
return {
...transformContents(
wrap,
poly
),
...transformContents(wrap, poly),
head: wrap(poly.head),
tail: wrap(poly.tail)
};

View File

@ -3,8 +3,7 @@ export const themes = {
default: 'default'
};
export const invertTheme = currentTheme => (
!currentTheme || currentTheme === themes.default ?
themes.night :
themes.default
);
export const invertTheme = currentTheme =>
!currentTheme || currentTheme === themes.default
? themes.night
: themes.default;

View File

@ -16,7 +16,5 @@ module.exports = {
transform: {
'^.+\\.js$': 'babel-jest'
},
transformIgnorePatterns: [
'node_modules/(?!(gatsby)/)'
]
transformIgnorePatterns: ['node_modules/(?!(gatsby)/)']
};

View File

@ -350,9 +350,8 @@ function createShowCert(app) {
messages: [
{
type: 'info',
message: `We could not find a user with the username "${
username
}"`
message:
'We could not find a user with the username "' + username + '"'
}
]
});

View File

@ -321,7 +321,7 @@ export default async function bootChallenge(app, done) {
) {
req.flash(
'danger',
'You haven\'t supplied the necessary URLs for us to inspect your work.'
"You haven't supplied the necessary URLs for us to inspect your work."
);
return res.sendStatus(403);
}

View File

@ -6,23 +6,13 @@ import dedent from 'dedent';
import { homeLocation } from '../../../config/env';
import nonprofits from '../utils/commit.json';
import {
commitGoals,
completeCommitment$
} from '../utils/commit';
import { commitGoals, completeCommitment$ } from '../utils/commit';
import {
unDasherize
} from '../utils';
import { unDasherize } from '../utils';
import {
observeQuery,
saveInstance
} from '../utils/rx';
import { observeQuery, saveInstance } from '../utils/rx';
import {
ifNoUserRedirectTo
} from '../utils/middleware';
import { ifNoUserRedirectTo } from '../utils/middleware';
const sendNonUserToSignIn = ifNoUserRedirectTo(
`${homeLocation}/signin`,
@ -41,12 +31,12 @@ const debug = debugFactory('fcc:commit');
function findNonprofit(name) {
let nonprofit;
if (name) {
nonprofit = _.find(nonprofits, (nonprofit) => {
nonprofit = _.find(nonprofits, nonprofit => {
return name === nonprofit.name;
});
}
nonprofit = nonprofit || nonprofits[ _.random(0, nonprofits.length - 1) ];
nonprofit = nonprofit || nonprofits[_.random(0, nonprofits.length - 1)];
return nonprofit;
}
@ -55,33 +45,15 @@ export default function commit(app) {
const api = app.loopback.Router();
const { Pledge } = app.models;
router.get(
'/commit',
commitToNonprofit
);
router.get('/commit', commitToNonprofit);
router.get(
'/commit/pledge',
sendNonUserToSignIn,
pledge
);
router.get('/commit/pledge', sendNonUserToSignIn, pledge);
router.get(
'/commit/directory',
renderDirectory
);
router.get('/commit/directory', renderDirectory);
api.post(
'/commit/stop-commitment',
sendNonUserToCommit,
stopCommit
);
api.post('/commit/stop-commitment', sendNonUserToCommit, stopCommit);
api.post(
'/commit/complete-goal',
sendNonUserToCommit,
completeCommitment
);
api.post('/commit/complete-goal', sendNonUserToCommit, completeCommitment);
app.use(api);
app.use(router);
@ -101,8 +73,7 @@ export default function commit(app) {
}
return Observable.just();
})
.subscribe(
pledge => {
.subscribe(pledge => {
if (pledge) {
debug('found previous pledge');
req.flash(
@ -115,19 +86,13 @@ export default function commit(app) {
`
);
}
res.render(
'commit/',
{
res.render('commit/', {
title: 'Commit to a nonprofit. Commit to your goal.',
pledge,
...commitGoals,
...nonprofit
}
);
},
next
);
});
}, next);
}
function pledge(req, res, next) {
@ -143,14 +108,12 @@ export default function commit(app) {
observeQuery(user, 'pledge')
.flatMap(oldPledge => {
// create new pledge for user
const pledge = Pledge(
{
const pledge = Pledge({
amount,
goal,
userId: user.id,
...nonprofit
}
);
});
if (oldPledge) {
debug('user already has pledge, creating a new one');
@ -159,15 +122,13 @@ export default function commit(app) {
oldPledge.formerUser = user.id;
oldPledge.endDate = new Date();
oldPledge.isOrphaned = true;
return saveInstance(oldPledge)
.flatMap(() => {
return saveInstance(oldPledge).flatMap(() => {
return saveInstance(pledge);
});
}
return saveInstance(pledge);
})
.subscribe(
({ displayName, goal, amount }) => {
.subscribe(({ displayName, goal, amount }) => {
req.flash(
'success',
dedent`
@ -178,9 +139,7 @@ export default function commit(app) {
`
);
res.redirect('/' + user.username);
},
next
);
}, next);
}
function renderDirectory(req, res) {
@ -193,16 +152,12 @@ export default function commit(app) {
function completeCommitment(req, res, next) {
const { user } = req;
return completeCommitment$(user)
.subscribe(
msgOrPledge => {
return completeCommitment$(user).subscribe(msgOrPledge => {
if (typeof msgOrPledge === 'string') {
return res.send(msgOrPledge);
}
return res.send(true);
},
next
);
}, next);
}
function stopCommit(req, res, next) {
@ -220,8 +175,7 @@ export default function commit(app) {
pledge.dateEnded = new Date();
return saveInstance(pledge);
})
.subscribe(
pledge => {
.subscribe(pledge => {
let msg = dedent`
You have successfully stopped your pledge. Please
remember to cancel your recurring donation directly
@ -235,8 +189,6 @@ export default function commit(app) {
}
req.flash('info', msg);
return res.redirect(`/${user.username}`);
},
next
);
}, next);
}
}

View File

@ -6,7 +6,6 @@ import keys from '../../../config/secrets';
const log = debug('fcc:boot:donate');
export default function donateBoot(app, done) {
let stripe = false;
const { User } = app.models;
const api = app.loopback.Router();
@ -25,7 +24,8 @@ export default function donateBoot(app, done) {
currency: 'usd',
id: `monthly-donation-${current}`
}
}), {}
}),
{}
);
function connectToStripe() {
@ -70,13 +70,16 @@ export default function donateBoot(app, done) {
return res.status(400).send({ error: 'Amount Required' });
}
const { amount, token: {email, id} } = body;
const {
amount,
token: { email, id }
} = body;
const fccUser = user ?
Promise.resolve(user) :
new Promise((resolve, reject) =>
const fccUser = user
? Promise.resolve(user)
: new Promise((resolve, reject) =>
User.findOrCreate(
{ where: { email }},
{ where: { email } },
{ email },
(err, instance, isNew) => {
log('is new user instance: ', isNew);
@ -96,11 +99,10 @@ export default function donateBoot(app, done) {
startDate: new Date(Date.now()).toISOString()
};
return fccUser.then(
user => {
return fccUser
.then(user => {
donatingUser = user;
return stripe.customers
.create({
return stripe.customers.create({
email,
card: id
});
@ -121,7 +123,9 @@ export default function donateBoot(app, done) {
return res.send(subscription);
})
.then(() => {
donatingUser.createDonation(donation).toPromise()
donatingUser
.createDonation(donation)
.toPromise()
.catch(err => {
throw new Error(err);
});

View File

@ -32,9 +32,7 @@ function createShortLinkHandler(app) {
if (!article) {
return res.redirect('/news');
}
const {
slugPart
} = article;
const { slugPart } = article;
const slug = `/news/${slugPart}`;
return res.redirect(slug);
}

View File

@ -88,7 +88,7 @@ module.exports = function(app) {
.then(() => {
req.flash(
'success',
'We\'ve successfully updated your email preferences.'
"We've successfully updated your email preferences."
);
return res.redirectWithFlash(
`${homeLocation}/unsubscribed/${unsubscribeId}`
@ -144,7 +144,7 @@ module.exports = function(app) {
.then(() => {
req.flash(
'success',
'We\'ve successfully updated your email preferences. Thank you ' +
"We've successfully updated your email preferences. Thank you " +
'for resubscribing.'
);
return res.redirectWithFlash(homeLocation);
@ -175,7 +175,7 @@ module.exports = function(app) {
}
pulls = pulls
? Object.keys(JSON.parse(pulls)).length
: 'Can\'t connect to github';
: "Can't connect to github";
return request(
[
@ -193,7 +193,7 @@ module.exports = function(app) {
issues =
pulls === parseInt(pulls, 10) && issues
? Object.keys(JSON.parse(issues)).length - pulls
: 'Can\'t connect to GitHub';
: "Can't connect to GitHub";
return res.send({
issues: issues,
pulls: pulls

View File

@ -1,6 +1,6 @@
export default function bootStatus(app) {
const api = app.loopback.Router();
api.get('/status/ping', (req, res) => res.json({msg: 'pong'}));
api.get('/status/ping', (req, res) => res.json({ msg: 'pong' }));
app.use(api);
}

View File

@ -5,8 +5,6 @@ module.exports = function(app) {
app.use(router);
function showForum(req, res) {
res.redirect(
'http://forum.freecodecamp.org/'
);
res.redirect('http://forum.freecodecamp.org/');
}
};

View File

@ -219,8 +219,7 @@ function createPostReportUserProfile(app) {
if (!username || !report || report === '') {
return res.json({
type: 'danger',
message:
'Oops, something is not right please re-check your submission.'
message: 'Oops, something is not right please re-check your submission.'
});
}
return Email.send$(

View File

@ -1,5 +1,7 @@
import passport from 'passport';
// eslint-disable-next-line
import {
// prettier ignore
PassportConfigurator
} from '@freecodecamp/loopback-component-passport';
import url from 'url';
@ -132,9 +134,7 @@ export function setupPassport(app) {
}
export const saveResponseAuthCookies = () => {
return (req, res, next) => {
const user = req.user;
if (!user) {
@ -157,7 +157,6 @@ export const saveResponseAuthCookies = () => {
};
export const loginRedirect = () => {
return (req, res) => {
const successRedirect = req => {
if (!!req && req.session && req.session.returnTo) {

View File

@ -11,11 +11,7 @@ const pathsOfNoReturn = [
'css'
];
const pathsWhiteList = [
'challenges',
'map',
'commit'
];
const pathsWhiteList = ['challenges', 'map', 'commit'];
const pathsOfNoReturnRegex = new RegExp(pathsOfNoReturn.join('|'), 'i');
const whiteListRegex = new RegExp(pathsWhiteList.join('|'), 'i');
@ -33,9 +29,9 @@ export default function addReturnToUrl() {
) {
return next();
}
req.session.returnTo = req.originalUrl.includes('/map') ?
'/' :
req.originalUrl;
req.session.returnTo = req.originalUrl.includes('/map')
? '/'
: req.originalUrl;
return next();
};
}

View File

@ -1,7 +1,8 @@
export default function constantHeaders() {
return function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers',
res.header(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept'
);
next();

View File

@ -3,7 +3,7 @@ import helmet from 'helmet';
import { homeLocation } from '../../../config/env';
let trusted = [
'\'self\'',
"'self'",
'https://search.freecodecamp.org',
homeLocation,
'https://' + process.env.AUTH0_DOMAIN
@ -31,8 +31,8 @@ export default function csp() {
'https://*.algolia.net'
]),
scriptSrc: [
'\'unsafe-eval\'',
'\'unsafe-inline\'',
"'unsafe-eval'",
"'unsafe-inline'",
'*.google-analytics.com',
'*.gstatic.com',
'https://*.cloudflare.com',
@ -48,7 +48,7 @@ export default function csp() {
'*.ytimg.com'
].concat(trusted),
styleSrc: [
'\'unsafe-inline\'',
"'unsafe-inline'",
'*.gstatic.com',
'*.googleapis.com',
'*.bootstrapcdn.com',

View File

@ -1,15 +1,12 @@
import csurf from 'csurf';
export default function() {
const protection = csurf(
{
const protection = csurf({
cookie: {
domain: process.env.COOKIE_DOMAIN || 'localhost'
}
}
);
});
return function csrf(req, res, next) {
const path = req.path.split('/')[1];
if ((/(^api$|^unauthenticated$|^internal$|^p$)/).test(path)) {
return next();

View File

@ -14,7 +14,9 @@ export default function flashCheaters() {
if (
ALLOWED_METHODS.indexOf(req.method) !== -1 &&
EXCLUDED_PATHS.indexOf(req.path) === -1 &&
req.user && req.url !== '/' && req.user.isCheater
req.user &&
req.url !== '/' &&
req.user.isCheater
) {
req.flash(
'danger',

View File

@ -20,11 +20,13 @@ export default function() {
return false;
}
const keys = Object.keys(value);
return !!keys.length &&
return (
!!keys.length &&
// every key is a file
keys.every(key => isObject(value[key])) &&
// every file has contents
keys.map(key => value[key]).every(file => isPoly(file));
keys.map(key => value[key]).every(file => isPoly(file))
);
}
},
customSanitizers: {
@ -32,16 +34,20 @@ export default function() {
trimTags(value) {
const tagBody = '(?:[^"\'>]|"[^"]*"|\'[^\']*\')*';
const tagOrComment = new RegExp(
'<(?:'
'<(?:' +
// Comment body.
+ '!--(?:(?:-*[^->])*--+|-?)'
'!--(?:(?:-*[^->])*--+|-?)' +
// Special "raw text" elements whose content should be elided.
+ '|script\\b' + tagBody + '>[\\s\\S]*?</script\\s*'
+ '|style\\b' + tagBody + '>[\\s\\S]*?</style\\s*'
'|script\\b' +
tagBody +
'>[\\s\\S]*?</script\\s*' +
'|style\\b' +
tagBody +
'>[\\s\\S]*?</style\\s*' +
// Regular name
+ '|/?[a-z]'
+ tagBody
+ ')>',
'|/?[a-z]' +
tagBody +
')>',
'gi'
);
let rawValue;

View File

@ -1,6 +1,5 @@
import { createActiveUsers } from '../utils/about.js';
module.exports = function(About) {
const activeUsers = createActiveUsers();
let activeUsersForRendering = 0;
@ -14,9 +13,7 @@ module.exports = function(About) {
About.getActiveUsersForRendering = () => activeUsersForRendering;
About.remoteMethod(
'getActiveUsers',
{
About.remoteMethod('getActiveUsers', {
http: {
path: '/get-active-users',
verb: 'get'
@ -25,6 +22,5 @@ module.exports = function(About) {
type: 'number',
arg: 'activeUsers'
}
}
);
});
};

View File

@ -11,7 +11,6 @@ log.enabled = true;
// this is where server starts booting up
const app = require('./server');
let timeoutHandler;
let killTime = 15;

View File

@ -11,7 +11,6 @@ const fiveMinutes = 1000 * 60 * 5;
class NewsFeed {
constructor() {
this.state = {
readyState: false,
mediumFeed: [],
@ -27,26 +26,23 @@ class NewsFeed {
const newState = stateUpdater(this.state);
this.state = _.merge({}, this.state, newState);
return;
}
};
refreshFeeds = () => {
const currentFeed = this.state.combinedFeed.slice(0);
log('grabbing feeds');
return Promise.all([
getMediumFeed(),
getLybsynFeed()
]).then(
([mediumFeed, lybsynFeed]) => this.setState(
state => ({
return Promise.all([getMediumFeed(), getLybsynFeed()])
.then(([mediumFeed, lybsynFeed]) =>
this.setState(state => ({
...state,
mediumFeed,
lybsynFeed
})
))
}))
)
.then(() => {
log('crossing the streams');
const { mediumFeed, lybsynFeed} = this.state;
const combinedFeed = [ ...mediumFeed, ...lybsynFeed ].sort((a, b) => {
const { mediumFeed, lybsynFeed } = this.state;
const combinedFeed = [...mediumFeed, ...lybsynFeed].sort((a, b) => {
return compareDesc(a.isoDate, b.isoDate);
});
this.setState(state => ({
@ -62,25 +58,24 @@ class NewsFeed {
combinedFeed: currentFeed
}));
});
}
};
getFeed = () => new Promise((resolve) => {
getFeed = () =>
new Promise(resolve => {
let notReadyCount = 0;
function waitForReady() {
log('notReadyCount', notReadyCount);
notReadyCount++;
return this.state.readyState || notReadyCount === 5 ?
resolve(this.state.combinedFeed) :
setTimeout(waitForReady, 100);
return this.state.readyState || notReadyCount === 5
? resolve(this.state.combinedFeed)
: setTimeout(waitForReady, 100);
}
log('are we ready?', this.state.readyState);
return this.state.readyState ?
resolve(this.state.combinedFeed) :
setTimeout(waitForReady, 100);
})
return this.state.readyState
? resolve(this.state.combinedFeed)
: setTimeout(waitForReady, 100);
});
}
export default NewsFeed;

View File

@ -9,7 +9,6 @@ function getExtract(str) {
return str.slice(0, str.indexOf('</p>') + 4);
}
function addResponsiveClass(str) {
return str.replace(/<img/g, '<img class="img-responsive"');
}
@ -22,17 +21,15 @@ export function getMediumFeed() {
}
const items = feed.items
.map(
item => _.pick(item, ['title', 'link', 'isoDate', 'content:encoded'])
.map(item =>
_.pick(item, ['title', 'link', 'isoDate', 'content:encoded'])
)
.map(
(item) => ({
.map(item => ({
...item,
extract: getExtract(item['content:encoded'])
})
)
}))
.map(item => _.omit(item, ['content:encoded']))
.map(item => ({ ...item, extract: addResponsiveClass(item.extract)}));
.map(item => ({ ...item, extract: addResponsiveClass(item.extract) }));
resolve(items);
});
});

View File

@ -64,7 +64,7 @@ export function createActiveUsers() {
credentials['client_email'],
null,
credentials['private_key'],
[scope],
[scope]
);
const authorize = observeMethod(client, 'authorize');
const options = {
@ -89,7 +89,5 @@ export function createActiveUsers() {
.do(null, err => console.error(err))
// always send a number down
.catch(() => Observable.of(0))
// cache for 2 seconds to prevent hitting our daily request limit
::timeCache(2, 'seconds');
}

View File

@ -1,18 +1,18 @@
const githubRegex = (/github/i);
const githubRegex = /github/i;
const providerHash = {
facebook: ({ id }) => id,
github: ({ username }) => username,
twitter: ({ username }) => username,
linkedin({ _json }) {
return _json && _json.publicProfileUrl || null;
return (_json && _json.publicProfileUrl) || null;
},
google: ({ id }) => id
};
export function getUsernameFromProvider(provider, profile) {
return typeof providerHash[provider] === 'function' ?
providerHash[provider](profile) :
null;
return typeof providerHash[provider] === 'function'
? providerHash[provider](profile)
: null;
}
// createProfileAttributes(provider: String, profile: {}) => Object
@ -32,13 +32,7 @@ function createProfileAttributesFromGithub(profile) {
const {
profileUrl: githubProfile,
username,
_json: {
avatar_url: picture,
blog: website,
location,
bio,
name
} = {}
_json: { avatar_url: picture, blog: website, location, bio, name } = {}
} = profile;
return {
name,

View File

@ -20,8 +20,7 @@ export function completeCommitment$(user) {
isInfosecQaCert
} = user;
return Observable.fromNodeCallback(user.pledge, user)()
.flatMap(pledge => {
return Observable.fromNodeCallback(user.pledge, user)().flatMap(pledge => {
if (!pledge) {
return Observable.just('No pledge found');
}
@ -36,8 +35,7 @@ export function completeCommitment$(user) {
(isFrontEndLibsCert && goal === commitGoals.frontEndLibsCert) ||
(isJsAlgoDataStructCert && goal === commitGoals.jsAlgoDataStructCert) ||
(isDataVisCert && goal === commitGoals.dataVisCert) ||
(isApisMicroservicesCert &&
goal === commitGoals.apisMicroservicesCert) ||
(isApisMicroservicesCert && goal === commitGoals.apisMicroservicesCert) ||
(isInfosecQaCert && goal === commitGoals.infosecQaCert)
) {
debug('marking goal complete');

View File

@ -8,25 +8,20 @@ export function unwrapHandledError(err) {
return err[_handledError] || {};
}
export function wrapHandledError(err, {
type,
message,
redirectTo,
status = 200
}) {
export function wrapHandledError(
err,
{ type, message, redirectTo, status = 200 }
) {
err[_handledError] = { type, message, redirectTo, status };
return err;
}
// for use with express-validator error formatter
export const createValidatorErrorFormatter = (type, redirectTo) =>
({ msg }) => wrapHandledError(
new Error(msg),
{
export const createValidatorErrorFormatter = (type, redirectTo) => ({ msg }) =>
wrapHandledError(new Error(msg), {
type,
message: msg,
redirectTo,
// we default to 400 as these are malformed requests
status: 400
}
);
});

View File

@ -3,9 +3,16 @@ import moment from 'moment-timezone';
// day count between two epochs (inclusive)
export function dayCount([head, tail], timezone = 'UTC') {
return Math.ceil(
moment(moment(head).tz(timezone).endOf('day')).diff(
moment(tail).tz(timezone).startOf('day'),
moment(
moment(head)
.tz(timezone)
.endOf('day')
).diff(
moment(tail)
.tz(timezone)
.startOf('day'),
'days',
true)
true
)
);
}

View File

@ -1,8 +1,4 @@
export default [
'auth',
'services',
'link'
].reduce((throughs, route) => {
export default ['auth', 'services', 'link'].reduce((throughs, route) => {
throughs[route] = true;
return throughs;
}, {});

View File

@ -32,12 +32,11 @@ const getFirstChallenge = _.once(_getFirstChallenge);
*/
export function _cachedMap({ Block, Challenge }) {
const challenges = Challenge.find$({
order: [ 'order ASC', 'suborder ASC' ],
order: ['order ASC', 'suborder ASC'],
where: { isPrivate: false }
});
const challengeMap = challenges
.map(
challenges => challenges
const challengeMap = challenges.map(challenges =>
challenges
.map(challenge => challenge.toJSON())
.reduce((hash, challenge) => {
hash[challenge.dashedName] = challenge;
@ -45,38 +44,33 @@ export function _cachedMap({ Block, Challenge }) {
}, {})
);
const blocks = Block.find$({
order: [ 'superOrder ASC', 'order ASC' ],
order: ['superOrder ASC', 'order ASC'],
where: { isPrivate: false }
});
const blockMap = Observable.combineLatest(
blocks.map(
blocks => blocks
.map(block => block.toJSON())
.reduce((hash, block) => {
blocks.map(blocks =>
blocks.map(block => block.toJSON()).reduce((hash, block) => {
hash[block.dashedName] = block;
return hash;
}, {})
),
challenges
)
.map(([ blocksMap, challenges ]) => {
).map(([blocksMap, challenges]) => {
return challenges.reduce((blocksMap, challenge) => {
if (blocksMap[challenge.block].challenges) {
blocksMap[challenge.block].challenges.push(challenge.dashedName);
} else {
blocksMap[challenge.block] = {
...blocksMap[challenge.block],
challenges: [ challenge.dashedName ]
challenges: [challenge.dashedName]
};
}
return blocksMap;
}, blocksMap);
});
const superBlockMap = blocks.map(blocks => blocks.reduce((map, block) => {
if (
map[block.superBlock] &&
map[block.superBlock].blocks
) {
const superBlockMap = blocks.map(blocks =>
blocks.reduce((map, block) => {
if (map[block.superBlock] && map[block.superBlock].blocks) {
map[block.superBlock].blocks.push(block.dashedName);
} else {
map[block.superBlock] = {
@ -89,7 +83,8 @@ export function _cachedMap({ Block, Challenge }) {
};
}
return map;
}, {}));
}, {})
);
const superBlocks = superBlockMap.map(superBlockMap => {
return Object.keys(superBlockMap)
.map(key => superBlockMap[key])
@ -126,8 +121,7 @@ export function getChallengeById(map, id) {
return Observable.if(
() => !id,
map.map(getFirstChallenge),
map.map(addNameIdMap)
.map(map => {
map.map(addNameIdMap).map(map => {
const {
entities: { challenge: challengeMap, challengeIdToName }
} = map;
@ -143,13 +137,9 @@ export function getChallengeById(map, id) {
}
export function getChallengeInfo(map) {
return map.map(addNameIdMap)
.map(({
entities: {
challenge: challengeMap,
challengeIdToName
}
}) => ({
return map
.map(addNameIdMap)
.map(({ entities: { challenge: challengeMap, challengeIdToName } }) => ({
challengeMap,
challengeIdToName
}));
@ -168,29 +158,24 @@ function loadComingSoonOrBetaChallenge({
// this is a hard search
// falls back to soft search
export function getChallenge(
challengeDashedName,
blockDashedName,
map) {
return map
.flatMap(({ entities, result: { superBlocks } }) => {
export function getChallenge(challengeDashedName, blockDashedName, map) {
return map.flatMap(({ entities, result: { superBlocks } }) => {
const superBlock = entities.superBlock;
const block = entities.block[blockDashedName];
const challenge = entities.challenge[challengeDashedName];
return Observable.if(
() => (
() =>
!blockDashedName ||
!block ||
!challenge ||
!loadComingSoonOrBetaChallenge(challenge)
),
!loadComingSoonOrBetaChallenge(challenge),
getChallengeByDashedName(challengeDashedName, map),
Observable.just({ block, challenge })
)
.map(({ challenge, block }) => ({
redirect: challenge.block !== blockDashedName ?
`/challenges/${block.dashedName}/${challenge.dashedName}` :
false,
).map(({ challenge, block }) => ({
redirect:
challenge.block !== blockDashedName
? `/challenges/${block.dashedName}/${challenge.dashedName}`
: false,
entities: {
superBlock,
challenge: {
@ -211,19 +196,21 @@ export function getBlockForChallenge(map, challenge) {
}
export function getChallengeByDashedName(dashedName, map) {
const challengeName = unDasherize(dashedName)
.replace(challengesRegex, '');
const challengeName = unDasherize(dashedName).replace(challengesRegex, '');
const testChallengeName = new RegExp(challengeName, 'i');
return map
.map(({ entities }) => entities.challenge)
.flatMap(challengeMap => {
return Observable.from(Object.keys(challengeMap))
.map(key => challengeMap[key]);
return Observable.from(Object.keys(challengeMap)).map(
key => challengeMap[key]
);
})
.filter(challenge => {
return loadComingSoonOrBetaChallenge(challenge) &&
testChallengeName.test(challenge.name);
return (
loadComingSoonOrBetaChallenge(challenge) &&
testChallengeName.test(challenge.name)
);
})
.last({ defaultValue: null })
.flatMap(challengeOrNull => {
@ -234,8 +221,9 @@ export function getChallengeByDashedName(dashedName, map) {
);
})
.flatMap(challenge => {
return getBlockForChallenge(map, challenge)
.map(block => ({ challenge, block }));
return getBlockForChallenge(map, challenge).map(block => ({
challenge,
block
}));
});
}

View File

@ -57,9 +57,11 @@ export const userPropsForSession = [
export function normaliseUserFields(user) {
const about = user.bio && !user.about ? user.bio : user.about;
const picture = user.picture || addPlaceholderImage(user.username);
const twitter = user.twitter && isURL(user.twitter) ?
user.twitter :
user.twitter && `https://www.twitter.com/${user.twitter.replace(/^@/, '')}`;
const twitter =
user.twitter && isURL(user.twitter)
? user.twitter
: user.twitter &&
`https://www.twitter.com/${user.twitter.replace(/^@/, '')}`;
return { about, picture, twitter };
}

View File

@ -49,7 +49,9 @@ export function timeCache(time, unit) {
// set new expire time in MS and create new subscription to source
if (!expireCacheAt || expireCacheAt < Date.now()) {
// set expire in ms;
expireCacheAt = moment().add(time, unit).valueOf();
expireCacheAt = moment()
.add(time, unit)
.valueOf();
cache = new AsyncSubject();
source.subscribe(cache);
}

View File

@ -25,13 +25,7 @@ export function getHost() {
export function getServerFullURL() {
if (!isDev) {
return getProtocol()
+ '://'
+ getHost();
return getProtocol() + '://' + getHost();
}
return getProtocol()
+ '://'
+ getHost()
+ ':'
+ getPort();
return getProtocol() + '://' + getHost() + ':' + getPort();
}

View File

@ -13,7 +13,6 @@ const hoursBetween = 24;
const hoursDay = 24;
export function prepUniqueDaysByHours(cals, tz = 'UTC') {
let prev = null;
// compose goes bottom to top (map > sortBy > transform)
@ -25,27 +24,34 @@ export function prepUniqueDaysByHours(cals, tz = 'UTC') {
} else if (
moment(cur)
.tz(tz)
.diff(moment(prev).tz(tz).startOf('day'), 'hours')
>= hoursDay
.diff(
moment(prev)
.tz(tz)
.startOf('day'),
'hours'
) >= hoursDay
) {
data.push(cur);
prev = cur;
}
}, []),
sortBy(e => e),
map(ts => moment(ts).tz(tz).startOf('hours').valueOf())
map(ts =>
moment(ts)
.tz(tz)
.startOf('hours')
.valueOf()
)
)(cals);
}
export function calcCurrentStreak(cals, tz = 'UTC') {
let prev = last(cals);
if (
moment()
.tz(tz)
.startOf('day')
.diff(moment(prev).tz(tz), 'hours')
> hoursBetween
.diff(moment(prev).tz(tz), 'hours') > hoursBetween
) {
return 0;
}
@ -56,8 +62,7 @@ export function calcCurrentStreak(cals, tz = 'UTC') {
moment(prev)
.tz(tz)
.startOf('day')
.diff(moment(cur).tz(tz), 'hours')
<= hoursBetween
.diff(moment(cur).tz(tz), 'hours') <= hoursBetween
) {
prev = cur;
currentStreak++;
@ -72,20 +77,26 @@ export function calcCurrentStreak(cals, tz = 'UTC') {
}
export function calcLongestStreak(cals, tz = 'UTC') {
let tail = cals[0];
const longest = cals.reduce((longest, head, index) => {
const longest = cals.reduce(
(longest, head, index) => {
const last = cals[index === 0 ? 0 : index - 1];
// is streak broken
if (moment(head).tz(tz).startOf('day').diff(moment(last).tz(tz), 'hours')
> hoursBetween) {
if (
moment(head)
.tz(tz)
.startOf('day')
.diff(moment(last).tz(tz), 'hours') > hoursBetween
) {
tail = head;
}
if (dayCount(longest, tz) < dayCount([head, tail], tz)) {
return [head, tail];
}
return longest;
}, [cals[0], cals[0]]);
},
[cals[0], cals[0]]
);
return dayCount(longest, tz);
}

View File

@ -16,7 +16,5 @@ module.exports = {
transform: {
'^.+\\.js$': '<rootDir>/jest.transform.js'
},
transformIgnorePatterns: [
'node_modules/(?!(gatsby)/)'
]
transformIgnorePatterns: ['node_modules/(?!(gatsby)/)']
};

View File

@ -1,12 +1,10 @@
const babelOptions = {
presets: [
'@babel/preset-env',
'@babel/react'
],
presets: ['@babel/preset-env', '@babel/react'],
plugins: [
'@babel/plugin-proposal-function-bind',
[
'transform-imports', {
'transform-imports',
{
'@freecodecamp/react-bootstrap': {
transform: '@freecodecamp/react-bootstrap/lib/${member}',
preventFullImport: true

View File

@ -29,7 +29,10 @@ exports.createNavigationNode = function createNavigationNode(node) {
const nodeDir = path.resolve(fileAbsolutePath).replace(indexMdRe, '');
const dashedName = nodeDir.split(path.sep).slice(-1)[0];
const nodePath = nodeDir.split(pagesDir)[1].split(path.sep).join('/');
const nodePath = nodeDir
.split(pagesDir)[1]
.split(path.sep)
.join('/');
const parentPath = nodePath
.split('/')
.slice(0, -1)

View File

@ -33,15 +33,9 @@ function DonateCompletion({ processing, reset, success, error = null }) {
/>
)}
{success && (
<p>
Thank you for supporting the freeCodeCamp.org community.
</p>
)}
{error && (
<p>
{error}
</p>
<p>Thank you for supporting the freeCodeCamp.org community.</p>
)}
{error && <p>{error}</p>}
</div>
<p className='donation-completion-buttons'>
{error && (

View File

@ -20,10 +20,9 @@ import DonateText from './DonateText';
import '../Donation.css';
const mapStateToProps = createSelector(
isDonationModalOpenSelector,
show => ({ show })
);
const mapStateToProps = createSelector(isDonationModalOpenSelector, show => ({
show
}));
const mapDispatchToProps = dispatch =>
bindActionCreators(
@ -73,7 +72,9 @@ class DonateModal extends Component {
};
return (
<div className='modal-close-btn-container'>
<Button bsStyle='link' onClick={handleClick}>Close</Button>
<Button bsStyle='link' onClick={handleClick}>
Close
</Button>
</div>
);
}

View File

@ -19,15 +19,14 @@ const DonateText = ({ activeDonations }) => {
return (
<div className='text-center'>
<p>
freeCodeCamp.org is a tiny nonprofit that's helping millions of
people learn to code for free.
freeCodeCamp.org is a tiny nonprofit that's helping millions of people
learn to code for free.
</p>
<p>
Join <strong>{donationsLocale}</strong> supporters.
</p>
<p>
Your $5 / month donation will help keep tech education free and
open.
Your $5 / month donation will help keep tech education free and open.
</p>
</div>
);

View File

@ -77,9 +77,7 @@ class StripeCardForm extends Component {
return (
<div className='donation-elements'>
<FormGroup>
<ControlLabel>
Your Card Number:
</ControlLabel>
<ControlLabel>Your Card Number:</ControlLabel>
<CardNumberElement
className='form-control donate-input-element'
onChange={this.handleInputChange}
@ -87,9 +85,7 @@ class StripeCardForm extends Component {
/>
</FormGroup>
<FormGroup>
<ControlLabel>
Your Card Expiration Month:
</ControlLabel>
<ControlLabel>Your Card Expiration Month:</ControlLabel>
<CardExpiryElement
className='form-control donate-input-element'
onChange={this.handleInputChange}
@ -97,9 +93,7 @@ class StripeCardForm extends Component {
/>
</FormGroup>
<FormGroup>
<ControlLabel>
Your Card CVC (3-digit security number):
</ControlLabel>
<ControlLabel>Your Card CVC (3-digit security number):</ControlLabel>
<CardCVCElement
className='form-control donate-input-element'
onChange={this.handleInputChange}

View File

@ -96,12 +96,8 @@ function Footer() {
</Col>
<Col lg={3} sm={2} xs={12}>
<ColHeader>Our Learning Resources</ColHeader>
<Link to='/learn'>
Learn
</Link>
<Link to='/guide'>
Guide
</Link>
<Link to='/learn'>Learn</Link>
<Link to='/guide'>Guide</Link>
<Link to='https://www.youtube.com/freecodecamp'>Youtube</Link>
<Link to='https://podcast.freecodecamp.org'>Podcast</Link>
<Link to='https://twitter.com/freecodecamp'>Twitter</Link>

View File

@ -154,4 +154,7 @@ export class Block extends Component {
Block.displayName = 'Block';
Block.propTypes = propTypes;
export default connect(mapStateToProps, mapDispatchToProps)(Block);
export default connect(
mapStateToProps,
mapDispatchToProps
)(Block);

View File

@ -33,7 +33,9 @@ export function DynamicForm({
errors,
fields,
handleSubmit,
fields: { _meta: { allPristine } },
fields: {
_meta: { allPristine }
},
// HOC
buttonText,

View File

@ -166,7 +166,7 @@ class DefaultLayout extends Component {
) : null}
{children}
</div>
{showFooter && (<Footer />)}
{showFooter && <Footer />}
</Fragment>
);
}

View File

@ -67,7 +67,9 @@ class NavPanel extends Component {
'caret ' + (isExpanded ? 'caretStyle expanded' : 'caretStyle')
}
/>
<Link onClick={this.handleTitleClick} to={path}>{title}</Link>
<Link onClick={this.handleTitleClick} to={path}>
{title}
</Link>
</div>
);
}

View File

@ -8,32 +8,38 @@ import ReactGA from '../analytics/index.js';
import Spacer from '../components/helpers/Spacer';
const paypalMonthlyDonations = [
{ eventLabel: 'paypal',
{
eventLabel: 'paypal',
eventValue: 5,
defaultValueHash: 'KTAXU8B4MYAT8',
defaultValue: 'Donate $5 each month'
},
{ eventLabel: 'paypal',
{
eventLabel: 'paypal',
eventValue: 10,
defaultValueHash: 'BYEBQEHS5LHNC',
defaultValue: 'Donate $10 each month'
},
{ eventLabel: 'paypal',
{
eventLabel: 'paypal',
eventValue: 35,
defaultValueHash: '57ZPMKJ8G893Y',
defaultValue: 'Donate $35 each month'
},
{ eventLabel: 'paypal',
{
eventLabel: 'paypal',
eventValue: 50,
defaultValueHash: '2ZVYTHK6Q7AFW',
defaultValue: 'Donate $50 each month'
},
{ eventLabel: 'paypal',
{
eventLabel: 'paypal',
eventValue: 100,
defaultValueHash: 'C7PUT3LMJHKK2',
defaultValue: 'Donate $100 each month'
},
{ eventLabel: 'paypal',
{
eventLabel: 'paypal',
eventValue: 250,
defaultValueHash: '69JGTY4DHSTEN',
defaultValue: 'Donate $250 each month'
@ -48,13 +54,19 @@ const paypalOneTimeDonation = {
};
class DonateOtherPage extends Component {
renderForm(item) {
return (
<form
action='https://www.paypal.com/cgi-bin/webscr'
method='post'
onSubmit={() => ReactGA.event({category: 'donation', action: 'click', label: item.eventLabel, value: item.eventValue})}
onSubmit={() =>
ReactGA.event({
category: 'donation',
action: 'click',
label: item.eventLabel,
value: item.eventValue
})
}
target='_blank'
>
<input defaultValue='_s-xclick' name='cmd' type='hidden' />{' '}
@ -85,54 +97,64 @@ class DonateOtherPage extends Component {
Other ways you can support the freeCodeCamp.org nonprofit
</h2>
<p>
freeCodeCamp is a small donor-supported 501(c)(3) public charity. We
are tax-exempt, so you can deduct donations you make to our
nonprofit from your taxes. You can{' '}
freeCodeCamp is a small donor-supported 501(c)(3) public
charity. We are tax-exempt, so you can deduct donations you make
to our nonprofit from your taxes. You can{' '}
<a href='https://s3.amazonaws.com/freecodecamp/Free+Code+Camp+Inc+IRS+Determination+Letter.pdf'>
download our IRS Determination Letter here
</a>.
</a>
.
</p>
<hr />
<h3>Set up a monthly donation using PayPal</h3>
<p>
You can set up a monthly donation to freeCodeCamp by clicking one of
the links below and following the instructions on PayPal. You can
easily stop your donations at any time in the future.
You can set up a monthly donation to freeCodeCamp by clicking
one of the links below and following the instructions on PayPal.
You can easily stop your donations at any time in the future.
</p>
{paypalMonthlyDonations.map((item) => {
{paypalMonthlyDonations.map(item => {
return this.renderForm(item);
})}
<hr />
<h3>Make a one-time donation using PayPal</h3>
<p>
You can make a one-time monthly donation to freeCodeCamp for any
amount of money by clicking one of the links below and following the
instructions on PayPal:
amount of money by clicking one of the links below and following
the instructions on PayPal:
</p>
{this.renderForm(paypalOneTimeDonation)}
<hr />
<h3>Get your employer to match your donation</h3>
<p>
Many freeCodeCamp supporters are able to get their employers to
match their donations to freeCodeCamp. Our Tax-exempt number (EIN)
is 82-0779546. If we can help you with setting this up, please email{' '}
<a href='mailto:team@freecodecamp.org'>team@freecodecamp.org</a>.
match their donations to freeCodeCamp. Our Tax-exempt number
(EIN) is 82-0779546. If we can help you with setting this up,
please email{' '}
<a href='mailto:team@freecodecamp.org'>team@freecodecamp.org</a>
.
</p>
<hr />
<h3>Donate through a payroll deduction</h3>
<p>
In the US and Canada, some employers have a convenient way to give
to freeCodeCamp through a payroll deduction. Ask your employer if
they can do this, and have them send any necessary paperwork to:
In the US and Canada, some employers have a convenient way to
give to freeCodeCamp through a payroll deduction. Ask your
employer if they can do this, and have them send any necessary
paperwork to:
</p>
<p>
Free Code Camp, Inc.<br />7800 W Hefner Rd, PO BOX 721024<br />Oklahoma
City, Oklahoma 73172<br />United States
Free Code Camp, Inc.
<br />
7800 W Hefner Rd, PO BOX 721024
<br />
Oklahoma City, Oklahoma 73172
<br />
United States
</p>
<hr />
<h3>Donate cryptocurrency to freeCodeCamp</h3>
<p>
Below are our wallets where we can receive cryptocurrency donations.
Below are our wallets where we can receive cryptocurrency
donations.
</p>
<h4>Make a one-time Bitcoin donation</h4>
<p className='negative-15'>
@ -158,22 +180,31 @@ class DonateOtherPage extends Component {
<h3>Donate to freeCodeCamp by mailing us a check</h3>
<p>Our mailing address is:</p>
<p>
Free Code Camp, Inc.<br />7800 W Hefner Rd, PO BOX 721024<br />Oklahoma
City, Oklahoma 73172<br />United States
Free Code Camp, Inc.
<br />
7800 W Hefner Rd, PO BOX 721024
<br />
Oklahoma City, Oklahoma 73172
<br />
United States
</p>
<hr />
<h3>Donate Stock to freeCodeCamp</h3>
<p>
If you want to donate stocks to freeCodeCamp, please email us at{' '}
<a href='mailto:team@freecodecamp.org'>team@freecodecamp.org</a>.
<a href='mailto:team@freecodecamp.org'>team@freecodecamp.org</a>
.
</p>
<hr />
<h3>Legacy Gift</h3>
<p>
You can help future generations of learners by listing freeCodeCamp
in your will or living trust. If you're interested in doing this,
email Quincy directly and we can discuss this:{' '}
<a href='mailto:quincy@freecodecamp.org'>quincy@freecodecamp.org</a>.
You can help future generations of learners by listing
freeCodeCamp in your will or living trust. If you're interested
in doing this, email Quincy directly and we can discuss this:{' '}
<a href='mailto:quincy@freecodecamp.org'>
quincy@freecodecamp.org
</a>
.
</p>
<hr />
<h3>
@ -182,7 +213,9 @@ class DonateOtherPage extends Component {
</h3>
<Spacer />
<div className='text-center'>
<Link to='/donate'>Or donate using a Credit or Debit Card.</Link>
<Link to='/donate'>
Or donate using a Credit or Debit Card.
</Link>
</div>
<Spacer />
</Col>

View File

@ -60,9 +60,7 @@ class DonatePage extends Component {
<Spacer />
<Row>
<Col sm={8} smOffset={2} xs={12}>
<h2 className='text-center'>
Become a Supporter
</h2>
<h2 className='text-center'>Become a Supporter</h2>
<DonateText />
</Col>
<Col sm={6} smOffset={3} xs={12}>

View File

@ -85,9 +85,7 @@ export const query = graphql`
slug
}
}
allChallengeNode(
sort: { fields: [superOrder, order, challengeOrder] }
) {
allChallengeNode(sort: { fields: [superOrder, order, challengeOrder] }) {
edges {
node {
fields {

View File

@ -16,7 +16,7 @@ function setTheme(currentTheme = defaultTheme, theme) {
html.classList.add(theme);
}
function* updateLocalThemeSaga({ payload: {user, theme } }) {
function* updateLocalThemeSaga({ payload: { user, theme } }) {
const currentTheme = store.get(themeKey) || defaultTheme;
if (user) {
const { theme = defaultTheme } = user;

View File

@ -6,10 +6,5 @@ import { sagas as challengeSagas } from '../templates/Challenges/redux';
import { sagas as settingsSagas } from './settings';
export default function* rootSaga() {
yield all([
...errorSagas,
...appSagas,
...challengeSagas,
...settingsSagas
]);
yield all([...errorSagas, ...appSagas, ...challengeSagas, ...settingsSagas]);
}

View File

@ -170,7 +170,7 @@ export class BackEnd extends Component {
<LearnLayout>
<Grid>
<Row>
<Col md={8} mdOffset={2} sm={10} smOffset={1} xs={12} >
<Col md={8} mdOffset={2} sm={10} smOffset={1} xs={12}>
<Spacer />
<ChallengeTitle>{blockNameTitle}</ChallengeTitle>
<ChallengeDescription

View File

@ -10,8 +10,9 @@ const propTypes = {
};
function emptyInstruction(instructions) {
return (/^<section\s+id\s*=\s*("|')instructions\1\s*>\s*<\/section>$/)
.test(instructions);
return (/^<section\s+id\s*=\s*("|')instructions\1\s*>\s*<\/section>$/).test(
instructions
);
}
function ChallengeDescription({ description, instructions, section }) {

View File

@ -73,4 +73,7 @@ function ResetModal({ reset, close, isOpen }) {
ResetModal.displayName = 'ResetModal';
ResetModal.propTypes = propTypes;
export default connect(mapStateToProps, mapDispatchToProps)(ResetModal);
export default connect(
mapStateToProps,
mapDispatchToProps
)(ResetModal);

View File

@ -41,9 +41,11 @@ function ToolPanel({
}) {
return (
<Fragment>
<div className={`tool-panel-group ${
<div
className={`tool-panel-group ${
isMobile ? 'tool-panel-group-mobile' : ''
}`}>
}`}
>
<Button block={true} bsStyle='primary' onClick={executeChallenge}>
{isMobile ? 'Run' : 'Run the Tests'}
</Button>
@ -92,7 +94,10 @@ function ToolPanel({
ToolPanel.displayName = 'ToolPanel';
ToolPanel.propTypes = propTypes;
export default connect(mapStateToProps, mapDispatchToProps)(ToolPanel);
export default connect(
mapStateToProps,
mapDispatchToProps
)(ToolPanel);
/*
<Button

View File

@ -89,7 +89,9 @@ export class ProjectForm extends Component {
}
}
handleSubmit(values) {
const { keysDown: { Control, Enter } } = this.state;
const {
keysDown: { Control, Enter }
} = this.state;
if ((Control && Enter) || !Enter) {
this.props.openModal('completion');
this.props.updateProjectForm(values);

View File

@ -55,35 +55,8 @@ export class ToolPanel extends Component {
ToolPanel.displayName = 'ProjectToolPanel';
ToolPanel.propTypes = propTypes;
export default connect(mapStateToProps, mapDispatchToProps)(ToolPanel);
export default connect(
mapStateToProps,
mapDispatchToProps
)(ToolPanel);
/**
*
* <Fragment>
<ProjectForm isFrontEnd={isFrontEnd} openModal={openCompletionModal} />
<ButtonSpacer />
{guideUrl && (
<Fragment>
<Button
block={true}
bsStyle='primary'
className='btn-primary-ghost btn-big'
href={guideUrl}
target='_blank'
>
Get a hint
</Button>
<ButtonSpacer />
</Fragment>
)}
<Button
block={true}
bsStyle='primary'
className='btn-primary-ghost btn-big'
onClick={openHelpModal}
>
Ask for help on the forum
</Button>
<ButtonSpacer />
</Fragment>
*/

View File

@ -1,4 +1,4 @@
import {cond, identity, stubTrue, conforms} from 'lodash';
import { cond, identity, stubTrue, conforms } from 'lodash';
const HTML$JSReg = /html|js/;

View File

@ -46,9 +46,7 @@ export const testJS$JSX = overSome(testJS, testJSX);
export const replaceNBSP = cond([
[
testHTML$JS$JSX,
partial(vinyl.transformContents, contents =>
contents.replace(NBSPReg, ' ')
)
partial(vinyl.transformContents, contents => contents.replace(NBSPReg, ' '))
],
[stubTrue, identity]
]);

View File

@ -3,7 +3,10 @@ import { ofType } from 'redux-observable';
import { types, unlockCode } from './';
function codeLockEpic(action$) {
return action$.pipe(ofType(types.updateFile), map(unlockCode));
return action$.pipe(
ofType(types.updateFile),
map(unlockCode)
);
}
export default codeLockEpic;

View File

@ -7,16 +7,12 @@ function* fetchIdToNameMapSaga() {
try {
const { data } = yield call(getIdToNameMap);
yield put(
fetchIdToNameMapComplete(data)
);
yield put(fetchIdToNameMapComplete(data));
} catch (e) {
yield put(fetchIdToNameMapError(e));
}
}
export function createIdToNameMapSaga(types) {
return [
takeEvery(types.fetchIdToNameMap, fetchIdToNameMapSaga)
];
return [takeEvery(types.fetchIdToNameMap, fetchIdToNameMapSaga)];
}

View File

@ -58,7 +58,6 @@ export function createFetchLink() {
}
const link = await axios
.get({ url: href, crossDomain })
.then(thing => { console.log(thing); return thing;})
.then(res => {
if (res.status !== 200) {
throw new Error('Request error: ' + res.status);

View File

@ -13,7 +13,10 @@ const propTypes = {
};
function SuperBlockIntroductionPage({ data: { markdownRemark } }) {
const { html, frontmatter: { superBlock } } = markdownRemark;
const {
html,
frontmatter: { superBlock }
} = markdownRemark;
return (
<Fragment>
<Helmet>

View File

@ -17,10 +17,11 @@ const arrToString = arr =>
exports.localeChallengesRootDir = getChallengesDirForLang(locale);
exports.replaceChallengeNode =
async function replaceChallengeNode(fullFilePath) {
exports.replaceChallengeNode = async function replaceChallengeNode(
fullFilePath
) {
return prepareChallenge(await createChallenge(fullFilePath));
};
};
exports.buildChallenges = async function buildChallenges() {
const curriculum = await getChallengesForLang(locale);

View File

@ -157,7 +157,7 @@ const stopWords = [
'in',
'into',
'it',
'it\'s',
"it's",
'its',
'no',
'nor',

View File

@ -17,7 +17,10 @@ function prototyper(str) {
if (prototypeRE.test(str)) {
if (str.length > 9) {
return prototyper(
str.trim().split('prototype').join('-prototype-')
str
.trim()
.split('prototype')
.join('-prototype-')
);
}
return str;
@ -26,15 +29,13 @@ function prototyper(str) {
})
.join(' ')
.split(' ');
const noProto = formatted
.filter(removeProto)
.filter(x => !!x);
const noProto = formatted.filter(removeProto).filter(x => !!x);
if (noProto.length === 2) {
const [ first, second ] = noProto;
const [first, second] = noProto;
const secondLC = second.toLowerCase();
const finalSecond = preFormatted[secondLC] ?
preFormatted[secondLC] :
secondLC;
const finalSecond = preFormatted[secondLC]
? preFormatted[secondLC]
: secondLC;
return `${titleify(first)}.prototype.${finalSecond}`;
}
if (noProto.length === 1) {
@ -62,9 +63,7 @@ function titleify(str, triedPrototyper) {
if (stopWords.some(x => x === word) && i !== 0) {
return word;
}
return preFormatted[word] ?
preFormatted[word] :
titleCase(word);
return preFormatted[word] ? preFormatted[word] : titleCase(word);
})
.join(' ');
}

View File

@ -114,7 +114,7 @@ function superBlockInfoFromPath(filePath) {
}
function superBlockInfoFromFullPath(fullFilePath) {
const [,, maybeSuper] = fullFilePath.split(path.sep).reverse();
const [, , maybeSuper] = fullFilePath.split(path.sep).reverse();
return superBlockInfo(maybeSuper);
}

View File

@ -1,13 +1,9 @@
const fs = require('fs-extra');
const gulp = require('gulp');
const {
locale
} = require('../config/env.json');
const { locale } = require('../config/env.json');
const {
getChallengesForLang
} = require('./getChallenges');
const { getChallengesForLang } = require('./getChallenges');
function generateCurriculum(done) {
return getChallengesForLang(locale)

View File

@ -8,9 +8,7 @@ const _ = require('lodash');
const createDebugger = require('debug');
const utils = require('../server/utils');
const getChallenges = require('./getChallenges');
const { validateChallenge } = require(
'./schema/challengeSchema'
);
const { validateChallenge } = require('./schema/challengeSchema');
const app = require('../server/server');
const log = createDebugger('fcc:seed');
@ -23,10 +21,14 @@ const nameify = utils.nameify;
const Observable = Rx.Observable;
const Challenge = app.models.Challenge;
const destroyChallenges =
Observable.fromNodeCallback(Challenge.destroyAll, Challenge);
const createChallenges =
Observable.fromNodeCallback(Challenge.create, Challenge);
const destroyChallenges = Observable.fromNodeCallback(
Challenge.destroyAll,
Challenge
);
const createChallenges = Observable.fromNodeCallback(
Challenge.create,
Challenge
);
const Block = app.models.Block;
const destroyBlocks = Observable.fromNodeCallback(Block.destroyAll, Block);
@ -34,12 +36,11 @@ const createBlocks = Observable.fromNodeCallback(Block.create, Block);
const arrToString = arr =>
Array.isArray(arr) ? arr.join('\n') : _.toString(arr);
Observable.combineLatest(
destroyChallenges(),
destroyBlocks()
)
Observable.combineLatest(destroyChallenges(), destroyBlocks())
.last()
.flatMap(function() { return Observable.from(getChallenges()); })
.flatMap(function() {
return Observable.from(getChallenges());
})
.flatMap(function(challengeSpec) {
const order = challengeSpec.order;
const blockName = challengeSpec.name;
@ -80,8 +81,7 @@ Observable.combineLatest(
.map(block => {
log('successfully created %s block', block.name);
return challengeSpec.challenges
.map(function(challenge, index) {
return challengeSpec.challenges.map(function(challenge, index) {
challenge.name = nameify(challenge.title);
challenge.dashedName = dasherize(challenge.name);
@ -96,7 +96,9 @@ Observable.combineLatest(
);
if (challenge.files) {
challenge.files = _.reduce(challenge.files, (map, file) => {
challenge.files = _.reduce(
challenge.files,
(map, file) => {
map[file.key] = {
...file,
head: arrToString(file.head),
@ -104,7 +106,9 @@ Observable.combineLatest(
tail: arrToString(file.tail)
};
return map;
}, {});
},
{}
);
}
challenge.fileName = fileName;
challenge.helpRoom = helpRoom;
@ -126,9 +130,7 @@ Observable.combineLatest(
.join(' ');
challenge.required = (challenge.required || []).concat(required);
challenge.template = challenge.template || template;
return _.omit(
challenge,
[
return _.omit(challenge, [
'betaSolutions',
'betaTests',
'hints',
@ -141,8 +143,7 @@ Observable.combineLatest(
'releasedOn',
'translations',
'type'
]
);
]);
});
})
.flatMap(challenges => {
@ -160,7 +161,9 @@ Observable.combineLatest(
function(challenges) {
log('%s successfully saved', challenges[0].block);
},
function(err) { throw err; },
function(err) {
throw err;
},
function() {
log('challenge seed completed');
process.exit(0);

View File

@ -55,11 +55,7 @@ async function translateChallenge(file) {
];
return Promise.all(translatePromises).then(
([title, description, instructions, ...tests]) => {
const {
files = {},
solutions = [],
...challengeMeta
} = challenge;
const { files = {}, solutions = [], ...challengeMeta } = challenge;
const md = `---
${YAML.dump(
Object.assign(challengeMeta, {

View File

@ -20,7 +20,7 @@ class ChallengeTitles {
The title ${title} is already assigned
`);
}
this.knownTitles = [ ...this.knownTitles, titleToCheck ];
this.knownTitles = [...this.knownTitles, titleToCheck];
}
}

View File

@ -17,7 +17,7 @@ class MongoIds {
The id for ${title} is already assigned
`);
}
this.knownIds = [ ...this.knownIds, id ];
this.knownIds = [...this.knownIds, id];
}
}

883
package-lock.json generated
View File

@ -1155,6 +1155,12 @@
"json-schema-traverse": "^0.3.0"
}
},
"ajv-keywords": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz",
"integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=",
"dev": true
},
"ansi-escapes": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz",
@ -1837,6 +1843,12 @@
"integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==",
"dev": true
},
"boolify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/boolify/-/boolify-1.0.1.tgz",
"integrity": "sha1-tcCeF8rNET0Rt7s+04TMASmU2Gs=",
"dev": true
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@ -2256,6 +2268,12 @@
"dev": true,
"optional": true
},
"common-tags": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz",
"integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==",
"dev": true
},
"compare-func": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/compare-func/-/compare-func-1.3.2.tgz",
@ -2801,6 +2819,12 @@
"path-type": "^3.0.0"
}
},
"dlv": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.2.tgz",
"integrity": "sha512-xxD4VSH67GbRvSGUrckvha94RD7hjgOH7rqGxiytLpkaeMvixOHFZTGFK6EkIm3T761OVHT8ABHmGkq9gXgu6Q==",
"dev": true
},
"doctrine": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
@ -5489,6 +5513,12 @@
"has": "^1.0.1"
}
},
"is-resolvable": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz",
"integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==",
"dev": true
},
"is-ssh": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.1.tgz",
@ -7097,6 +7127,18 @@
"integrity": "sha1-I+89lTVWUgOmbO/VuDD4SJEa+0g=",
"dev": true
},
"lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
"integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=",
"dev": true
},
"lodash.merge": {
"version": "4.6.1",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.1.tgz",
"integrity": "sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ==",
"dev": true
},
"lodash.set": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz",
@ -7128,6 +7170,12 @@
"lodash._reinterpolate": "~3.0.0"
}
},
"lodash.unescape": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz",
"integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=",
"dev": true
},
"lodash.uniq": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
@ -7143,6 +7191,58 @@
"chalk": "^2.0.1"
}
},
"loglevel": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.1.tgz",
"integrity": "sha1-4PyVEztu8nbNyIh82vJKpvFW+Po=",
"dev": true
},
"loglevel-colored-level-prefix": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/loglevel-colored-level-prefix/-/loglevel-colored-level-prefix-1.0.0.tgz",
"integrity": "sha1-akAhj9x64V/HbD0PPmdsRlOIYD4=",
"dev": true,
"requires": {
"chalk": "^1.1.3",
"loglevel": "^1.4.1"
},
"dependencies": {
"ansi-styles": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
"dev": true
},
"chalk": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
"dev": true,
"requires": {
"ansi-styles": "^2.2.1",
"escape-string-regexp": "^1.0.2",
"has-ansi": "^2.0.0",
"strip-ansi": "^3.0.0",
"supports-color": "^2.0.0"
}
},
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true,
"requires": {
"ansi-regex": "^2.0.0"
}
},
"supports-color": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
"dev": true
}
}
},
"loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
@ -7214,6 +7314,24 @@
"ssri": "^6.0.0"
}
},
"make-plural": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/make-plural/-/make-plural-4.3.0.tgz",
"integrity": "sha512-xTYd4JVHpSCW+aqDof6w/MebaMVNTVYBZhbB/vi513xXdiPT92JMVCo0Jq8W2UZnzYRFeVbQiQ+I25l13JuKvA==",
"dev": true,
"requires": {
"minimist": "^1.2.0"
},
"dependencies": {
"minimist": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"dev": true,
"optional": true
}
}
},
"makeerror": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz",
@ -7322,6 +7440,41 @@
"integrity": "sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA==",
"dev": true
},
"messageformat": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/messageformat/-/messageformat-1.1.1.tgz",
"integrity": "sha512-Q0uXcDtF5pEZsVSyhzDOGgZZK6ykN79VY9CwU3Nv0gsqx62BjdJW0MT+63UkHQ4exe3HE33ZlxR2/YwoJarRTg==",
"dev": true,
"requires": {
"glob": "~7.0.6",
"make-plural": "^4.1.1",
"messageformat-parser": "^1.1.0",
"nopt": "~3.0.6",
"reserved-words": "^0.1.2"
},
"dependencies": {
"glob": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz",
"integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.2",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
}
}
},
"messageformat-parser": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/messageformat-parser/-/messageformat-parser-1.1.0.tgz",
"integrity": "sha512-Hwem6G3MsKDLS1FtBRGIs8T50P1Q00r3srS6QJePCFbad9fq0nYxwf3rnU2BreApRGhmpKMV7oZI06Sy1c9TPA==",
"dev": true
},
"micromatch": {
"version": "3.1.10",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
@ -8433,6 +8586,569 @@
"integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=",
"dev": true
},
"prettier": {
"version": "1.16.4",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-1.16.4.tgz",
"integrity": "sha512-ZzWuos7TI5CKUeQAtFd6Zhm2s6EpAD/ZLApIhsF9pRvRtM1RFo61dM/4MSRUA0SuLugA/zgrZD8m0BaY46Og7g==",
"dev": true
},
"prettier-eslint": {
"version": "8.8.2",
"resolved": "https://registry.npmjs.org/prettier-eslint/-/prettier-eslint-8.8.2.tgz",
"integrity": "sha512-2UzApPuxi2yRoyMlXMazgR6UcH9DKJhNgCviIwY3ixZ9THWSSrUww5vkiZ3C48WvpFl1M1y/oU63deSy1puWEA==",
"dev": true,
"requires": {
"babel-runtime": "^6.26.0",
"common-tags": "^1.4.0",
"dlv": "^1.1.0",
"eslint": "^4.0.0",
"indent-string": "^3.2.0",
"lodash.merge": "^4.6.0",
"loglevel-colored-level-prefix": "^1.0.0",
"prettier": "^1.7.0",
"pretty-format": "^23.0.1",
"require-relative": "^0.8.7",
"typescript": "^2.5.1",
"typescript-eslint-parser": "^16.0.0",
"vue-eslint-parser": "^2.0.2"
},
"dependencies": {
"acorn-jsx": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
"integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=",
"dev": true,
"requires": {
"acorn": "^3.0.4"
},
"dependencies": {
"acorn": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
"integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=",
"dev": true
}
}
},
"chardet": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz",
"integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=",
"dev": true
},
"debug": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
"dev": true,
"requires": {
"ms": "^2.1.1"
}
},
"eslint": {
"version": "4.19.1",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz",
"integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==",
"dev": true,
"requires": {
"ajv": "^5.3.0",
"babel-code-frame": "^6.22.0",
"chalk": "^2.1.0",
"concat-stream": "^1.6.0",
"cross-spawn": "^5.1.0",
"debug": "^3.1.0",
"doctrine": "^2.1.0",
"eslint-scope": "^3.7.1",
"eslint-visitor-keys": "^1.0.0",
"espree": "^3.5.4",
"esquery": "^1.0.0",
"esutils": "^2.0.2",
"file-entry-cache": "^2.0.0",
"functional-red-black-tree": "^1.0.1",
"glob": "^7.1.2",
"globals": "^11.0.1",
"ignore": "^3.3.3",
"imurmurhash": "^0.1.4",
"inquirer": "^3.0.6",
"is-resolvable": "^1.0.0",
"js-yaml": "^3.9.1",
"json-stable-stringify-without-jsonify": "^1.0.1",
"levn": "^0.3.0",
"lodash": "^4.17.4",
"minimatch": "^3.0.2",
"mkdirp": "^0.5.1",
"natural-compare": "^1.4.0",
"optionator": "^0.8.2",
"path-is-inside": "^1.0.2",
"pluralize": "^7.0.0",
"progress": "^2.0.0",
"regexpp": "^1.0.1",
"require-uncached": "^1.0.3",
"semver": "^5.3.0",
"strip-ansi": "^4.0.0",
"strip-json-comments": "~2.0.1",
"table": "4.0.2",
"text-table": "~0.2.0"
}
},
"eslint-scope": {
"version": "3.7.3",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz",
"integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==",
"dev": true,
"requires": {
"esrecurse": "^4.1.0",
"estraverse": "^4.1.1"
}
},
"espree": {
"version": "3.5.4",
"resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz",
"integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==",
"dev": true,
"requires": {
"acorn": "^5.5.0",
"acorn-jsx": "^3.0.0"
}
},
"external-editor": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz",
"integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==",
"dev": true,
"requires": {
"chardet": "^0.4.0",
"iconv-lite": "^0.4.17",
"tmp": "^0.0.33"
}
},
"inquirer": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz",
"integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==",
"dev": true,
"requires": {
"ansi-escapes": "^3.0.0",
"chalk": "^2.0.0",
"cli-cursor": "^2.1.0",
"cli-width": "^2.0.0",
"external-editor": "^2.0.4",
"figures": "^2.0.0",
"lodash": "^4.3.0",
"mute-stream": "0.0.7",
"run-async": "^2.2.0",
"rx-lite": "^4.0.8",
"rx-lite-aggregates": "^4.0.8",
"string-width": "^2.1.0",
"strip-ansi": "^4.0.0",
"through": "^2.3.6"
}
},
"ms": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
"dev": true
},
"regexpp": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz",
"integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==",
"dev": true
},
"slice-ansi": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz",
"integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==",
"dev": true,
"requires": {
"is-fullwidth-code-point": "^2.0.0"
}
},
"table": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz",
"integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==",
"dev": true,
"requires": {
"ajv": "^5.2.3",
"ajv-keywords": "^2.1.0",
"chalk": "^2.1.0",
"lodash": "^4.17.4",
"slice-ansi": "1.0.0",
"string-width": "^2.1.1"
}
}
}
},
"prettier-eslint-cli": {
"version": "4.7.1",
"resolved": "https://registry.npmjs.org/prettier-eslint-cli/-/prettier-eslint-cli-4.7.1.tgz",
"integrity": "sha512-hQbsGaEVz97oBBcKdsJ46khv0kOGkMyWrXzcFOXW6X8UuetZ/j0yDJkNJgUTVc6PVFbbzBXk+qgd5vos9qzXPQ==",
"dev": true,
"requires": {
"arrify": "^1.0.1",
"babel-runtime": "^6.23.0",
"boolify": "^1.0.0",
"camelcase-keys": "^4.1.0",
"chalk": "2.3.0",
"common-tags": "^1.4.0",
"eslint": "^4.5.0",
"find-up": "^2.1.0",
"get-stdin": "^5.0.1",
"glob": "^7.1.1",
"ignore": "^3.2.7",
"indent-string": "^3.1.0",
"lodash.memoize": "^4.1.2",
"loglevel-colored-level-prefix": "^1.0.0",
"messageformat": "^1.0.2",
"prettier-eslint": "^8.5.0",
"rxjs": "^5.3.0",
"yargs": "10.0.3"
},
"dependencies": {
"acorn-jsx": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
"integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=",
"dev": true,
"requires": {
"acorn": "^3.0.4"
},
"dependencies": {
"acorn": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
"integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=",
"dev": true
}
}
},
"chalk": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
"integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
"dev": true,
"requires": {
"ansi-styles": "^3.1.0",
"escape-string-regexp": "^1.0.5",
"supports-color": "^4.0.0"
}
},
"chardet": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz",
"integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=",
"dev": true
},
"cliui": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
"integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
"dev": true,
"requires": {
"string-width": "^1.0.1",
"strip-ansi": "^3.0.1",
"wrap-ansi": "^2.0.0"
},
"dependencies": {
"is-fullwidth-code-point": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
"dev": true,
"requires": {
"number-is-nan": "^1.0.0"
}
},
"string-width": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
"dev": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
"strip-ansi": "^3.0.0"
}
},
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true,
"requires": {
"ansi-regex": "^2.0.0"
}
}
}
},
"debug": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
"dev": true,
"requires": {
"ms": "^2.1.1"
}
},
"eslint": {
"version": "4.19.1",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz",
"integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==",
"dev": true,
"requires": {
"ajv": "^5.3.0",
"babel-code-frame": "^6.22.0",
"chalk": "^2.1.0",
"concat-stream": "^1.6.0",
"cross-spawn": "^5.1.0",
"debug": "^3.1.0",
"doctrine": "^2.1.0",
"eslint-scope": "^3.7.1",
"eslint-visitor-keys": "^1.0.0",
"espree": "^3.5.4",
"esquery": "^1.0.0",
"esutils": "^2.0.2",
"file-entry-cache": "^2.0.0",
"functional-red-black-tree": "^1.0.1",
"glob": "^7.1.2",
"globals": "^11.0.1",
"ignore": "^3.3.3",
"imurmurhash": "^0.1.4",
"inquirer": "^3.0.6",
"is-resolvable": "^1.0.0",
"js-yaml": "^3.9.1",
"json-stable-stringify-without-jsonify": "^1.0.1",
"levn": "^0.3.0",
"lodash": "^4.17.4",
"minimatch": "^3.0.2",
"mkdirp": "^0.5.1",
"natural-compare": "^1.4.0",
"optionator": "^0.8.2",
"path-is-inside": "^1.0.2",
"pluralize": "^7.0.0",
"progress": "^2.0.0",
"regexpp": "^1.0.1",
"require-uncached": "^1.0.3",
"semver": "^5.3.0",
"strip-ansi": "^4.0.0",
"strip-json-comments": "~2.0.1",
"table": "4.0.2",
"text-table": "~0.2.0"
}
},
"eslint-scope": {
"version": "3.7.3",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz",
"integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==",
"dev": true,
"requires": {
"esrecurse": "^4.1.0",
"estraverse": "^4.1.1"
}
},
"espree": {
"version": "3.5.4",
"resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz",
"integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==",
"dev": true,
"requires": {
"acorn": "^5.5.0",
"acorn-jsx": "^3.0.0"
}
},
"execa": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
"integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
"dev": true,
"requires": {
"cross-spawn": "^5.0.1",
"get-stream": "^3.0.0",
"is-stream": "^1.1.0",
"npm-run-path": "^2.0.0",
"p-finally": "^1.0.0",
"signal-exit": "^3.0.0",
"strip-eof": "^1.0.0"
}
},
"external-editor": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz",
"integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==",
"dev": true,
"requires": {
"chardet": "^0.4.0",
"iconv-lite": "^0.4.17",
"tmp": "^0.0.33"
}
},
"find-up": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
"integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
"dev": true,
"requires": {
"locate-path": "^2.0.0"
}
},
"get-stdin": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz",
"integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=",
"dev": true
},
"get-stream": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
"dev": true
},
"has-flag": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
"integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
"dev": true
},
"inquirer": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz",
"integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==",
"dev": true,
"requires": {
"ansi-escapes": "^3.0.0",
"chalk": "^2.0.0",
"cli-cursor": "^2.1.0",
"cli-width": "^2.0.0",
"external-editor": "^2.0.4",
"figures": "^2.0.0",
"lodash": "^4.3.0",
"mute-stream": "0.0.7",
"run-async": "^2.2.0",
"rx-lite": "^4.0.8",
"rx-lite-aggregates": "^4.0.8",
"string-width": "^2.1.0",
"strip-ansi": "^4.0.0",
"through": "^2.3.6"
}
},
"invert-kv": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
"integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=",
"dev": true
},
"lcid": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
"integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
"dev": true,
"requires": {
"invert-kv": "^1.0.0"
}
},
"mem": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz",
"integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=",
"dev": true,
"requires": {
"mimic-fn": "^1.0.0"
}
},
"ms": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
"dev": true
},
"os-locale": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz",
"integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==",
"dev": true,
"requires": {
"execa": "^0.7.0",
"lcid": "^1.0.0",
"mem": "^1.1.0"
}
},
"regexpp": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz",
"integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==",
"dev": true
},
"slice-ansi": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz",
"integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==",
"dev": true,
"requires": {
"is-fullwidth-code-point": "^2.0.0"
}
},
"supports-color": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
"integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
"dev": true,
"requires": {
"has-flag": "^2.0.0"
}
},
"table": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz",
"integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==",
"dev": true,
"requires": {
"ajv": "^5.2.3",
"ajv-keywords": "^2.1.0",
"chalk": "^2.1.0",
"lodash": "^4.17.4",
"slice-ansi": "1.0.0",
"string-width": "^2.1.1"
}
},
"y18n": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
"integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=",
"dev": true
},
"yargs": {
"version": "10.0.3",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-10.0.3.tgz",
"integrity": "sha512-DqBpQ8NAUX4GyPP/ijDGHsJya4tYqLQrjPr95HNsr1YwL3+daCfvBwg7+gIC6IdJhR2kATh3hb61vjzMWEtjdw==",
"dev": true,
"requires": {
"cliui": "^3.2.0",
"decamelize": "^1.1.1",
"find-up": "^2.1.0",
"get-caller-file": "^1.0.1",
"os-locale": "^2.0.0",
"require-directory": "^2.1.1",
"require-main-filename": "^1.0.1",
"set-blocking": "^2.0.0",
"string-width": "^2.0.0",
"which-module": "^2.0.0",
"y18n": "^3.2.1",
"yargs-parser": "^8.0.0"
}
},
"yargs-parser": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-8.1.0.tgz",
"integrity": "sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ==",
"dev": true,
"requires": {
"camelcase": "^4.1.0"
}
}
}
},
"pretty-format": {
"version": "23.6.0",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-23.6.0.tgz",
@ -8965,6 +9681,51 @@
"integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
"dev": true
},
"require-relative": {
"version": "0.8.7",
"resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz",
"integrity": "sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=",
"dev": true
},
"require-uncached": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
"integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=",
"dev": true,
"requires": {
"caller-path": "^0.1.0",
"resolve-from": "^1.0.0"
},
"dependencies": {
"caller-path": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz",
"integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=",
"dev": true,
"requires": {
"callsites": "^0.2.0"
}
},
"callsites": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz",
"integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=",
"dev": true
},
"resolve-from": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz",
"integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=",
"dev": true
}
}
},
"reserved-words": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/reserved-words/-/reserved-words-0.1.2.tgz",
"integrity": "sha1-AKCUD5jNUBrqqsMWQR2a3FKzGrE=",
"dev": true
},
"resolve": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz",
@ -9058,6 +9819,30 @@
"aproba": "^1.1.1"
}
},
"rx-lite": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz",
"integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=",
"dev": true
},
"rx-lite-aggregates": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz",
"integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=",
"dev": true,
"requires": {
"rx-lite": "*"
}
},
"rxjs": {
"version": "5.5.12",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz",
"integrity": "sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==",
"dev": true,
"requires": {
"symbol-observable": "1.0.1"
}
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
@ -9689,6 +10474,12 @@
"has-flag": "^3.0.0"
}
},
"symbol-observable": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz",
"integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=",
"dev": true
},
"symbol-tree": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz",
@ -10109,6 +10900,30 @@
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
"dev": true
},
"typescript": {
"version": "2.9.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz",
"integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==",
"dev": true
},
"typescript-eslint-parser": {
"version": "16.0.1",
"resolved": "https://registry.npmjs.org/typescript-eslint-parser/-/typescript-eslint-parser-16.0.1.tgz",
"integrity": "sha512-IKawLTu4A2xN3aN/cPLxvZ0bhxZHILGDKTZWvWNJ3sLNhJ3PjfMEDQmR2VMpdRPrmWOadgWXRwjLBzSA8AGsaQ==",
"dev": true,
"requires": {
"lodash.unescape": "4.0.1",
"semver": "5.5.0"
},
"dependencies": {
"semver": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
"integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
"dev": true
}
}
},
"uglify-js": {
"version": "3.4.9",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz",
@ -10336,6 +11151,74 @@
"extsprintf": "^1.2.0"
}
},
"vue-eslint-parser": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-2.0.3.tgz",
"integrity": "sha512-ZezcU71Owm84xVF6gfurBQUGg8WQ+WZGxgDEQu1IHFBZNx7BFZg3L1yHxrCBNNwbwFtE1GuvfJKMtb6Xuwc/Bw==",
"dev": true,
"requires": {
"debug": "^3.1.0",
"eslint-scope": "^3.7.1",
"eslint-visitor-keys": "^1.0.0",
"espree": "^3.5.2",
"esquery": "^1.0.0",
"lodash": "^4.17.4"
},
"dependencies": {
"acorn-jsx": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
"integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=",
"dev": true,
"requires": {
"acorn": "^3.0.4"
},
"dependencies": {
"acorn": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
"integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=",
"dev": true
}
}
},
"debug": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
"dev": true,
"requires": {
"ms": "^2.1.1"
}
},
"eslint-scope": {
"version": "3.7.3",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz",
"integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==",
"dev": true,
"requires": {
"esrecurse": "^4.1.0",
"estraverse": "^4.1.1"
}
},
"espree": {
"version": "3.5.4",
"resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz",
"integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==",
"dev": true,
"requires": {
"acorn": "^5.5.0",
"acorn-jsx": "^3.0.0"
}
},
"ms": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
"dev": true
}
}
},
"w3c-hr-time": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz",

View File

@ -8,6 +8,7 @@
"develop:client": "cd ./client && npm run develop",
"develop:server": "cd ./api-server && node development-entry.js",
"ensure-env": "cross-env DEBUG=fcc:* node ./tools/scripts/ensure-env.js",
"format": "prettier-eslint --trailing-comma none --semi --eslint-ignore --ignore curriculum/challenges --ignore guide --ignore mock-guide --write './**/*.js'",
"lint": "eslint .",
"seed": "npm-run-all -p seed:*",
"seed:auth-user": "cross-env DEBUG=fcc:* node ./tools/scripts/seed/seedAuthUser",
@ -39,6 +40,7 @@
"lodash": "^4.17.11",
"npm-run-all": "^4.1.5",
"ora": "^3.0.0",
"prettier-eslint-cli": "^4.7.1",
"readdirp-walk": "^1.6.0",
"shortid": "^2.2.14",
"slugg": "^1.2.1"

View File

@ -36,9 +36,7 @@ describe('createRedirects', () => {
const { api, forum } = testLocations;
expect(redirects.includes(`${api}/internal/:splat`)).toBe(true);
expect(
redirects.includes(
`${forum}/t/free-code-camp-privacy-policy/19545 301`
)
redirects.includes(`${forum}/t/free-code-camp-privacy-policy/19545 301`)
).toBe(true);
expect(redirects.includes(`${forum}`)).toBe(true);
});

View File

@ -22,10 +22,10 @@ function handleError(err, client) {
}
}
MongoClient.connect(
MONGOHQ_URL,
{ useNewUrlParser: true },
function(err, client) {
MongoClient.connect(MONGOHQ_URL, { useNewUrlParser: true }, function(
err,
client
) {
handleError(err, client);
log('Connected successfully to mongo');
@ -33,12 +33,11 @@ MongoClient.connect(
const db = client.db('freecodecamp');
const user = db.collection('user');
user.deleteOne({_id: ObjectId('5bd30e0f1caf6ac3ddddddb5') }, (err) => {
user.deleteOne({ _id: ObjectId('5bd30e0f1caf6ac3ddddddb5') }, err => {
handleError(err, client);
try {
user.insertOne(
{
user.insertOne({
_id: ObjectId('5bd30e0f1caf6ac3ddddddb5'),
email: 'foo@bar.com',
emailVerified: true,
@ -88,8 +87,7 @@ MongoClient.connect(
isDonating: false,
emailAuthLinkTTL: null,
emailVerifyTTL: null
}
);
});
} catch (e) {
handleError(e, client);
} finally {
@ -97,5 +95,4 @@ MongoClient.connect(
client.close();
}
});
}
);
});

View File

@ -26,10 +26,10 @@ function handleError(err, client) {
}
}
MongoClient.connect(
MONGOHQ_URL,
{ useNewUrlParser: true },
function(err, client) {
MongoClient.connect(MONGOHQ_URL, { useNewUrlParser: true }, function(
err,
client
) {
handleError(err, client);
log('Connected successfully to mongo at %s', MONGOHQ_URL);
@ -60,15 +60,11 @@ MongoClient.connect(
});
try {
challengeCollection.insertMany(
allChallenges,
{ ordered: false },
err => {
challengeCollection.insertMany(allChallenges, { ordered: false }, err => {
handleError(err, client);
log('challenge seed complete');
client.close();
}
);
});
} catch (e) {
handleError(e, client);
} finally {
@ -87,5 +83,4 @@ MongoClient.connect(
});
}
});
}
);
});