From 69d6ee32bf108bce29a1a556f84325bab1c68b56 Mon Sep 17 00:00:00 2001 From: Oliver Eyton-Williams Date: Fri, 28 Jul 2023 07:36:25 +0200 Subject: [PATCH] feat: python in the browser (#50913) Co-authored-by: Beau Carnes <1513130+beaucarnes@users.noreply.github.com> --- .eslintrc.json | 1 + .gitignore | 1 + client/gatsby-config.js | 12 +- client/i18n/locales/english/intro.json | 14 + client/package.json | 7 +- client/src/assets/icons/index.tsx | 3 +- .../src/pages/learn/upcoming-python/index.md | 9 + .../index.md | 9 + client/src/resources/cert-and-project-map.ts | 14 + .../Challenges/classic/editor-tabs.tsx | 13 +- .../templates/Challenges/classic/editor.tsx | 4 +- .../Challenges/classic/multifile-editor.tsx | 18 +- .../src/templates/Challenges/classic/show.tsx | 6 +- .../Challenges/rechallenge/builders.ts | 8 + .../rechallenge/transform-python.js | 120 +++ .../rechallenge/transform-python.test.ts | 41 + .../Challenges/rechallenge/transformers.js | 19 + .../redux/execute-challenge-saga.js | 40 +- .../templates/Challenges/redux/selectors.js | 3 +- .../src/templates/Challenges/utils/build.ts | 119 ++- .../src/templates/Challenges/utils/frame.ts | 131 ++- .../components/cert-challenge.tsx | 5 +- client/utils/gatsby/challenge-page-creator.js | 4 +- config/challenge-types.ts | 10 +- config/superblocks.ts | 36 +- .../meta.json | 32 + .../_meta/python-for-everybody/meta.json | 2 +- .../meta.json | 2 +- .../_meta/upcoming-python-project/meta.json | 16 + .../upcoming-python-certification.yml | 9 + .../5daa813381b9e3db6c126b43.md | 46 + .../64a5229b99ff0e8250cd9a72.md | 40 + .../64b163c20e59cbd4a64940b0.md | 36 + .../64b171849f925b0773aa434c.md | 34 + .../64afc37bf3b37856e035b85e.md | 40 + curriculum/schema/challenge-schema.js | 2 +- curriculum/test/test-challenges.js | 85 +- curriculum/utils.js | 1 + curriculum/utils.test.ts | 4 +- pnpm-lock.yaml | 798 ++++++++++++++---- pnpm-workspace.yaml | 3 +- tools/challenge-auditor/index.ts | 1 + .../api/configs/super-block-list.ts | 8 + tools/challenge-editor/client/package.json | 2 +- tools/challenge-helper-scripts/fs-utils.ts | 1 + .../parser/plugins/utils/get-file-visitor.js | 4 +- .../browser-scripts}/frame-runner.ts | 40 +- .../client-plugins/browser-scripts/index.d.ts | 33 + .../browser-scripts/package.json | 60 ++ .../browser-scripts/python-runner.ts | 280 ++++++ .../browser-scripts}/sass-compile.ts | 0 .../browser-scripts}/test-evaluator.ts | 2 +- .../browser-scripts/tsconfig.json | 12 + .../browser-scripts/utils/format.js | 22 + .../browser-scripts/webpack.config.js | 18 +- .../gatsby-node.js | 4 +- .../gatsby-remark-node-identity/package.json | 4 +- .../create-challenge-nodes.js | 0 .../gatsby-source-challenges}/gatsby-node.js | 0 .../gatsby-source-challenges}/package.json | 4 +- .../build-external-curricula-data.test.ts | 1 + 61 files changed, 1937 insertions(+), 356 deletions(-) create mode 100644 client/src/pages/learn/upcoming-python/index.md create mode 100644 client/src/pages/learn/upcoming-python/learn-python-by-building-a-blackjack-game/index.md create mode 100644 client/src/templates/Challenges/rechallenge/transform-python.js create mode 100644 client/src/templates/Challenges/rechallenge/transform-python.test.ts create mode 100644 curriculum/challenges/_meta/learn-python-by-building-a-blackjack-game/meta.json create mode 100644 curriculum/challenges/_meta/upcoming-python-project/meta.json create mode 100644 curriculum/challenges/english/00-certifications/upcoming-python-certification/upcoming-python-certification.yml create mode 100644 curriculum/challenges/english/20-upcoming-python/learn-python-by-building-a-blackjack-game/5daa813381b9e3db6c126b43.md create mode 100644 curriculum/challenges/english/20-upcoming-python/learn-python-by-building-a-blackjack-game/64a5229b99ff0e8250cd9a72.md create mode 100644 curriculum/challenges/english/20-upcoming-python/learn-python-by-building-a-blackjack-game/64b163c20e59cbd4a64940b0.md create mode 100644 curriculum/challenges/english/20-upcoming-python/learn-python-by-building-a-blackjack-game/64b171849f925b0773aa434c.md create mode 100644 curriculum/challenges/english/20-upcoming-python/upcoming-python-project/64afc37bf3b37856e035b85e.md rename {client/src/client => tools/client-plugins/browser-scripts}/frame-runner.ts (79%) create mode 100644 tools/client-plugins/browser-scripts/index.d.ts create mode 100644 tools/client-plugins/browser-scripts/package.json create mode 100644 tools/client-plugins/browser-scripts/python-runner.ts rename {client/src/client/workers => tools/client-plugins/browser-scripts}/sass-compile.ts (100%) rename {client/src/client/workers => tools/client-plugins/browser-scripts}/test-evaluator.ts (98%) create mode 100644 tools/client-plugins/browser-scripts/tsconfig.json create mode 100644 tools/client-plugins/browser-scripts/utils/format.js rename client/webpack-workers.js => tools/client-plugins/browser-scripts/webpack.config.js (79%) rename {client/plugins => tools/client-plugins}/gatsby-remark-node-identity/gatsby-node.js (74%) rename {client/plugins => tools/client-plugins}/gatsby-remark-node-identity/package.json (86%) rename {client/plugins/fcc-source-challenges => tools/client-plugins/gatsby-source-challenges}/create-challenge-nodes.js (100%) rename {client/plugins/fcc-source-challenges => tools/client-plugins/gatsby-source-challenges}/gatsby-node.js (100%) rename {client/plugins/fcc-source-challenges => tools/client-plugins/gatsby-source-challenges}/package.json (88%) diff --git a/.eslintrc.json b/.eslintrc.json index acf94d4ce63..d4abab9718e 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -70,6 +70,7 @@ "./api/tsconfig.json", "./config/tsconfig.json", "./tools/ui-components/tsconfig.json", + "./tools/client-plugins/browser-scripts/tsconfig.json", "./utils/tsconfig.json", "./web/tsconfig.json", "./curriculum-server/tsconfig.json", diff --git a/.gitignore b/.gitignore index f3529f1c73f..e81629eb1ab 100644 --- a/.gitignore +++ b/.gitignore @@ -161,6 +161,7 @@ config/env.json config/client/sass-compile.json config/client/frame-runner.json config/client/test-evaluator.json +config/client/python-runner.json config/curriculum.json config/i18n.js config/misc.js diff --git a/client/gatsby-config.js b/client/gatsby-config.js index 53749705d2d..610075b8b3d 100644 --- a/client/gatsby-config.js +++ b/client/gatsby-config.js @@ -51,7 +51,9 @@ module.exports = { } }, { - resolve: 'fcc-source-challenges', + resolve: require.resolve( + '../tools/client-plugins/gatsby-source-challenges' + ), options: { name: 'challenges', source: buildChallenges, @@ -70,7 +72,9 @@ module.exports = { resolve: 'gatsby-transformer-remark' }, { - resolve: 'gatsby-remark-node-identity', + resolve: require.resolve( + '../tools/client-plugins/gatsby-remark-node-identity' + ), options: { identity: 'blockIntroMarkdown', predicate: ({ frontmatter }) => { @@ -83,7 +87,9 @@ module.exports = { } }, { - resolve: 'gatsby-remark-node-identity', + resolve: require.resolve( + '../tools/client-plugins/gatsby-remark-node-identity' + ), options: { identity: 'superBlockIntroMarkdown', predicate: ({ frontmatter }) => { diff --git a/client/i18n/locales/english/intro.json b/client/i18n/locales/english/intro.json index da157bf0cd4..1e8fbdc9e09 100644 --- a/client/i18n/locales/english/intro.json +++ b/client/i18n/locales/english/intro.json @@ -1057,6 +1057,20 @@ } } }, + "upcoming-python": { + "title": "Upcoming Python", + "intro": ["placeholder"], + "blocks": { + "learn-python-by-building-a-blackjack-game": { + "title": "Learn Python by Building a Blackjack Game", + "intro": ["Learn Python.", ""] + }, + "upcoming-python-project": { + "title": "Upcoming Python Project", + "intro": ["placeholder"] + } + } + }, "example-certification": { "title": "Example Certification", "intro": ["placeholder"], diff --git a/client/package.json b/client/package.json index df990ce4f84..3f741157f2a 100644 --- a/client/package.json +++ b/client/package.json @@ -19,11 +19,11 @@ "author": "freeCodeCamp ", "main": "none", "scripts": { - "prebuild": "pnpm -w run create:config && pnpm run build:workers --env production && pnpm run build:components-library", + "prebuild": "pnpm -w run create:config && pnpm run build:scripts --env production && pnpm run build:components-library", "build": "cross-env NODE_OPTIONS=\"--max-old-space-size=7168\" gatsby build --prefix-paths", - "build:workers": "cross-env NODE_OPTIONS=\"--max-old-space-size=7168\" webpack --config ./webpack-workers.js", + "build:scripts": "pnpm run -F=browser-scripts build", "clean": "gatsby clean", - "predevelop": "pnpm run build:workers --env development && pnpm run build:components-library", + "predevelop": "pnpm run build:scripts --env development && pnpm run build:components-library", "build:components-library": "pnpm run -F=@freecodecamp/ui build", "develop": "cross-env NODE_OPTIONS=\"--max-old-space-size=5000\" gatsby develop --inspect=9230", "lint": "ts-node ./i18n/schema-validation.ts", @@ -71,7 +71,6 @@ "crypto-browserify": "3.12.0", "date-fns": "2.30.0", "enzyme": "3.11.0", - "enzyme-adapter-react-16": "1.15.7", "final-form": "4.20.9", "gatsby": "3.15.0", "gatsby-cli": "3.15.0", diff --git a/client/src/assets/icons/index.tsx b/client/src/assets/icons/index.tsx index 164d2a8732d..b3f7ef33273 100644 --- a/client/src/assets/icons/index.tsx +++ b/client/src/assets/icons/index.tsx @@ -36,7 +36,8 @@ const iconMap = { [SuperBlocks.ProjectEuler]: Graduation, [SuperBlocks.CollegeAlgebraPy]: CollegeAlgebra, [SuperBlocks.FoundationalCSharp]: CSharpLogo, - [SuperBlocks.ExampleCertification]: ResponsiveDesign + [SuperBlocks.ExampleCertification]: ResponsiveDesign, + [SuperBlocks.UpcomingPython]: PythonIcon }; const generateIconComponent = ( diff --git a/client/src/pages/learn/upcoming-python/index.md b/client/src/pages/learn/upcoming-python/index.md new file mode 100644 index 00000000000..fdfca81fe6e --- /dev/null +++ b/client/src/pages/learn/upcoming-python/index.md @@ -0,0 +1,9 @@ +--- +title: Upcoming Python Certification +superBlock: upcoming-python +certification: upcoming-python +--- + +## Upcoming Python Certification + +Learn the basics of Python. diff --git a/client/src/pages/learn/upcoming-python/learn-python-by-building-a-blackjack-game/index.md b/client/src/pages/learn/upcoming-python/learn-python-by-building-a-blackjack-game/index.md new file mode 100644 index 00000000000..fde82c07443 --- /dev/null +++ b/client/src/pages/learn/upcoming-python/learn-python-by-building-a-blackjack-game/index.md @@ -0,0 +1,9 @@ +--- +title: Introduction to Learn Python by Building a Blackjack Game +block: learn-python-by-building-a-blackjack-game +superBlock: scientific-computing-with-python +--- + +## Introduction to Learn Python by Building a Blackjack Game + +Learn Python! diff --git a/client/src/resources/cert-and-project-map.ts b/client/src/resources/cert-and-project-map.ts index 8619f8ff3ca..db826d0514e 100644 --- a/client/src/resources/cert-and-project-map.ts +++ b/client/src/resources/cert-and-project-map.ts @@ -28,6 +28,7 @@ const machineLearningPyBase = const collegeAlgebraPyBase = '/learn/college-algebra-with-python'; const takeHomeBase = '/learn/coding-interview-prep/take-home-projects'; const foundationalCSharpBase = '/learn/foundational-c-sharp-with-microsoft'; +const upcomingPythonBase = '/learn/upcoming-python'; const exampleCertBase = '/learn/example-certification'; const legacyFrontEndBase = feLibsBase; const legacyFrontEndResponsiveBase = responsiveWebBase; @@ -769,6 +770,19 @@ const upcomingCertMap = [ certSlug: 'example-certification-v8' } ] + }, + { + id: '64afc4e8f3b37856e035b85f', + title: 'Upcoming Python Certification', + certSlug: 'upcoming-python-v8', + projects: [ + { + id: '64afc37bf3b37856e035b85e', + title: 'Upcoming Python Project', + link: `${upcomingPythonBase}/upcoming-python-project`, + certSlug: 'upcoming-python-v8' + } + ] } ] as const; diff --git a/client/src/templates/Challenges/classic/editor-tabs.tsx b/client/src/templates/Challenges/classic/editor-tabs.tsx index 4ee838ff61e..89a52572749 100644 --- a/client/src/templates/Challenges/classic/editor-tabs.tsx +++ b/client/src/templates/Challenges/classic/editor-tabs.tsx @@ -11,9 +11,8 @@ import { challengeFilesSelector } from '../redux/selectors'; -type VisibleEditors = { - [key: string]: boolean; -}; +import type { VisibleEditors } from './multifile-editor'; + interface EditorTabsProps { challengeFiles: ChallengeFiles; toggleVisibleEditor: typeof toggleVisibleEditor; @@ -43,7 +42,13 @@ class EditorTabs extends Component { {sortChallengeFiles(challengeFiles).map( (challengeFile: ChallengeFile) => (