From d75e43a1e7ab608fa89221f36bce8b961c36151d Mon Sep 17 00:00:00 2001 From: Shaun Hamilton Date: Fri, 19 Nov 2021 14:19:40 +0000 Subject: [PATCH] chore: use constants for superblocks (#43886) * chore: use constants for superblocks * add prettier ts dec to challenge-helper-scripts * config/ to ts. broken * typescripterise tools/ and config/ * create global tsconfig, remove alternate configs * delete temp ts->js, add to gitignore * fix gitignore * re-import SuperBlocks in super-block-intro.tsx * remove renamed files added again * fix config * remove accidental files * remove snap * delete built files * adjust eslintrc for enums * add node types to root * ignore build files in lint and prettier * fix tools/ in tsconfig * ignore annoying ts warnings * prettierise Map/index.tsx * fix enum to match lint rule * rejig Map to render RWD superblock * 'pretty minor' - implicitly tsc within root Co-authored-by: Oliver Eyton-Williams * fix client/package.json for Gitpod * broken: migrate @types to root * fix: use typeRoots to prevent duplication * fix show.tsx, try typeroots in root * silly fix for duplicate node_modules types * remove typeRoots from root * fix: tsconfig or not tsconfig, that is the... * fix: ...question: Whether 'tis nobler in the mind to suffer the slings and arrows of outrageous configs... * fix: Or to take Arms against a Sea of lint errors And by opposing end them Co-authored-by: Oliver Eyton-Williams --- .eslintignore | 3 + .eslintrc.json | 10 +- .gitignore | 4 + .prettierignore | 3 + client/package.json | 25 +- client/src/assets/icons/index.tsx | 31 +- client/src/components/Flash/redux/index.ts | 18 +- client/src/components/Map/index.tsx | 32 +- client/src/redux/index.js | 11 +- client/src/redux/prop-types.ts | 7 +- client/src/resources/cert-and-project-map.ts | 74 +- .../src/templates/Challenges/classic/show.tsx | 1 - .../components/completion-modal-body.test.tsx | 4 +- .../Introduction/super-block-intro.tsx | 5 +- ...-settings.js => certification-settings.ts} | 70 +- config/i18n/{all-langs.js => all-langs.ts} | 108 +- cypress/integration/ShowCertification.js | 4 +- .../integration/learn/challenges/projects.js | 5 +- .../claim-cert-from-learn.js | 4 +- package-lock.json | 1103 +++++++++++++++++ package.json | 27 +- .../create-project.ts | 35 +- tools/challenge-helper-scripts/package.json | 2 - tools/challenge-helper-scripts/tsconfig.json | 12 - .../build/{ensure-env.js => ensure-env.ts} | 29 +- tools/scripts/build/tsconfig.json | 6 + tools/ui-components/package.json | 7 +- tools/ui-components/tsconfig.json | 3 +- client/tsconfig.json => tsconfig.json | 10 +- 29 files changed, 1391 insertions(+), 262 deletions(-) rename config/{certification-settings.js => certification-settings.ts} (72%) rename config/i18n/{all-langs.js => all-langs.ts} (53%) delete mode 100644 tools/challenge-helper-scripts/tsconfig.json rename tools/scripts/build/{ensure-env.js => ensure-env.ts} (74%) create mode 100644 tools/scripts/build/tsconfig.json rename client/tsconfig.json => tsconfig.json (67%) diff --git a/.eslintignore b/.eslintignore index e7660cd850..17c85c3b36 100644 --- a/.eslintignore +++ b/.eslintignore @@ -4,3 +4,6 @@ client/public/** api-server/src/public/** api-server/lib/** tools/contributor/** +tools/scripts/build/ensure-env.js +config/i18n/all-langs.js +config/certification-settings.js diff --git a/.eslintrc.json b/.eslintrc.json index a183b8c4c6..4d6f6fc7a9 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -45,9 +45,9 @@ "parser": "@typescript-eslint/parser", "parserOptions": { "project": [ - "./client/tsconfig.json", - "./tools/challenge-helper-scripts/tsconfig.json", - "./tools/ui-components/tsconfig.json" + "./tsconfig.json", + "./tools/ui-components/tsconfig.json", + "./tools/scripts/build/tsconfig.json" ] }, "extends": [ @@ -91,6 +91,10 @@ { "selector": "function", "format": ["camelCase", "PascalCase"] + }, + { + "selector": "enumMember", + "format": ["PascalCase"] } ] } diff --git a/.gitignore b/.gitignore index af03aec09a..456a80128c 100644 --- a/.gitignore +++ b/.gitignore @@ -163,6 +163,10 @@ config/client/sass-compile.json config/client/frame-runner.json config/client/test-evaluator.json config/curriculum.json +config/i18n/all-langs.js +config/certification-settings.js + +tools/scripts/build/ensure-env.js ### vim ### # Swap diff --git a/.prettierignore b/.prettierignore index a4d7798f05..449ccbf291 100644 --- a/.prettierignore +++ b/.prettierignore @@ -5,6 +5,9 @@ client/static curriculum/challenges/_meta/*/* curriculum/challenges/**/* config/**/*.json +config/i18n/all-langs.js +config/certification-settings.js client/i18n/**/*.json docs/i18n **/package-lock.json +tools/scripts/build/ensure-env.js \ No newline at end of file diff --git a/client/package.json b/client/package.json index caa52c5ad6..263d3e5adb 100644 --- a/client/package.json +++ b/client/package.json @@ -19,11 +19,11 @@ "author": "freeCodeCamp ", "main": "none", "scripts": { - "prebuild": "node ../tools/scripts/build/ensure-env.js && npm run build:workers -- --env production", + "prebuild": "tsc -p ../tools/scripts/build/ && node ../tools/scripts/build/ensure-env.js && npm run build:workers -- --env production", "build": "node --max_old_space_size=7168 node_modules/gatsby-cli build --prefix-paths", "build:workers": "node --max_old_space_size=7168 node_modules/webpack-cli/bin/cli --config ./webpack-workers.js", "clean": "gatsby clean", - "predevelop": "node ../tools/scripts/build/ensure-env.js && npm run build:workers -- --env development", + "predevelop": "tsc -p ../tools/scripts/build/ && node ../tools/scripts/build/ensure-env.js && npm run build:workers -- --env development", "develop": "node --max_old_space_size=4000 node_modules/gatsby-cli develop --inspect=9230", "lint": "node ./i18n/schema-validation.js", "serve": "gatsby serve -p 8000", @@ -132,27 +132,6 @@ "@codesee/tracker": "0.143.0", "@testing-library/jest-dom": "5.15.0", "@testing-library/react": "12.1.2", - "@types/chai": "4.2.22", - "@types/jest": "26.0.24", - "@types/loadable__component": "5.13.4", - "@types/lodash-es": "4.17.5", - "@types/node": "16.11.7", - "@types/prismjs": "1.16.6", - "@types/psl": "1.1.0", - "@types/reach__router": "1.3.9", - "@types/react-dom": "17.0.11", - "@types/react-helmet": "6.1.4", - "@types/react-instantsearch-dom": "6.12.0", - "@types/react-monaco-editor": "0.16.0", - "@types/react-redux": "7.1.16", - "@types/react-responsive": "8.0.2", - "@types/react-spinkit": "3.0.7", - "@types/react-test-renderer": "17.0.1", - "@types/react-transition-group": "4.4.4", - "@types/redux-actions": "2.6.2", - "@types/sanitize-html": "2.5.0", - "@types/store": "2.0.2", - "@types/validator": "13.7.0", "autoprefixer": "10.4.0", "babel-plugin-transform-imports": "2.0.0", "chokidar": "3.5.2", diff --git a/client/src/assets/icons/index.tsx b/client/src/assets/icons/index.tsx index 65018d72f3..a0d9e24d4c 100644 --- a/client/src/assets/icons/index.tsx +++ b/client/src/assets/icons/index.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import { SuperBlocks } from '../../../../config/certification-settings'; import APIIcon from './API-icon'; import D3Icon from './D3-icon'; import DatabaseIcon from './Database-icon'; @@ -13,24 +14,22 @@ import ResponsiveDesign from './responsive-design'; import Shield from './shield'; const iconMap = { - 'responsive-web-design': ResponsiveDesign, - 'javascript-algorithms-and-data-structures': JavaScriptIcon, - 'front-end-development-libraries': ReactIcon, - 'data-visualization': D3Icon, - 'back-end-development-and-apis': APIIcon, - 'relational-databases': DatabaseIcon, - 'quality-assurance': Clipboard, - 'scientific-computing-with-python': PythonIcon, - 'data-analysis-with-python': Analytics, - 'information-security': Shield, - 'machine-learning-with-python': TensorflowIcon, - 'coding-interview-prep': Algorithm + [SuperBlocks.RespWebDesign]: ResponsiveDesign, + [SuperBlocks.JsAlgoDataStruct]: JavaScriptIcon, + [SuperBlocks.FrontEndDevLibs]: ReactIcon, + [SuperBlocks.DataVis]: D3Icon, + [SuperBlocks.BackEndDevApis]: APIIcon, + [SuperBlocks.RelationalDb]: DatabaseIcon, + [SuperBlocks.QualityAssurance]: Clipboard, + [SuperBlocks.SciCompPy]: PythonIcon, + [SuperBlocks.DataAnalysisPy]: Analytics, + [SuperBlocks.InfoSec]: Shield, + [SuperBlocks.MachineLearningPy]: TensorflowIcon, + [SuperBlocks.CodingInterviewPrep]: Algorithm }; -type SuperBlock = keyof typeof iconMap; - const generateIconComponent = ( - superBlock: SuperBlock, + superBlock: SuperBlocks, className: string ): JSX.Element => { // fallback in case super block doesn't exist and for tests @@ -39,4 +38,4 @@ const generateIconComponent = ( return ; }; -export { generateIconComponent, SuperBlock }; +export { generateIconComponent }; diff --git a/client/src/components/Flash/redux/index.ts b/client/src/components/Flash/redux/index.ts index 8dd13fe89b..bbb4bbd71c 100644 --- a/client/src/components/Flash/redux/index.ts +++ b/client/src/components/Flash/redux/index.ts @@ -20,8 +20,8 @@ export const flashMessageSelector = (state: State): FlashState['message'] => // ACTION DEFINITIONS enum FlashActionTypes { - createFlashMessage = 'createFlashMessage', - removeFlashMessage = 'removeFlashMessage' + CreateFlashMessage = 'createFlashMessage', + RemoveFlashMessage = 'removeFlashMessage' } export type FlashMessageArg = { @@ -32,7 +32,7 @@ export type FlashMessageArg = { export const createFlashMessage = ( flash: FlashMessageArg -): ReducerPayload => { +): ReducerPayload => { const playSound = store.get('fcc-sound') as boolean | undefined; if (playSound) { void import('tone').then(tone => { @@ -54,20 +54,20 @@ export const createFlashMessage = ( }); } return { - type: FlashActionTypes.createFlashMessage, + type: FlashActionTypes.CreateFlashMessage, payload: { ...flash, id: nanoid() } }; }; export const removeFlashMessage = - (): ReducerPayload => ({ - type: FlashActionTypes.removeFlashMessage + (): ReducerPayload => ({ + type: FlashActionTypes.RemoveFlashMessage }); // REDUCER type ReducerBase = { type: T }; type ReducerPayload = - T extends FlashActionTypes.createFlashMessage + T extends FlashActionTypes.CreateFlashMessage ? ReducerBase & { payload: FlashState['message']; } @@ -79,9 +79,9 @@ export const reducer = ( action: ReducerPayload ): FlashState => { switch (action.type) { - case FlashActionTypes.createFlashMessage: + case FlashActionTypes.CreateFlashMessage: return { ...state, message: action.payload }; - case FlashActionTypes.removeFlashMessage: + case FlashActionTypes.RemoveFlashMessage: return { ...state, message: initialState.message }; default: return state; diff --git a/client/src/components/Map/index.tsx b/client/src/components/Map/index.tsx index 34df2a2e38..70d210e789 100644 --- a/client/src/components/Map/index.tsx +++ b/client/src/components/Map/index.tsx @@ -2,9 +2,10 @@ import { graphql, useStaticQuery } from 'gatsby'; import i18next from 'i18next'; import React from 'react'; +import { SuperBlocks } from '../../../../config/certification-settings'; import envData from '../../../../config/env.json'; import { isAuditedCert } from '../../../../utils/is-audited'; -import { generateIconComponent, SuperBlock } from '../../assets/icons'; +import { generateIconComponent } from '../../assets/icons'; import LinkButton from '../../assets/icons/link-button'; import { ChallengeNode } from '../../redux/prop-types'; import { Link, Spacer } from '../helpers'; @@ -14,7 +15,7 @@ import './map.css'; const { curriculumLocale } = envData; interface MapProps { - currentSuperBlock?: string; + currentSuperBlock?: SuperBlocks | null; forLanding?: boolean; } @@ -24,7 +25,7 @@ interface MapData { }; } -function createSuperBlockTitle(superBlock: string) { +function createSuperBlockTitle(superBlock: SuperBlocks) { const superBlockTitle = i18next.t(`intro:${superBlock}.title`); return superBlock === 'coding-interview-prep' ? i18next.t('learn.cert-map-estimates.coding-prep', { @@ -40,7 +41,9 @@ const linkSpacingStyle = { }; function renderLandingMap(nodes: ChallengeNode[]) { - nodes = nodes.filter(node => node.superBlock !== 'coding-interview-prep'); + nodes = nodes.filter( + node => node.superBlock !== SuperBlocks.CodingInterviewPrep + ); return (
    {nodes.map((node, i) => ( @@ -50,7 +53,7 @@ function renderLandingMap(nodes: ChallengeNode[]) { to={`/learn/${node.superBlock}/`} >
    - {generateIconComponent(node.superBlock as SuperBlock, 'map-icon')} + {generateIconComponent(node.superBlock, 'map-icon')} {i18next.t(`intro:${node.superBlock}.title`)}
    @@ -61,7 +64,10 @@ function renderLandingMap(nodes: ChallengeNode[]) { ); } -function renderLearnMap(nodes: ChallengeNode[], currentSuperBlock = '') { +function renderLearnMap( + nodes: ChallengeNode[], + currentSuperBlock: MapProps['currentSuperBlock'] +) { nodes = nodes.filter(node => node.superBlock !== currentSuperBlock); return curriculumLocale === 'english' ? (
      @@ -72,7 +78,7 @@ function renderLearnMap(nodes: ChallengeNode[], currentSuperBlock = '') { to={`/learn/${node.superBlock}/`} >
      - {generateIconComponent(node.superBlock as SuperBlock, 'map-icon')} + {generateIconComponent(node.superBlock, 'map-icon')} {createSuperBlockTitle(node.superBlock)}
      @@ -90,10 +96,7 @@ function renderLearnMap(nodes: ChallengeNode[], currentSuperBlock = '') { to={`/learn/${node.superBlock}/`} >
      - {generateIconComponent( - node.superBlock as SuperBlock, - 'map-icon' - )} + {generateIconComponent(node.superBlock, 'map-icon')} {createSuperBlockTitle(node.superBlock)}
      @@ -120,10 +123,7 @@ function renderLearnMap(nodes: ChallengeNode[], currentSuperBlock = '') { to={`/learn/${node.superBlock}/`} >
      - {generateIconComponent( - node.superBlock as SuperBlock, - 'map-icon' - )} + {generateIconComponent(node.superBlock, 'map-icon')} {createSuperBlockTitle(node.superBlock)}
      @@ -135,7 +135,7 @@ function renderLearnMap(nodes: ChallengeNode[], currentSuperBlock = '') { export function Map({ forLanding = false, - currentSuperBlock = '' + currentSuperBlock = null }: MapProps): React.ReactElement { /* * this query gets the first challenge from each block and the second block diff --git a/client/src/redux/index.js b/client/src/redux/index.js index 276d06772c..4028f4d8cb 100644 --- a/client/src/redux/index.js +++ b/client/src/redux/index.js @@ -2,6 +2,7 @@ import { uniqBy } from 'lodash-es'; import { createAction, handleActions } from 'redux-actions'; import store from 'store'; +import { SuperBlocks } from '../../../config/certification-settings'; import { actionTypes as challengeTypes } from '../templates/Challenges/redux/action-types'; import { CURRENT_CHALLENGE_KEY } from '../templates/Challenges/redux/current-challenge-saga'; import { createAcceptTermsSaga } from './accept-terms-saga'; @@ -292,27 +293,27 @@ export const certificatesByNameSelector = username => state => { { show: isRespWebDesignCert, title: 'Responsive Web Design Certification', - certSlug: 'responsive-web-design' + certSlug: SuperBlocks.RespWebDesign }, { show: isJsAlgoDataStructCert, title: 'JavaScript Algorithms and Data Structures Certification', - certSlug: 'javascript-algorithms-and-data-structures' + certSlug: SuperBlocks.JsAlgoDataStruct }, { show: isFrontEndLibsCert, title: 'Front End Development Libraries Certification', - certSlug: 'front-end-development-libraries' + certSlug: SuperBlocks.FrontEndDevLibs }, { show: is2018DataVisCert, title: 'Data Visualization Certification', - certSlug: 'data-visualization' + certSlug: SuperBlocks.DataVis }, { show: isApisMicroservicesCert, title: 'Back End Development and APIs Certification', - certSlug: 'back-end-development-and-apis' + certSlug: SuperBlocks.BackEndDevApis }, { show: isQaCertV7, diff --git a/client/src/redux/prop-types.ts b/client/src/redux/prop-types.ts index 3b520df1f8..1ac13fbbac 100644 --- a/client/src/redux/prop-types.ts +++ b/client/src/redux/prop-types.ts @@ -1,5 +1,6 @@ import PropTypes from 'prop-types'; import { HandlerProps } from 'react-reflex'; +import { SuperBlocks } from '../../../config/certification-settings'; export const UserPropType = PropTypes.shape({ about: PropTypes.string, @@ -81,7 +82,7 @@ export type MarkdownRemark = { frontmatter: { block: string; isBeta: boolean; - superBlock: string; + superBlock: SuperBlocks; title: string; }; headings: [ @@ -159,7 +160,7 @@ export type ChallengeNode = { }; sourceInstanceName: string; superOrder: number; - superBlock: string; + superBlock: SuperBlocks; tail: string[]; template: string; tests: Test[]; @@ -302,7 +303,7 @@ export type ChallengeMeta = { nextChallengePath: string; prevChallengePath: string; removeComments: boolean; - superBlock: string; + superBlock: SuperBlocks; title?: string; challengeType?: number; helpCategory: string; diff --git a/client/src/resources/cert-and-project-map.ts b/client/src/resources/cert-and-project-map.ts index 8aa41ba7db..084ce891d7 100644 --- a/client/src/resources/cert-and-project-map.ts +++ b/client/src/resources/cert-and-project-map.ts @@ -1,3 +1,5 @@ +import { SuperBlocks } from '../../../config/certification-settings'; + const responsiveWebBase = '/learn/responsive-web-design/responsive-web-design-projects'; const jsAlgoBase = @@ -289,228 +291,228 @@ const certMap = [ { id: '561add10cb82ac38a17513bc', title: 'Responsive Web Design', - certSlug: 'responsive-web-design', + certSlug: SuperBlocks.RespWebDesign, flag: 'isRespWebDesignCert', projects: [ { id: 'bd7158d8c442eddfaeb5bd18', title: 'Build a Tribute Page', link: `${responsiveWebBase}/build-a-tribute-page`, - certSlug: 'responsive-web-design' + certSlug: SuperBlocks.RespWebDesign }, { id: '587d78af367417b2b2512b03', title: 'Build a Survey Form', link: `${responsiveWebBase}/build-a-survey-form`, - certSlug: 'responsive-web-design' + certSlug: SuperBlocks.RespWebDesign }, { id: '587d78af367417b2b2512b04', title: 'Build a Product Landing Page', link: `${responsiveWebBase}/build-a-product-landing-page`, - certSlug: 'responsive-web-design' + certSlug: SuperBlocks.RespWebDesign }, { id: '587d78b0367417b2b2512b05', title: 'Build a Technical Documentation Page', link: `${responsiveWebBase}/build-a-technical-documentation-page`, - certSlug: 'responsive-web-design' + certSlug: SuperBlocks.RespWebDesign }, { id: 'bd7158d8c242eddfaeb5bd13', title: 'Build a Personal Portfolio Webpage', link: `${responsiveWebBase}/build-a-personal-portfolio-webpage`, - certSlug: 'responsive-web-design' + certSlug: SuperBlocks.RespWebDesign } ] }, { id: '561abd10cb81ac38a17513bc', title: 'JavaScript Algorithms and Data Structures', - certSlug: 'javascript-algorithms-and-data-structures', + certSlug: SuperBlocks.JsAlgoDataStruct, flag: 'isJsAlgoDataStructCert', projects: [ { id: 'aaa48de84e1ecc7c742e1124', title: 'Palindrome Checker', link: `${jsAlgoBase}/palindrome-checker`, - certSlug: 'javascript-algorithms-and-data-structures' + certSlug: SuperBlocks.JsAlgoDataStruct }, { id: 'a7f4d8f2483413a6ce226cac', title: 'Roman Numeral Converter', link: `${jsAlgoBase}/roman-numeral-converter`, - certSlug: 'javascript-algorithms-and-data-structures' + certSlug: SuperBlocks.JsAlgoDataStruct }, { id: '56533eb9ac21ba0edf2244e2', title: 'Caesars Cipher', link: `${jsAlgoBase}/caesars-cipher`, - certSlug: 'javascript-algorithms-and-data-structures' + certSlug: SuperBlocks.JsAlgoDataStruct }, { id: 'aff0395860f5d3034dc0bfc9', title: 'Telephone Number Validator', link: `${jsAlgoBase}/telephone-number-validator`, - certSlug: 'javascript-algorithms-and-data-structures' + certSlug: SuperBlocks.JsAlgoDataStruct }, { id: 'aa2e6f85cab2ab736c9a9b24', title: 'Cash Register', link: `${jsAlgoBase}/cash-register`, - certSlug: 'javascript-algorithms-and-data-structures' + certSlug: SuperBlocks.JsAlgoDataStruct } ] }, { id: '561acd10cb82ac38a17513bc', title: 'Front End Development Libraries', - certSlug: 'front-end-development-libraries', + certSlug: SuperBlocks.FrontEndDevLibs, flag: 'isFrontEndLibsCert', projects: [ { id: 'bd7158d8c442eddfaeb5bd13', title: 'Build a Random Quote Machine', link: `${feLibsBase}/build-a-random-quote-machine`, - certSlug: 'front-end-development-libraries' + certSlug: SuperBlocks.FrontEndDevLibs }, { id: 'bd7157d8c242eddfaeb5bd13', title: 'Build a Markdown Previewer', link: `${feLibsBase}/build-a-markdown-previewer`, - certSlug: 'front-end-development-libraries' + certSlug: SuperBlocks.FrontEndDevLibs }, { id: '587d7dbc367417b2b2512bae', title: 'Build a Drum Machine', link: `${feLibsBase}/build-a-drum-machine`, - certSlug: 'front-end-development-libraries' + certSlug: SuperBlocks.FrontEndDevLibs }, { id: 'bd7158d8c442eddfaeb5bd17', title: 'Build a JavaScript Calculator', link: `${feLibsBase}/build-a-javascript-calculator`, - certSlug: 'front-end-development-libraries' + certSlug: SuperBlocks.FrontEndDevLibs }, { id: 'bd7158d8c442eddfaeb5bd0f', title: 'Build a 25 + 5 Clock', link: `${feLibsBase}/build-a-25--5-clock`, - certSlug: 'front-end-development-libraries' + certSlug: SuperBlocks.FrontEndDevLibs } ] }, { id: '5a553ca864b52e1d8bceea14', title: 'Data Visualization', - certSlug: 'data-visualization', + certSlug: SuperBlocks.DataVis, flag: 'is2018DataVisCert', projects: [ { id: 'bd7168d8c242eddfaeb5bd13', title: 'Visualize Data with a Bar Chart', link: `${dataVisBase}/visualize-data-with-a-bar-chart`, - certSlug: 'data-visualization' + certSlug: SuperBlocks.DataVis }, { id: 'bd7178d8c242eddfaeb5bd13', title: 'Visualize Data with a Scatterplot Graph', link: `${dataVisBase}/visualize-data-with-a-scatterplot-graph`, - certSlug: 'data-visualization' + certSlug: SuperBlocks.DataVis }, { id: 'bd7188d8c242eddfaeb5bd13', title: 'Visualize Data with a Heat Map', link: `${dataVisBase}/visualize-data-with-a-heat-map`, - certSlug: 'data-visualization' + certSlug: SuperBlocks.DataVis }, { id: '587d7fa6367417b2b2512bbf', title: 'Visualize Data with a Choropleth Map', link: `${dataVisBase}/visualize-data-with-a-choropleth-map`, - certSlug: 'data-visualization' + certSlug: SuperBlocks.DataVis }, { id: '587d7fa6367417b2b2512bc0', title: 'Visualize Data with a Treemap Diagram', link: `${dataVisBase}/visualize-data-with-a-treemap-diagram`, - certSlug: 'data-visualization' + certSlug: SuperBlocks.DataVis } ] }, { id: '606243f50267e718b1e755f4', title: 'Relational Databases', - certSlug: 'relational-databases', + certSlug: SuperBlocks.RelationalDb, flag: 'isRelationalDatabasesCert', projects: [ { id: '5f1a4ef5d5d6b5ab580fc6ae', title: 'Celestial Bodies Database', link: `${relationalDatabasesBase}/celestial-bodies-database`, - superBlock: 'relational-databases' + superBlock: SuperBlocks.RelationalDb }, { id: '5f87ac112ae598023a42df1a', title: 'Salon Appointment Scheduler', link: `${relationalDatabasesBase}/salon-appointment-scheduler`, - superBlock: 'relational-databases' + superBlock: SuperBlocks.RelationalDb }, { id: '5f9771307d4d22b9d2b75a94', title: 'World Cup Database', link: `${relationalDatabasesBase}/world-cup-database`, - superBlock: 'relational-databases' + superBlock: SuperBlocks.RelationalDb }, { id: '602d9ff222201c65d2a019f2', title: 'Periodic Table Database', link: `${relationalDatabasesBase}/periodic-table-database`, - superBlock: 'relational-databases' + superBlock: SuperBlocks.RelationalDb }, { id: '602da04c22201c65d2a019f4', title: 'Number Guessing Game', link: `${relationalDatabasesBase}/number-guessing-game`, - superBlock: 'relational-databases' + superBlock: SuperBlocks.RelationalDb } ] }, { id: '561add10cb82ac38a17523bc', title: 'Back End Development and APIs', - certSlug: 'back-end-development-and-apis', + certSlug: SuperBlocks.BackEndDevApis, flag: 'isApisMicroservicesCert', projects: [ { id: 'bd7158d8c443edefaeb5bdef', title: 'Timestamp Microservice', link: `${apiMicroBase}/timestamp-microservice`, - certSlug: 'back-end-development-and-apis' + certSlug: SuperBlocks.BackEndDevApis }, { id: 'bd7158d8c443edefaeb5bdff', title: 'Request Header Parser Microservice', link: `${apiMicroBase}/request-header-parser-microservice`, - certSlug: 'back-end-development-and-apis' + certSlug: SuperBlocks.BackEndDevApis }, { id: 'bd7158d8c443edefaeb5bd0e', title: 'URL Shortener Microservice', link: `${apiMicroBase}/url-shortener-microservice`, - certSlug: 'back-end-development-and-apis' + certSlug: SuperBlocks.BackEndDevApis }, { id: '5a8b073d06fa14fcfde687aa', title: 'Exercise Tracker', link: `${apiMicroBase}/exercise-tracker`, - certSlug: 'back-end-development-and-apis' + certSlug: SuperBlocks.BackEndDevApis }, { id: 'bd7158d8c443edefaeb5bd0f', title: 'File Metadata Microservice', link: `${apiMicroBase}/file-metadata-microservice`, - certSlug: 'back-end-development-and-apis' + certSlug: SuperBlocks.BackEndDevApis } ] }, diff --git a/client/src/templates/Challenges/classic/show.tsx b/client/src/templates/Challenges/classic/show.tsx index 2b7dc13a66..dd975d58e3 100644 --- a/client/src/templates/Challenges/classic/show.tsx +++ b/client/src/templates/Challenges/classic/show.tsx @@ -333,7 +333,6 @@ class ShowClassic extends Component { containerRef={this.containerRef} description={description} editorRef={this.editorRef} - hasEditableBoundaries={this.hasEditableBoundaries()} initialTests={tests} resizeProps={this.resizeProps} title={title} diff --git a/client/src/templates/Challenges/components/completion-modal-body.test.tsx b/client/src/templates/Challenges/components/completion-modal-body.test.tsx index af1d8fd617..04d9a4a40b 100644 --- a/client/src/templates/Challenges/components/completion-modal-body.test.tsx +++ b/client/src/templates/Challenges/components/completion-modal-body.test.tsx @@ -1,12 +1,14 @@ import { render, fireEvent, screen } from '@testing-library/react'; import React from 'react'; +import { SuperBlocks } from '../../../../../config/certification-settings'; + import CompletionModalBody from './completion-modal-body'; const props = { block: 'basic-html-and-html5', completedPercent: Math.floor(Math.random() * 101), - superBlock: 'responsive-web-design' + superBlock: SuperBlocks.RespWebDesign }; describe('', () => { diff --git a/client/src/templates/Introduction/super-block-intro.tsx b/client/src/templates/Introduction/super-block-intro.tsx index 256e5eaaf5..2e631bd6c0 100644 --- a/client/src/templates/Introduction/super-block-intro.tsx +++ b/client/src/templates/Introduction/super-block-intro.tsx @@ -10,6 +10,7 @@ import { configureAnchors } from 'react-scrollable-anchor'; import { bindActionCreators, Dispatch } from 'redux'; import { createSelector } from 'reselect'; +import { SuperBlocks } from '../../../../config/certification-settings'; import DonateModal from '../../components/Donation/DonationModal'; import Login from '../../components/Header/components/Login'; import Map from '../../components/Map'; @@ -172,7 +173,7 @@ const SuperBlockIntroductionPage = (props: SuperBlockProp) => { const blockDashedNames = uniq(nodesForSuperBlock.map(({ block }) => block)); const i18nSuperBlock = t(`intro:${superBlock}.title`); const i18nTitle = - superBlock === 'coding-interview-prep' + superBlock === SuperBlocks.CodingInterviewPrep ? i18nSuperBlock : t(`intro:misc-text.certification`, { cert: i18nSuperBlock @@ -209,7 +210,7 @@ const SuperBlockIntroductionPage = (props: SuperBlockProp) => { {blockDashedName !== 'project-euler' ? : null} ))} - {superBlock !== 'coding-interview-prep' && ( + {superBlock !== SuperBlocks.CodingInterviewPrep && (
      { cy.login(); cy.fixture('../../config/curriculum.json').then(curriculum => { const { challenges, meta } = - curriculum['javascript-algorithms-and-data-structures'].blocks[ + curriculum[SuperBlocks.JsAlgoDataStruct].blocks[ 'javascript-algorithms-and-data-structures-projects' ]; diff --git a/cypress/integration/learn/responsive-web-design/claim-cert-from-learn.js b/cypress/integration/learn/responsive-web-design/claim-cert-from-learn.js index f98d84d3db..49aaecfc5a 100644 --- a/cypress/integration/learn/responsive-web-design/claim-cert-from-learn.js +++ b/cypress/integration/learn/responsive-web-design/claim-cert-from-learn.js @@ -1,5 +1,7 @@ +import { SuperBlocks } from '../../../../config/certification-settings'; + const projects = { - superBlock: 'responsive-web-design', + superBlock: SuperBlocks.RespWebDesign, block: 'responsive-web-design-projects', challenges: [ { diff --git a/package-lock.json b/package-lock.json index 791205ed5e..f9ebb77bfb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,29 @@ "@testing-library/dom": "8.11.1", "@testing-library/jest-dom": "5.15.0", "@testing-library/user-event": "13.5.0", + "@types/chai": "^4.2.22", + "@types/inquirer": "^8.1.3", + "@types/jest": "^27.0.2", + "@types/loadable__component": "^5.13.4", + "@types/lodash-es": "^4.17.5", + "@types/node": "^16.11.7", + "@types/prismjs": "^1.16.6", + "@types/psl": "^1.1.0", + "@types/reach__router": "^1.3.9", + "@types/react": "^17.0.35", + "@types/react-dom": "^17.0.11", + "@types/react-helmet": "^6.1.4", + "@types/react-instantsearch-dom": "^6.12.0", + "@types/react-monaco-editor": "^0.16.0", + "@types/react-redux": "^7.1.20", + "@types/react-responsive": "^8.0.4", + "@types/react-spinkit": "^3.0.7", + "@types/react-test-renderer": "^17.0.1", + "@types/react-transition-group": "^4.4.4", + "@types/redux-actions": "^2.6.2", + "@types/sanitize-html": "^2.5.0", + "@types/store": "^2.0.2", + "@types/validator": "^13.7.0", "@typescript-eslint/eslint-plugin": "4.33.0", "@typescript-eslint/parser": "4.33.0", "babel-eslint": "10.1.0", @@ -63,6 +86,135 @@ "npm": ">=8" } }, + "node_modules/@algolia/cache-browser-local-storage": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.11.0.tgz", + "integrity": "sha512-4sr9vHIG1fVA9dONagdzhsI/6M5mjs/qOe2xUP0yBmwsTsuwiZq3+Xu6D3dsxsuFetcJgC6ydQoCW8b7fDJHYQ==", + "dev": true, + "dependencies": { + "@algolia/cache-common": "4.11.0" + } + }, + "node_modules/@algolia/cache-common": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.11.0.tgz", + "integrity": "sha512-lODcJRuPXqf+6mp0h6bOxPMlbNoyn3VfjBVcQh70EDP0/xExZbkpecgHyyZK4kWg+evu+mmgvTK3GVHnet/xKw==", + "dev": true + }, + "node_modules/@algolia/cache-in-memory": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.11.0.tgz", + "integrity": "sha512-aBz+stMSTBOBaBEQ43zJXz2DnwS7fL6dR0e2myehAgtfAWlWwLDHruc/98VOy1ZAcBk1blE2LCU02bT5HekGxQ==", + "dev": true, + "dependencies": { + "@algolia/cache-common": "4.11.0" + } + }, + "node_modules/@algolia/client-account": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.11.0.tgz", + "integrity": "sha512-jwmFBoUSzoMwMqgD3PmzFJV/d19p1RJXB6C1ADz4ju4mU7rkaQLtqyZroQpheLoU5s5Tilmn/T8/0U2XLoJCRQ==", + "dev": true, + "dependencies": { + "@algolia/client-common": "4.11.0", + "@algolia/client-search": "4.11.0", + "@algolia/transporter": "4.11.0" + } + }, + "node_modules/@algolia/client-analytics": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.11.0.tgz", + "integrity": "sha512-v5U9585aeEdYml7JqggHAj3E5CQ+jPwGVztPVhakBk8H/cmLyPS2g8wvmIbaEZCHmWn4TqFj3EBHVYxAl36fSA==", + "dev": true, + "dependencies": { + "@algolia/client-common": "4.11.0", + "@algolia/client-search": "4.11.0", + "@algolia/requester-common": "4.11.0", + "@algolia/transporter": "4.11.0" + } + }, + "node_modules/@algolia/client-common": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.11.0.tgz", + "integrity": "sha512-Qy+F+TZq12kc7tgfC+FM3RvYH/Ati7sUiUv/LkvlxFwNwNPwWGoZO81AzVSareXT/ksDDrabD4mHbdTbBPTRmQ==", + "dev": true, + "dependencies": { + "@algolia/requester-common": "4.11.0", + "@algolia/transporter": "4.11.0" + } + }, + "node_modules/@algolia/client-personalization": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.11.0.tgz", + "integrity": "sha512-mI+X5IKiijHAzf9fy8VSl/GTT67dzFDnJ0QAM8D9cMPevnfX4U72HRln3Mjd0xEaYUOGve8TK/fMg7d3Z5yG6g==", + "dev": true, + "dependencies": { + "@algolia/client-common": "4.11.0", + "@algolia/requester-common": "4.11.0", + "@algolia/transporter": "4.11.0" + } + }, + "node_modules/@algolia/client-search": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.11.0.tgz", + "integrity": "sha512-iovPLc5YgiXBdw2qMhU65sINgo9umWbHFzInxoNErWnYoTQWfXsW6P54/NlKx5uscoLVjSf+5RUWwFu5BX+lpw==", + "dev": true, + "dependencies": { + "@algolia/client-common": "4.11.0", + "@algolia/requester-common": "4.11.0", + "@algolia/transporter": "4.11.0" + } + }, + "node_modules/@algolia/logger-common": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.11.0.tgz", + "integrity": "sha512-pRMJFeOY8hoWKIxWuGHIrqnEKN/kqKh7UilDffG/+PeEGxBuku+Wq5CfdTFG0C9ewUvn8mAJn5BhYA5k8y0Jqg==", + "dev": true + }, + "node_modules/@algolia/logger-console": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.11.0.tgz", + "integrity": "sha512-wXztMk0a3VbNmYP8Kpc+F7ekuvaqZmozM2eTLok0XIshpAeZ/NJDHDffXK2Pw+NF0wmHqurptLYwKoikjBYvhQ==", + "dev": true, + "dependencies": { + "@algolia/logger-common": "4.11.0" + } + }, + "node_modules/@algolia/requester-browser-xhr": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.11.0.tgz", + "integrity": "sha512-Fp3SfDihAAFR8bllg8P5ouWi3+qpEVN5e7hrtVIYldKBOuI/qFv80Zv/3/AMKNJQRYglS4zWyPuqrXm58nz6KA==", + "dev": true, + "dependencies": { + "@algolia/requester-common": "4.11.0" + } + }, + "node_modules/@algolia/requester-common": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.11.0.tgz", + "integrity": "sha512-+cZGe/9fuYgGuxjaBC+xTGBkK7OIYdfapxhfvEf03dviLMPmhmVYFJtJlzAjQ2YmGDJpHrGgAYj3i/fbs8yhiA==", + "dev": true + }, + "node_modules/@algolia/requester-node-http": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.11.0.tgz", + "integrity": "sha512-qJIk9SHRFkKDi6dMT9hba8X1J1z92T5AZIgl+tsApjTGIRQXJLTIm+0q4yOefokfu4CoxYwRZ9QAq+ouGwfeOg==", + "dev": true, + "dependencies": { + "@algolia/requester-common": "4.11.0" + } + }, + "node_modules/@algolia/transporter": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.11.0.tgz", + "integrity": "sha512-k4dyxiaEfYpw4UqybK9q7lrFzehygo6KV3OCYJMMdX0IMWV0m4DXdU27c1zYRYtthaFYaBzGF4Kjcl8p8vxCKw==", + "dev": true, + "dependencies": { + "@algolia/cache-common": "4.11.0", + "@algolia/logger-common": "4.11.0", + "@algolia/requester-common": "4.11.0" + } + }, "node_modules/@babel/code-frame": { "version": "7.12.11", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", @@ -6779,6 +6931,12 @@ "@babel/types": "^7.3.0" } }, + "node_modules/@types/chai": { + "version": "4.2.22", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.22.tgz", + "integrity": "sha512-tFfcE+DSTzWAgifkjik9AySNqIyNoYwmR+uecPwwD/XRNfvOjmC/FjCxpiUGDkDVDphPfCUecSQVFw+lN3M3kQ==", + "dev": true + }, "node_modules/@types/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", @@ -6798,6 +6956,41 @@ "@types/node": "*" } }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", + "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "dev": true, + "dependencies": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, + "node_modules/@types/inquirer": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-8.1.3.tgz", + "integrity": "sha512-AayK4ZL5ssPzR1OtnOLGAwpT0Dda3Xi/h1G0l1oJDNrowp7T1423q4Zb8/emr7tzRlCy4ssEri0LWVexAqHyKQ==", + "dev": true, + "dependencies": { + "@types/through": "*", + "rxjs": "^7.2.0" + } + }, + "node_modules/@types/inquirer/node_modules/rxjs": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.4.0.tgz", + "integrity": "sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w==", + "dev": true, + "dependencies": { + "tslib": "~2.1.0" + } + }, + "node_modules/@types/inquirer/node_modules/tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", + "dev": true + }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", @@ -6981,6 +7174,30 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "node_modules/@types/loadable__component": { + "version": "5.13.4", + "resolved": "https://registry.npmjs.org/@types/loadable__component/-/loadable__component-5.13.4.tgz", + "integrity": "sha512-YhoCCxyuvP2XeZNbHbi8Wb9EMaUJuA2VGHxJffcQYrJKIKSkymJrhbzsf9y4zpTmr5pExAAEh5hbF628PAZ8Dg==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/lodash": { + "version": "4.14.177", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.177.tgz", + "integrity": "sha512-0fDwydE2clKe9MNfvXHBHF9WEahRuj+msTuQqOmAApNORFvhMYZKNGGJdCzuhheVjMps/ti0Ak/iJPACMaevvw==", + "dev": true + }, + "node_modules/@types/lodash-es": { + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.5.tgz", + "integrity": "sha512-SHBoI8/0aoMQWAgUHMQ599VM6ZiSKg8sh/0cFqqlQQMyY9uEplc0ULU5yQNzcvdR4ZKa0ey8+vFmahuRbOCT1A==", + "dev": true, + "dependencies": { + "@types/lodash": "*" + } + }, "node_modules/@types/minimatch": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", @@ -6993,6 +7210,12 @@ "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", "dev": true }, + "node_modules/@types/node": { + "version": "16.11.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.7.tgz", + "integrity": "sha512-QB5D2sqfSjCmTuWcBWyJ+/44bcjO7VbjSbOE0ucoVbAsSNQc4Lt6QkgkVXkTDwkL4z/beecZNDvVX15D4P8Jbw==", + "dev": true + }, "node_modules/@types/normalize-package-data": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", @@ -7011,6 +7234,162 @@ "integrity": "sha512-Fo79ojj3vdEZOHg3wR9ksAMRz4P3S5fDB5e/YWZiFnyFQI1WY2Vftu9XoXVVtJfxB7Bpce/QTqWSSntkz2Znrw==", "dev": true }, + "node_modules/@types/prismjs": { + "version": "1.16.6", + "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.16.6.tgz", + "integrity": "sha512-dTvnamRITNqNkqhlBd235kZl3KfVJQQoT5jkXeiWSBK7i4/TLKBNLV0S1wOt8gy4E2TY722KLtdmv2xc6+Wevg==", + "dev": true + }, + "node_modules/@types/prop-types": { + "version": "15.7.4", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz", + "integrity": "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==", + "dev": true + }, + "node_modules/@types/psl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@types/psl/-/psl-1.1.0.tgz", + "integrity": "sha512-HhZnoLAvI2koev3czVPzBNRYvdrzJGLjQbWZhqFmS9Q6a0yumc5qtfSahBGb5g+6qWvA8iiQktqGkwoIXa/BNQ==", + "dev": true + }, + "node_modules/@types/reach__router": { + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/@types/reach__router/-/reach__router-1.3.9.tgz", + "integrity": "sha512-N6rqQqTTAV/zKLfK3iq9Ww3wqCEhTZvsilhl0zI09zETdVq1QGmJH6+/xnj8AFUWIrle2Cqo+PGM/Ltr1vBb9w==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.35.tgz", + "integrity": "sha512-r3C8/TJuri/SLZiiwwxQoLAoavaczARfT9up9b4Jr65+ErAUX3MIkU0oMOQnrpfgHme8zIqZLX7O5nnjm5Wayw==", + "dev": true, + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "17.0.11", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.11.tgz", + "integrity": "sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-helmet": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@types/react-helmet/-/react-helmet-6.1.4.tgz", + "integrity": "sha512-jyx50RNZXVaTGHY3MsoRPNpeiVk8b0XTPgD/O6KHF6COTDnG/+lRjPYvTK5nfWtR3xDOux0w6bHLAsaHo2ZLTA==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-instantsearch-core": { + "version": "6.10.5", + "resolved": "https://registry.npmjs.org/@types/react-instantsearch-core/-/react-instantsearch-core-6.10.5.tgz", + "integrity": "sha512-VjXJFUfsPdWMSiugJiQc950G9ZRjCEIzqQ9/K915d1f1BsVE2TE57PcfHSxAy1pGDDR8FT5uAgAaOMyKJ66NJQ==", + "dev": true, + "dependencies": { + "@types/react": "*", + "algoliasearch": ">=4", + "algoliasearch-helper": ">=3" + } + }, + "node_modules/@types/react-instantsearch-dom": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@types/react-instantsearch-dom/-/react-instantsearch-dom-6.12.0.tgz", + "integrity": "sha512-O08H+ye4e4kEnYHmMrov9FPNRDJwfCWthNZf4aztqahpU8LSbAiuFQGVy84SHUvg/jfNcG4333SsVnAQLtbS7A==", + "dev": true, + "dependencies": { + "@types/react": "*", + "@types/react-instantsearch-core": "*" + } + }, + "node_modules/@types/react-monaco-editor": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@types/react-monaco-editor/-/react-monaco-editor-0.16.0.tgz", + "integrity": "sha512-3YxNIyZ+mlU6WN9UfQ/T66LYjHH3ZWOK4csfefkkXdDmUbHDbuDpfmVSYyJt1W0wlwhcfu4zc7BMwYrimN/GUg==", + "deprecated": "This is a stub types definition. react-monaco-editor provides its own type definitions, so you don't need this installed.", + "dev": true, + "dependencies": { + "react-monaco-editor": "*" + } + }, + "node_modules/@types/react-redux": { + "version": "7.1.20", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.20.tgz", + "integrity": "sha512-q42es4c8iIeTgcnB+yJgRTTzftv3eYYvCZOh1Ckn2eX/3o5TdsQYKUWpLoLuGlcY/p+VAhV9IOEZJcWk/vfkXw==", + "dev": true, + "dependencies": { + "@types/hoist-non-react-statics": "^3.3.0", + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0", + "redux": "^4.0.0" + } + }, + "node_modules/@types/react-responsive": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/@types/react-responsive/-/react-responsive-8.0.4.tgz", + "integrity": "sha512-/IrXSbm5aeSvtAD2vFGgPpQsHRQEJ2eWr6EdPEBPlTvad/qJYjXZax4CfOi5xCM5fjq/xpNW3WIHwKOrcdIGcA==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-spinkit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/react-spinkit/-/react-spinkit-3.0.7.tgz", + "integrity": "sha512-y/Jnzx/WCJ8QpkL4hJ0umfhApV9tEmuiN4XKentBCBhAkxERD7hNACJaH7VUzCyhE7LkVYTq8l1vmlK1o+PhuA==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-test-renderer": { + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-17.0.1.tgz", + "integrity": "sha512-3Fi2O6Zzq/f3QR9dRnlnHso9bMl7weKCviFmfF6B4LS1Uat6Hkm15k0ZAQuDz+UBq6B3+g+NM6IT2nr5QgPzCw==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-transition-group": { + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.4.tgz", + "integrity": "sha512-7gAPz7anVK5xzbeQW9wFBDg7G++aPLAFY0QaSMOou9rJZpbuI58WAuJrgu+qR92l61grlnCUe7AFX8KGahAgug==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/redux-actions": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@types/redux-actions/-/redux-actions-2.6.2.tgz", + "integrity": "sha512-TvcINy8rWFANcpc3EiEQX9Yv3owM3d3KIrqr2ryUIOhYIYzXA/bhDZeGSSSuai62iVR2qMZUgz9tQ5kr0Kl+Tg==", + "dev": true + }, + "node_modules/@types/sanitize-html": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@types/sanitize-html/-/sanitize-html-2.5.0.tgz", + "integrity": "sha512-PeFIEZsO9m1+ACJlXUaimgrR+5DEDiIXhz7Hso307jmq5Yz0lb5kDp8LiTr5dMMMliC/jNNx/qds7Zoxa4zexw==", + "dev": true, + "dependencies": { + "htmlparser2": "^6.0.0" + } + }, + "node_modules/@types/scheduler": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", + "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", + "dev": true + }, "node_modules/@types/sinonjs__fake-timers": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.3.tgz", @@ -7029,6 +7408,12 @@ "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, + "node_modules/@types/store": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/store/-/store-2.0.2.tgz", + "integrity": "sha512-ZPHnXkzmGMfk+pHqAGzTSpA9CbsHmJLgkvOl5w52LZ0XTxB1ZIHWZzQ7lEtjTNWScBbsQekg8TjApMXkMe4nkw==", + "dev": true + }, "node_modules/@types/testing-library__jest-dom": { "version": "5.14.0", "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.0.tgz", @@ -7038,6 +7423,21 @@ "@types/jest": "*" } }, + "node_modules/@types/through": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.30.tgz", + "integrity": "sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/validator": { + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.0.tgz", + "integrity": "sha512-+jBxVvXVuggZOrm04NR8z+5+bgoW4VZyLzUO+hmPPW1mVFL/HaitLAkizfv4yg9TbG8lkfHWVMQ11yDqrVVCzA==", + "dev": true + }, "node_modules/@types/yargs": { "version": "15.0.13", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.13.tgz", @@ -7790,6 +8190,40 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/algoliasearch": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.11.0.tgz", + "integrity": "sha512-IXRj8kAP2WrMmj+eoPqPc6P7Ncq1yZkFiyDrjTBObV1ADNL8Z/KdZ+dWC5MmYcBLAbcB/mMCpak5N/D1UIZvsA==", + "dev": true, + "dependencies": { + "@algolia/cache-browser-local-storage": "4.11.0", + "@algolia/cache-common": "4.11.0", + "@algolia/cache-in-memory": "4.11.0", + "@algolia/client-account": "4.11.0", + "@algolia/client-analytics": "4.11.0", + "@algolia/client-common": "4.11.0", + "@algolia/client-personalization": "4.11.0", + "@algolia/client-search": "4.11.0", + "@algolia/logger-common": "4.11.0", + "@algolia/logger-console": "4.11.0", + "@algolia/requester-browser-xhr": "4.11.0", + "@algolia/requester-common": "4.11.0", + "@algolia/requester-node-http": "4.11.0", + "@algolia/transporter": "4.11.0" + } + }, + "node_modules/algoliasearch-helper": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.6.2.tgz", + "integrity": "sha512-Xx0NOA6k4ySn+R2l3UMSONAaMkyfmrZ3AP1geEMo32MxDJQJesZABZYsldO9fa6FKQxH91afhi4hO1G0Zc2opg==", + "dev": true, + "dependencies": { + "events": "^1.1.1" + }, + "peerDependencies": { + "algoliasearch": ">= 3.1 < 5" + } + }, "node_modules/ansi-align": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", @@ -10295,6 +10729,12 @@ "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", "dev": true }, + "node_modules/csstype": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz", + "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==", + "dev": true + }, "node_modules/currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -10369,6 +10809,12 @@ "node": ">=12.0.0" } }, + "node_modules/cypress/node_modules/@types/node": { + "version": "14.17.33", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.33.tgz", + "integrity": "sha512-noEeJ06zbn3lOh4gqe2v7NMGS33jrulfNqYFDjjEbhpDEHR5VTxgYNQSBqBlJIsBJW3uEYDgD6kvMnrrhGzq8g==", + "dev": true + }, "node_modules/cypress/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -11022,6 +11468,32 @@ "integrity": "sha512-Xu9mD0UjrJisTmv7lmVSDMagQcU9R5hwAbxsaAE/35XPnPLJobbuREfV/rraiSaEj/UOvgrzQs66zyTWTlyd+g==", "dev": true }, + "node_modules/dom-serializer": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", + "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, "node_modules/domexception": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", @@ -11043,12 +11515,41 @@ "node": ">=8" } }, + "node_modules/domhandler": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.2.tgz", + "integrity": "sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w==", + "dev": true, + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, "node_modules/dompurify": { "version": "2.2.6", "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.2.6.tgz", "integrity": "sha512-7b7ZArhhH0SP6W2R9cqK6RjaU82FZ2UPM7RO8qN1b1wyvC/NY1FNWcX1Pu00fFOAnzEORtwXe4bPaClg6pUybQ==", "dev": true }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, "node_modules/dot-prop": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.1.tgz", @@ -12193,6 +12694,15 @@ "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", "dev": true }, + "node_modules/events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -14382,6 +14892,15 @@ "node": ">=8" } }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dev": true, + "dependencies": { + "react-is": "^16.7.0" + } + }, "node_modules/hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", @@ -14406,6 +14925,25 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, "node_modules/http-cache-semantics": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", @@ -20736,6 +21274,13 @@ "node": ">=0.10.0" } }, + "node_modules/monaco-editor": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.28.1.tgz", + "integrity": "sha512-P1vPqxB4B1ZFzTeR1ScggSp9/5NoQrLCq88fnlNUsuRAP1usEBN4TIpI2lw0AYIZNVIanHk0qwjze2uJwGOHUw==", + "dev": true, + "peer": true + }, "node_modules/move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -22505,12 +23050,40 @@ "rc": "cli.js" } }, + "node_modules/react": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", + "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "dev": true, + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "dev": true }, + "node_modules/react-monaco-editor": { + "version": "0.46.0", + "resolved": "https://registry.npmjs.org/react-monaco-editor/-/react-monaco-editor-0.46.0.tgz", + "integrity": "sha512-/GyQ0tQLbjHAuMUNRfKecBYN68o8TwA4fnwH9P+lHbF80ayMAo0PQ60joTQH6R6j839kMn6o9Kk/cbzOxK5DzA==", + "dev": true, + "dependencies": { + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "@types/react": "^17.x", + "monaco-editor": "^0.28.1", + "react": "^17.x" + } + }, "node_modules/read": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", @@ -22654,6 +23227,15 @@ "node": ">=8" } }, + "node_modules/redux": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.2.tgz", + "integrity": "sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.9.2" + } + }, "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -26165,6 +26747,135 @@ } }, "dependencies": { + "@algolia/cache-browser-local-storage": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.11.0.tgz", + "integrity": "sha512-4sr9vHIG1fVA9dONagdzhsI/6M5mjs/qOe2xUP0yBmwsTsuwiZq3+Xu6D3dsxsuFetcJgC6ydQoCW8b7fDJHYQ==", + "dev": true, + "requires": { + "@algolia/cache-common": "4.11.0" + } + }, + "@algolia/cache-common": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.11.0.tgz", + "integrity": "sha512-lODcJRuPXqf+6mp0h6bOxPMlbNoyn3VfjBVcQh70EDP0/xExZbkpecgHyyZK4kWg+evu+mmgvTK3GVHnet/xKw==", + "dev": true + }, + "@algolia/cache-in-memory": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.11.0.tgz", + "integrity": "sha512-aBz+stMSTBOBaBEQ43zJXz2DnwS7fL6dR0e2myehAgtfAWlWwLDHruc/98VOy1ZAcBk1blE2LCU02bT5HekGxQ==", + "dev": true, + "requires": { + "@algolia/cache-common": "4.11.0" + } + }, + "@algolia/client-account": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.11.0.tgz", + "integrity": "sha512-jwmFBoUSzoMwMqgD3PmzFJV/d19p1RJXB6C1ADz4ju4mU7rkaQLtqyZroQpheLoU5s5Tilmn/T8/0U2XLoJCRQ==", + "dev": true, + "requires": { + "@algolia/client-common": "4.11.0", + "@algolia/client-search": "4.11.0", + "@algolia/transporter": "4.11.0" + } + }, + "@algolia/client-analytics": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.11.0.tgz", + "integrity": "sha512-v5U9585aeEdYml7JqggHAj3E5CQ+jPwGVztPVhakBk8H/cmLyPS2g8wvmIbaEZCHmWn4TqFj3EBHVYxAl36fSA==", + "dev": true, + "requires": { + "@algolia/client-common": "4.11.0", + "@algolia/client-search": "4.11.0", + "@algolia/requester-common": "4.11.0", + "@algolia/transporter": "4.11.0" + } + }, + "@algolia/client-common": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.11.0.tgz", + "integrity": "sha512-Qy+F+TZq12kc7tgfC+FM3RvYH/Ati7sUiUv/LkvlxFwNwNPwWGoZO81AzVSareXT/ksDDrabD4mHbdTbBPTRmQ==", + "dev": true, + "requires": { + "@algolia/requester-common": "4.11.0", + "@algolia/transporter": "4.11.0" + } + }, + "@algolia/client-personalization": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.11.0.tgz", + "integrity": "sha512-mI+X5IKiijHAzf9fy8VSl/GTT67dzFDnJ0QAM8D9cMPevnfX4U72HRln3Mjd0xEaYUOGve8TK/fMg7d3Z5yG6g==", + "dev": true, + "requires": { + "@algolia/client-common": "4.11.0", + "@algolia/requester-common": "4.11.0", + "@algolia/transporter": "4.11.0" + } + }, + "@algolia/client-search": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.11.0.tgz", + "integrity": "sha512-iovPLc5YgiXBdw2qMhU65sINgo9umWbHFzInxoNErWnYoTQWfXsW6P54/NlKx5uscoLVjSf+5RUWwFu5BX+lpw==", + "dev": true, + "requires": { + "@algolia/client-common": "4.11.0", + "@algolia/requester-common": "4.11.0", + "@algolia/transporter": "4.11.0" + } + }, + "@algolia/logger-common": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.11.0.tgz", + "integrity": "sha512-pRMJFeOY8hoWKIxWuGHIrqnEKN/kqKh7UilDffG/+PeEGxBuku+Wq5CfdTFG0C9ewUvn8mAJn5BhYA5k8y0Jqg==", + "dev": true + }, + "@algolia/logger-console": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.11.0.tgz", + "integrity": "sha512-wXztMk0a3VbNmYP8Kpc+F7ekuvaqZmozM2eTLok0XIshpAeZ/NJDHDffXK2Pw+NF0wmHqurptLYwKoikjBYvhQ==", + "dev": true, + "requires": { + "@algolia/logger-common": "4.11.0" + } + }, + "@algolia/requester-browser-xhr": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.11.0.tgz", + "integrity": "sha512-Fp3SfDihAAFR8bllg8P5ouWi3+qpEVN5e7hrtVIYldKBOuI/qFv80Zv/3/AMKNJQRYglS4zWyPuqrXm58nz6KA==", + "dev": true, + "requires": { + "@algolia/requester-common": "4.11.0" + } + }, + "@algolia/requester-common": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.11.0.tgz", + "integrity": "sha512-+cZGe/9fuYgGuxjaBC+xTGBkK7OIYdfapxhfvEf03dviLMPmhmVYFJtJlzAjQ2YmGDJpHrGgAYj3i/fbs8yhiA==", + "dev": true + }, + "@algolia/requester-node-http": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.11.0.tgz", + "integrity": "sha512-qJIk9SHRFkKDi6dMT9hba8X1J1z92T5AZIgl+tsApjTGIRQXJLTIm+0q4yOefokfu4CoxYwRZ9QAq+ouGwfeOg==", + "dev": true, + "requires": { + "@algolia/requester-common": "4.11.0" + } + }, + "@algolia/transporter": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.11.0.tgz", + "integrity": "sha512-k4dyxiaEfYpw4UqybK9q7lrFzehygo6KV3OCYJMMdX0IMWV0m4DXdU27c1zYRYtthaFYaBzGF4Kjcl8p8vxCKw==", + "dev": true, + "requires": { + "@algolia/cache-common": "4.11.0", + "@algolia/logger-common": "4.11.0", + "@algolia/requester-common": "4.11.0" + } + }, "@babel/code-frame": { "version": "7.12.11", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", @@ -31410,6 +32121,12 @@ "@babel/types": "^7.3.0" } }, + "@types/chai": { + "version": "4.2.22", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.22.tgz", + "integrity": "sha512-tFfcE+DSTzWAgifkjik9AySNqIyNoYwmR+uecPwwD/XRNfvOjmC/FjCxpiUGDkDVDphPfCUecSQVFw+lN3M3kQ==", + "dev": true + }, "@types/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", @@ -31429,6 +32146,43 @@ "@types/node": "*" } }, + "@types/hoist-non-react-statics": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", + "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "dev": true, + "requires": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, + "@types/inquirer": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-8.1.3.tgz", + "integrity": "sha512-AayK4ZL5ssPzR1OtnOLGAwpT0Dda3Xi/h1G0l1oJDNrowp7T1423q4Zb8/emr7tzRlCy4ssEri0LWVexAqHyKQ==", + "dev": true, + "requires": { + "@types/through": "*", + "rxjs": "^7.2.0" + }, + "dependencies": { + "rxjs": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.4.0.tgz", + "integrity": "sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w==", + "dev": true, + "requires": { + "tslib": "~2.1.0" + } + }, + "tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", + "dev": true + } + } + }, "@types/istanbul-lib-coverage": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", @@ -31580,6 +32334,30 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "@types/loadable__component": { + "version": "5.13.4", + "resolved": "https://registry.npmjs.org/@types/loadable__component/-/loadable__component-5.13.4.tgz", + "integrity": "sha512-YhoCCxyuvP2XeZNbHbi8Wb9EMaUJuA2VGHxJffcQYrJKIKSkymJrhbzsf9y4zpTmr5pExAAEh5hbF628PAZ8Dg==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, + "@types/lodash": { + "version": "4.14.177", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.177.tgz", + "integrity": "sha512-0fDwydE2clKe9MNfvXHBHF9WEahRuj+msTuQqOmAApNORFvhMYZKNGGJdCzuhheVjMps/ti0Ak/iJPACMaevvw==", + "dev": true + }, + "@types/lodash-es": { + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.5.tgz", + "integrity": "sha512-SHBoI8/0aoMQWAgUHMQ599VM6ZiSKg8sh/0cFqqlQQMyY9uEplc0ULU5yQNzcvdR4ZKa0ey8+vFmahuRbOCT1A==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, "@types/minimatch": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", @@ -31592,6 +32370,12 @@ "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", "dev": true }, + "@types/node": { + "version": "16.11.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.7.tgz", + "integrity": "sha512-QB5D2sqfSjCmTuWcBWyJ+/44bcjO7VbjSbOE0ucoVbAsSNQc4Lt6QkgkVXkTDwkL4z/beecZNDvVX15D4P8Jbw==", + "dev": true + }, "@types/normalize-package-data": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", @@ -31610,6 +32394,161 @@ "integrity": "sha512-Fo79ojj3vdEZOHg3wR9ksAMRz4P3S5fDB5e/YWZiFnyFQI1WY2Vftu9XoXVVtJfxB7Bpce/QTqWSSntkz2Znrw==", "dev": true }, + "@types/prismjs": { + "version": "1.16.6", + "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.16.6.tgz", + "integrity": "sha512-dTvnamRITNqNkqhlBd235kZl3KfVJQQoT5jkXeiWSBK7i4/TLKBNLV0S1wOt8gy4E2TY722KLtdmv2xc6+Wevg==", + "dev": true + }, + "@types/prop-types": { + "version": "15.7.4", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz", + "integrity": "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==", + "dev": true + }, + "@types/psl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@types/psl/-/psl-1.1.0.tgz", + "integrity": "sha512-HhZnoLAvI2koev3czVPzBNRYvdrzJGLjQbWZhqFmS9Q6a0yumc5qtfSahBGb5g+6qWvA8iiQktqGkwoIXa/BNQ==", + "dev": true + }, + "@types/reach__router": { + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/@types/reach__router/-/reach__router-1.3.9.tgz", + "integrity": "sha512-N6rqQqTTAV/zKLfK3iq9Ww3wqCEhTZvsilhl0zI09zETdVq1QGmJH6+/xnj8AFUWIrle2Cqo+PGM/Ltr1vBb9w==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, + "@types/react": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.35.tgz", + "integrity": "sha512-r3C8/TJuri/SLZiiwwxQoLAoavaczARfT9up9b4Jr65+ErAUX3MIkU0oMOQnrpfgHme8zIqZLX7O5nnjm5Wayw==", + "dev": true, + "requires": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "@types/react-dom": { + "version": "17.0.11", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.11.tgz", + "integrity": "sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, + "@types/react-helmet": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@types/react-helmet/-/react-helmet-6.1.4.tgz", + "integrity": "sha512-jyx50RNZXVaTGHY3MsoRPNpeiVk8b0XTPgD/O6KHF6COTDnG/+lRjPYvTK5nfWtR3xDOux0w6bHLAsaHo2ZLTA==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, + "@types/react-instantsearch-core": { + "version": "6.10.5", + "resolved": "https://registry.npmjs.org/@types/react-instantsearch-core/-/react-instantsearch-core-6.10.5.tgz", + "integrity": "sha512-VjXJFUfsPdWMSiugJiQc950G9ZRjCEIzqQ9/K915d1f1BsVE2TE57PcfHSxAy1pGDDR8FT5uAgAaOMyKJ66NJQ==", + "dev": true, + "requires": { + "@types/react": "*", + "algoliasearch": ">=4", + "algoliasearch-helper": ">=3" + } + }, + "@types/react-instantsearch-dom": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@types/react-instantsearch-dom/-/react-instantsearch-dom-6.12.0.tgz", + "integrity": "sha512-O08H+ye4e4kEnYHmMrov9FPNRDJwfCWthNZf4aztqahpU8LSbAiuFQGVy84SHUvg/jfNcG4333SsVnAQLtbS7A==", + "dev": true, + "requires": { + "@types/react": "*", + "@types/react-instantsearch-core": "*" + } + }, + "@types/react-monaco-editor": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@types/react-monaco-editor/-/react-monaco-editor-0.16.0.tgz", + "integrity": "sha512-3YxNIyZ+mlU6WN9UfQ/T66LYjHH3ZWOK4csfefkkXdDmUbHDbuDpfmVSYyJt1W0wlwhcfu4zc7BMwYrimN/GUg==", + "dev": true, + "requires": { + "react-monaco-editor": "*" + } + }, + "@types/react-redux": { + "version": "7.1.20", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.20.tgz", + "integrity": "sha512-q42es4c8iIeTgcnB+yJgRTTzftv3eYYvCZOh1Ckn2eX/3o5TdsQYKUWpLoLuGlcY/p+VAhV9IOEZJcWk/vfkXw==", + "dev": true, + "requires": { + "@types/hoist-non-react-statics": "^3.3.0", + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0", + "redux": "^4.0.0" + } + }, + "@types/react-responsive": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/@types/react-responsive/-/react-responsive-8.0.4.tgz", + "integrity": "sha512-/IrXSbm5aeSvtAD2vFGgPpQsHRQEJ2eWr6EdPEBPlTvad/qJYjXZax4CfOi5xCM5fjq/xpNW3WIHwKOrcdIGcA==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, + "@types/react-spinkit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/react-spinkit/-/react-spinkit-3.0.7.tgz", + "integrity": "sha512-y/Jnzx/WCJ8QpkL4hJ0umfhApV9tEmuiN4XKentBCBhAkxERD7hNACJaH7VUzCyhE7LkVYTq8l1vmlK1o+PhuA==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, + "@types/react-test-renderer": { + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-17.0.1.tgz", + "integrity": "sha512-3Fi2O6Zzq/f3QR9dRnlnHso9bMl7weKCviFmfF6B4LS1Uat6Hkm15k0ZAQuDz+UBq6B3+g+NM6IT2nr5QgPzCw==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, + "@types/react-transition-group": { + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.4.tgz", + "integrity": "sha512-7gAPz7anVK5xzbeQW9wFBDg7G++aPLAFY0QaSMOou9rJZpbuI58WAuJrgu+qR92l61grlnCUe7AFX8KGahAgug==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, + "@types/redux-actions": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@types/redux-actions/-/redux-actions-2.6.2.tgz", + "integrity": "sha512-TvcINy8rWFANcpc3EiEQX9Yv3owM3d3KIrqr2ryUIOhYIYzXA/bhDZeGSSSuai62iVR2qMZUgz9tQ5kr0Kl+Tg==", + "dev": true + }, + "@types/sanitize-html": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@types/sanitize-html/-/sanitize-html-2.5.0.tgz", + "integrity": "sha512-PeFIEZsO9m1+ACJlXUaimgrR+5DEDiIXhz7Hso307jmq5Yz0lb5kDp8LiTr5dMMMliC/jNNx/qds7Zoxa4zexw==", + "dev": true, + "requires": { + "htmlparser2": "^6.0.0" + } + }, + "@types/scheduler": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", + "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", + "dev": true + }, "@types/sinonjs__fake-timers": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.3.tgz", @@ -31628,6 +32567,12 @@ "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, + "@types/store": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/store/-/store-2.0.2.tgz", + "integrity": "sha512-ZPHnXkzmGMfk+pHqAGzTSpA9CbsHmJLgkvOl5w52LZ0XTxB1ZIHWZzQ7lEtjTNWScBbsQekg8TjApMXkMe4nkw==", + "dev": true + }, "@types/testing-library__jest-dom": { "version": "5.14.0", "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.0.tgz", @@ -31637,6 +32582,21 @@ "@types/jest": "*" } }, + "@types/through": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.30.tgz", + "integrity": "sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/validator": { + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.0.tgz", + "integrity": "sha512-+jBxVvXVuggZOrm04NR8z+5+bgoW4VZyLzUO+hmPPW1mVFL/HaitLAkizfv4yg9TbG8lkfHWVMQ11yDqrVVCzA==", + "dev": true + }, "@types/yargs": { "version": "15.0.13", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.13.tgz", @@ -32133,6 +33093,37 @@ "uri-js": "^4.2.2" } }, + "algoliasearch": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.11.0.tgz", + "integrity": "sha512-IXRj8kAP2WrMmj+eoPqPc6P7Ncq1yZkFiyDrjTBObV1ADNL8Z/KdZ+dWC5MmYcBLAbcB/mMCpak5N/D1UIZvsA==", + "dev": true, + "requires": { + "@algolia/cache-browser-local-storage": "4.11.0", + "@algolia/cache-common": "4.11.0", + "@algolia/cache-in-memory": "4.11.0", + "@algolia/client-account": "4.11.0", + "@algolia/client-analytics": "4.11.0", + "@algolia/client-common": "4.11.0", + "@algolia/client-personalization": "4.11.0", + "@algolia/client-search": "4.11.0", + "@algolia/logger-common": "4.11.0", + "@algolia/logger-console": "4.11.0", + "@algolia/requester-browser-xhr": "4.11.0", + "@algolia/requester-common": "4.11.0", + "@algolia/requester-node-http": "4.11.0", + "@algolia/transporter": "4.11.0" + } + }, + "algoliasearch-helper": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.6.2.tgz", + "integrity": "sha512-Xx0NOA6k4ySn+R2l3UMSONAaMkyfmrZ3AP1geEMo32MxDJQJesZABZYsldO9fa6FKQxH91afhi4hO1G0Zc2opg==", + "dev": true, + "requires": { + "events": "^1.1.1" + } + }, "ansi-align": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", @@ -34100,6 +35091,12 @@ } } }, + "csstype": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz", + "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==", + "dev": true + }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -34164,6 +35161,12 @@ "yauzl": "^2.10.0" }, "dependencies": { + "@types/node": { + "version": "14.17.33", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.33.tgz", + "integrity": "sha512-noEeJ06zbn3lOh4gqe2v7NMGS33jrulfNqYFDjjEbhpDEHR5VTxgYNQSBqBlJIsBJW3uEYDgD6kvMnrrhGzq8g==", + "dev": true + }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -34666,6 +35669,23 @@ "integrity": "sha512-Xu9mD0UjrJisTmv7lmVSDMagQcU9R5hwAbxsaAE/35XPnPLJobbuREfV/rraiSaEj/UOvgrzQs66zyTWTlyd+g==", "dev": true }, + "dom-serializer": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", + "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + } + }, + "domelementtype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", + "dev": true + }, "domexception": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", @@ -34683,12 +35703,32 @@ } } }, + "domhandler": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.2.tgz", + "integrity": "sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w==", + "dev": true, + "requires": { + "domelementtype": "^2.2.0" + } + }, "dompurify": { "version": "2.2.6", "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.2.6.tgz", "integrity": "sha512-7b7ZArhhH0SP6W2R9cqK6RjaU82FZ2UPM7RO8qN1b1wyvC/NY1FNWcX1Pu00fFOAnzEORtwXe4bPaClg6pUybQ==", "dev": true }, + "domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + }, "dot-prop": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.1.tgz", @@ -35575,6 +36615,12 @@ "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", "dev": true }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "dev": true + }, "execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -37313,6 +38359,15 @@ "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", "dev": true }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dev": true, + "requires": { + "react-is": "^16.7.0" + } + }, "hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", @@ -37334,6 +38389,18 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, "http-cache-semantics": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", @@ -42206,6 +43273,13 @@ "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", "dev": true }, + "monaco-editor": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.28.1.tgz", + "integrity": "sha512-P1vPqxB4B1ZFzTeR1ScggSp9/5NoQrLCq88fnlNUsuRAP1usEBN4TIpI2lw0AYIZNVIanHk0qwjze2uJwGOHUw==", + "dev": true, + "peer": true + }, "move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -43597,12 +44671,32 @@ "strip-json-comments": "~2.0.1" } }, + "react": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", + "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "dev": true, + "peer": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, "react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "dev": true }, + "react-monaco-editor": { + "version": "0.46.0", + "resolved": "https://registry.npmjs.org/react-monaco-editor/-/react-monaco-editor-0.46.0.tgz", + "integrity": "sha512-/GyQ0tQLbjHAuMUNRfKecBYN68o8TwA4fnwH9P+lHbF80ayMAo0PQ60joTQH6R6j839kMn6o9Kk/cbzOxK5DzA==", + "dev": true, + "requires": { + "prop-types": "^15.7.2" + } + }, "read": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", @@ -43724,6 +44818,15 @@ } } }, + "redux": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.2.tgz", + "integrity": "sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.9.2" + } + }, "regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", diff --git a/package.json b/package.json index 9e4210ebfa..bb9a976d0b 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "e2e:dev:watch": "start-test develop ':3000/status/ping|8000' cypress:dev:watch", "e2e:prd:run": "npm run build && start-test ':3000/status/ping|8000' cypress:dev:run", "e2e:prd:watch": "npm run build && start-test ':3000/status/ping|8000' cypress:dev:watch", - "ensure-env": "cross-env DEBUG=fcc:* node ./tools/scripts/build/ensure-env.js", + "ensure-env": "cross-env DEBUG=fcc:* tsc ./tools/scripts/build/ensure-env.ts && node ./tools/scripts/build/ensure-env.js", "format": "run-s format:eslint format:prettier", "format:eslint": "eslint . --fix", "format:prettier": "prettier --write .", @@ -64,7 +64,7 @@ "lint": "npm-run-all ensure-env -p lint:*", "lint:challenges": "cd ./curriculum && npm run lint", "lint:js": "eslint --max-warnings 0 .", - "lint:ts": "tsc -p client && tsc -p tools/ui-components", + "lint:ts": "tsc && tsc -p tools/ui-components && tsc -p tools/scripts/build", "lint:prettier": "prettier --list-different .", "postinstall": "npm run bootstrap", "seed": "cross-env DEBUG=fcc:* node ./tools/scripts/seed/seedAuthUser", @@ -101,6 +101,29 @@ "@testing-library/dom": "8.11.1", "@testing-library/jest-dom": "5.15.0", "@testing-library/user-event": "13.5.0", + "@types/chai": "^4.2.22", + "@types/inquirer": "^8.1.3", + "@types/jest": "^27.0.2", + "@types/loadable__component": "^5.13.4", + "@types/lodash-es": "^4.17.5", + "@types/node": "^16.11.7", + "@types/prismjs": "^1.16.6", + "@types/psl": "^1.1.0", + "@types/reach__router": "^1.3.9", + "@types/react": "^17.0.35", + "@types/react-dom": "^17.0.11", + "@types/react-helmet": "^6.1.4", + "@types/react-instantsearch-dom": "^6.12.0", + "@types/react-monaco-editor": "^0.16.0", + "@types/react-redux": "^7.1.20", + "@types/react-responsive": "^8.0.4", + "@types/react-spinkit": "^3.0.7", + "@types/react-test-renderer": "^17.0.1", + "@types/react-transition-group": "^4.4.4", + "@types/redux-actions": "^2.6.2", + "@types/sanitize-html": "^2.5.0", + "@types/store": "^2.0.2", + "@types/validator": "^13.7.0", "@typescript-eslint/eslint-plugin": "4.33.0", "@typescript-eslint/parser": "4.33.0", "babel-eslint": "10.1.0", diff --git a/tools/challenge-helper-scripts/create-project.ts b/tools/challenge-helper-scripts/create-project.ts index 82a116328c..bbe269370c 100644 --- a/tools/challenge-helper-scripts/create-project.ts +++ b/tools/challenge-helper-scripts/create-project.ts @@ -4,25 +4,10 @@ import path from 'path'; import { prompt } from 'inquirer'; import { format } from 'prettier'; +import { SuperBlocks } from '../../config/certification-settings'; import { blockNameify } from '../../utils/block-nameify'; import { createStepFile } from './utils.js'; -const superBlocks = [ - 'responsive-web-design', - 'javascript-algorithms-and-data-structures', - 'front-end-development-libraries', - 'data-visualization', - 'back-end-development-and-apis', - 'quality-assurance', - 'scientific-computing-with-python', - 'data-analysis-with-python', - 'information-security', - 'machine-learning-with-python', - 'coding-interview-prep' -] as const; - -type SuperBlock = typeof superBlocks[number]; - const helpCategories = ['HTML-CSS', 'JavaScript', 'Python'] as const; type BlockInfo = { @@ -34,7 +19,7 @@ type SuperBlockInfo = { blocks: Record; }; -type IntroJson = Record; +type IntroJson = Record; type Meta = { name: string; @@ -51,7 +36,7 @@ type Meta = { }; async function createProject( - superBlock: SuperBlock, + superBlock: SuperBlocks, block: string, helpCategory: string, order: number, @@ -86,7 +71,7 @@ async function createProject( } async function updateIntroJson( - superBlock: SuperBlock, + superBlock: SuperBlocks, block: string, title: string ) { @@ -138,7 +123,7 @@ async function updateBlockNames(block: string, title: string) { } async function createMetaJson( - superBlock: SuperBlock, + superBlock: SuperBlocks, block: string, title: string, order: number, @@ -149,7 +134,7 @@ async function createMetaJson( newMeta.name = title; newMeta.dashedName = block; newMeta.order = order; - newMeta.superOrder = superBlocks.indexOf(superBlock) + 1; + newMeta.superOrder = Object.values(SuperBlocks).indexOf(superBlock) + 1; newMeta.superBlock = superBlock; newMeta.challengeOrder = [[challengeId, 'Step 1']]; const newMetaDir = path.resolve(metaDir, block); @@ -190,10 +175,10 @@ This is a test for the new project-based curriculum. } async function createFirstChallenge( - superBlock: SuperBlock, + superBlock: SuperBlocks, block: string ): Promise { - const superBlockId = (superBlocks.indexOf(superBlock) + 1) + const superBlockId = (Object.values(SuperBlocks).indexOf(superBlock) + 1) .toString() .padStart(2, '0'); const newChallengeDir = path.resolve( @@ -234,9 +219,9 @@ prompt([ { name: 'superBlock', message: 'Which certification does this belong to?', - default: 'responsive-web-design', + default: SuperBlocks.RespWebDesign, type: 'list', - choices: superBlocks + choices: SuperBlocks }, { name: 'block', diff --git a/tools/challenge-helper-scripts/package.json b/tools/challenge-helper-scripts/package.json index fbb7990da6..035e8627fa 100644 --- a/tools/challenge-helper-scripts/package.json +++ b/tools/challenge-helper-scripts/package.json @@ -23,8 +23,6 @@ "create-project": "ts-node create-project" }, "devDependencies": { - "@types/inquirer": "7.3.3", - "@types/node": "16.11.7", "bson-objectid": "2.0.1", "cross-env": "7.0.3", "gray-matter": "4.0.3", diff --git a/tools/challenge-helper-scripts/tsconfig.json b/tools/challenge-helper-scripts/tsconfig.json deleted file mode 100644 index abcb5a97ba..0000000000 --- a/tools/challenge-helper-scripts/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "noEmit": true, - "strict": true, - "moduleResolution": "node", - "esModuleInterop": true, - "resolveJsonModule": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true - } -} diff --git a/tools/scripts/build/ensure-env.js b/tools/scripts/build/ensure-env.ts similarity index 74% rename from tools/scripts/build/ensure-env.js rename to tools/scripts/build/ensure-env.ts index b374a683a3..145a319897 100644 --- a/tools/scripts/build/ensure-env.js +++ b/tools/scripts/build/ensure-env.ts @@ -1,9 +1,11 @@ -const { spawn } = require('child_process'); -const fs = require('fs'); -const path = require('path'); +import { spawn } from 'child_process'; +import * as fs from 'fs'; +import * as path from 'path'; -const { availableLangs } = require('../../../config/i18n/all-langs'); -const env = require('../../../config/read-env'); +import { availableLangs } from '../../../config/i18n/all-langs'; + +// eslint-disable-next-line +const env = require('../../../config/read-env.js'); const globalConfigPath = path.resolve(__dirname, '../../../config'); @@ -11,21 +13,25 @@ const { FREECODECAMP_NODE_ENV } = process.env; function checkClientLocale() { if (!availableLangs.client.includes(process.env.CLIENT_LOCALE)) { + /* eslint-disable @typescript-eslint/restrict-template-expressions */ throw Error(` CLIENT_LOCALE, ${process.env.CLIENT_LOCALE}, is not an available language in config/i18n/all-langs.js `); + /* eslint-enable @typescript-eslint/restrict-template-expressions */ } } function checkCurriculumLocale() { if (!availableLangs.curriculum.includes(process.env.CURRICULUM_LOCALE)) { + /* eslint-disable @typescript-eslint/restrict-template-expressions */ throw Error(` CURRICULUM_LOCALE, ${process.env.CURRICULUM_LOCALE}, is not an available language in config/i18n/all-langs.js `); + /* eslint-enable @typescript-eslint/restrict-template-expressions */ } } @@ -57,6 +63,7 @@ if (FREECODECAMP_NODE_ENV !== 'development') { expectedVariables.sort(); receivedvariables.sort(); if (expectedVariables.length !== receivedvariables.length) { + /* eslint-disable @typescript-eslint/restrict-template-expressions */ throw Error(` Env. variable validation failed. Make sure these keys are used and configured. @@ -71,9 +78,11 @@ if (FREECODECAMP_NODE_ENV !== 'development') { )} `); + /* eslint-enable @typescript-eslint/restrict-template-expressions */ } for (const key of expectedVariables) { + /* eslint-disable @typescript-eslint/no-unsafe-member-access */ if (typeof env[key] === 'undefined' || env[key] === null) { throw Error(` @@ -86,16 +95,16 @@ if (FREECODECAMP_NODE_ENV !== 'development') { if (env['environment'] !== 'production') throw Error(` - Production environment should be 'production' + Production environment should be 'production' - `); + `); if (env['showUpcomingChanges']) throw Error(` - SHOW_UPCOMING_CHANGES should never be 'true' in production + SHOW_UPCOMING_CHANGES should never be 'true' in production - `); + `); checkClientLocale(); checkCurriculumLocale(); @@ -103,8 +112,10 @@ if (FREECODECAMP_NODE_ENV !== 'development') { checkClientLocale(); checkCurriculumLocale(); if (fs.existsSync(`${globalConfigPath}/env.json`)) { + // eslint-disable-next-line const { showUpcomingChanges } = require(`${globalConfigPath}/env.json`); if (env['showUpcomingChanges'] !== showUpcomingChanges) { + /* eslint-enable @typescript-eslint/no-unsafe-member-access */ console.log( 'SHOW_UPCOMING_CHANGES value has changed, cleaning client cache.' ); diff --git a/tools/scripts/build/tsconfig.json b/tools/scripts/build/tsconfig.json new file mode 100644 index 0000000000..32a028d99a --- /dev/null +++ b/tools/scripts/build/tsconfig.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "typeRoots": ["../../node_modules/@types"], + "types": ["node"] + } +} diff --git a/tools/ui-components/package.json b/tools/ui-components/package.json index eae4325f0b..5d75226e59 100644 --- a/tools/ui-components/package.json +++ b/tools/ui-components/package.json @@ -20,7 +20,6 @@ "homepage": "https://github.com/freeCodeCamp/freeCodeCamp#readme", "dependencies": { "@babel/preset-typescript": "7.16.0", - "@types/jest": "27.0.2", "@types/node": "16.11.7", "@types/react": "17.0.33", "@types/react-dom": "17.0.11", @@ -39,18 +38,20 @@ "@storybook/addon-links": "6.3.12", "@storybook/addon-postcss": "2.0.0", "@storybook/react": "6.3.12", + "@testing-library/jest-dom": "^5.15.0", "@testing-library/react": "12.1.2", + "@types/jest": "^27.0.2", "autoprefixer": "10.4.0", "babel-loader": "8.2.3", "babel-plugin-transform-react-remove-prop-types": "0.4.24", "cross-env": "7.0.3", "postcss": "8.3.11", "postcss-import": "14.0.2", - "tailwindcss": "2.2.19", "rimraf": "3.0.2", "rollup": "2.60.0", "rollup-plugin-postcss": "4.0.1", - "rollup-plugin-terser": "7.0.2" + "rollup-plugin-terser": "7.0.2", + "tailwindcss": "2.2.19" }, "scripts": { "storybook": "start-storybook -p 6006", diff --git a/tools/ui-components/tsconfig.json b/tools/ui-components/tsconfig.json index 2a4d9c6b60..b66d04d586 100644 --- a/tools/ui-components/tsconfig.json +++ b/tools/ui-components/tsconfig.json @@ -8,6 +8,7 @@ "esModuleInterop": true, "moduleResolution": "node", "strict": true, - "noEmit": true + "noEmit": true, + "typeRoots": ["./node_modules/@types"] } } diff --git a/client/tsconfig.json b/tsconfig.json similarity index 67% rename from client/tsconfig.json rename to tsconfig.json index e2eb106f61..1a6e33ef0f 100644 --- a/client/tsconfig.json +++ b/tsconfig.json @@ -1,5 +1,13 @@ { - "include": ["./i18n/**/*", "./plugins/**/*", "./src/**/*", "./utils/**/*"], + "include": [ + "client/i18n/**/*", + "client/plugins/**/*", + "client/src/**/*", + "client/utils/**/*", + "tools/challenge-helper-scripts/**/*", + "config/certification-settings.ts", + "config/i18n/**/*" + ], "compilerOptions": { "lib": ["WebWorker", "DOM", "DOM.Iterable"], "target": "es2020",