feat: Use prettier-eslint to format code
This commit is contained in:
committed by
mrugesh mohapatra
parent
1ba67c4e2b
commit
b13e5fb41a
@ -115,10 +115,10 @@ export default function(UserIdent) {
|
|||||||
return identity
|
return identity
|
||||||
? Observable.of(identity.user())
|
? Observable.of(identity.user())
|
||||||
: User.findOne$({ where: { email } }).flatMap(user => {
|
: User.findOne$({ where: { email } }).flatMap(user => {
|
||||||
return user
|
return user
|
||||||
? Observable.of(user)
|
? Observable.of(user)
|
||||||
: User.create$({ email }).toPromise();
|
: User.create$({ email }).toPromise();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.flatMap(user => {
|
.flatMap(user => {
|
||||||
const createToken = observeQuery(AccessToken, 'create', {
|
const createToken = observeQuery(AccessToken, 'create', {
|
||||||
|
@ -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);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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';
|
||||||
|
@ -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: {
|
result: { superBlocks }
|
||||||
challenge,
|
}) {
|
||||||
block,
|
|
||||||
superBlock
|
|
||||||
},
|
|
||||||
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,12 +41,10 @@ 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] =
|
return map;
|
||||||
challenge[challengeName].dashedName;
|
}, {})
|
||||||
return map;
|
|
||||||
}, {})
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// addNameIdMap(
|
// addNameIdMap(
|
||||||
|
@ -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',
|
||||||
@ -71,7 +54,7 @@ export function createPoly({
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
...rest,
|
...rest,
|
||||||
history: Array.isArray(history) ? history : [ name + ext ],
|
history: Array.isArray(history) ? history : [name + ext],
|
||||||
name,
|
name,
|
||||||
ext,
|
ext,
|
||||||
path: name + '.' + ext,
|
path: name + '.' + ext,
|
||||||
@ -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
|
||||||
@ -125,7 +110,7 @@ export function setExt(ext, poly) {
|
|||||||
path: poly.name + '.' + ext,
|
path: poly.name + '.' + ext,
|
||||||
key: poly.name + ext
|
key: poly.name + ext
|
||||||
};
|
};
|
||||||
newPoly.history = [ ...poly.history, newPoly.path ];
|
newPoly.history = [...poly.history, newPoly.path];
|
||||||
return newPoly;
|
return newPoly;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +123,7 @@ export function setName(name, poly) {
|
|||||||
path: name + '.' + poly.ext,
|
path: name + '.' + poly.ext,
|
||||||
key: name + poly.ext
|
key: name + poly.ext
|
||||||
};
|
};
|
||||||
newPoly.history = [ ...poly.history, newPoly.path ];
|
newPoly.history = [...poly.history, newPoly.path];
|
||||||
return newPoly;
|
return newPoly;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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(
|
||||||
() => [ poly.head, poly.contents, poly.tail ].join(padding),
|
transformContents(
|
||||||
poly
|
() => [poly.head, poly.contents, poly.tail].join(padding),
|
||||||
));
|
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)
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
);
|
|
||||||
|
@ -16,7 +16,5 @@ module.exports = {
|
|||||||
transform: {
|
transform: {
|
||||||
'^.+\\.js$': 'babel-jest'
|
'^.+\\.js$': 'babel-jest'
|
||||||
},
|
},
|
||||||
transformIgnorePatterns: [
|
transformIgnorePatterns: ['node_modules/(?!(gatsby)/)']
|
||||||
'node_modules/(?!(gatsby)/)'
|
|
||||||
]
|
|
||||||
};
|
};
|
||||||
|
@ -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 + '"'
|
||||||
}"`
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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,12 +31,12 @@ 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;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
nonprofit = nonprofit || nonprofits[ _.random(0, nonprofits.length - 1) ];
|
nonprofit = nonprofit || nonprofits[_.random(0, nonprofits.length - 1)];
|
||||||
return nonprofit;
|
return nonprofit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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,33 +73,26 @@ 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(
|
'info',
|
||||||
'info',
|
dedent`
|
||||||
dedent`
|
|
||||||
Looks like you already have a pledge to ${pledge.displayName}.
|
Looks like you already have a pledge to ${pledge.displayName}.
|
||||||
Clicking "Commit" here will replace your old commitment. If you
|
Clicking "Commit" here will replace your old commitment. If you
|
||||||
do change your commitment, please remember to cancel your
|
do change your commitment, please remember to cancel your
|
||||||
previous recurring donation directly with ${pledge.displayName}.
|
previous recurring donation directly with ${pledge.displayName}.
|
||||||
`
|
`
|
||||||
);
|
|
||||||
}
|
|
||||||
res.render(
|
|
||||||
'commit/',
|
|
||||||
{
|
|
||||||
title: 'Commit to a nonprofit. Commit to your goal.',
|
|
||||||
pledge,
|
|
||||||
...commitGoals,
|
|
||||||
...nonprofit
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
next
|
res.render('commit/', {
|
||||||
);
|
title: 'Commit to a nonprofit. Commit to your goal.',
|
||||||
|
pledge,
|
||||||
|
...commitGoals,
|
||||||
|
...nonprofit
|
||||||
|
});
|
||||||
|
}, 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,28 +122,24 @@ 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`
|
|
||||||
Congratulations, you have committed to giving
|
Congratulations, you have committed to giving
|
||||||
${displayName} $${amount} each month until you have completed
|
${displayName} $${amount} each month until you have completed
|
||||||
your ${goal}. Please remember to cancel your pledge directly
|
your ${goal}. Please remember to cancel your pledge directly
|
||||||
with ${displayName} once you finish.
|
with ${displayName} once you finish.
|
||||||
`
|
`
|
||||||
);
|
);
|
||||||
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(
|
if (typeof msgOrPledge === 'string') {
|
||||||
msgOrPledge => {
|
return res.send(msgOrPledge);
|
||||||
if (typeof msgOrPledge === 'string') {
|
}
|
||||||
return res.send(msgOrPledge);
|
return res.send(true);
|
||||||
}
|
}, next);
|
||||||
return res.send(true);
|
|
||||||
},
|
|
||||||
next
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopCommit(req, res, next) {
|
function stopCommit(req, res, next) {
|
||||||
@ -220,23 +175,20 @@ 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
|
||||||
with the nonprofit if you haven't already done so.
|
with the nonprofit if you haven't already done so.
|
||||||
`;
|
`;
|
||||||
if (!pledge) {
|
if (!pledge) {
|
||||||
msg = dedent`
|
msg = dedent`
|
||||||
It doesn't look like you had an active pledge, so
|
It doesn't look like you had an active pledge, so
|
||||||
there's no pledge to stop.
|
there's no pledge to stop.
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
req.flash('info', msg);
|
req.flash('info', msg);
|
||||||
return res.redirect(`/${user.username}`);
|
return res.redirect(`/${user.username}`);
|
||||||
},
|
}, next);
|
||||||
next
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,23 +70,26 @@ 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 },
|
||||||
(err, instance, isNew) => {
|
(err, instance, isNew) => {
|
||||||
log('is new user instance: ', isNew);
|
log('is new user instance: ', isNew);
|
||||||
if (err) {
|
if (err) {
|
||||||
return reject(err);
|
return reject(err);
|
||||||
}
|
}
|
||||||
return resolve(instance);
|
return resolve(instance);
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
let donatingUser = {};
|
let donatingUser = {};
|
||||||
let donation = {
|
let donation = {
|
||||||
@ -96,14 +99,13 @@ 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
|
});
|
||||||
});
|
|
||||||
})
|
})
|
||||||
.then(customer => {
|
.then(customer => {
|
||||||
donation.customerId = customer.id;
|
donation.customerId = customer.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);
|
||||||
});
|
});
|
||||||
|
@ -15,7 +15,7 @@ module.exports = function mountLoopBackExplorer(app) {
|
|||||||
app.once('started', function() {
|
app.once('started', function() {
|
||||||
log(
|
log(
|
||||||
'Run `npm install loopback-component-explorer` to enable ' +
|
'Run `npm install loopback-component-explorer` to enable ' +
|
||||||
'the LoopBack explorer'
|
'the LoopBack explorer'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
export default function bootStatus(app) {
|
export default function bootStatus(app) {
|
||||||
const api = app.loopback.Router();
|
const api = app.loopback.Router();
|
||||||
|
|
||||||
api.get('/status/ping', (req, res) => res.json({msg: 'pong'}));
|
api.get('/status/ping', (req, res) => res.json({ msg: 'pong' }));
|
||||||
app.use(api);
|
app.use(api);
|
||||||
}
|
}
|
||||||
|
@ -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/'
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -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$(
|
||||||
|
@ -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) {
|
||||||
|
@ -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();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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',
|
||||||
|
@ -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();
|
||||||
|
@ -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',
|
||||||
|
@ -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 +
|
||||||
// Regular name
|
'>[\\s\\S]*?</script\\s*' +
|
||||||
+ '|/?[a-z]'
|
'|style\\b' +
|
||||||
+ tagBody
|
tagBody +
|
||||||
+ ')>',
|
'>[\\s\\S]*?</style\\s*' +
|
||||||
|
// Regular name
|
||||||
|
'|/?[a-z]' +
|
||||||
|
tagBody +
|
||||||
|
')>',
|
||||||
'gi'
|
'gi'
|
||||||
);
|
);
|
||||||
let rawValue;
|
let rawValue;
|
||||||
|
@ -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,17 +13,14 @@ module.exports = function(About) {
|
|||||||
|
|
||||||
About.getActiveUsersForRendering = () => activeUsersForRendering;
|
About.getActiveUsersForRendering = () => activeUsersForRendering;
|
||||||
|
|
||||||
About.remoteMethod(
|
About.remoteMethod('getActiveUsers', {
|
||||||
'getActiveUsers',
|
http: {
|
||||||
{
|
path: '/get-active-users',
|
||||||
http: {
|
verb: 'get'
|
||||||
path: '/get-active-users',
|
},
|
||||||
verb: 'get'
|
returns: {
|
||||||
},
|
type: 'number',
|
||||||
returns: {
|
arg: 'activeUsers'
|
||||||
type: 'number',
|
|
||||||
arg: 'activeUsers'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
);
|
});
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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,26 +26,23 @@ 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;
|
||||||
const combinedFeed = [ ...mediumFeed, ...lybsynFeed ].sort((a, b) => {
|
const combinedFeed = [...mediumFeed, ...lybsynFeed].sort((a, b) => {
|
||||||
return compareDesc(a.isoDate, b.isoDate);
|
return compareDesc(a.isoDate, b.isoDate);
|
||||||
});
|
});
|
||||||
this.setState(state => ({
|
this.setState(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;
|
||||||
|
@ -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,17 +21,15 @@ 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(
|
|
||||||
(item) => ({
|
|
||||||
...item,
|
|
||||||
extract: getExtract(item['content:encoded'])
|
|
||||||
})
|
|
||||||
)
|
)
|
||||||
|
.map(item => ({
|
||||||
|
...item,
|
||||||
|
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);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -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');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -20,36 +20,34 @@ 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');
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const { goal } = pledge;
|
const { goal } = pledge;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(isFrontEndCert && goal === commitGoals.frontEndCert) ||
|
(isFrontEndCert && goal === commitGoals.frontEndCert) ||
|
||||||
(isBackEndCert && goal === commitGoals.backEndCert) ||
|
(isBackEndCert && goal === commitGoals.backEndCert) ||
|
||||||
(isFullStackCert && goal === commitGoals.fullStackCert) ||
|
(isFullStackCert && goal === commitGoals.fullStackCert) ||
|
||||||
(isRespWebDesignCert && goal === commitGoals.respWebDesignCert) ||
|
(isRespWebDesignCert && goal === commitGoals.respWebDesignCert) ||
|
||||||
(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');
|
pledge.isCompleted = true;
|
||||||
pledge.isCompleted = true;
|
pledge.dateEnded = new Date();
|
||||||
pledge.dateEnded = new Date();
|
pledge.formerUserId = pledge.userId;
|
||||||
pledge.formerUserId = pledge.userId;
|
pledge.userId = null;
|
||||||
pledge.userId = null;
|
return Observable.fromNodeCallback(pledge.save, pledge)();
|
||||||
return Observable.fromNodeCallback(pledge.save, pledge)();
|
}
|
||||||
}
|
return Observable.just(dedent`
|
||||||
return Observable.just(dedent`
|
|
||||||
You have not yet reached your goal of completing the ${goal}
|
You have not yet reached your goal of completing the ${goal}
|
||||||
Please retry when you have met the requirements.
|
Please retry when you have met the requirements.
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
{
|
message: msg,
|
||||||
type,
|
redirectTo,
|
||||||
message: msg,
|
// we default to 400 as these are malformed requests
|
||||||
redirectTo,
|
status: 400
|
||||||
// we default to 400 as these are malformed requests
|
});
|
||||||
status: 400
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
@ -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
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}, {});
|
}, {});
|
||||||
|
@ -32,64 +32,59 @@ const getFirstChallenge = _.once(_getFirstChallenge);
|
|||||||
*/
|
*/
|
||||||
export function _cachedMap({ Block, Challenge }) {
|
export function _cachedMap({ Block, Challenge }) {
|
||||||
const challenges = Challenge.find$({
|
const challenges = Challenge.find$({
|
||||||
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;
|
return hash;
|
||||||
return hash;
|
}, {})
|
||||||
}, {})
|
);
|
||||||
);
|
|
||||||
const blocks = Block.find$({
|
const blocks = Block.find$({
|
||||||
order: [ 'superOrder ASC', 'order ASC' ],
|
order: ['superOrder ASC', 'order ASC'],
|
||||||
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())
|
hash[block.dashedName] = block;
|
||||||
.reduce((hash, block) => {
|
return hash;
|
||||||
hash[block.dashedName] = block;
|
}, {})
|
||||||
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);
|
} else {
|
||||||
} else {
|
blocksMap[challenge.block] = {
|
||||||
blocksMap[challenge.block] = {
|
...blocksMap[challenge.block],
|
||||||
...blocksMap[challenge.block],
|
challenges: [challenge.dashedName]
|
||||||
challenges: [ challenge.dashedName ]
|
};
|
||||||
};
|
}
|
||||||
}
|
return blocksMap;
|
||||||
return blocksMap;
|
}, blocksMap);
|
||||||
}, blocksMap);
|
});
|
||||||
});
|
const superBlockMap = blocks.map(blocks =>
|
||||||
const superBlockMap = blocks.map(blocks => blocks.reduce((map, block) => {
|
blocks.reduce((map, block) => {
|
||||||
if (
|
if (map[block.superBlock] && map[block.superBlock].blocks) {
|
||||||
map[block.superBlock] &&
|
map[block.superBlock].blocks.push(block.dashedName);
|
||||||
map[block.superBlock].blocks
|
} else {
|
||||||
) {
|
map[block.superBlock] = {
|
||||||
map[block.superBlock].blocks.push(block.dashedName);
|
title: _.startCase(block.superBlock),
|
||||||
} else {
|
order: block.superOrder,
|
||||||
map[block.superBlock] = {
|
name: nameify(_.startCase(block.superBlock)),
|
||||||
title: _.startCase(block.superBlock),
|
dashedName: block.superBlock,
|
||||||
order: block.superOrder,
|
blocks: [block.dashedName],
|
||||||
name: nameify(_.startCase(block.superBlock)),
|
message: block.superBlockMessage
|
||||||
dashedName: block.superBlock,
|
};
|
||||||
blocks: [block.dashedName],
|
}
|
||||||
message: block.superBlockMessage
|
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,30 +121,25 @@ 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;
|
let finalChallenge;
|
||||||
let finalChallenge;
|
const dashedName = challengeIdToName[id];
|
||||||
const dashedName = challengeIdToName[id];
|
finalChallenge = challengeMap[dashedName];
|
||||||
finalChallenge = challengeMap[dashedName];
|
if (!finalChallenge) {
|
||||||
if (!finalChallenge) {
|
finalChallenge = getFirstChallenge(map);
|
||||||
finalChallenge = getFirstChallenge(map);
|
}
|
||||||
}
|
return finalChallenge;
|
||||||
return finalChallenge;
|
})
|
||||||
})
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
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,42 +158,37 @@ 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,
|
const superBlock = entities.superBlock;
|
||||||
map) {
|
const block = entities.block[blockDashedName];
|
||||||
return map
|
const challenge = entities.challenge[challengeDashedName];
|
||||||
.flatMap(({ entities, result: { superBlocks } }) => {
|
return Observable.if(
|
||||||
const superBlock = entities.superBlock;
|
() =>
|
||||||
const block = entities.block[blockDashedName];
|
!blockDashedName ||
|
||||||
const challenge = entities.challenge[challengeDashedName];
|
!block ||
|
||||||
return Observable.if(
|
!challenge ||
|
||||||
() => (
|
!loadComingSoonOrBetaChallenge(challenge),
|
||||||
!blockDashedName ||
|
getChallengeByDashedName(challengeDashedName, map),
|
||||||
!block ||
|
Observable.just({ block, challenge })
|
||||||
!challenge ||
|
).map(({ challenge, block }) => ({
|
||||||
!loadComingSoonOrBetaChallenge(challenge)
|
redirect:
|
||||||
),
|
challenge.block !== blockDashedName
|
||||||
getChallengeByDashedName(challengeDashedName, map),
|
? `/challenges/${block.dashedName}/${challenge.dashedName}`
|
||||||
Observable.just({ block, challenge })
|
: false,
|
||||||
)
|
entities: {
|
||||||
.map(({ challenge, block }) => ({
|
superBlock,
|
||||||
redirect: challenge.block !== blockDashedName ?
|
challenge: {
|
||||||
`/challenges/${block.dashedName}/${challenge.dashedName}` :
|
[challenge.dashedName]: challenge
|
||||||
false,
|
}
|
||||||
entities: {
|
},
|
||||||
superBlock,
|
result: {
|
||||||
challenge: {
|
block: block.dashedName,
|
||||||
[challenge.dashedName]: challenge
|
challenge: challenge.dashedName,
|
||||||
}
|
superBlocks
|
||||||
},
|
}
|
||||||
result: {
|
}));
|
||||||
block: block.dashedName,
|
});
|
||||||
challenge: challenge.dashedName,
|
|
||||||
superBlocks
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getBlockForChallenge(map, challenge) {
|
export function getBlockForChallenge(map, 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
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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();
|
|
||||||
}
|
}
|
||||||
|
@ -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(
|
||||||
const last = cals[index === 0 ? 0 : index - 1];
|
(longest, head, index) => {
|
||||||
// is streak broken
|
const last = cals[index === 0 ? 0 : index - 1];
|
||||||
if (moment(head).tz(tz).startOf('day').diff(moment(last).tz(tz), 'hours')
|
// is streak broken
|
||||||
> hoursBetween) {
|
if (
|
||||||
tail = head;
|
moment(head)
|
||||||
}
|
.tz(tz)
|
||||||
if (dayCount(longest, tz) < dayCount([head, tail], tz)) {
|
.startOf('day')
|
||||||
return [head, tail];
|
.diff(moment(last).tz(tz), 'hours') > hoursBetween
|
||||||
}
|
) {
|
||||||
return longest;
|
tail = head;
|
||||||
}, [cals[0], cals[0]]);
|
}
|
||||||
|
if (dayCount(longest, tz) < dayCount([head, tail], tz)) {
|
||||||
|
return [head, tail];
|
||||||
|
}
|
||||||
|
return longest;
|
||||||
|
},
|
||||||
|
[cals[0], cals[0]]
|
||||||
|
);
|
||||||
|
|
||||||
return dayCount(longest, tz);
|
return dayCount(longest, tz);
|
||||||
}
|
}
|
||||||
|
@ -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)/)'
|
|
||||||
]
|
|
||||||
};
|
};
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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 && (
|
||||||
|
@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -84,25 +85,25 @@ class DonateModal extends Component {
|
|||||||
ga.modalview('/donation-modal');
|
ga.modalview('/donation-modal');
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<StripeProvider stripe={this.state.stripe}>
|
<StripeProvider stripe={this.state.stripe}>
|
||||||
<Elements>
|
<Elements>
|
||||||
<Modal bsSize='lg' className='donation-modal' show={show}>
|
<Modal bsSize='lg' className='donation-modal' show={show}>
|
||||||
<Modal.Header className='fcc-modal'>
|
<Modal.Header className='fcc-modal'>
|
||||||
<Modal.Title className='text-center'>
|
<Modal.Title className='text-center'>
|
||||||
Support Our NonProfit
|
Support Our NonProfit
|
||||||
</Modal.Title>
|
</Modal.Title>
|
||||||
</Modal.Header>
|
</Modal.Header>
|
||||||
<Modal.Body>
|
<Modal.Body>
|
||||||
<DonateText />
|
<DonateText />
|
||||||
<DonateForm />
|
<DonateForm />
|
||||||
{this.renderMaybe()}
|
{this.renderMaybe()}
|
||||||
</Modal.Body>
|
</Modal.Body>
|
||||||
<Modal.Footer>
|
<Modal.Footer>
|
||||||
<PoweredByStripe />
|
<PoweredByStripe />
|
||||||
</Modal.Footer>
|
</Modal.Footer>
|
||||||
</Modal>
|
</Modal>
|
||||||
</Elements>
|
</Elements>
|
||||||
</StripeProvider>
|
</StripeProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
);
|
);
|
||||||
|
@ -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}
|
||||||
|
@ -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>
|
||||||
|
@ -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);
|
||||||
|
@ -33,7 +33,9 @@ export function DynamicForm({
|
|||||||
errors,
|
errors,
|
||||||
fields,
|
fields,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
fields: { _meta: { allPristine } },
|
fields: {
|
||||||
|
_meta: { allPristine }
|
||||||
|
},
|
||||||
|
|
||||||
// HOC
|
// HOC
|
||||||
buttonText,
|
buttonText,
|
||||||
|
@ -166,7 +166,7 @@ class DefaultLayout extends Component {
|
|||||||
) : null}
|
) : null}
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
{showFooter && (<Footer />)}
|
{showFooter && <Footer />}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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' />{' '}
|
||||||
@ -74,122 +86,143 @@ class DonateOtherPage extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Helmet title='Other ways to donate | freeCodeCamp.org' />
|
<Helmet title='Other ways to donate | freeCodeCamp.org' />
|
||||||
<Spacer />
|
<Spacer />
|
||||||
<Grid className='container'>
|
<Grid className='container'>
|
||||||
<Row>
|
<Row>
|
||||||
<Col md={6} mdOffset={3} sm={10} smOffset={1} xs={12}>
|
<Col md={6} mdOffset={3} sm={10} smOffset={1} xs={12}>
|
||||||
<h2 className='text-center'>
|
<h2 className='text-center'>
|
||||||
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>
|
.
|
||||||
<hr />
|
</p>
|
||||||
<h3>Set up a monthly donation using PayPal</h3>
|
<hr />
|
||||||
<p>
|
<h3>Set up a monthly donation using PayPal</h3>
|
||||||
You can set up a monthly donation to freeCodeCamp by clicking one of
|
<p>
|
||||||
the links below and following the instructions on PayPal. You can
|
You can set up a monthly donation to freeCodeCamp by clicking
|
||||||
easily stop your donations at any time in the future.
|
one of the links below and following the instructions on PayPal.
|
||||||
</p>
|
You can easily stop your donations at any time in the future.
|
||||||
{paypalMonthlyDonations.map((item) => {
|
</p>
|
||||||
return this.renderForm(item);
|
{paypalMonthlyDonations.map(item => {
|
||||||
})}
|
return this.renderForm(item);
|
||||||
<hr />
|
})}
|
||||||
<h3>Make a one-time donation using PayPal</h3>
|
<hr />
|
||||||
<p>
|
<h3>Make a one-time donation using PayPal</h3>
|
||||||
You can make a one-time monthly donation to freeCodeCamp for any
|
<p>
|
||||||
amount of money by clicking one of the links below and following the
|
You can make a one-time monthly donation to freeCodeCamp for any
|
||||||
instructions on PayPal:
|
amount of money by clicking one of the links below and following
|
||||||
</p>
|
the instructions on PayPal:
|
||||||
{this.renderForm(paypalOneTimeDonation)}
|
</p>
|
||||||
<hr />
|
{this.renderForm(paypalOneTimeDonation)}
|
||||||
<h3>Get your employer to match your donation</h3>
|
<hr />
|
||||||
<p>
|
<h3>Get your employer to match your donation</h3>
|
||||||
Many freeCodeCamp supporters are able to get their employers to
|
<p>
|
||||||
match their donations to freeCodeCamp. Our Tax-exempt number (EIN)
|
Many freeCodeCamp supporters are able to get their employers to
|
||||||
is 82-0779546. If we can help you with setting this up, please email{' '}
|
match their donations to freeCodeCamp. Our Tax-exempt number
|
||||||
<a href='mailto:team@freecodecamp.org'>team@freecodecamp.org</a>.
|
(EIN) is 82-0779546. If we can help you with setting this up,
|
||||||
</p>
|
please email{' '}
|
||||||
<hr />
|
<a href='mailto:team@freecodecamp.org'>team@freecodecamp.org</a>
|
||||||
<h3>Donate through a payroll deduction</h3>
|
.
|
||||||
<p>
|
</p>
|
||||||
In the US and Canada, some employers have a convenient way to give
|
<hr />
|
||||||
to freeCodeCamp through a payroll deduction. Ask your employer if
|
<h3>Donate through a payroll deduction</h3>
|
||||||
they can do this, and have them send any necessary paperwork to:
|
<p>
|
||||||
</p>
|
In the US and Canada, some employers have a convenient way to
|
||||||
<p>
|
give to freeCodeCamp through a payroll deduction. Ask your
|
||||||
Free Code Camp, Inc.<br />7800 W Hefner Rd, PO BOX 721024<br />Oklahoma
|
employer if they can do this, and have them send any necessary
|
||||||
City, Oklahoma 73172<br />United States
|
paperwork to:
|
||||||
</p>
|
</p>
|
||||||
<hr />
|
<p>
|
||||||
<h3>Donate cryptocurrency to freeCodeCamp</h3>
|
Free Code Camp, Inc.
|
||||||
<p>
|
<br />
|
||||||
Below are our wallets where we can receive cryptocurrency donations.
|
7800 W Hefner Rd, PO BOX 721024
|
||||||
</p>
|
<br />
|
||||||
<h4>Make a one-time Bitcoin donation</h4>
|
Oklahoma City, Oklahoma 73172
|
||||||
<p className='negative-15'>
|
<br />
|
||||||
Our Bitcoin wallet is{' '}
|
United States
|
||||||
<code>12skYi7aMCjDUdrVdoB3JjZ77ug8gxJfbL</code>
|
</p>
|
||||||
</p>
|
<hr />
|
||||||
<h4>Make a one-time Ethereum donation</h4>
|
<h3>Donate cryptocurrency to freeCodeCamp</h3>
|
||||||
<p className='negative-15'>
|
<p>
|
||||||
Our Ethereum wallet is{' '}
|
Below are our wallets where we can receive cryptocurrency
|
||||||
<code>0x0ADbEf2471416BD8732cf0f3944294eE393CcAF5</code>
|
donations.
|
||||||
</p>
|
</p>
|
||||||
<h4>Make a one-time Litecoin donation</h4>
|
<h4>Make a one-time Bitcoin donation</h4>
|
||||||
<p className='negative-15'>
|
<p className='negative-15'>
|
||||||
Our Litecoin wallet is{' '}
|
Our Bitcoin wallet is{' '}
|
||||||
<code>LKu8UG8Z1nbTxnq9Do96PsC3FwbNtycf3X</code>
|
<code>12skYi7aMCjDUdrVdoB3JjZ77ug8gxJfbL</code>
|
||||||
</p>
|
</p>
|
||||||
<h4>Make a one-time Bitcoin Cash donation</h4>
|
<h4>Make a one-time Ethereum donation</h4>
|
||||||
<p className='negative-15'>
|
<p className='negative-15'>
|
||||||
Our Bitcoin Cash wallet is{' '}
|
Our Ethereum wallet is{' '}
|
||||||
<code>1EBxPEJWrGZWxe2UayyAsnd5VsRg5H9xfu</code>
|
<code>0x0ADbEf2471416BD8732cf0f3944294eE393CcAF5</code>
|
||||||
</p>
|
</p>
|
||||||
<hr />
|
<h4>Make a one-time Litecoin donation</h4>
|
||||||
<h3>Donate to freeCodeCamp by mailing us a check</h3>
|
<p className='negative-15'>
|
||||||
<p>Our mailing address is:</p>
|
Our Litecoin wallet is{' '}
|
||||||
<p>
|
<code>LKu8UG8Z1nbTxnq9Do96PsC3FwbNtycf3X</code>
|
||||||
Free Code Camp, Inc.<br />7800 W Hefner Rd, PO BOX 721024<br />Oklahoma
|
</p>
|
||||||
City, Oklahoma 73172<br />United States
|
<h4>Make a one-time Bitcoin Cash donation</h4>
|
||||||
</p>
|
<p className='negative-15'>
|
||||||
<hr />
|
Our Bitcoin Cash wallet is{' '}
|
||||||
<h3>Donate Stock to freeCodeCamp</h3>
|
<code>1EBxPEJWrGZWxe2UayyAsnd5VsRg5H9xfu</code>
|
||||||
<p>
|
</p>
|
||||||
If you want to donate stocks to freeCodeCamp, please email us at{' '}
|
<hr />
|
||||||
<a href='mailto:team@freecodecamp.org'>team@freecodecamp.org</a>.
|
<h3>Donate to freeCodeCamp by mailing us a check</h3>
|
||||||
</p>
|
<p>Our mailing address is:</p>
|
||||||
<hr />
|
<p>
|
||||||
<h3>Legacy Gift</h3>
|
Free Code Camp, Inc.
|
||||||
<p>
|
<br />
|
||||||
You can help future generations of learners by listing freeCodeCamp
|
7800 W Hefner Rd, PO BOX 721024
|
||||||
in your will or living trust. If you're interested in doing this,
|
<br />
|
||||||
email Quincy directly and we can discuss this:{' '}
|
Oklahoma City, Oklahoma 73172
|
||||||
<a href='mailto:quincy@freecodecamp.org'>quincy@freecodecamp.org</a>.
|
<br />
|
||||||
</p>
|
United States
|
||||||
<hr />
|
</p>
|
||||||
<h3>
|
<hr />
|
||||||
Thank you for supporting our nonprofit and the freeCodeCamp
|
<h3>Donate Stock to freeCodeCamp</h3>
|
||||||
community.
|
<p>
|
||||||
</h3>
|
If you want to donate stocks to freeCodeCamp, please email us at{' '}
|
||||||
<Spacer />
|
<a href='mailto:team@freecodecamp.org'>team@freecodecamp.org</a>
|
||||||
<div className='text-center'>
|
.
|
||||||
<Link to='/donate'>Or donate using a Credit or Debit Card.</Link>
|
</p>
|
||||||
</div>
|
<hr />
|
||||||
<Spacer />
|
<h3>Legacy Gift</h3>
|
||||||
</Col>
|
<p>
|
||||||
</Row>
|
You can help future generations of learners by listing
|
||||||
</Grid>
|
freeCodeCamp in your will or living trust. If you're interested
|
||||||
</Fragment>
|
in doing this, email Quincy directly and we can discuss this:{' '}
|
||||||
);
|
<a href='mailto:quincy@freecodecamp.org'>
|
||||||
|
quincy@freecodecamp.org
|
||||||
|
</a>
|
||||||
|
.
|
||||||
|
</p>
|
||||||
|
<hr />
|
||||||
|
<h3>
|
||||||
|
Thank you for supporting our nonprofit and the freeCodeCamp
|
||||||
|
community.
|
||||||
|
</h3>
|
||||||
|
<Spacer />
|
||||||
|
<div className='text-center'>
|
||||||
|
<Link to='/donate'>
|
||||||
|
Or donate using a Credit or Debit Card.
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
<Spacer />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Grid>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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}>
|
||||||
|
@ -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 {
|
||||||
|
@ -16,7 +16,7 @@ function setTheme(currentTheme = defaultTheme, theme) {
|
|||||||
html.classList.add(theme);
|
html.classList.add(theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
function* updateLocalThemeSaga({ payload: {user, theme } }) {
|
function* updateLocalThemeSaga({ payload: { user, theme } }) {
|
||||||
const currentTheme = store.get(themeKey) || defaultTheme;
|
const currentTheme = store.get(themeKey) || defaultTheme;
|
||||||
if (user) {
|
if (user) {
|
||||||
const { theme = defaultTheme } = user;
|
const { theme = defaultTheme } = user;
|
||||||
|
@ -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
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
@ -170,7 +170,7 @@ export class BackEnd extends Component {
|
|||||||
<LearnLayout>
|
<LearnLayout>
|
||||||
<Grid>
|
<Grid>
|
||||||
<Row>
|
<Row>
|
||||||
<Col md={8} mdOffset={2} sm={10} smOffset={1} xs={12} >
|
<Col md={8} mdOffset={2} sm={10} smOffset={1} xs={12}>
|
||||||
<Spacer />
|
<Spacer />
|
||||||
<ChallengeTitle>{blockNameTitle}</ChallengeTitle>
|
<ChallengeTitle>{blockNameTitle}</ChallengeTitle>
|
||||||
<ChallengeDescription
|
<ChallengeDescription
|
||||||
|
@ -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 }) {
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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>
|
|
||||||
*/
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {cond, identity, stubTrue, conforms} from 'lodash';
|
import { cond, identity, stubTrue, conforms } from 'lodash';
|
||||||
|
|
||||||
const HTML$JSReg = /html|js/;
|
const HTML$JSReg = /html|js/;
|
||||||
|
|
||||||
|
@ -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]
|
||||||
]);
|
]);
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
@ -67,7 +66,7 @@ export function createFetchLink() {
|
|||||||
.then(({ data }) => data)
|
.then(({ data }) => data)
|
||||||
.then(styles => `<style>${styles}</style>`)
|
.then(styles => `<style>${styles}</style>`)
|
||||||
.catch(() => '');
|
.catch(() => '');
|
||||||
cache.set(href, link);
|
cache.set(href, link);
|
||||||
return link;
|
return link;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
@ -17,10 +17,11 @@ 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));
|
||||||
|
};
|
||||||
|
|
||||||
exports.buildChallenges = async function buildChallenges() {
|
exports.buildChallenges = async function buildChallenges() {
|
||||||
const curriculum = await getChallengesForLang(locale);
|
const curriculum = await getChallengesForLang(locale);
|
||||||
|
@ -157,7 +157,7 @@ const stopWords = [
|
|||||||
'in',
|
'in',
|
||||||
'into',
|
'into',
|
||||||
'it',
|
'it',
|
||||||
'it\'s',
|
"it's",
|
||||||
'its',
|
'its',
|
||||||
'no',
|
'no',
|
||||||
'nor',
|
'nor',
|
||||||
|
@ -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) {
|
||||||
@ -43,7 +44,7 @@ function prototyper(str) {
|
|||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.split('.')
|
.split('.')
|
||||||
.join('-')
|
.join('-')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return titleify(str, true);
|
return titleify(str, true);
|
||||||
}
|
}
|
||||||
@ -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(' ');
|
||||||
}
|
}
|
||||||
|
@ -114,7 +114,7 @@ function superBlockInfoFromPath(filePath) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function superBlockInfoFromFullPath(fullFilePath) {
|
function superBlockInfoFromFullPath(fullFilePath) {
|
||||||
const [,, maybeSuper] = fullFilePath.split(path.sep).reverse();
|
const [, , maybeSuper] = fullFilePath.split(path.sep).reverse();
|
||||||
return superBlockInfo(maybeSuper);
|
return superBlockInfo(maybeSuper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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,23 +81,24 @@ 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);
|
||||||
|
|
||||||
challenge.checksum = adler32.sum(
|
challenge.checksum = adler32.sum(
|
||||||
Buffer(
|
Buffer(
|
||||||
challenge.title +
|
challenge.title +
|
||||||
JSON.stringify(challenge.description) +
|
JSON.stringify(challenge.description) +
|
||||||
JSON.stringify(challenge.challengeSeed) +
|
JSON.stringify(challenge.challengeSeed) +
|
||||||
JSON.stringify(challenge.tests)
|
JSON.stringify(challenge.tests)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
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,46 +106,45 @@ Observable.combineLatest(
|
|||||||
tail: arrToString(file.tail)
|
tail: arrToString(file.tail)
|
||||||
};
|
};
|
||||||
return map;
|
return map;
|
||||||
}, {});
|
},
|
||||||
}
|
{}
|
||||||
challenge.fileName = fileName;
|
|
||||||
challenge.helpRoom = helpRoom;
|
|
||||||
challenge.order = order;
|
|
||||||
challenge.suborder = index + 1;
|
|
||||||
challenge.block = dasherize(blockName);
|
|
||||||
challenge.blockId = '' + block.id;
|
|
||||||
challenge.isBeta = challenge.isBeta || isBeta;
|
|
||||||
challenge.isComingSoon = challenge.isComingSoon || isComingSoon;
|
|
||||||
challenge.isLocked = challenge.isLocked || isLocked;
|
|
||||||
challenge.isPrivate = challenge.isPrivate || isPrivate;
|
|
||||||
challenge.time = challengeSpec.time;
|
|
||||||
challenge.superOrder = superOrder;
|
|
||||||
challenge.superBlock = superBlock
|
|
||||||
.split('-')
|
|
||||||
.map(function(word) {
|
|
||||||
return _.capitalize(word);
|
|
||||||
})
|
|
||||||
.join(' ');
|
|
||||||
challenge.required = (challenge.required || []).concat(required);
|
|
||||||
challenge.template = challenge.template || template;
|
|
||||||
return _.omit(
|
|
||||||
challenge,
|
|
||||||
[
|
|
||||||
'betaSolutions',
|
|
||||||
'betaTests',
|
|
||||||
'hints',
|
|
||||||
'MDNlinks',
|
|
||||||
'null',
|
|
||||||
'rawSolutions',
|
|
||||||
'react',
|
|
||||||
'reactRedux',
|
|
||||||
'redux',
|
|
||||||
'releasedOn',
|
|
||||||
'translations',
|
|
||||||
'type'
|
|
||||||
]
|
|
||||||
);
|
);
|
||||||
});
|
}
|
||||||
|
challenge.fileName = fileName;
|
||||||
|
challenge.helpRoom = helpRoom;
|
||||||
|
challenge.order = order;
|
||||||
|
challenge.suborder = index + 1;
|
||||||
|
challenge.block = dasherize(blockName);
|
||||||
|
challenge.blockId = '' + block.id;
|
||||||
|
challenge.isBeta = challenge.isBeta || isBeta;
|
||||||
|
challenge.isComingSoon = challenge.isComingSoon || isComingSoon;
|
||||||
|
challenge.isLocked = challenge.isLocked || isLocked;
|
||||||
|
challenge.isPrivate = challenge.isPrivate || isPrivate;
|
||||||
|
challenge.time = challengeSpec.time;
|
||||||
|
challenge.superOrder = superOrder;
|
||||||
|
challenge.superBlock = superBlock
|
||||||
|
.split('-')
|
||||||
|
.map(function(word) {
|
||||||
|
return _.capitalize(word);
|
||||||
|
})
|
||||||
|
.join(' ');
|
||||||
|
challenge.required = (challenge.required || []).concat(required);
|
||||||
|
challenge.template = challenge.template || template;
|
||||||
|
return _.omit(challenge, [
|
||||||
|
'betaSolutions',
|
||||||
|
'betaTests',
|
||||||
|
'hints',
|
||||||
|
'MDNlinks',
|
||||||
|
'null',
|
||||||
|
'rawSolutions',
|
||||||
|
'react',
|
||||||
|
'reactRedux',
|
||||||
|
'redux',
|
||||||
|
'releasedOn',
|
||||||
|
'translations',
|
||||||
|
'type'
|
||||||
|
]);
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.flatMap(challenges => {
|
.flatMap(challenges => {
|
||||||
challenges.forEach(challenge => {
|
challenges.forEach(challenge => {
|
||||||
@ -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);
|
||||||
|
@ -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, {
|
||||||
|
@ -20,7 +20,7 @@ class ChallengeTitles {
|
|||||||
The title ${title} is already assigned
|
The title ${title} is already assigned
|
||||||
`);
|
`);
|
||||||
}
|
}
|
||||||
this.knownTitles = [ ...this.knownTitles, titleToCheck ];
|
this.knownTitles = [...this.knownTitles, titleToCheck];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ class MongoIds {
|
|||||||
The id for ${title} is already assigned
|
The id for ${title} is already assigned
|
||||||
`);
|
`);
|
||||||
}
|
}
|
||||||
this.knownIds = [ ...this.knownIds, id ];
|
this.knownIds = [...this.knownIds, id];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
883
package-lock.json
generated
883
package-lock.json
generated
@ -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",
|
||||||
|
@ -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"
|
||||||
|
@ -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);
|
||||||
});
|
});
|
||||||
|
@ -22,80 +22,77 @@ 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);
|
||||||
|
|
||||||
|
log('Connected successfully to mongo');
|
||||||
|
|
||||||
|
const db = client.db('freecodecamp');
|
||||||
|
const user = db.collection('user');
|
||||||
|
|
||||||
|
user.deleteOne({ _id: ObjectId('5bd30e0f1caf6ac3ddddddb5') }, err => {
|
||||||
handleError(err, client);
|
handleError(err, client);
|
||||||
|
|
||||||
log('Connected successfully to mongo');
|
try {
|
||||||
|
user.insertOne({
|
||||||
const db = client.db('freecodecamp');
|
_id: ObjectId('5bd30e0f1caf6ac3ddddddb5'),
|
||||||
const user = db.collection('user');
|
email: 'foo@bar.com',
|
||||||
|
emailVerified: true,
|
||||||
user.deleteOne({_id: ObjectId('5bd30e0f1caf6ac3ddddddb5') }, (err) => {
|
progressTimestamps: [],
|
||||||
handleError(err, client);
|
isBanned: false,
|
||||||
|
isCheater: false,
|
||||||
try {
|
username: 'DevelopmentUser',
|
||||||
user.insertOne(
|
about: '',
|
||||||
{
|
name: 'Development User',
|
||||||
_id: ObjectId('5bd30e0f1caf6ac3ddddddb5'),
|
location: '',
|
||||||
email: 'foo@bar.com',
|
picture: 'https://identicon.org/?t=dev&s=256',
|
||||||
emailVerified: true,
|
acceptedPrivacyTerms: true,
|
||||||
progressTimestamps: [],
|
sendQuincyEmail: false,
|
||||||
isBanned: false,
|
currentChallengeId: '',
|
||||||
isCheater: false,
|
isHonest: false,
|
||||||
username: 'DevelopmentUser',
|
isFrontEndCert: false,
|
||||||
about: '',
|
isDataVisCert: false,
|
||||||
name: 'Development User',
|
isBackEndCert: false,
|
||||||
location: '',
|
isFullStackCert: false,
|
||||||
picture: 'https://identicon.org/?t=dev&s=256',
|
isRespWebDesignCert: false,
|
||||||
acceptedPrivacyTerms: true,
|
is2018DataVisCert: false,
|
||||||
sendQuincyEmail: false,
|
isFrontEndLibsCert: false,
|
||||||
currentChallengeId: '',
|
isJsAlgoDataStructCert: false,
|
||||||
isHonest: false,
|
isApisMicroservicesCert: false,
|
||||||
isFrontEndCert: false,
|
isInfosecQaCert: false,
|
||||||
isDataVisCert: false,
|
is2018FullStackCert: false,
|
||||||
isBackEndCert: false,
|
completedChallenges: [],
|
||||||
isFullStackCert: false,
|
portfolio: [],
|
||||||
isRespWebDesignCert: false,
|
yearsTopContributor: [],
|
||||||
is2018DataVisCert: false,
|
rand: 0.6126749173148205,
|
||||||
isFrontEndLibsCert: false,
|
theme: 'default',
|
||||||
isJsAlgoDataStructCert: false,
|
profileUI: {
|
||||||
isApisMicroservicesCert: false,
|
isLocked: true,
|
||||||
isInfosecQaCert: false,
|
showAbout: false,
|
||||||
is2018FullStackCert: false,
|
showCerts: false,
|
||||||
completedChallenges: [],
|
showDonation: false,
|
||||||
portfolio: [],
|
showHeatMap: false,
|
||||||
yearsTopContributor: [],
|
showLocation: false,
|
||||||
rand: 0.6126749173148205,
|
showName: false,
|
||||||
theme: 'default',
|
showPoints: false,
|
||||||
profileUI: {
|
showPortfolio: false,
|
||||||
isLocked: true,
|
showTimeLine: false
|
||||||
showAbout: false,
|
},
|
||||||
showCerts: false,
|
badges: {
|
||||||
showDonation: false,
|
coreTeam: []
|
||||||
showHeatMap: false,
|
},
|
||||||
showLocation: false,
|
isDonating: false,
|
||||||
showName: false,
|
emailAuthLinkTTL: null,
|
||||||
showPoints: false,
|
emailVerifyTTL: null
|
||||||
showPortfolio: false,
|
});
|
||||||
showTimeLine: false
|
} catch (e) {
|
||||||
},
|
handleError(e, client);
|
||||||
badges: {
|
} finally {
|
||||||
coreTeam: []
|
log('local auth user seed complete');
|
||||||
},
|
client.close();
|
||||||
isDonating: false,
|
}
|
||||||
emailAuthLinkTTL: null,
|
});
|
||||||
emailVerifyTTL: null
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
handleError(e, client);
|
|
||||||
} finally {
|
|
||||||
log('local auth user seed complete');
|
|
||||||
client.close();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
@ -26,66 +26,61 @@ 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);
|
||||||
|
|
||||||
|
log('Connected successfully to mongo at %s', MONGOHQ_URL);
|
||||||
|
|
||||||
|
const db = client.db('freecodecamp');
|
||||||
|
const challengeCollection = db.collection('challenge');
|
||||||
|
|
||||||
|
challengeCollection.deleteMany({}, async err => {
|
||||||
handleError(err, client);
|
handleError(err, client);
|
||||||
|
|
||||||
log('Connected successfully to mongo at %s', MONGOHQ_URL);
|
log('deleted all the challenges');
|
||||||
|
|
||||||
const db = client.db('freecodecamp');
|
const curriculum = await getChallengesForLang(lang);
|
||||||
const challengeCollection = db.collection('challenge');
|
|
||||||
|
|
||||||
challengeCollection.deleteMany({}, async err => {
|
const allChallenges = Object.keys(curriculum)
|
||||||
handleError(err, client);
|
.map(key => curriculum[key].blocks)
|
||||||
|
.reduce((challengeArray, superBlock) => {
|
||||||
log('deleted all the challenges');
|
const challengesForBlock = Object.keys(superBlock).map(
|
||||||
|
key => superBlock[key].challenges
|
||||||
const curriculum = await getChallengesForLang(lang);
|
|
||||||
|
|
||||||
const allChallenges = Object.keys(curriculum)
|
|
||||||
.map(key => curriculum[key].blocks)
|
|
||||||
.reduce((challengeArray, superBlock) => {
|
|
||||||
const challengesForBlock = Object.keys(superBlock).map(
|
|
||||||
key => superBlock[key].challenges
|
|
||||||
);
|
|
||||||
return [...challengeArray, ...flatten(challengesForBlock)];
|
|
||||||
}, [])
|
|
||||||
.map(challenge => {
|
|
||||||
const currentId = challenge.id.slice(0);
|
|
||||||
challenge._id = ObjectID(currentId);
|
|
||||||
delete challenge.id;
|
|
||||||
return challenge;
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
challengeCollection.insertMany(
|
|
||||||
allChallenges,
|
|
||||||
{ ordered: false },
|
|
||||||
err => {
|
|
||||||
handleError(err, client);
|
|
||||||
log('challenge seed complete');
|
|
||||||
client.close();
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
} catch (e) {
|
return [...challengeArray, ...flatten(challengesForBlock)];
|
||||||
handleError(e, client);
|
}, [])
|
||||||
} finally {
|
.map(challenge => {
|
||||||
log('generating path migration map');
|
const currentId = challenge.id.slice(0);
|
||||||
const pathMap = createPathMigrationMap(curriculum);
|
challenge._id = ObjectID(currentId);
|
||||||
const outputDir = path.resolve(
|
delete challenge.id;
|
||||||
__dirname,
|
return challenge;
|
||||||
'../../../api-server/server/resources/pathMigration.json'
|
});
|
||||||
);
|
|
||||||
fs.writeFile(outputDir, JSON.stringify(pathMap), err => {
|
try {
|
||||||
if (err) {
|
challengeCollection.insertMany(allChallenges, { ordered: false }, err => {
|
||||||
console.error('Oh noes!!');
|
handleError(err, client);
|
||||||
console.error(err);
|
log('challenge seed complete');
|
||||||
}
|
client.close();
|
||||||
log('path migration map generated');
|
});
|
||||||
});
|
} catch (e) {
|
||||||
}
|
handleError(e, client);
|
||||||
});
|
} finally {
|
||||||
}
|
log('generating path migration map');
|
||||||
);
|
const pathMap = createPathMigrationMap(curriculum);
|
||||||
|
const outputDir = path.resolve(
|
||||||
|
__dirname,
|
||||||
|
'../../../api-server/server/resources/pathMigration.json'
|
||||||
|
);
|
||||||
|
fs.writeFile(outputDir, JSON.stringify(pathMap), err => {
|
||||||
|
if (err) {
|
||||||
|
console.error('Oh noes!!');
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
log('path migration map generated');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
Reference in New Issue
Block a user