chore(deps): upgrade eslint, prettier & related packages
This commit is contained in:
parent
0a53a1d7f0
commit
6c91f81b0e
@ -1,4 +1,3 @@
|
||||
**/node_modules/**
|
||||
client/.cache/**
|
||||
client/static/**
|
||||
client/public/**
|
||||
|
@ -1,210 +1,210 @@
|
||||
{
|
||||
"rules": {
|
||||
"max-len": [
|
||||
"error",
|
||||
{ "code": 80, "ignoreUrls": true, "ignoreTemplateLiterals": true }
|
||||
],
|
||||
"block-scoped-var": 0,
|
||||
"brace-style": [2, "1tbs", { "allowSingleLine": true }],
|
||||
"camelcase": 2,
|
||||
"comma-dangle": 2,
|
||||
"comma-spacing": [2, { "before": false, "after": true }],
|
||||
"comma-style": [2, "last"],
|
||||
"complexity": 0,
|
||||
"consistent-return": 2,
|
||||
"consistent-this": 0,
|
||||
"curly": 2,
|
||||
"default-case": 2,
|
||||
"dot-notation": 0,
|
||||
"eol-last": 2,
|
||||
"eqeqeq": 2,
|
||||
"func-call-spacing": 2,
|
||||
"func-names": 0,
|
||||
"func-style": 0,
|
||||
"guard-for-in": 2,
|
||||
"handle-callback-err": 2,
|
||||
"import/default": 2,
|
||||
"import/export": 2,
|
||||
"import/extensions": [0, "always"],
|
||||
"import/first": 2,
|
||||
"import/named": 2,
|
||||
"import/namespace": 2,
|
||||
"import/newline-after-import": 2,
|
||||
"import/no-duplicates": 2,
|
||||
"import/no-unresolved": [2, {"commonjs": true}],
|
||||
"import/unambiguous": 2,
|
||||
"jsx-quotes": [2, "prefer-single"],
|
||||
"jsx-a11y/accessible-emoji": "error",
|
||||
"jsx-a11y/alt-text": "error",
|
||||
"jsx-a11y/anchor-has-content": "error",
|
||||
"jsx-a11y/anchor-is-valid": "error",
|
||||
"jsx-a11y/aria-activedescendant-has-tabindex": "error",
|
||||
"jsx-a11y/aria-props": "error",
|
||||
"jsx-a11y/aria-proptypes": "error",
|
||||
"jsx-a11y/aria-role": "error",
|
||||
"jsx-a11y/aria-unsupported-elements": "error",
|
||||
"jsx-a11y/control-has-associated-label": "error",
|
||||
"jsx-a11y/click-events-have-key-events": "error",
|
||||
"jsx-a11y/heading-has-content": "error",
|
||||
"jsx-a11y/html-has-lang": "error",
|
||||
"jsx-a11y/iframe-has-title": "error",
|
||||
"jsx-a11y/img-redundant-alt": "error",
|
||||
"jsx-a11y/interactive-supports-focus": "error",
|
||||
"jsx-a11y/label-has-associated-control": "error",
|
||||
"jsx-a11y/lang": "error",
|
||||
"jsx-a11y/media-has-caption": "error",
|
||||
"jsx-a11y/mouse-events-have-key-events": "error",
|
||||
"jsx-a11y/no-access-key": "error",
|
||||
"jsx-a11y/no-autofocus": "error",
|
||||
"jsx-a11y/no-distracting-elements": "error",
|
||||
"jsx-a11y/no-interactive-element-to-noninteractive-role": "error",
|
||||
"jsx-a11y/no-noninteractive-element-interactions": "error",
|
||||
"jsx-a11y/no-noninteractive-element-to-interactive-role": "error",
|
||||
"jsx-a11y/no-noninteractive-tabindex": "error",
|
||||
"jsx-a11y/no-onchange": "error",
|
||||
"jsx-a11y/no-redundant-roles": "error",
|
||||
"jsx-a11y/no-static-element-interactions": "error",
|
||||
"jsx-a11y/role-has-required-aria-props": "error",
|
||||
"jsx-a11y/role-supports-aria-props": "error",
|
||||
"jsx-a11y/scope": "error",
|
||||
"jsx-a11y/tabindex-no-positive": "error",
|
||||
"key-spacing": [2, { "beforeColon": false, "afterColon": true }],
|
||||
"keyword-spacing": [2],
|
||||
"max-depth": 0,
|
||||
"max-nested-callbacks": 0,
|
||||
"max-params": 0,
|
||||
"max-statements": 0,
|
||||
"new-cap": 0,
|
||||
"new-parens": 2,
|
||||
"no-alert": 2,
|
||||
"no-array-constructor": 2,
|
||||
"no-bitwise": 2,
|
||||
"no-caller": 2,
|
||||
"no-cond-assign": 2,
|
||||
"no-console": 0,
|
||||
"no-constant-condition": 2,
|
||||
"no-control-regex": 2,
|
||||
"no-debugger": 2,
|
||||
"no-delete-var": 2,
|
||||
"no-div-regex": 2,
|
||||
"no-dupe-keys": 2,
|
||||
"no-else-return": 0,
|
||||
"no-empty": 2,
|
||||
"no-empty-character-class": 2,
|
||||
"no-eq-null": 2,
|
||||
"no-eval": 2,
|
||||
"no-ex-assign": 2,
|
||||
"no-extend-native": 2,
|
||||
"no-extra-bind": 2,
|
||||
"no-extra-boolean-cast": 2,
|
||||
"no-extra-parens": 0,
|
||||
"no-extra-semi": 2,
|
||||
"no-fallthrough": 2,
|
||||
"no-floating-decimal": 2,
|
||||
"no-func-assign": 2,
|
||||
"no-global-assign": 2,
|
||||
"no-implied-eval": 2,
|
||||
"no-inline-comments": 2,
|
||||
"no-inner-declarations": 2,
|
||||
"no-invalid-regexp": 2,
|
||||
"no-irregular-whitespace": 2,
|
||||
"no-iterator": 2,
|
||||
"no-label-var": 2,
|
||||
"no-labels": 2,
|
||||
"no-lone-blocks": 2,
|
||||
"no-lonely-if": 2,
|
||||
"no-loop-func": 2,
|
||||
"no-mixed-requires": 0,
|
||||
"no-mixed-spaces-and-tabs": 2,
|
||||
"no-multi-spaces": 2,
|
||||
"no-multi-str": 2,
|
||||
"no-multiple-empty-lines": [2, { "max": 2 }],
|
||||
"no-nested-ternary": 2,
|
||||
"no-new": 2,
|
||||
"no-new-func": 2,
|
||||
"no-new-object": 2,
|
||||
"no-new-require": 2,
|
||||
"no-new-wrappers": 2,
|
||||
"no-obj-calls": 2,
|
||||
"no-octal": 2,
|
||||
"no-octal-escape": 2,
|
||||
"no-path-concat": 2,
|
||||
"no-plusplus": 0,
|
||||
"no-process-env": 0,
|
||||
"no-process-exit": 2,
|
||||
"no-proto": 2,
|
||||
"no-regex-spaces": 2,
|
||||
"no-reserved-keys": 0,
|
||||
"no-restricted-modules": 0,
|
||||
"no-return-assign": 2,
|
||||
"no-script-url": 2,
|
||||
"no-self-compare": 2,
|
||||
"no-sequences": 2,
|
||||
"no-shadow": 0,
|
||||
"no-shadow-restricted-names": 2,
|
||||
"no-sparse-arrays": 2,
|
||||
"no-sync": 0,
|
||||
"no-ternary": 0,
|
||||
"no-trailing-spaces": 2,
|
||||
"no-undef": 2,
|
||||
"no-undef-init": 2,
|
||||
"no-undefined": 2,
|
||||
"no-underscore-dangle": 0,
|
||||
"no-unreachable": 2,
|
||||
"no-unsafe-negation": 2,
|
||||
"no-unused-expressions": 2,
|
||||
"no-unused-vars": 2,
|
||||
"no-use-before-define": 0,
|
||||
"no-void": 0,
|
||||
"no-warning-comments": [2, { "terms": ["fixme"], "location": "start" }],
|
||||
"no-with": 2,
|
||||
"one-var": 0,
|
||||
"operator-assignment": 0,
|
||||
"padded-blocks": 0,
|
||||
"prefer-object-spread/prefer-object-spread": 2,
|
||||
"prettier/prettier": "error",
|
||||
"quote-props": [2, "as-needed"],
|
||||
"quotes": [2, "single", "avoid-escape"],
|
||||
"radix": 2,
|
||||
"react/display-name": 2,
|
||||
"react/jsx-boolean-value": [2, "always"],
|
||||
"react/jsx-closing-bracket-location": [
|
||||
2,
|
||||
{ "selfClosing": "line-aligned", "nonEmpty": "props-aligned" }
|
||||
],
|
||||
"react/jsx-no-undef": 2,
|
||||
"react/jsx-sort-props": [2, { "ignoreCase": true }],
|
||||
"react/jsx-uses-react": 2,
|
||||
"react/jsx-uses-vars": 2,
|
||||
"react/jsx-wrap-multilines": 2,
|
||||
"react/no-did-mount-set-state": 2,
|
||||
"react/no-did-update-set-state": 2,
|
||||
"react/no-multi-comp": [2, { "ignoreStateless": true }],
|
||||
"react/no-unescaped-entities": 0,
|
||||
"react/no-unknown-property": 2,
|
||||
"react/prop-types": 2,
|
||||
"react/react-in-jsx-scope": 2,
|
||||
"react/self-closing-comp": 2,
|
||||
"react/sort-prop-types": 2,
|
||||
"react-hooks/rules-of-hooks": "error",
|
||||
"react-hooks/exhaustive-deps": "error",
|
||||
"semi": [2, "always"],
|
||||
"semi-spacing": [2, { "before": false, "after": true }],
|
||||
"sort-vars": 0,
|
||||
"space-before-blocks": [2, "always"],
|
||||
"space-before-function-paren": [2, "never"],
|
||||
"space-in-brackets": 0,
|
||||
"space-in-parens": 0,
|
||||
"space-infix-ops": 2,
|
||||
"space-unary-ops": [2, { "words": true, "nonwords": false }],
|
||||
"spaced-comment": [2, "always", { "exceptions": ["-"] }],
|
||||
"strict": 0,
|
||||
"use-isnan": 2,
|
||||
"valid-jsdoc": 0,
|
||||
"valid-typeof": 2,
|
||||
"vars-on-top": 0,
|
||||
"wrap-iife": [2, "any"],
|
||||
"wrap-regex": 2,
|
||||
"yoda": 0
|
||||
}
|
||||
"rules": {
|
||||
"max-len": [
|
||||
"error",
|
||||
{ "code": 80, "ignoreUrls": true, "ignoreTemplateLiterals": true }
|
||||
],
|
||||
"block-scoped-var": 0,
|
||||
"brace-style": [2, "1tbs", { "allowSingleLine": true }],
|
||||
"camelcase": 2,
|
||||
"comma-dangle": 2,
|
||||
"comma-spacing": [2, { "before": false, "after": true }],
|
||||
"comma-style": [2, "last"],
|
||||
"complexity": 0,
|
||||
"consistent-return": 2,
|
||||
"consistent-this": 0,
|
||||
"curly": 2,
|
||||
"default-case": 2,
|
||||
"dot-notation": 0,
|
||||
"eol-last": 2,
|
||||
"eqeqeq": 2,
|
||||
"func-call-spacing": 2,
|
||||
"func-names": 0,
|
||||
"func-style": 0,
|
||||
"guard-for-in": 2,
|
||||
"handle-callback-err": 2,
|
||||
"import/default": 2,
|
||||
"import/export": 2,
|
||||
"import/extensions": [0, "always"],
|
||||
"import/first": 2,
|
||||
"import/named": 2,
|
||||
"import/namespace": 2,
|
||||
"import/newline-after-import": 2,
|
||||
"import/no-duplicates": 2,
|
||||
"import/no-unresolved": [2, { "commonjs": true }],
|
||||
"import/unambiguous": 2,
|
||||
"jsx-quotes": [2, "prefer-single"],
|
||||
"jsx-a11y/accessible-emoji": "error",
|
||||
"jsx-a11y/alt-text": "error",
|
||||
"jsx-a11y/anchor-has-content": "error",
|
||||
"jsx-a11y/anchor-is-valid": "error",
|
||||
"jsx-a11y/aria-activedescendant-has-tabindex": "error",
|
||||
"jsx-a11y/aria-props": "error",
|
||||
"jsx-a11y/aria-proptypes": "error",
|
||||
"jsx-a11y/aria-role": "error",
|
||||
"jsx-a11y/aria-unsupported-elements": "error",
|
||||
"jsx-a11y/control-has-associated-label": "error",
|
||||
"jsx-a11y/click-events-have-key-events": "error",
|
||||
"jsx-a11y/heading-has-content": "error",
|
||||
"jsx-a11y/html-has-lang": "error",
|
||||
"jsx-a11y/iframe-has-title": "error",
|
||||
"jsx-a11y/img-redundant-alt": "error",
|
||||
"jsx-a11y/interactive-supports-focus": "error",
|
||||
"jsx-a11y/label-has-associated-control": "error",
|
||||
"jsx-a11y/lang": "error",
|
||||
"jsx-a11y/media-has-caption": "error",
|
||||
"jsx-a11y/mouse-events-have-key-events": "error",
|
||||
"jsx-a11y/no-access-key": "error",
|
||||
"jsx-a11y/no-autofocus": "error",
|
||||
"jsx-a11y/no-distracting-elements": "error",
|
||||
"jsx-a11y/no-interactive-element-to-noninteractive-role": "error",
|
||||
"jsx-a11y/no-noninteractive-element-interactions": "error",
|
||||
"jsx-a11y/no-noninteractive-element-to-interactive-role": "error",
|
||||
"jsx-a11y/no-noninteractive-tabindex": "error",
|
||||
"jsx-a11y/no-onchange": "error",
|
||||
"jsx-a11y/no-redundant-roles": "error",
|
||||
"jsx-a11y/no-static-element-interactions": "error",
|
||||
"jsx-a11y/role-has-required-aria-props": "error",
|
||||
"jsx-a11y/role-supports-aria-props": "error",
|
||||
"jsx-a11y/scope": "error",
|
||||
"jsx-a11y/tabindex-no-positive": "error",
|
||||
"key-spacing": [2, { "beforeColon": false, "afterColon": true }],
|
||||
"keyword-spacing": [2],
|
||||
"max-depth": 0,
|
||||
"max-nested-callbacks": 0,
|
||||
"max-params": 0,
|
||||
"max-statements": 0,
|
||||
"new-cap": 0,
|
||||
"new-parens": 2,
|
||||
"no-alert": 2,
|
||||
"no-array-constructor": 2,
|
||||
"no-bitwise": 2,
|
||||
"no-caller": 2,
|
||||
"no-cond-assign": 2,
|
||||
"no-console": 0,
|
||||
"no-constant-condition": 2,
|
||||
"no-control-regex": 2,
|
||||
"no-debugger": 2,
|
||||
"no-delete-var": 2,
|
||||
"no-div-regex": 2,
|
||||
"no-dupe-keys": 2,
|
||||
"no-else-return": 0,
|
||||
"no-empty": 2,
|
||||
"no-empty-character-class": 2,
|
||||
"no-eq-null": 2,
|
||||
"no-eval": 2,
|
||||
"no-ex-assign": 2,
|
||||
"no-extend-native": 2,
|
||||
"no-extra-bind": 2,
|
||||
"no-extra-boolean-cast": 2,
|
||||
"no-extra-parens": 0,
|
||||
"no-extra-semi": 2,
|
||||
"no-fallthrough": 2,
|
||||
"no-floating-decimal": 2,
|
||||
"no-func-assign": 2,
|
||||
"no-global-assign": 2,
|
||||
"no-implied-eval": 2,
|
||||
"no-inline-comments": 2,
|
||||
"no-inner-declarations": 2,
|
||||
"no-invalid-regexp": 2,
|
||||
"no-irregular-whitespace": 2,
|
||||
"no-iterator": 2,
|
||||
"no-label-var": 2,
|
||||
"no-labels": 2,
|
||||
"no-lone-blocks": 2,
|
||||
"no-lonely-if": 2,
|
||||
"no-loop-func": 2,
|
||||
"no-mixed-requires": 0,
|
||||
"no-mixed-spaces-and-tabs": 2,
|
||||
"no-multi-spaces": 2,
|
||||
"no-multi-str": 2,
|
||||
"no-multiple-empty-lines": [2, { "max": 2 }],
|
||||
"no-nested-ternary": 2,
|
||||
"no-new": 2,
|
||||
"no-new-func": 2,
|
||||
"no-new-object": 2,
|
||||
"no-new-require": 2,
|
||||
"no-new-wrappers": 2,
|
||||
"no-obj-calls": 2,
|
||||
"no-octal": 2,
|
||||
"no-octal-escape": 2,
|
||||
"no-path-concat": 2,
|
||||
"no-plusplus": 0,
|
||||
"no-process-env": 0,
|
||||
"no-process-exit": 2,
|
||||
"no-proto": 2,
|
||||
"no-regex-spaces": 2,
|
||||
"no-reserved-keys": 0,
|
||||
"no-restricted-modules": 0,
|
||||
"no-return-assign": 2,
|
||||
"no-script-url": 2,
|
||||
"no-self-compare": 2,
|
||||
"no-sequences": 2,
|
||||
"no-shadow": 0,
|
||||
"no-shadow-restricted-names": 2,
|
||||
"no-sparse-arrays": 2,
|
||||
"no-sync": 0,
|
||||
"no-ternary": 0,
|
||||
"no-trailing-spaces": 2,
|
||||
"no-undef": 2,
|
||||
"no-undef-init": 2,
|
||||
"no-undefined": 2,
|
||||
"no-underscore-dangle": 0,
|
||||
"no-unreachable": 2,
|
||||
"no-unsafe-negation": 2,
|
||||
"no-unused-expressions": 2,
|
||||
"no-unused-vars": 2,
|
||||
"no-use-before-define": 0,
|
||||
"no-void": 0,
|
||||
"no-warning-comments": [2, { "terms": ["fixme"], "location": "start" }],
|
||||
"no-with": 2,
|
||||
"one-var": 0,
|
||||
"operator-assignment": 0,
|
||||
"padded-blocks": 0,
|
||||
"prefer-object-spread/prefer-object-spread": 2,
|
||||
"prettier/prettier": "error",
|
||||
"quote-props": [2, "as-needed"],
|
||||
"quotes": [2, "single", "avoid-escape"],
|
||||
"radix": 2,
|
||||
"react/display-name": 2,
|
||||
"react/jsx-boolean-value": [2, "always"],
|
||||
"react/jsx-closing-bracket-location": [
|
||||
2,
|
||||
{ "selfClosing": "line-aligned", "nonEmpty": "props-aligned" }
|
||||
],
|
||||
"react/jsx-no-undef": 2,
|
||||
"react/jsx-sort-props": [2, { "ignoreCase": true }],
|
||||
"react/jsx-uses-react": 2,
|
||||
"react/jsx-uses-vars": 2,
|
||||
"react/jsx-wrap-multilines": 2,
|
||||
"react/no-did-mount-set-state": 2,
|
||||
"react/no-did-update-set-state": 2,
|
||||
"react/no-multi-comp": [2, { "ignoreStateless": true }],
|
||||
"react/no-unescaped-entities": 0,
|
||||
"react/no-unknown-property": 2,
|
||||
"react/prop-types": 2,
|
||||
"react/react-in-jsx-scope": 2,
|
||||
"react/self-closing-comp": 2,
|
||||
"react/sort-prop-types": 2,
|
||||
"react-hooks/rules-of-hooks": "error",
|
||||
"react-hooks/exhaustive-deps": "error",
|
||||
"semi": [2, "always"],
|
||||
"semi-spacing": [2, { "before": false, "after": true }],
|
||||
"sort-vars": 0,
|
||||
"space-before-blocks": [2, "always"],
|
||||
"space-before-function-paren": [2, "never"],
|
||||
"space-in-brackets": 0,
|
||||
"space-in-parens": 0,
|
||||
"space-infix-ops": 2,
|
||||
"space-unary-ops": [2, { "words": true, "nonwords": false }],
|
||||
"spaced-comment": [2, "always", { "exceptions": ["-"] }],
|
||||
"strict": 0,
|
||||
"use-isnan": 2,
|
||||
"valid-jsdoc": 0,
|
||||
"valid-typeof": 2,
|
||||
"vars-on-top": 0,
|
||||
"wrap-iife": [2, "any"],
|
||||
"wrap-regex": 2,
|
||||
"yoda": 0
|
||||
}
|
||||
}
|
||||
|
@ -1,27 +1,43 @@
|
||||
{
|
||||
"env": {
|
||||
"es6": true,
|
||||
"browser": true,
|
||||
"mocha": true,
|
||||
"node": true
|
||||
"es6": true,
|
||||
"browser": true,
|
||||
"mocha": true,
|
||||
"node": true
|
||||
},
|
||||
"parser": "babel-eslint",
|
||||
"root": true,
|
||||
"extends": ["./.eslintrc-base.json", "prettier", "prettier/react"],
|
||||
"plugins": ["react", "import", "prefer-object-spread", "prettier", "react-hooks", "jsx-a11y"],
|
||||
"extends": [
|
||||
"./.eslintrc-base.json",
|
||||
"prettier"
|
||||
],
|
||||
"plugins": [
|
||||
"react",
|
||||
"import",
|
||||
"prefer-object-spread",
|
||||
"prettier",
|
||||
"react-hooks",
|
||||
"jsx-a11y"
|
||||
],
|
||||
"globals": {
|
||||
"Promise": true,
|
||||
"window": true,
|
||||
"$": true,
|
||||
"ga": true,
|
||||
"jQuery": true,
|
||||
"router": true
|
||||
},
|
||||
"Promise": true,
|
||||
"window": true,
|
||||
"$": true,
|
||||
"ga": true,
|
||||
"jQuery": true,
|
||||
"router": true
|
||||
},
|
||||
"settings": {
|
||||
"react": {
|
||||
"version": "16.4.2",
|
||||
"import/ignore": ["node_modules", "\\.json$"],
|
||||
"import/extensions": [".js", ".jsx"]
|
||||
"import/ignore": [
|
||||
"node_modules",
|
||||
"\\.json$"
|
||||
],
|
||||
"import/extensions": [
|
||||
".js",
|
||||
".jsx"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -4,5 +4,6 @@
|
||||
"singleQuote": true,
|
||||
"jsxSingleQuote": true,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "none"
|
||||
"trailingComma": "none",
|
||||
"arrowParens": "avoid"
|
||||
}
|
||||
|
@ -8,8 +8,8 @@ import {
|
||||
} from '../../server/utils/auth';
|
||||
|
||||
const log = debug('fcc:models:UserCredential');
|
||||
module.exports = function(UserCredential) {
|
||||
UserCredential.link = function(
|
||||
module.exports = function (UserCredential) {
|
||||
UserCredential.link = function (
|
||||
userId,
|
||||
_provider,
|
||||
authScheme,
|
||||
|
@ -14,12 +14,12 @@ export function ensureLowerCaseEmail(profile) {
|
||||
: '';
|
||||
}
|
||||
|
||||
export default function(UserIdent) {
|
||||
export default function (UserIdent) {
|
||||
UserIdent.on('dataSourceAttached', () => {
|
||||
UserIdent.findOne$ = observeMethod(UserIdent, 'findOne');
|
||||
});
|
||||
|
||||
UserIdent.login = function(
|
||||
UserIdent.login = function (
|
||||
_provider,
|
||||
authScheme,
|
||||
profile,
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Observable } from 'rx';
|
||||
|
||||
export default function(Block) {
|
||||
export default function (Block) {
|
||||
Block.on('dataSourceAttached', () => {
|
||||
Block.findOne$ = Observable.fromNodeCallback(Block.findOne, Block);
|
||||
Block.findById$ = Observable.fromNodeCallback(Block.findById, Block);
|
||||
|
@ -152,7 +152,7 @@ function populateRequiredFields(user) {
|
||||
return;
|
||||
}
|
||||
|
||||
export default function(User) {
|
||||
export default function (User) {
|
||||
// set salt factor for passwords
|
||||
User.settings.saltWorkFactor = 5;
|
||||
// set user.rand to random number
|
||||
@ -180,7 +180,7 @@ export default function(User) {
|
||||
);
|
||||
});
|
||||
|
||||
User.observe('before save', function(ctx) {
|
||||
User.observe('before save', function (ctx) {
|
||||
const beforeCreate = Observable.of(ctx)
|
||||
.filter(({ isNewInstance }) => isNewInstance)
|
||||
// User.create
|
||||
@ -229,7 +229,7 @@ export default function(User) {
|
||||
});
|
||||
|
||||
// remove lingering user identities before deleting user
|
||||
User.observe('before delete', function(ctx, next) {
|
||||
User.observe('before delete', function (ctx, next) {
|
||||
const UserIdentity = User.app.models.UserIdentity;
|
||||
const UserCredential = User.app.models.UserCredential;
|
||||
log('removing user', ctx.where);
|
||||
@ -240,21 +240,21 @@ export default function(User) {
|
||||
return Observable.combineLatest(
|
||||
destroyAll(id, UserIdentity),
|
||||
destroyAll(id, UserCredential),
|
||||
function(identData, credData) {
|
||||
function (identData, credData) {
|
||||
return {
|
||||
identData: identData,
|
||||
credData: credData
|
||||
};
|
||||
}
|
||||
).subscribe(
|
||||
function(data) {
|
||||
function (data) {
|
||||
log('deleted', data);
|
||||
},
|
||||
function(err) {
|
||||
function (err) {
|
||||
log('error deleting user %s stuff', id, err);
|
||||
next(err);
|
||||
},
|
||||
function() {
|
||||
function () {
|
||||
log('user stuff deleted for user %s', id);
|
||||
next();
|
||||
}
|
||||
@ -263,7 +263,7 @@ export default function(User) {
|
||||
|
||||
log('setting up user hooks');
|
||||
// overwrite lb confirm
|
||||
User.confirm = function(uid, token, redirectTo) {
|
||||
User.confirm = function (uid, token, redirectTo) {
|
||||
return this.findById(uid).then(user => {
|
||||
if (!user) {
|
||||
throw wrapHandledError(new Error(`User not found: ${uid}`), {
|
||||
@ -339,7 +339,7 @@ export default function(User) {
|
||||
);
|
||||
};
|
||||
|
||||
User.afterRemote('logout', function({ req, res }, result, next) {
|
||||
User.afterRemote('logout', function ({ req, res }, result, next) {
|
||||
removeCookies(req, res);
|
||||
next();
|
||||
});
|
||||
@ -802,7 +802,7 @@ export default function(User) {
|
||||
...user,
|
||||
about: showAbout ? about : '',
|
||||
calendar: showHeatMap ? calendar : {},
|
||||
completedChallenges: (function() {
|
||||
completedChallenges: (function () {
|
||||
if (showTimeLine) {
|
||||
return showCerts
|
||||
? completedChallenges
|
||||
|
@ -41,9 +41,9 @@ export default function donateBoot(app, done) {
|
||||
metadata: {
|
||||
/* eslint-disable camelcase */
|
||||
sb_service: `freeCodeCamp.org`,
|
||||
sb_tier: `${
|
||||
donationSubscriptionConfig.duration[duration]
|
||||
} $${amount / 100} Donation`
|
||||
sb_tier: `${donationSubscriptionConfig.duration[duration]} $${
|
||||
amount / 100
|
||||
} Donation`
|
||||
/* eslint-enable camelcase */
|
||||
}
|
||||
},
|
||||
@ -68,11 +68,11 @@ export default function donateBoot(app, done) {
|
||||
}
|
||||
|
||||
function connectToStripe() {
|
||||
return new Promise(function(resolve) {
|
||||
return new Promise(function (resolve) {
|
||||
// connect to stripe API
|
||||
stripe = Stripe(keys.stripe.secret);
|
||||
// parse stripe plans
|
||||
stripe.plans.list({}, function(err, stripePlans) {
|
||||
stripe.plans.list({}, function (err, stripePlans) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
@ -96,7 +96,7 @@ export default function donateBoot(app, done) {
|
||||
|
||||
function createStripePlan(plan) {
|
||||
log(`Creating subscription plan: ${plan.product.name}`);
|
||||
stripe.plans.create(plan, function(err) {
|
||||
stripe.plans.create(plan, function (err) {
|
||||
if (err) {
|
||||
log(err);
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ module.exports = function mountLoopBackExplorer(app) {
|
||||
} catch (err) {
|
||||
// Print the message only when the app was started via `app.listen()`.
|
||||
// Do not print any message when the project is used as a component.
|
||||
app.once('started', function() {
|
||||
app.once('started', function () {
|
||||
log(
|
||||
'Run `npm install loopback-component-explorer` to enable ' +
|
||||
'the LoopBack explorer'
|
||||
@ -25,7 +25,7 @@ module.exports = function mountLoopBackExplorer(app) {
|
||||
const mountPath = '/explorer';
|
||||
|
||||
explorer(app, { basePath: restApiRoot, mountPath });
|
||||
app.once('started', function() {
|
||||
app.once('started', function () {
|
||||
const baseUrl = app.get('url').replace(/\/$/, '');
|
||||
|
||||
log('Browse your REST API at %s%s', baseUrl, mountPath);
|
||||
|
@ -6,7 +6,7 @@ import { getRedirectParams } from '../utils/redirection';
|
||||
const githubClient = process.env.GITHUB_ID;
|
||||
const githubSecret = process.env.GITHUB_SECRET;
|
||||
|
||||
module.exports = function(app) {
|
||||
module.exports = function (app) {
|
||||
const router = app.loopback.Router();
|
||||
const User = app.models.User;
|
||||
|
||||
@ -168,7 +168,7 @@ module.exports = function(app) {
|
||||
githubSecret
|
||||
].join(''),
|
||||
githubHeaders,
|
||||
function(err, status1, pulls) {
|
||||
function (err, status1, pulls) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
@ -185,7 +185,7 @@ module.exports = function(app) {
|
||||
githubSecret
|
||||
].join(''),
|
||||
githubHeaders,
|
||||
function(err, status2, issues) {
|
||||
function (err, status2, issues) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
@ -77,9 +77,7 @@ function refetchCompletedChallenges(req, res, next) {
|
||||
}
|
||||
|
||||
const updateMyEmailValidators = [
|
||||
check('email')
|
||||
.isEmail()
|
||||
.withMessage('Email format is invalid.')
|
||||
check('email').isEmail().withMessage('Email format is invalid.')
|
||||
];
|
||||
|
||||
function updateMyEmail(req, res, next) {
|
||||
@ -117,9 +115,7 @@ function updateMyCurrentChallenge(req, res, next) {
|
||||
}
|
||||
|
||||
const updateMyThemeValidators = [
|
||||
check('theme')
|
||||
.isIn(Object.keys(themes))
|
||||
.withMessage('Theme is invalid.')
|
||||
check('theme').isIn(Object.keys(themes)).withMessage('Theme is invalid.')
|
||||
];
|
||||
|
||||
function updateMyTheme(req, res, next) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
module.exports = function(app) {
|
||||
module.exports = function (app) {
|
||||
var router = app.loopback.Router();
|
||||
router.get('/wiki/*', showForum);
|
||||
|
||||
|
@ -125,7 +125,7 @@ function getUnlinkSocial(req, res, next) {
|
||||
}
|
||||
};
|
||||
|
||||
return user.identities(query, function(err, identities) {
|
||||
return user.identities(query, function (err, identities) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
@ -137,7 +137,7 @@ function getUnlinkSocial(req, res, next) {
|
||||
return res.redirect('/' + username);
|
||||
}
|
||||
|
||||
return identity.destroy(function(err) {
|
||||
return identity.destroy(function (err) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
@ -181,7 +181,7 @@ function postResetProgress(req, res, next) {
|
||||
isMachineLearningPyCertV7: false,
|
||||
completedChallenges: []
|
||||
},
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
@ -193,7 +193,7 @@ function postResetProgress(req, res, next) {
|
||||
function createPostDeleteAccount(app) {
|
||||
const { User } = app.models;
|
||||
return function postDeleteAccount(req, res, next) {
|
||||
return User.destroyById(req.user.id, function(err) {
|
||||
return User.destroyById(req.user.id, function (err) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import accepts from 'accepts';
|
||||
import { getRedirectParams } from '../utils/redirection';
|
||||
|
||||
export default function fourOhFour(app) {
|
||||
app.all('*', function(req, res) {
|
||||
app.all('*', function (req, res) {
|
||||
const accept = accepts(req);
|
||||
const type = accept.type('html', 'json', 'text');
|
||||
const { path } = req;
|
||||
|
@ -53,7 +53,7 @@ export function setupPassport(app) {
|
||||
|
||||
configurator.init();
|
||||
|
||||
Object.keys(passportProviders).map(function(strategy) {
|
||||
Object.keys(passportProviders).map(function (strategy) {
|
||||
let config = passportProviders[strategy];
|
||||
config.session = config.session !== false;
|
||||
|
||||
|
@ -64,9 +64,12 @@ boot(app, __dirname, err => {
|
||||
setupPassport(app);
|
||||
|
||||
const { db } = app.datasources;
|
||||
db.on('connected', _.once(() => log('db connected')));
|
||||
app.start = _.once(function() {
|
||||
const server = app.listen(app.get('port'), function() {
|
||||
db.on(
|
||||
'connected',
|
||||
_.once(() => log('db connected'))
|
||||
);
|
||||
app.start = _.once(function () {
|
||||
const server = app.listen(app.get('port'), function () {
|
||||
app.emit('started');
|
||||
log(
|
||||
'freeCodeCamp server listening on port %d in %s',
|
||||
|
@ -2,7 +2,7 @@ import { homeLocation } from '../../../../config/env';
|
||||
import { allowedOrigins } from '../../../../config/cors-settings';
|
||||
|
||||
export default function constantHeaders() {
|
||||
return function(req, res, next) {
|
||||
return function (req, res, next) {
|
||||
if (
|
||||
req.headers &&
|
||||
req.headers.origin &&
|
||||
|
@ -1,6 +1,6 @@
|
||||
import csurf from 'csurf';
|
||||
|
||||
export default function() {
|
||||
export default function () {
|
||||
const protection = csurf({
|
||||
cookie: {
|
||||
domain: process.env.COOKIE_DOMAIN || 'localhost',
|
||||
|
@ -25,7 +25,7 @@ const isDev = process.env.FREECODECAMP_NODE_ENV !== 'production';
|
||||
export default function prodErrorHandler() {
|
||||
// error handling in production.
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
return function(err, req, res, next) {
|
||||
return function (err, req, res, next) {
|
||||
const { origin } = getRedirectParams(req);
|
||||
const handled = unwrapHandledError(err);
|
||||
// respect handled error status
|
||||
|
@ -1,7 +1,7 @@
|
||||
import qs from 'query-string';
|
||||
|
||||
// add rx methods to express
|
||||
export default function() {
|
||||
export default function () {
|
||||
return function expressExtensions(req, res, next) {
|
||||
res.redirectWithFlash = uri => {
|
||||
const flash = req.flash();
|
||||
|
@ -10,7 +10,7 @@ const EXCLUDED_PATHS = [
|
||||
];
|
||||
|
||||
export default function flashCheaters() {
|
||||
return function(req, res, next) {
|
||||
return function (req, res, next) {
|
||||
if (
|
||||
ALLOWED_METHODS.indexOf(req.method) !== -1 &&
|
||||
EXCLUDED_PATHS.indexOf(req.path) === -1 &&
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Observable } from 'rx';
|
||||
|
||||
export default function(AuthToken) {
|
||||
export default function (AuthToken) {
|
||||
AuthToken.on('dataSourceAttached', () => {
|
||||
AuthToken.findOne$ = Observable.fromNodeCallback(
|
||||
AuthToken.findOne.bind(AuthToken)
|
||||
|
@ -7,7 +7,7 @@ import InMemoryCache from '../utils/in-memory-cache';
|
||||
const log = debug('fcc:boot:donate');
|
||||
const fiveMinutes = 1000 * 60 * 5;
|
||||
|
||||
export default function(Donation) {
|
||||
export default function (Donation) {
|
||||
let activeDonationUpdateInterval = null;
|
||||
const activeDonationCountCacheTTL = fiveMinutes;
|
||||
const activeDonationCountCache = InMemoryCache(0, reportError);
|
||||
|
@ -3,14 +3,8 @@ import moment from 'moment-timezone';
|
||||
// day count between two epochs (inclusive)
|
||||
export function dayCount([head, tail], timezone = 'UTC') {
|
||||
return Math.ceil(
|
||||
moment(
|
||||
moment(head)
|
||||
.tz(timezone)
|
||||
.endOf('day')
|
||||
).diff(
|
||||
moment(tail)
|
||||
.tz(timezone)
|
||||
.startOf('day'),
|
||||
moment(moment(head).tz(timezone).endOf('day')).diff(
|
||||
moment(tail).tz(timezone).startOf('day'),
|
||||
'days',
|
||||
true
|
||||
)
|
||||
|
@ -28,7 +28,7 @@ export async function getAsyncPaypalToken() {
|
||||
}
|
||||
|
||||
export function capitalizeKeys(object) {
|
||||
Object.keys(object).forEach(function(key) {
|
||||
Object.keys(object).forEach(function (key) {
|
||||
object[key.toUpperCase()] = object[key];
|
||||
});
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ export default function populateUser(db, user) {
|
||||
{ $match: { _id: user.id } },
|
||||
{ $project: { points: { $size: '$progressTimestamps' } } }
|
||||
])
|
||||
.get(function(err, [{ points = 1 } = {}]) {
|
||||
.get(function (err, [{ points = 1 } = {}]) {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import {
|
||||
import { getRedirectParams } from './redirection';
|
||||
|
||||
export function ifNoUserRedirectHome(message, type = 'errors') {
|
||||
return function(req, res, next) {
|
||||
return function (req, res, next) {
|
||||
const { path } = req;
|
||||
if (req.user) {
|
||||
return next();
|
||||
@ -24,7 +24,7 @@ export function ifNoUserRedirectHome(message, type = 'errors') {
|
||||
}
|
||||
|
||||
export function ifNoUserSend(sendThis) {
|
||||
return function(req, res, next) {
|
||||
return function (req, res, next) {
|
||||
if (req.user) {
|
||||
return next();
|
||||
}
|
||||
|
@ -5,13 +5,13 @@ import debugFactory from 'debug';
|
||||
const debug = debugFactory('fcc:rxUtils');
|
||||
|
||||
export function saveInstance(instance) {
|
||||
return new Rx.Observable.create(function(observer) {
|
||||
return new Rx.Observable.create(function (observer) {
|
||||
if (!instance || typeof instance.save !== 'function') {
|
||||
debug('no instance or save method');
|
||||
observer.onNext();
|
||||
return observer.onCompleted();
|
||||
}
|
||||
return instance.save(function(err, savedInstance) {
|
||||
return instance.save(function (err, savedInstance) {
|
||||
if (err) {
|
||||
return observer.onError(err);
|
||||
}
|
||||
@ -49,9 +49,7 @@ export function timeCache(time, unit) {
|
||||
// set new expire time in MS and create new subscription to source
|
||||
if (!expireCacheAt || expireCacheAt < Date.now()) {
|
||||
// set expire in ms;
|
||||
expireCacheAt = moment()
|
||||
.add(time, unit)
|
||||
.valueOf();
|
||||
expireCacheAt = moment().add(time, unit).valueOf();
|
||||
cache = new AsyncSubject();
|
||||
source.subscribe(cache);
|
||||
}
|
||||
|
@ -25,36 +25,23 @@ export function prepUniqueDaysByHours(cals, tz = 'UTC') {
|
||||
data.push(cur);
|
||||
prev = cur;
|
||||
} else if (
|
||||
moment(cur)
|
||||
.tz(tz)
|
||||
.diff(
|
||||
moment(prev)
|
||||
.tz(tz)
|
||||
.startOf('day'),
|
||||
'hours'
|
||||
) >= hoursDay
|
||||
moment(cur).tz(tz).diff(moment(prev).tz(tz).startOf('day'), 'hours') >=
|
||||
hoursDay
|
||||
) {
|
||||
data.push(cur);
|
||||
prev = cur;
|
||||
}
|
||||
}, []),
|
||||
sortBy(e => e),
|
||||
map(ts =>
|
||||
moment(ts)
|
||||
.tz(tz)
|
||||
.startOf('hours')
|
||||
.valueOf()
|
||||
)
|
||||
map(ts => moment(ts).tz(tz).startOf('hours').valueOf())
|
||||
)(cals);
|
||||
}
|
||||
|
||||
export function calcCurrentStreak(cals, tz = 'UTC') {
|
||||
let prev = last(cals);
|
||||
if (
|
||||
moment()
|
||||
.tz(tz)
|
||||
.startOf('day')
|
||||
.diff(moment(prev).tz(tz), 'hours') > hoursBetween
|
||||
moment().tz(tz).startOf('day').diff(moment(prev).tz(tz), 'hours') >
|
||||
hoursBetween
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
@ -62,10 +49,8 @@ export function calcCurrentStreak(cals, tz = 'UTC') {
|
||||
let streakContinues = true;
|
||||
forEachRight(cur => {
|
||||
if (
|
||||
moment(prev)
|
||||
.tz(tz)
|
||||
.startOf('day')
|
||||
.diff(moment(cur).tz(tz), 'hours') <= hoursBetween
|
||||
moment(prev).tz(tz).startOf('day').diff(moment(cur).tz(tz), 'hours') <=
|
||||
hoursBetween
|
||||
) {
|
||||
prev = cur;
|
||||
currentStreak++;
|
||||
@ -86,10 +71,8 @@ export function calcLongestStreak(cals, tz = 'UTC') {
|
||||
const last = cals[index === 0 ? 0 : index - 1];
|
||||
// is streak broken
|
||||
if (
|
||||
moment(head)
|
||||
.tz(tz)
|
||||
.startOf('day')
|
||||
.diff(moment(last).tz(tz), 'hours') > hoursBetween
|
||||
moment(head).tz(tz).startOf('day').diff(moment(last).tz(tz), 'hours') >
|
||||
hoursBetween
|
||||
) {
|
||||
tail = head;
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ describe('user stats', () => {
|
||||
);
|
||||
});
|
||||
|
||||
describe('calcCurrentStreak', function() {
|
||||
describe('calcCurrentStreak', function () {
|
||||
it('should return 1 day when today one challenge was completed', () => {
|
||||
expect(
|
||||
calcCurrentStreak(
|
||||
@ -291,7 +291,7 @@ describe('user stats', () => {
|
||||
);
|
||||
});
|
||||
|
||||
describe('calcLongestStreak', function() {
|
||||
describe('calcLongestStreak', function () {
|
||||
it(
|
||||
'should return 1 when there is the only one one-day-long ' +
|
||||
'streak available',
|
||||
|
@ -11,7 +11,8 @@ function createChallengeNode(challenge, reporter) {
|
||||
// sections.
|
||||
if (
|
||||
typeof challenge.description !== 'string' &&
|
||||
(challenge.challengeType !== 11 && challenge.challengeType !== 7)
|
||||
challenge.challengeType !== 11 &&
|
||||
challenge.challengeType !== 7
|
||||
) {
|
||||
reporter.warn(`
|
||||
|
||||
|
@ -298,8 +298,9 @@ const ShowCertification = props => {
|
||||
bsSize='lg'
|
||||
bsStyle='primary'
|
||||
target='_blank'
|
||||
href={`https://www.linkedin.com/profile/add?startTask=CERTIFICATION_NAME&name=${certTitle}&organizationId=4831032&issueYear=${certYear}&issueMonth=${certMonth +
|
||||
1}&certUrl=${certURL}`}
|
||||
href={`https://www.linkedin.com/profile/add?startTask=CERTIFICATION_NAME&name=${certTitle}&organizationId=4831032&issueYear=${certYear}&issueMonth=${
|
||||
certMonth + 1
|
||||
}&certUrl=${certURL}`}
|
||||
>
|
||||
{t('profile.add-linkedin')}
|
||||
</Button>
|
||||
@ -399,7 +400,4 @@ const ShowCertification = props => {
|
||||
ShowCertification.displayName = 'ShowCertification';
|
||||
ShowCertification.propTypes = propTypes;
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(ShowCertification);
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(ShowCertification);
|
||||
|
@ -211,7 +211,4 @@ export function ShowSettings(props) {
|
||||
ShowSettings.displayName = 'ShowSettings';
|
||||
ShowSettings.propTypes = propTypes;
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(ShowSettings);
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(ShowSettings);
|
||||
|
@ -155,8 +155,5 @@ ShowUser.displayName = 'ShowUser';
|
||||
ShowUser.propTypes = propTypes;
|
||||
|
||||
export default withTranslation()(
|
||||
connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(ShowUser)
|
||||
connect(mapStateToProps, mapDispatchToProps)(ShowUser)
|
||||
);
|
||||
|
@ -33,7 +33,7 @@ async function initTestFrame(e = { code: {} }) {
|
||||
// Hardcode Deep Freeze dependency
|
||||
const DeepFreeze = o => {
|
||||
Object.freeze(o);
|
||||
Object.getOwnPropertyNames(o).forEach(function(prop) {
|
||||
Object.getOwnPropertyNames(o).forEach(function (prop) {
|
||||
if (
|
||||
o.hasOwnProperty(prop) &&
|
||||
o[prop] !== null &&
|
||||
|
@ -2,7 +2,7 @@
|
||||
// https://github.com/medialize/sass.js/issues/96#issuecomment-424386171
|
||||
if (!self.crypto) {
|
||||
self.crypto = {
|
||||
getRandomValues: function(array) {
|
||||
getRandomValues: function (array) {
|
||||
for (var i = 0, l = array.length; i < l; i++) {
|
||||
array[i] = Math.floor(Math.random() * 256);
|
||||
}
|
||||
|
@ -24,7 +24,4 @@ AppMountNotifier.propTypes = {
|
||||
render: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(AppMountNotifier);
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(AppMountNotifier);
|
||||
|
@ -163,7 +163,4 @@ function DonateModal({
|
||||
DonateModal.displayName = 'DonateModal';
|
||||
DonateModal.propTypes = propTypes;
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(DonateModal);
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(DonateModal);
|
||||
|
@ -13,7 +13,7 @@ describe('<UniversalNav />', () => {
|
||||
displayMenu: false,
|
||||
menuButtonRef: {},
|
||||
searchBarRef: {},
|
||||
toggleDisplayMenu: function() {},
|
||||
toggleDisplayMenu: function () {},
|
||||
pathName: '/',
|
||||
fetchState: {
|
||||
pending: false
|
||||
|
@ -10,12 +10,9 @@ import { apiLocation, homeLocation } from '../../../../../config/env.json';
|
||||
|
||||
import './login.css';
|
||||
|
||||
const mapStateToProps = createSelector(
|
||||
isSignedInSelector,
|
||||
isSignedIn => ({
|
||||
isSignedIn
|
||||
})
|
||||
);
|
||||
const mapStateToProps = createSelector(isSignedInSelector, isSignedIn => ({
|
||||
isSignedIn
|
||||
}));
|
||||
|
||||
function Login(props) {
|
||||
const { t } = useTranslation();
|
||||
|
@ -207,7 +207,4 @@ export class NavLinks extends Component {
|
||||
NavLinks.propTypes = propTypes;
|
||||
NavLinks.displayName = 'NavLinks';
|
||||
|
||||
export default connect(
|
||||
null,
|
||||
mapDispatchToProps
|
||||
)(withTranslation()(NavLinks));
|
||||
export default connect(null, mapDispatchToProps)(withTranslation()(NavLinks));
|
||||
|
@ -22,7 +22,7 @@ function OfflineWarning({ isOnline, isSignedIn }) {
|
||||
}
|
||||
|
||||
function timeout() {
|
||||
id = setTimeout(function() {
|
||||
id = setTimeout(function () {
|
||||
setShowWarning(true);
|
||||
}, delayInMilliSeconds);
|
||||
}
|
||||
|
@ -7,10 +7,7 @@ const createLanguageRedirect = ({ clientLocale, lang }) => {
|
||||
.filter(item => (item !== clientLocale && item !== lang ? item : ''))
|
||||
.join('/');
|
||||
|
||||
const hostTail = window?.location?.host
|
||||
.split('.')
|
||||
.slice(1)
|
||||
.join('.');
|
||||
const hostTail = window?.location?.host.split('.').slice(1).join('.');
|
||||
const nextClient = lang !== 'chinese' ? 'www' : 'chinese';
|
||||
const nextLocation = `${window?.location?.protocol}//${nextClient}.${hostTail}`;
|
||||
|
||||
|
@ -6,12 +6,9 @@ import { fetchUser, isSignedInSelector, executeGA } from '../../redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import Helmet from 'react-helmet';
|
||||
|
||||
const mapStateToProps = createSelector(
|
||||
isSignedInSelector,
|
||||
isSignedIn => ({
|
||||
isSignedIn
|
||||
})
|
||||
);
|
||||
const mapStateToProps = createSelector(isSignedInSelector, isSignedIn => ({
|
||||
isSignedIn
|
||||
}));
|
||||
|
||||
const mapDispatchToProps = { fetchUser, executeGA };
|
||||
|
||||
|
@ -90,7 +90,4 @@ LearnLayout.propTypes = {
|
||||
})
|
||||
};
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(LearnLayout);
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(LearnLayout);
|
||||
|
@ -336,9 +336,17 @@ function useIdToNameMap() {
|
||||
certPath: getPathFromID(id)
|
||||
});
|
||||
}
|
||||
edges.forEach(({ node: { id, title, fields: { slug } } }) => {
|
||||
idToNameMap.set(id, { challengeTitle: title, challengePath: slug });
|
||||
});
|
||||
edges.forEach(
|
||||
({
|
||||
node: {
|
||||
id,
|
||||
title,
|
||||
fields: { slug }
|
||||
}
|
||||
}) => {
|
||||
idToNameMap.set(id, { challengeTitle: title, challengePath: slug });
|
||||
}
|
||||
);
|
||||
return idToNameMap;
|
||||
}
|
||||
|
||||
|
@ -386,9 +386,7 @@ export class CertificationSettings extends Component {
|
||||
newChallengeFound = true;
|
||||
}
|
||||
|
||||
const valuesSaved = values(formChalObj)
|
||||
.filter(Boolean)
|
||||
.filter(isString);
|
||||
const valuesSaved = values(formChalObj).filter(Boolean).filter(isString);
|
||||
|
||||
const isProjectSectionComplete = valuesSaved.length === oldSubmissions;
|
||||
|
||||
@ -409,7 +407,7 @@ export class CertificationSettings extends Component {
|
||||
const initialObject = {};
|
||||
let filledforms = 0;
|
||||
legacyProjectMap[certName].forEach(project => {
|
||||
let completedProject = find(completedChallenges, function(challenge) {
|
||||
let completedProject = find(completedChallenges, function (challenge) {
|
||||
return challenge['id'] === project['id'];
|
||||
});
|
||||
if (!completedProject) {
|
||||
|
@ -14,12 +14,9 @@ import Spacer from '../helpers/Spacer';
|
||||
import ToggleSetting from './ToggleSetting';
|
||||
import SectionHeader from './SectionHeader';
|
||||
|
||||
const mapStateToProps = createSelector(
|
||||
userSelector,
|
||||
user => ({
|
||||
user
|
||||
})
|
||||
);
|
||||
const mapStateToProps = createSelector(userSelector, user => ({
|
||||
user
|
||||
}));
|
||||
|
||||
const mapDispatchToProps = dispatch =>
|
||||
bindActionCreators({ submitProfileUI }, dispatch);
|
||||
|
@ -45,7 +45,4 @@ class SearchPage extends Component {
|
||||
SearchPage.displayName = 'SearchPage';
|
||||
SearchPage.propTypes = propTypes;
|
||||
|
||||
export default connect(
|
||||
null,
|
||||
mapDispatchToProps
|
||||
)(withTranslation()(SearchPage));
|
||||
export default connect(null, mapDispatchToProps)(withTranslation()(SearchPage));
|
||||
|
@ -971,9 +971,6 @@ Editor.propTypes = propTypes;
|
||||
|
||||
// NOTE: withRef gets replaced by forwardRef in react-redux 6,
|
||||
// https://github.com/reduxjs/react-redux/releases/tag/v6.0.0
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps,
|
||||
null,
|
||||
{ withRef: true }
|
||||
)(Editor);
|
||||
export default connect(mapStateToProps, mapDispatchToProps, null, {
|
||||
withRef: true
|
||||
})(Editor);
|
||||
|
@ -86,7 +86,4 @@ class EditorTabs extends Component {
|
||||
EditorTabs.displayName = 'EditorTabs';
|
||||
EditorTabs.propTypes = propTypes;
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(EditorTabs);
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(EditorTabs);
|
||||
|
@ -101,7 +101,4 @@ class MobileLayout extends Component {
|
||||
MobileLayout.displayName = 'MobileLayout';
|
||||
MobileLayout.propTypes = propTypes;
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(MobileLayout);
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(MobileLayout);
|
||||
|
@ -274,9 +274,6 @@ MultifileEditor.propTypes = propTypes;
|
||||
|
||||
// NOTE: withRef gets replaced by forwardRef in react-redux 6,
|
||||
// https://github.com/reduxjs/react-redux/releases/tag/v6.0.0
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps,
|
||||
null,
|
||||
{ withRef: true }
|
||||
)(MultifileEditor);
|
||||
export default connect(mapStateToProps, mapDispatchToProps, null, {
|
||||
withRef: true
|
||||
})(MultifileEditor);
|
||||
|
@ -54,7 +54,7 @@ const mapStateToProps = createSelector(
|
||||
})
|
||||
);
|
||||
|
||||
const mapDispatchToProps = function(dispatch) {
|
||||
const mapDispatchToProps = function (dispatch) {
|
||||
const dispatchers = {
|
||||
close: () => dispatch(closeModal('completion')),
|
||||
submitChallenge: () => {
|
||||
|
@ -90,7 +90,4 @@ function Hotkeys({
|
||||
Hotkeys.displayName = 'Hotkeys';
|
||||
Hotkeys.propTypes = propTypes;
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(Hotkeys);
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Hotkeys);
|
||||
|
@ -63,7 +63,4 @@ class Preview extends Component {
|
||||
Preview.displayName = 'Preview';
|
||||
Preview.propTypes = propTypes;
|
||||
|
||||
export default connect(
|
||||
null,
|
||||
mapDispatchToProps
|
||||
)(withTranslation()(Preview));
|
||||
export default connect(null, mapDispatchToProps)(withTranslation()(Preview));
|
||||
|
@ -18,12 +18,9 @@ const propTypes = {
|
||||
reset: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
const mapStateToProps = createSelector(
|
||||
isResetModalOpenSelector,
|
||||
isOpen => ({
|
||||
isOpen
|
||||
})
|
||||
);
|
||||
const mapStateToProps = createSelector(isResetModalOpenSelector, isOpen => ({
|
||||
isOpen
|
||||
}));
|
||||
|
||||
const mapDispatchToProps = dispatch =>
|
||||
bindActionCreators(
|
||||
@ -80,7 +77,4 @@ function ResetModal({ reset, close, isOpen }) {
|
||||
ResetModal.displayName = 'ResetModal';
|
||||
ResetModal.propTypes = propTypes;
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(ResetModal);
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(ResetModal);
|
||||
|
@ -47,7 +47,10 @@ export class SidePanel extends Component {
|
||||
// users navigate from another challenge
|
||||
MathJax.Hub.Config({
|
||||
tex2jax: {
|
||||
inlineMath: [['$', '$'], ['\\(', '\\)']],
|
||||
inlineMath: [
|
||||
['$', '$'],
|
||||
['\\(', '\\)']
|
||||
],
|
||||
processEscapes: true,
|
||||
processClass: 'rosetta-code|project-euler'
|
||||
}
|
||||
|
@ -105,7 +105,4 @@ function ToolPanel({
|
||||
ToolPanel.displayName = 'ToolPanel';
|
||||
ToolPanel.propTypes = propTypes;
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(ToolPanel);
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(ToolPanel);
|
||||
|
@ -43,11 +43,7 @@ const padContentWithCssCatch = partial(compileHeadTail, cssCatch);
|
||||
export const jsToHtml = cond([
|
||||
[
|
||||
matchesProperty('ext', 'js'),
|
||||
flow(
|
||||
padContentWithJsCatch,
|
||||
wrapInScript,
|
||||
setExtToHTML
|
||||
)
|
||||
flow(padContentWithJsCatch, wrapInScript, setExtToHTML)
|
||||
],
|
||||
[stubTrue, identity]
|
||||
]);
|
||||
@ -55,11 +51,7 @@ export const jsToHtml = cond([
|
||||
export const cssToHtml = cond([
|
||||
[
|
||||
matchesProperty('ext', 'css'),
|
||||
flow(
|
||||
padContentWithCssCatch,
|
||||
wrapInStyle,
|
||||
setExtToHTML
|
||||
)
|
||||
flow(padContentWithCssCatch, wrapInStyle, setExtToHTML)
|
||||
],
|
||||
[stubTrue, identity]
|
||||
]);
|
||||
|
@ -29,7 +29,7 @@ const nestedJQCallReg = /\$\s*?\(\s*?\$\s*?\)/gi;
|
||||
const throwIfNestedJquery = cond([
|
||||
[
|
||||
testHTMLJS,
|
||||
function({ contents }) {
|
||||
function ({ contents }) {
|
||||
if (nestedJQCallReg.test(contents)) {
|
||||
throw new SyntaxError('Nested jQuery calls breaks browsers');
|
||||
}
|
||||
@ -44,7 +44,7 @@ const functionCallReg = /function\s*?\(|function\s+\w+\s*?\(/gi;
|
||||
const ThrowIfUnfinishedFunction = cond([
|
||||
[
|
||||
testHTMLJS,
|
||||
function({ contents }) {
|
||||
function ({ contents }) {
|
||||
if (functionReg.test(contents) && !functionCallReg.test(contents)) {
|
||||
throw new SyntaxError('Unsafe or unfinished function declaration');
|
||||
}
|
||||
@ -58,7 +58,7 @@ const unsafeConsoleCallReg = /if\s\(null\)\sconsole\.log\(1\);/gi;
|
||||
const throwIfUnsafeConsoleCall = cond([
|
||||
[
|
||||
testHTMLJS,
|
||||
function({ contents }) {
|
||||
function ({ contents }) {
|
||||
if (unsafeConsoleCallReg.test(contents)) {
|
||||
throw new SyntaxError(
|
||||
'`if (null) console.log(1)` detected. This will break tests'
|
||||
@ -74,7 +74,7 @@ const goMixReg = /glitch\.(com|me)/gi;
|
||||
const throwIfGomixDetected = cond([
|
||||
[
|
||||
testHTMLJS,
|
||||
function({ contents }) {
|
||||
function ({ contents }) {
|
||||
if (goMixReg.test(contents)) {
|
||||
throw new Error('Glitch.com or Glitch.me should not be in the code');
|
||||
}
|
||||
|
@ -199,7 +199,7 @@ async function transformScript(element) {
|
||||
});
|
||||
}
|
||||
|
||||
const transformHtml = async function(file) {
|
||||
const transformHtml = async function (file) {
|
||||
const div = document.createElement('div');
|
||||
div.innerHTML = file.contents;
|
||||
await Promise.all([transformSASS(div), transformScript(div)]);
|
||||
|
@ -3,10 +3,7 @@ import { ofType } from 'redux-observable';
|
||||
import { types, unlockCode } from './';
|
||||
|
||||
function codeLockEpic(action$) {
|
||||
return action$.pipe(
|
||||
ofType(types.updateFile),
|
||||
map(unlockCode)
|
||||
);
|
||||
return action$.pipe(ofType(types.updateFile), map(unlockCode));
|
||||
}
|
||||
|
||||
export default codeLockEpic;
|
||||
|
@ -58,9 +58,11 @@ function createQuestionEpic(action$, state$, { window }) {
|
||||
? `**Your project link(s)**\n`
|
||||
: `**Your code so far**`
|
||||
}
|
||||
${projectFormValues
|
||||
?.map(([key, val]) => `${key}: ${val}\n`)
|
||||
?.join('') || filesToMarkdown(files)}
|
||||
${
|
||||
projectFormValues
|
||||
?.map(([key, val]) => `${key}: ${val}\n`)
|
||||
?.join('') || filesToMarkdown(files)
|
||||
}
|
||||
|
||||
${endingText}`
|
||||
);
|
||||
|
@ -74,9 +74,9 @@ export function* executeChallengeSaga({
|
||||
yield put(initLogs());
|
||||
yield put(initConsole(i18next.t('learn.running-tests')));
|
||||
// reset tests to initial state
|
||||
const tests = (yield select(challengeTestsSelector)).map(
|
||||
({ text, testString }) => ({ text, testString })
|
||||
);
|
||||
const tests = (yield select(
|
||||
challengeTestsSelector
|
||||
)).map(({ text, testString }) => ({ text, testString }));
|
||||
yield put(updateTests(tests));
|
||||
|
||||
yield fork(takeEveryLog, consoleProxy);
|
||||
@ -116,7 +116,7 @@ export function* executeChallengeSaga({
|
||||
function* takeEveryLog(channel) {
|
||||
// TODO: move all stringifying and escaping into the reducer so there is a
|
||||
// single place responsible for formatting the logs.
|
||||
yield takeEvery(channel, function*(args) {
|
||||
yield takeEvery(channel, function* (args) {
|
||||
yield put(updateLogs(escape(args)));
|
||||
});
|
||||
}
|
||||
@ -124,7 +124,7 @@ function* takeEveryLog(channel) {
|
||||
function* takeEveryConsole(channel) {
|
||||
// TODO: move all stringifying and escaping into the reducer so there is a
|
||||
// single place responsible for formatting the console output.
|
||||
yield takeEvery(channel, function*(args) {
|
||||
yield takeEvery(channel, function* (args) {
|
||||
yield put(updateConsole(escape(args)));
|
||||
});
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ const globalRequires = [
|
||||
];
|
||||
|
||||
const applyFunction = fn =>
|
||||
async function(file) {
|
||||
async function (file) {
|
||||
try {
|
||||
if (file.error) {
|
||||
return file;
|
||||
|
@ -49,7 +49,7 @@ const createHeader = (id = mainId) => `
|
||||
</script>
|
||||
`;
|
||||
|
||||
export const runTestInTestFrame = async function(document, test, timeout) {
|
||||
export const runTestInTestFrame = async function (document, test, timeout) {
|
||||
const { contentDocument: frame } = document.getElementById(testId);
|
||||
return await Promise.race([
|
||||
new Promise((_, reject) => setTimeout(() => reject('timeout'), timeout)),
|
||||
@ -115,7 +115,7 @@ const initMainFrame = (frameReady, proxyLogger) => ctx => {
|
||||
// Overwriting the onerror added by createHeader to catch any errors thrown
|
||||
// after the frame is ready. It has to be overwritten, as proxyLogger cannot
|
||||
// be added as part of createHeader.
|
||||
ctx.window.onerror = function(msg) {
|
||||
ctx.window.onerror = function (msg) {
|
||||
var string = msg.toLowerCase();
|
||||
if (string.includes('script error')) {
|
||||
msg = 'Error, open your browser console to learn more.';
|
||||
|
@ -65,7 +65,7 @@ class WorkerExecutor {
|
||||
|
||||
execute(data, timeout = 1000) {
|
||||
const task = eventify({});
|
||||
task._execute = function(getWorker) {
|
||||
task._execute = function (getWorker) {
|
||||
getWorker().then(
|
||||
worker => {
|
||||
task._worker = worker;
|
||||
|
@ -3,7 +3,7 @@
|
||||
import createWorker from './worker-executor';
|
||||
|
||||
function mockWorker({ init, postMessage, terminate } = {}) {
|
||||
global.Worker = jest.fn(function() {
|
||||
global.Worker = jest.fn(function () {
|
||||
setImmediate(
|
||||
(init && init(this)) ||
|
||||
(() =>
|
||||
@ -12,7 +12,7 @@ function mockWorker({ init, postMessage, terminate } = {}) {
|
||||
this.onmessage = null;
|
||||
this.postMessage =
|
||||
postMessage ||
|
||||
function(data) {
|
||||
function (data) {
|
||||
setImmediate(
|
||||
() => this.onmessage && this.onmessage({ data: `${data} processed` })
|
||||
);
|
||||
@ -169,7 +169,7 @@ it('Worker executor should reject task', async () => {
|
||||
|
||||
it('Worker executor should emit LOG events', async () => {
|
||||
mockWorker({
|
||||
postMessage: function(data) {
|
||||
postMessage: function (data) {
|
||||
setImmediate(() => {
|
||||
for (let i = 0; i < 3; i++) {
|
||||
// eslint-disable-next-line no-unused-expressions
|
||||
|
@ -18,12 +18,9 @@ const propTypes = {
|
||||
};
|
||||
|
||||
const mapStateToProps = state => {
|
||||
return createSelector(
|
||||
userSelector,
|
||||
user => ({
|
||||
user
|
||||
})
|
||||
)(state);
|
||||
return createSelector(userSelector, user => ({
|
||||
user
|
||||
}))(state);
|
||||
};
|
||||
|
||||
export class CertChallenge extends Component {
|
||||
|
@ -11,12 +11,9 @@ import GreenPass from '../../../assets/icons/GreenPass';
|
||||
import GreenNotCompleted from '../../../assets/icons/GreenNotCompleted';
|
||||
|
||||
const mapStateToProps = state => {
|
||||
return createSelector(
|
||||
completedChallengesSelector,
|
||||
completedChallenges => ({
|
||||
completedChallenges: completedChallenges.map(({ id }) => id)
|
||||
})
|
||||
)(state);
|
||||
return createSelector(completedChallengesSelector, completedChallenges => ({
|
||||
completedChallenges: completedChallenges.map(({ id }) => id)
|
||||
}))(state);
|
||||
};
|
||||
|
||||
const mapDispatchToProps = dispatch =>
|
||||
|
@ -16,12 +16,7 @@ function prototyper(str) {
|
||||
.map(str => {
|
||||
if (prototypeRE.test(str)) {
|
||||
if (str.length > 9) {
|
||||
return prototyper(
|
||||
str
|
||||
.trim()
|
||||
.split('prototype')
|
||||
.join('-prototype-')
|
||||
);
|
||||
return prototyper(str.trim().split('prototype').join('-prototype-'));
|
||||
}
|
||||
return str;
|
||||
}
|
||||
@ -39,12 +34,7 @@ function prototyper(str) {
|
||||
return `${titleify(first)}.prototype.${finalSecond}`;
|
||||
}
|
||||
if (noProto.length === 1) {
|
||||
return prototyper(
|
||||
noProto[0]
|
||||
.toLowerCase()
|
||||
.split('.')
|
||||
.join('-')
|
||||
);
|
||||
return prototyper(noProto[0].toLowerCase().split('.').join('-'));
|
||||
}
|
||||
return titleify(str, true);
|
||||
}
|
||||
|
@ -53,22 +53,22 @@ const donationSubscriptionConfig = {
|
||||
const paypalConfigTypes = {
|
||||
live: {
|
||||
month: {
|
||||
'500': { planId: 'P-1L11422374370240ULZKX3PA' },
|
||||
'1000': { planId: 'P-61K21421WY874920PL6E36YI' },
|
||||
'2000': { planId: 'P-31999436LF709112VL6E374A' },
|
||||
'3000': { planId: 'P-1KY930839N8045117L6E4BKY' },
|
||||
'4000': { planId: 'P-0JW4843250567551AL6E4CAI' },
|
||||
'5000': { planId: 'P-0WR49877YD949401BL6E4CTA' }
|
||||
500: { planId: 'P-1L11422374370240ULZKX3PA' },
|
||||
1000: { planId: 'P-61K21421WY874920PL6E36YI' },
|
||||
2000: { planId: 'P-31999436LF709112VL6E374A' },
|
||||
3000: { planId: 'P-1KY930839N8045117L6E4BKY' },
|
||||
4000: { planId: 'P-0JW4843250567551AL6E4CAI' },
|
||||
5000: { planId: 'P-0WR49877YD949401BL6E4CTA' }
|
||||
}
|
||||
},
|
||||
staging: {
|
||||
month: {
|
||||
'500': { planId: 'P-37N14480BW163382FLZYPVMA' },
|
||||
'1000': { planId: 'P-28B62039J8092810UL6E3FXA' },
|
||||
'2000': { planId: 'P-7HR706961M9170433L6HI5VI' },
|
||||
'3000': { planId: 'P-35V33574BU596924JL6HI6XY' },
|
||||
'4000': { planId: 'P-45M45060289267734L6HJSXA' },
|
||||
'5000': { planId: 'P-0MD70861FY4172444L6HJTUQ' }
|
||||
500: { planId: 'P-37N14480BW163382FLZYPVMA' },
|
||||
1000: { planId: 'P-28B62039J8092810UL6E3FXA' },
|
||||
2000: { planId: 'P-7HR706961M9170433L6HI5VI' },
|
||||
3000: { planId: 'P-35V33574BU596924JL6HI6XY' },
|
||||
4000: { planId: 'P-45M45060289267734L6HJSXA' },
|
||||
5000: { planId: 'P-0MD70861FY4172444L6HJTUQ' }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -25,10 +25,7 @@ const schema = Joi.object()
|
||||
block: Joi.string().regex(slugRE),
|
||||
blockId: Joi.objectId(),
|
||||
challengeOrder: Joi.number(),
|
||||
challengeType: Joi.number()
|
||||
.min(0)
|
||||
.max(11)
|
||||
.required(),
|
||||
challengeType: Joi.number().min(0).max(11).required(),
|
||||
checksum: Joi.number(),
|
||||
// TODO: require this only for normal challenges, not certs
|
||||
dashedName: Joi.string().regex(slugRE),
|
||||
@ -62,9 +59,7 @@ const schema = Joi.object()
|
||||
}),
|
||||
question: Joi.object().keys({
|
||||
text: Joi.string().required(),
|
||||
answers: Joi.array()
|
||||
.items(Joi.string())
|
||||
.required(),
|
||||
answers: Joi.array().items(Joi.string()).required(),
|
||||
solution: Joi.number().required()
|
||||
}),
|
||||
required: Joi.array().items(
|
||||
@ -92,9 +87,7 @@ const schema = Joi.object()
|
||||
Joi.object().keys({
|
||||
id: Joi.string().allow(''),
|
||||
text: Joi.string().required(),
|
||||
testString: Joi.string()
|
||||
.allow('')
|
||||
.required()
|
||||
testString: Joi.string().allow('').required()
|
||||
}),
|
||||
// our tests used in certification verification
|
||||
Joi.object().keys({
|
||||
|
@ -91,7 +91,7 @@ const dom = new jsdom.JSDOM('');
|
||||
global.document = dom.window.document;
|
||||
|
||||
const oldRunnerFail = Mocha.Runner.prototype.fail;
|
||||
Mocha.Runner.prototype.fail = function(test, err) {
|
||||
Mocha.Runner.prototype.fail = function (test, err) {
|
||||
if (err instanceof AssertionError) {
|
||||
const errMessage = String(err.message || '');
|
||||
const assertIndex = errMessage.indexOf(': expected');
|
||||
@ -198,9 +198,9 @@ async function setup() {
|
||||
for (const challenge of challenges) {
|
||||
const dashedBlockName = challenge.block;
|
||||
if (!meta[dashedBlockName]) {
|
||||
meta[dashedBlockName] = (await getMetaForBlock(
|
||||
dashedBlockName
|
||||
)).challengeOrder;
|
||||
meta[dashedBlockName] = (
|
||||
await getMetaForBlock(dashedBlockName)
|
||||
).challengeOrder;
|
||||
}
|
||||
}
|
||||
return {
|
||||
@ -221,8 +221,8 @@ function cleanup() {
|
||||
}
|
||||
|
||||
function runTests(challengeData) {
|
||||
describe('Check challenges', function() {
|
||||
after(function() {
|
||||
describe('Check challenges', function () {
|
||||
after(function () {
|
||||
cleanup();
|
||||
});
|
||||
populateTestsForLang(challengeData);
|
||||
@ -252,15 +252,15 @@ function populateTestsForLang({ lang, challenges, meta }) {
|
||||
const challengeTitles = new ChallengeTitles();
|
||||
const validateChallenge = challengeSchemaValidator();
|
||||
|
||||
describe(`Check challenges (${lang})`, function() {
|
||||
describe(`Check challenges (${lang})`, function () {
|
||||
this.timeout(5000);
|
||||
challenges.forEach((challenge, id) => {
|
||||
const dashedBlockName = challenge.block;
|
||||
describe(challenge.block || 'No block', function() {
|
||||
describe(challenge.title || 'No title', function() {
|
||||
describe(challenge.block || 'No block', function () {
|
||||
describe(challenge.title || 'No title', function () {
|
||||
// Note: the title in meta.json are purely for human readability and
|
||||
// do not include translations, so we do not validate against them.
|
||||
it('Matches an ID in meta.json', function() {
|
||||
it('Matches an ID in meta.json', function () {
|
||||
const index = meta[dashedBlockName].findIndex(
|
||||
arr => arr[0] === challenge.id
|
||||
);
|
||||
@ -272,7 +272,7 @@ function populateTestsForLang({ lang, challenges, meta }) {
|
||||
}
|
||||
});
|
||||
|
||||
it('Common checks', function() {
|
||||
it('Common checks', function () {
|
||||
const result = validateChallenge(challenge);
|
||||
|
||||
if (result.error) {
|
||||
@ -374,9 +374,9 @@ function populateTestsForLang({ lang, challenges, meta }) {
|
||||
return;
|
||||
}
|
||||
|
||||
describe('Check tests syntax', function() {
|
||||
describe('Check tests syntax', function () {
|
||||
tests.forEach(test => {
|
||||
it(`Check for: ${test.text}`, function() {
|
||||
it(`Check for: ${test.text}`, function () {
|
||||
assert.doesNotThrow(() => new vm.Script(test.testString));
|
||||
});
|
||||
});
|
||||
@ -393,7 +393,7 @@ function populateTestsForLang({ lang, challenges, meta }) {
|
||||
? buildJSChallenge
|
||||
: buildDOMChallenge;
|
||||
|
||||
it('Test suite must fail on the initial contents', async function() {
|
||||
it('Test suite must fail on the initial contents', async function () {
|
||||
this.timeout(5000 * tests.length + 1000);
|
||||
// suppress errors in the console.
|
||||
const oldConsoleError = console.error;
|
||||
@ -473,9 +473,11 @@ function populateTestsForLang({ lang, challenges, meta }) {
|
||||
return;
|
||||
}
|
||||
|
||||
describe('Check tests against solutions', function() {
|
||||
describe('Check tests against solutions', function () {
|
||||
solutions.forEach((solution, index) => {
|
||||
it(`Solution ${index + 1} must pass the tests`, async function() {
|
||||
it(`Solution ${
|
||||
index + 1
|
||||
} must pass the tests`, async function () {
|
||||
this.timeout(5000 * tests.length + 2000);
|
||||
const testRunner = await createTestRunner(
|
||||
challenge,
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* global cy */
|
||||
|
||||
describe('A certification,', function() {
|
||||
describe('while viewing your own,', function() {
|
||||
describe('A certification,', function () {
|
||||
describe('while viewing your own,', function () {
|
||||
before(() => {
|
||||
cy.visit('/');
|
||||
cy.contains("Get started (it's free)").click({ force: true });
|
||||
@ -51,7 +51,7 @@ describe('A certification,', function() {
|
||||
.click({ force: true });
|
||||
});
|
||||
|
||||
it('should render a LinkedIn button', function() {
|
||||
it('should render a LinkedIn button', function () {
|
||||
cy.contains('Add this certification to my LinkedIn profile')
|
||||
.should('have.attr', 'href')
|
||||
.and(
|
||||
@ -61,7 +61,7 @@ describe('A certification,', function() {
|
||||
);
|
||||
});
|
||||
|
||||
it('should render a Twitter button', function() {
|
||||
it('should render a Twitter button', function () {
|
||||
cy.contains('Share this certification on Twitter').should(
|
||||
'have.attr',
|
||||
'href',
|
||||
@ -78,20 +78,20 @@ describe('A certification,', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe("while viewing someone else's,", function() {
|
||||
describe("while viewing someone else's,", function () {
|
||||
before(() => {
|
||||
cy.go('back');
|
||||
cy.contains('Sign me out of freeCodeCamp').click({ force: true });
|
||||
cy.visit('/certification/developmentuser/legacy-front-end');
|
||||
});
|
||||
|
||||
it('should not render a LinkedIn button', function() {
|
||||
it('should not render a LinkedIn button', function () {
|
||||
cy.contains('Add this certification to my LinkedIn profile').should(
|
||||
'not.exist'
|
||||
);
|
||||
});
|
||||
|
||||
it('should not render a Twitter button', function() {
|
||||
it('should not render a Twitter button', function () {
|
||||
cy.contains('Share this certification on Twitter').should('not.exist');
|
||||
});
|
||||
});
|
||||
|
@ -43,43 +43,28 @@ describe('Landing page', () => {
|
||||
});
|
||||
|
||||
it('Has 5 brand logos', () => {
|
||||
cy.get('.logo-row')
|
||||
.children()
|
||||
.its('length')
|
||||
.should('eq', 5);
|
||||
cy.get('.logo-row').children().its('length').should('eq', 5);
|
||||
});
|
||||
|
||||
it('Has `as seens as` section', () => {
|
||||
cy.contains('Build projects.').should('be.visible');
|
||||
cy.get('.big-heading')
|
||||
.siblings()
|
||||
.get('svg');
|
||||
cy.get('.big-heading').siblings().get('svg');
|
||||
});
|
||||
|
||||
it('Has a visible large image on large viewports', function() {
|
||||
cy.viewport(1200, 660)
|
||||
.get(selectors.landingPageImage)
|
||||
.should('be.visible');
|
||||
it('Has a visible large image on large viewports', function () {
|
||||
cy.viewport(1200, 660).get(selectors.landingPageImage).should('be.visible');
|
||||
|
||||
cy.viewport(1199, 660)
|
||||
.get(selectors.landingPageImage)
|
||||
.should('not.exist');
|
||||
cy.viewport(1199, 660).get(selectors.landingPageImage).should('not.exist');
|
||||
});
|
||||
|
||||
it('Has links to all the certifications', function() {
|
||||
cy.get(selectors.certifications)
|
||||
.children()
|
||||
.its('length')
|
||||
.should('eq', 10);
|
||||
it('Has links to all the certifications', function () {
|
||||
cy.get(selectors.certifications).children().its('length').should('eq', 10);
|
||||
cy.wrap(certifications).each(cert => {
|
||||
cy.get(selectors.certifications).contains(cert);
|
||||
});
|
||||
});
|
||||
|
||||
it('Has 3 testimonial cards', function() {
|
||||
cy.get(selectors.testimonials)
|
||||
.children()
|
||||
.its('length')
|
||||
.should('eq', 3);
|
||||
it('Has 3 testimonial cards', function () {
|
||||
cy.get(selectors.testimonials).children().its('length').should('eq', 3);
|
||||
});
|
||||
});
|
||||
|
@ -15,7 +15,7 @@ const unhandledErrorMessage = 'Something is not quite right';
|
||||
const runningOutput = '// running tests';
|
||||
const finishedOutput = '// tests completed';
|
||||
|
||||
describe('Backend challenge', function() {
|
||||
describe('Backend challenge', function () {
|
||||
it('renders', () => {
|
||||
cy.visit(locations.index);
|
||||
|
||||
|
@ -23,7 +23,7 @@ const defaultOutput = `
|
||||
// const runningOutput = '// running tests';
|
||||
// const finishedOutput = '// tests completed';
|
||||
|
||||
describe('Classic challenge', function() {
|
||||
describe('Classic challenge', function () {
|
||||
it('renders', () => {
|
||||
cy.visit(locations.index);
|
||||
|
||||
|
@ -12,7 +12,7 @@ const selectors = {
|
||||
let appHasStarted;
|
||||
function spyOnListener(win) {
|
||||
const addListener = win.EventTarget.prototype.addEventListener;
|
||||
win.EventTarget.prototype.addEventListener = function(name) {
|
||||
win.EventTarget.prototype.addEventListener = function (name) {
|
||||
if (name === 'click') {
|
||||
appHasStarted = true;
|
||||
win.EventTarget.prototype.addEventListener = addListener;
|
||||
@ -68,9 +68,7 @@ describe('Navbar', () => {
|
||||
() => {
|
||||
cy.get(selectors.menuButton).click();
|
||||
cy.get(selectors.navigationLinks).contains('Forum');
|
||||
cy.get(selectors.navigationLinks)
|
||||
.contains('Curriculum')
|
||||
.click();
|
||||
cy.get(selectors.navigationLinks).contains('Curriculum').click();
|
||||
cy.url().should('include', '/learn');
|
||||
cy.get(selectors.navigationLinks).contains('Curriculum');
|
||||
cy.get(selectors.navigationLinks).contains('Forum');
|
||||
@ -84,9 +82,7 @@ describe('Navbar', () => {
|
||||
() => {
|
||||
cy.contains(selectors.smallCallToAction, 'Sign in');
|
||||
cy.get(selectors.menuButton).click();
|
||||
cy.get(selectors.navigationLinks)
|
||||
.contains('Curriculum')
|
||||
.click();
|
||||
cy.get(selectors.navigationLinks).contains('Curriculum').click();
|
||||
cy.contains(selectors.smallCallToAction, 'Sign in');
|
||||
}
|
||||
);
|
||||
@ -95,9 +91,7 @@ describe('Navbar', () => {
|
||||
cy.login();
|
||||
cy.get('a[href*="/settings"]').should('be.visible');
|
||||
cy.get(selectors.menuButton).click();
|
||||
cy.get(selectors.navigationLinks)
|
||||
.contains('Profile')
|
||||
.click();
|
||||
cy.get(selectors.navigationLinks).contains('Profile').click();
|
||||
cy.url().should('include', '/developmentuser');
|
||||
});
|
||||
|
||||
|
@ -30,17 +30,13 @@ describe('Search bar', () => {
|
||||
it('Should accept input and display hits', () => {
|
||||
search('freeCodeCamp');
|
||||
|
||||
cy.get('.ais-Hits-list')
|
||||
.children()
|
||||
.should('to.have.length.of.at.least', 1);
|
||||
cy.get('.ais-Hits-list').children().should('to.have.length.of.at.least', 1);
|
||||
});
|
||||
|
||||
it('Should clear hits when input is cleared', () => {
|
||||
search('freeCodeCamp');
|
||||
|
||||
cy.get('.ais-Hits-list')
|
||||
.children()
|
||||
.should('to.have.length.of.at.least', 1);
|
||||
cy.get('.ais-Hits-list').children().should('to.have.length.of.at.least', 1);
|
||||
|
||||
clear();
|
||||
|
||||
@ -52,9 +48,7 @@ describe('Search bar', () => {
|
||||
|
||||
search('freeCodeCamp');
|
||||
|
||||
cy.get('.ais-Hits-list')
|
||||
.children()
|
||||
.should('to.have.length.of', 8);
|
||||
cy.get('.ais-Hits-list').children().should('to.have.length.of', 8);
|
||||
});
|
||||
|
||||
it('Should show up to 5 hits when height < 768px', () => {
|
||||
@ -62,17 +56,13 @@ describe('Search bar', () => {
|
||||
|
||||
search('freeCodeCamp');
|
||||
|
||||
cy.get('.ais-Hits-list')
|
||||
.children()
|
||||
.should('to.have.length.of', 5);
|
||||
cy.get('.ais-Hits-list').children().should('to.have.length.of', 5);
|
||||
});
|
||||
|
||||
it('Should show no hits for queries that do not exist in the Algolia index', () => {
|
||||
search('testtttt');
|
||||
|
||||
cy.get('.ais-Hits-list')
|
||||
.children()
|
||||
.should('to.have.length.of', 0);
|
||||
cy.get('.ais-Hits-list').children().should('to.have.length.of', 0);
|
||||
|
||||
cy.contains('No tutorials found');
|
||||
});
|
||||
|
@ -1,11 +1,11 @@
|
||||
/* global cy */
|
||||
|
||||
describe('The `Update my account settings` button works properly', function() {
|
||||
describe('The `Update my account settings` button works properly', function () {
|
||||
beforeEach(() => {
|
||||
cy.login();
|
||||
});
|
||||
|
||||
it('Should take user to their account settings when clicked', function() {
|
||||
it('Should take user to their account settings when clicked', function () {
|
||||
cy.contains('Update my account settings').click();
|
||||
cy.url().should('include', '/settings');
|
||||
});
|
||||
|
@ -13,7 +13,7 @@ const locations = {
|
||||
'/learn/responsive-web-design/basic-html-and-html5/say-hello-to-html-elements'
|
||||
};
|
||||
|
||||
describe('challenges/superblock redirect', function() {
|
||||
describe('challenges/superblock redirect', function () {
|
||||
it('redirects to learn/superblock', () => {
|
||||
cy.visit(locations.chalSuper);
|
||||
|
||||
@ -24,7 +24,7 @@ describe('challenges/superblock redirect', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('challenges/superblock/block redirect', function() {
|
||||
describe('challenges/superblock/block redirect', function () {
|
||||
it('redirects to learn/superblock/block', () => {
|
||||
cy.visit(locations.chalBlock);
|
||||
|
||||
@ -35,7 +35,7 @@ describe('challenges/superblock/block redirect', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('challenges/superblock/block/challenge redirect', function() {
|
||||
describe('challenges/superblock/block/challenge redirect', function () {
|
||||
it('redirects to learn/superblock/block/challenge', () => {
|
||||
cy.visit(locations.chalChallenge);
|
||||
|
||||
|
@ -61,7 +61,7 @@ const warningMessage =
|
||||
'If the tests fail, try disabling your extensions for the most reliable ' +
|
||||
'experience.';
|
||||
|
||||
describe('Basic Css Introduction page', function() {
|
||||
describe('Basic Css Introduction page', function () {
|
||||
it('renders', () => {
|
||||
cy.visit(locations.index);
|
||||
|
||||
|
@ -96,9 +96,7 @@ describe('Username input field', () => {
|
||||
'the URL to your profile and your certifications.'
|
||||
).should('not.exist');
|
||||
|
||||
cy.get('@usernameForm')
|
||||
.contains('Save')
|
||||
.should('be.disabled');
|
||||
cy.get('@usernameForm').contains('Save').should('be.disabled');
|
||||
});
|
||||
|
||||
it('Should not show anything if user types their current name', () => {
|
||||
@ -106,9 +104,7 @@ describe('Username input field', () => {
|
||||
.clear({ force: true })
|
||||
.type('developmentuser', { force: true });
|
||||
|
||||
cy.get('@usernameForm')
|
||||
.contains('Save')
|
||||
.should('be.disabled');
|
||||
cy.get('@usernameForm').contains('Save').should('be.disabled');
|
||||
});
|
||||
|
||||
// eslint-disable-next-line max-len
|
||||
@ -117,9 +113,7 @@ describe('Username input field', () => {
|
||||
.clear({ force: true })
|
||||
.type('developmentuser', { force: true });
|
||||
|
||||
cy.get('@usernameForm')
|
||||
.contains('Save')
|
||||
.should('be.disabled');
|
||||
cy.get('@usernameForm').contains('Save').should('be.disabled');
|
||||
});
|
||||
|
||||
it('Should show warning if username includes invalid character', () => {
|
||||
@ -141,9 +135,7 @@ describe('Username input field', () => {
|
||||
.clear({ force: true })
|
||||
.type('Quincy Larson', { force: true });
|
||||
|
||||
cy.get('@usernameForm')
|
||||
.contains('Save')
|
||||
.should('be.disabled');
|
||||
cy.get('@usernameForm').contains('Save').should('be.disabled');
|
||||
});
|
||||
|
||||
it('Should change username if `Save` button is clicked', () => {
|
||||
@ -153,9 +145,7 @@ describe('Username input field', () => {
|
||||
|
||||
cy.contains('Username is available');
|
||||
|
||||
cy.get('@usernameForm')
|
||||
.contains('Save')
|
||||
.click({ force: true });
|
||||
cy.get('@usernameForm').contains('Save').click({ force: true });
|
||||
cy.contains('Account Settings for quincy').should('be.visible');
|
||||
|
||||
cy.resetUsername();
|
||||
|
1746
package-lock.json
generated
1746
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -71,8 +71,8 @@
|
||||
"cypress": "^6.6.0",
|
||||
"debug": "^4.3.1",
|
||||
"docsify-cli": "^4.4.3",
|
||||
"eslint": "^5.16.0",
|
||||
"eslint-config-prettier": "^6.12.0",
|
||||
"eslint": "^7.21.0",
|
||||
"eslint-config-prettier": "^8.1.0",
|
||||
"eslint-plugin-babel": "^5.3.1",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-jsx-a11y": "^6.4.1",
|
||||
@ -92,7 +92,7 @@
|
||||
"markdownlint": "^0.21.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"ora": "^3.4.0",
|
||||
"prettier": "^1.18.2",
|
||||
"prettier": "^2.2.1",
|
||||
"prismjs": "^1.23.0",
|
||||
"readdirp-walk": "^1.7.0",
|
||||
"shx": "^0.3.3",
|
||||
|
@ -24,8 +24,10 @@ if (
|
||||
start < 1 ||
|
||||
start !== end - 1
|
||||
) {
|
||||
throw 'Step not created. Steps specified must be' +
|
||||
' consecutive numbers and start step must be greater than 0.';
|
||||
throw (
|
||||
'Step not created. Steps specified must be' +
|
||||
' consecutive numbers and start step must be greater than 0.'
|
||||
);
|
||||
}
|
||||
|
||||
const existingSteps = getExistingStepNums(projectPath);
|
||||
|
@ -73,14 +73,8 @@ const reorderSteps = () => {
|
||||
const projectPath = getProjectPath();
|
||||
|
||||
const projectName = process.env.CALLING_DIR
|
||||
? process.env.CALLING_DIR.split(path.sep)
|
||||
.slice(-1)
|
||||
.toString()
|
||||
: process
|
||||
.cwd()
|
||||
.split(path.sep)
|
||||
.slice(-1)
|
||||
.toString();
|
||||
? process.env.CALLING_DIR.split(path.sep).slice(-1).toString()
|
||||
: process.cwd().split(path.sep).slice(-1).toString();
|
||||
|
||||
const curriculumPath = process.env.CALLING_DIR
|
||||
? ''
|
||||
@ -187,8 +181,10 @@ const getExistingStepNums = projectPath => {
|
||||
) {
|
||||
let stepNum = fileName.split('.')[0].split('-')[1];
|
||||
if (!/^\d{3}$/.test(stepNum)) {
|
||||
throw `Step not created. File ${fileName} has a step number containing non-digits.` +
|
||||
' Please run reorder-steps script first.';
|
||||
throw (
|
||||
`Step not created. File ${fileName} has a step number containing non-digits.` +
|
||||
' Please run reorder-steps script first.'
|
||||
);
|
||||
}
|
||||
stepNum = parseInt(stepNum, 10);
|
||||
stepNums.push(stepNum);
|
||||
|
@ -51,7 +51,7 @@ exports.parseMD = function parseMD(filename) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const file = readSync(filename);
|
||||
const tree = processor.parse(file);
|
||||
processor.run(tree, file, function(err, node, file) {
|
||||
processor.run(tree, file, function (err, node, file) {
|
||||
if (!err) {
|
||||
delete file.contents;
|
||||
resolve(file.data);
|
||||
|
@ -90,14 +90,16 @@ function validateEditableMarkers({ value, position }) {
|
||||
lines.forEach((line, index) => {
|
||||
if (line.match(twoMarkersRE)) {
|
||||
throw Error(
|
||||
`Line ${baseLineNumber +
|
||||
index} has two markers. Each line should only have one.`
|
||||
`Line ${
|
||||
baseLineNumber + index
|
||||
} has two markers. Each line should only have one.`
|
||||
);
|
||||
}
|
||||
if (line.match(formattedMarkerRE)) {
|
||||
throw Error(
|
||||
`Line ${baseLineNumber +
|
||||
index} has a malformed marker. It should be --fcc-editable-region--`
|
||||
`Line ${
|
||||
baseLineNumber + index
|
||||
} has a malformed marker. It should be --fcc-editable-region--`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -11,9 +11,7 @@ const { editableRegionMarker } = require('./add-seed');
|
||||
const tableAndStrikeThrough = require('./table-and-strikethrough');
|
||||
|
||||
async function parse(file) {
|
||||
return await remark()
|
||||
.use(tableAndStrikeThrough)
|
||||
.parse(file);
|
||||
return await remark().use(tableAndStrikeThrough).parse(file);
|
||||
}
|
||||
|
||||
function plugin() {
|
||||
|
@ -12,7 +12,7 @@ const usernameIsHttpStatusCode = {
|
||||
const isNumeric = num => !isNaN(num);
|
||||
const validCharsRE = /^[a-zA-Z0-9\-_+]*$/;
|
||||
const isHttpStatusCode = str =>
|
||||
isNumeric(str) && (parseInt(str, 10) >= 100 && parseInt(str, 10) <= 599);
|
||||
isNumeric(str) && parseInt(str, 10) >= 100 && parseInt(str, 10) <= 599;
|
||||
const isValidUsername = str => {
|
||||
if (!validCharsRE.test(str)) return invalidCharError;
|
||||
if (str.length < 3) return usernameTooShort;
|
||||
|
Loading…
x
Reference in New Issue
Block a user