diff --git a/.env b/.env index 60a2d2a26..e10a70f1c 100644 --- a/.env +++ b/.env @@ -1,2 +1,3 @@ -REACT_APP_VERSION=$npm_package_version -REACT_APP_NAME=$npm_package_name +VITE_VERSION=$npm_package_version +VITE_NAME=$npm_package_name +VITE_FULL_URL=/ diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 000000000..cacd0111b --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,63 @@ +module.exports = { + root: true, + env: { browser: true, es2020: true }, + extends: [ + "eslint:recommended", + // We should switch to recommended-type-checked but there are many issues to review + "plugin:@typescript-eslint/recommended", + //"plugin:@typescript-eslint/recommended-type-checked", + "plugin:react-hooks/recommended", + "plugin:react/recommended", + "plugin:react/jsx-runtime", + ], + ignorePatterns: [ + "dist", + ".eslintrc.cjs", + "deployment.cjs", + "bin/**/*.js", + "bootstrap-template.js", + "playwright.config.ts", + ], + parser: "@typescript-eslint/parser", + parserOptions: { + ecmaVersion: "latest", + sourceType: "module", + project: ["./tsconfig.json", "./tsconfig.node.json"], + tsconfigRootDir: __dirname, + }, + plugins: ["react-refresh"], + settings: { + react: { + version: "18", + }, + }, + rules: { + // More trouble than it's worth + "react/no-unescaped-entities": "off", + // False positives from library imports from Chakra UI + "@typescript-eslint/unbound-method": "off", + "@typescript-eslint/no-misused-promises": [ + "error", + { + checksVoidReturn: false, + }, + ], + "@typescript-eslint/no-unused-vars": [ + "error", + { + args: "all", + argsIgnorePattern: "^_", + caughtErrors: "all", + // Let's remove e from here + caughtErrorsIgnorePattern: "^_|e", + destructuredArrayIgnorePattern: "^_", + varsIgnorePattern: "^_", + ignoreRestSiblings: true, + }, + ], + // Temporary, new rules on Vite migration that are widely flouted + "@typescript-eslint/no-explicit-any": "off", + "prefer-const": "off", + "react/display-name": "off", + }, +}; diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e67aea4b9..413b03a36 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,7 +22,7 @@ jobs: PRODUCTION_CLOUDFRONT_DISTRIBUTION_ID: E2ELTBTA2OFPY2 STAGING_CLOUDFRONT_DISTRIBUTION_ID: E2ELTBTA2OFPY2 REVIEW_CLOUDFRONT_DISTRIBUTION_ID: E3267W09ZJHQG9 - REACT_APP_FOUNDATION_BUILD: ${{ github.repository_owner == 'microbit-foundation' }} + VITE_FOUNDATION_BUILD: ${{ github.repository_owner == 'microbit-foundation' }} steps: # Note: This workflow disables deployment steps and micro:bit branding installation on forks. @@ -36,20 +36,18 @@ jobs: - run: npm ci env: NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - run: npm install --no-save @microbit-foundation/python-editor-v3-microbit@0.2.0-dev.31 @microbit-foundation/website-deploy-aws@0.3.0 @microbit-foundation/website-deploy-aws-config@0.7.1 @microbit-foundation/circleci-npm-package-versioner@1 + - run: npm install --no-save @microbit-foundation/python-editor-v3-microbit@0.2.0-vite.35 @microbit-foundation/website-deploy-aws@0.6.0 @microbit-foundation/website-deploy-aws-config@0.9.0 @microbit-foundation/circleci-npm-package-versioner@1 if: github.repository_owner == 'microbit-foundation' env: NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - run: node ./bin/print-ci-env-stage.js >> $GITHUB_ENV - - run: node ./bin/print-ci-env-public-url.js >> $GITHUB_ENV + - run: node ./bin/print-ci-env-stage.cjs >> $GITHUB_ENV + - run: node ./bin/print-ci-env-public-url.cjs >> $GITHUB_ENV - run: npm run ci:update-version if: github.repository_owner == 'microbit-foundation' - run: npm run ci env: - REACT_APP_GA_COOKIE_PREFIX: ${{ secrets.REACT_APP_GA_COOKIE_PREFIX }} - REACT_APP_GA_MEASUREMENT_ID: ${{ secrets.GA_MEASUREMENT_ID }} - REACT_APP_SENTRY_DSN: ${{ secrets.REACT_APP_SENTRY_DSN }} - - run: mkdir -p /tmp/app${PUBLIC_URL} && cp -r build/* /tmp/app${PUBLIC_URL} && npx serve --no-clipboard -l 3000 /tmp/app & + VITE_SENTRY_DSN: ${{ secrets.SENTRY_DSN }} + - run: mkdir -p /tmp/app${BASE_URL} && cp -r build/* /tmp/app${BASE_URL} && npx serve --no-clipboard -l 3000 /tmp/app & if: env.STAGE == 'REVIEW' || env.STAGE == 'STAGING' - run: curl --insecure -4 --retry 7 --retry-connrefused http://localhost:3000 1>/dev/null if: env.STAGE == 'REVIEW' || env.STAGE == 'STAGING' diff --git a/README.md b/README.md index f73bbd801..9742a32f1 100644 --- a/README.md +++ b/README.md @@ -30,15 +30,18 @@ Getting up and running: ### `npm start` -Runs the app in the development mode.\ +Runs the app in the development mode. + Open [http://localhost:3000](http://localhost:3000) to view it in the browser. -The page will reload if you make edits.\ -You will also see any lint errors in the console. +The page will reload if you make edits. + +This does not show TypeScript or lint errors. +Use the eslint plugin for your editor and consider also running `npm run typecheck:watch` to see full type checking errors. ### `npm test` -Launches the test runner in the interactive watch mode.\ +Launches the [test runner](https://vitest.dev/) in interactive mode (unless the `CI` environment variable is defined). See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. If you have a connected micro:bit device, then setting the environment variable `TEST_MODE_DEVICE=1` will enable additional tests that will connect to your micro:bit. The tests will overwrite programs and data on the micro:bit. @@ -55,10 +58,6 @@ We use [Puppeteer](https://pptr.dev/) and the helpers provided by [Testing Libra The CI tests run these end-to-end tests against a production build. -### `npm run test:all --testPathPattern autocomplete` - -An example of how to use jest options to filter to a specific subset of the tests (e2e or unit). - ### `npm run build` Builds the app for production to the `build` folder.\ @@ -68,11 +67,11 @@ It correctly bundles React in production mode and optimizes the build for the be Most users should use the supported Foundation deployment at https://python.microbit.org/ -The editor is deployed by [CircleCI](https://circleci.com/gh/microbit-foundation/python-editor-v3). +The editor is deployed by [GitHub actions](https://github.com/microbit-foundation/python-editor-v3/actions). The `main` branch is deployed to https://python.microbit.org/v/beta on each push. -Other branches (e.g. for PRs) are deployed to https://review-python-editor-v3.microbit.org/{branch}. Special characters in the branch name are replaced by hyphens. +Other branches (e.g. for PRs) are deployed to https://review-python-editor-v3.microbit.org/{branch}. Special characters in the branch name are replaced by hyphens. Deployments will not run in forks. ## License diff --git a/bin/crowdin-convert.js b/bin/crowdin-convert.cjs similarity index 100% rename from bin/crowdin-convert.js rename to bin/crowdin-convert.cjs diff --git a/bin/fix-licensing-headers.js b/bin/fix-licensing-headers.cjs similarity index 100% rename from bin/fix-licensing-headers.js rename to bin/fix-licensing-headers.cjs diff --git a/bin/print-ci-env-public-url.cjs b/bin/print-ci-env-public-url.cjs new file mode 100644 index 000000000..0b7e6c80a --- /dev/null +++ b/bin/print-ci-env-public-url.cjs @@ -0,0 +1,17 @@ +#!/usr/bin/env node +let baseUrl; +if (process.env.GITHUB_REPOSITORY_OWNER === "microbit-foundation") { + // STAGE must be defined before this is imported + const { bucketPrefix, bucketName } = require("../deployment.cjs"); + baseUrl = `/${bucketPrefix}/`; + + const fullUrl = `https://${bucketName}${baseUrl}`; + // This is used for og:url and similar. Not quite right for review domain but we don't really care. + console.log(`VITE_FULL_URL=${fullUrl}`); +} else { + baseUrl = "/"; +} + +// Two env vars as BASE_URL seems to be blank when running jest even if we set it. +console.log(`BASE_URL=${baseUrl}`); +console.log(`E2E_BASE_URL=${baseUrl}`); diff --git a/bin/print-ci-env-public-url.js b/bin/print-ci-env-public-url.js deleted file mode 100644 index 1b0f6aa0b..000000000 --- a/bin/print-ci-env-public-url.js +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env node -let url; -if (process.env.GITHUB_REPOSITORY_OWNER === "microbit-foundation") { - // STAGE must be defined before this is imported - const { bucketPrefix } = require("../deployment"); - url = `/${bucketPrefix}/`; -} else { - url = "/"; -} -// Two env vars as PUBLIC_URL seems to be blank when running jest even if we set it. -console.log(`PUBLIC_URL=${url}`); -console.log(`E2E_PUBLIC_URL=${url}`); diff --git a/bin/print-ci-env-stage.js b/bin/print-ci-env-stage.cjs similarity index 86% rename from bin/print-ci-env-stage.js rename to bin/print-ci-env-stage.cjs index 8fe0be3a4..8afa27508 100644 --- a/bin/print-ci-env-stage.js +++ b/bin/print-ci-env-stage.cjs @@ -10,4 +10,4 @@ if (ref === "refs/heads/main") { } console.log(`STAGE=${stage}`); -console.log(`REACT_APP_STAGE=${stage}`); +console.log(`VITE_STAGE=${stage}`); diff --git a/bin/tidy-lang.js b/bin/tidy-lang.cjs similarity index 100% rename from bin/tidy-lang.js rename to bin/tidy-lang.cjs diff --git a/deployment.js b/deployment.cjs similarity index 100% rename from deployment.js rename to deployment.cjs diff --git a/docs/tech-overview.md b/docs/tech-overview.md index fd159cbe7..d253c2bbe 100644 --- a/docs/tech-overview.md +++ b/docs/tech-overview.md @@ -6,11 +6,13 @@ The document assumes some familiarity with the app as a user. [Try it out](http: ## User interface -The editor is written in [TypeScript](https://www.typescriptlang.org/) using [React](https://reactjs.org/). The best documentation for React at the time of writing is their [beta documentation](https://beta.reactjs.org/). +The editor is written in [TypeScript](https://www.typescriptlang.org/) using [React](https://reactjs.org/). -We use the [Chakra UI component library](https://chakra-ui.com/docs/getting-started) which provides a base set of accessible components. We're currently using Chakra UI 1.x. +We use the [Chakra UI component library](https://chakra-ui.com/docs/getting-started) which provides a base set of accessible components. We're currently using Chakra UI 2.x. -The project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). We're using [Craco](https://github.com/dilanx/craco) to override some parts of the Create React App configuration. +The project is bundled using [Vite](https://vitejs.dev/). The test runner is [Vitest](https://vitest.dev/) and we're using [eslint](https://eslint.org/). + +We use Prettier to format code. Please set this up to format before committing changes, ideally on save (there's [a VS Code plugin](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)). The UI is split into different areas by the [workbench component](../src/workbench/Workbench.tsx). This component manages layout including expand/collapse of the sidebar and simulator and is a good starting point to navigate the codebase. The main areas are: @@ -18,7 +20,7 @@ The UI is split into different areas by the [workbench component](../src/workben 2. The main editing area with the text editor for the current file, header with the project title and the project action bar with buttons for key interactions. When a micro:bit device is connected over WebUSB, the serial area appears between the text editor and the project actions. 3. The simulator on the right, with its own serial area and controls. -The branding that you see on the [Foundation deployment](https://python.microbit.org/v/3) is not Open Source and is managed in a private GitHub project. This is swapped in via a webpack alias for `theme-package` configured by Craco. +The branding that you see on the [Foundation deployment](https://python.microbit.org/v/3) is not Open Source and is managed in a private GitHub project. This is swapped in via an alias for `theme-package` in the Vite config. ## Connecting to the micro:bit via WebUSB, flashing and hex files diff --git a/public/index.html b/index.html similarity index 61% rename from public/index.html rename to index.html index 00ae47ae9..149dbcbe5 100644 --- a/public/index.html +++ b/index.html @@ -2,7 +2,7 @@ - + micro:bit Python Editor @@ -11,26 +11,32 @@ property="og:description" content="Built by the Micro:bit Educational Foundation and the global Python Community." /> - - - <% if (process.env.REACT_APP_FOUNDATION_BUILD === 'true') { %> - - + + <% if (typeof VITE_FOUNDATION_BUILD !== 'undefined' && VITE_FOUNDATION_BUILD + === 'true') { %> + + <% } %> +