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) { export default function(Block) {
Block.on('dataSourceAttached', () => { Block.on('dataSourceAttached', () => {
Block.findOne$ = Block.findOne$ = Observable.fromNodeCallback(Block.findOne, Block);
Observable.fromNodeCallback(Block.findOne, Block); Block.findById$ = Observable.fromNodeCallback(Block.findById, Block);
Block.findById$ = Block.find$ = Observable.fromNodeCallback(Block.find, Block);
Observable.fromNodeCallback(Block.findById, Block);
Block.find$ =
Observable.fromNodeCallback(Block.find, Block);
}); });
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -350,9 +350,8 @@ function createShowCert(app) {
messages: [ messages: [
{ {
type: 'info', type: 'info',
message: `We could not find a user with the username "${ message:
username '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( req.flash(
'danger', '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); return res.sendStatus(403);
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -57,9 +57,11 @@ export const userPropsForSession = [
export function normaliseUserFields(user) { export function normaliseUserFields(user) {
const about = user.bio && !user.about ? user.bio : user.about; const about = user.bio && !user.about ? user.bio : user.about;
const picture = user.picture || addPlaceholderImage(user.username); const picture = user.picture || addPlaceholderImage(user.username);
const twitter = user.twitter && isURL(user.twitter) ? const twitter =
user.twitter : user.twitter && isURL(user.twitter)
user.twitter && `https://www.twitter.com/${user.twitter.replace(/^@/, '')}`; ? user.twitter
: user.twitter &&
`https://www.twitter.com/${user.twitter.replace(/^@/, '')}`;
return { about, picture, twitter }; 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 // set new expire time in MS and create new subscription to source
if (!expireCacheAt || expireCacheAt < Date.now()) { if (!expireCacheAt || expireCacheAt < Date.now()) {
// set expire in ms; // set expire in ms;
expireCacheAt = moment().add(time, unit).valueOf(); expireCacheAt = moment()
.add(time, unit)
.valueOf();
cache = new AsyncSubject(); cache = new AsyncSubject();
source.subscribe(cache); source.subscribe(cache);
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -154,4 +154,7 @@ export class Block extends Component {
Block.displayName = 'Block'; Block.displayName = 'Block';
Block.propTypes = propTypes; 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, errors,
fields, fields,
handleSubmit, handleSubmit,
fields: { _meta: { allPristine } }, fields: {
_meta: { allPristine }
},
// HOC // HOC
buttonText, buttonText,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -55,35 +55,8 @@ export class ToolPanel extends Component {
ToolPanel.displayName = 'ProjectToolPanel'; ToolPanel.displayName = 'ProjectToolPanel';
ToolPanel.propTypes = propTypes; 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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

883
package-lock.json generated
View File

@ -1155,6 +1155,12 @@
"json-schema-traverse": "^0.3.0" "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": { "ansi-escapes": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz",
@ -1837,6 +1843,12 @@
"integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==", "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==",
"dev": true "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": { "brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@ -2256,6 +2268,12 @@
"dev": true, "dev": true,
"optional": 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": { "compare-func": {
"version": "1.3.2", "version": "1.3.2",
"resolved": "https://registry.npmjs.org/compare-func/-/compare-func-1.3.2.tgz", "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-1.3.2.tgz",
@ -2801,6 +2819,12 @@
"path-type": "^3.0.0" "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": { "doctrine": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
@ -5489,6 +5513,12 @@
"has": "^1.0.1" "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": { "is-ssh": {
"version": "1.3.1", "version": "1.3.1",
"resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.1.tgz", "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.1.tgz",
@ -7097,6 +7127,18 @@
"integrity": "sha1-I+89lTVWUgOmbO/VuDD4SJEa+0g=", "integrity": "sha1-I+89lTVWUgOmbO/VuDD4SJEa+0g=",
"dev": true "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": { "lodash.set": {
"version": "4.3.2", "version": "4.3.2",
"resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz",
@ -7128,6 +7170,12 @@
"lodash._reinterpolate": "~3.0.0" "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": { "lodash.uniq": {
"version": "4.5.0", "version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
@ -7143,6 +7191,58 @@
"chalk": "^2.0.1" "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": { "loose-envify": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
@ -7214,6 +7314,24 @@
"ssri": "^6.0.0" "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": { "makeerror": {
"version": "1.0.11", "version": "1.0.11",
"resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz",
@ -7322,6 +7440,41 @@
"integrity": "sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA==", "integrity": "sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA==",
"dev": true "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": { "micromatch": {
"version": "3.1.10", "version": "3.1.10",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
@ -8433,6 +8586,569 @@
"integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=",
"dev": true "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": { "pretty-format": {
"version": "23.6.0", "version": "23.6.0",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-23.6.0.tgz", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-23.6.0.tgz",
@ -8965,6 +9681,51 @@
"integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
"dev": true "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": { "resolve": {
"version": "1.10.0", "version": "1.10.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz",
@ -9058,6 +9819,30 @@
"aproba": "^1.1.1" "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": { "safe-buffer": {
"version": "5.1.2", "version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
@ -9689,6 +10474,12 @@
"has-flag": "^3.0.0" "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": { "symbol-tree": {
"version": "3.2.2", "version": "3.2.2",
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz",
@ -10109,6 +10900,30 @@
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
"dev": true "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": { "uglify-js": {
"version": "3.4.9", "version": "3.4.9",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz",
@ -10336,6 +11151,74 @@
"extsprintf": "^1.2.0" "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": { "w3c-hr-time": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", "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:client": "cd ./client && npm run develop",
"develop:server": "cd ./api-server && node development-entry.js", "develop:server": "cd ./api-server && node development-entry.js",
"ensure-env": "cross-env DEBUG=fcc:* node ./tools/scripts/ensure-env.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 .", "lint": "eslint .",
"seed": "npm-run-all -p seed:*", "seed": "npm-run-all -p seed:*",
"seed:auth-user": "cross-env DEBUG=fcc:* node ./tools/scripts/seed/seedAuthUser", "seed:auth-user": "cross-env DEBUG=fcc:* node ./tools/scripts/seed/seedAuthUser",
@ -39,6 +40,7 @@
"lodash": "^4.17.11", "lodash": "^4.17.11",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"ora": "^3.0.0", "ora": "^3.0.0",
"prettier-eslint-cli": "^4.7.1",
"readdirp-walk": "^1.6.0", "readdirp-walk": "^1.6.0",
"shortid": "^2.2.14", "shortid": "^2.2.14",
"slugg": "^1.2.1" "slugg": "^1.2.1"

View File

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

View File

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

View File

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