Skip to content

Commit

Permalink
TypeScript support in core (#4662)
Browse files Browse the repository at this point in the history
Co-authored-by: Nina <[email protected]>
Co-authored-by: Steve Piercy <[email protected]>
Co-authored-by: Piero Nicolli <[email protected]>
  • Loading branch information
4 people authored and erral committed Sep 19, 2023
1 parent 8592c34 commit 3f03d9f
Show file tree
Hide file tree
Showing 21 changed files with 2,615 additions and 915 deletions.
29 changes: 26 additions & 3 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"mocha": true,
"jasmine": true
},
"parser": "babel-eslint",
"parser": "@babel/eslint-parser",
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module",
Expand Down Expand Up @@ -38,14 +38,37 @@
["@package", "./src"],
["@root", "./src"]
],
"extensions": [".js", ".jsx", ".json"]
"extensions": [".js", ".jsx", ".ts", ".tsx", ".json"]
},
"babel-plugin-root-import": {
"rootPathSuffix": "src"
}
},
"import/core-modules": ["load-volto-addons"]
"import/core-modules": ["load-volto-addons"],
"react": {
"version": "detect"
}
},
"overrides": [
{
"files": ["**/*.ts", "**/*.tsx"],
// "react-app" already loads plugin:@typescript-eslint/eslint-plugin
// and it complains on having two different versions around.
// Re-add it if at some point, we stop relying on it
"extends": ["react-app", "prettier", "plugin:jsx-a11y/recommended"],
"plugins": ["prettier", "react-hooks", "jsx-a11y"],
"parser": "@typescript-eslint/parser"
},
{
"files": [
"**/*.stories.js",
"**/*.stories.jsx"
],
"rules": {
"import/no-anonymous-default-export": "off"
}
}
],
"globals": {
"root": true,
"__DEVELOPMENT__": true,
Expand Down
11 changes: 10 additions & 1 deletion addon-registry.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ const debug = require('debug')('shadowing');
const { map } = require('lodash');
const { DepGraph } = require('dependency-graph');

const excludedCompilerOptionsPaths = [
'@plone/volto/*',
'@plone/volto-slate/*',
'@root/*',
];

function getPackageBasePath(base) {
while (!fs.existsSync(`${base}/package.json`)) {
base = path.join(base, '../');
Expand Down Expand Up @@ -197,7 +203,10 @@ class AddonConfigurationRegistry {
addons: require(packageJsonPath).addons || [],
};

this.packages[name] = Object.assign(this.packages[name] || {}, pkg);
// Removed excluded paths from CompilerOptions
if (!excludedCompilerOptionsPaths.includes(name)) {
this.packages[name] = Object.assign(this.packages[name] || {}, pkg);
}
});
}
this.initPackagesFolder();
Expand Down
125 changes: 121 additions & 4 deletions docs/source/contributing/typescript.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,131 @@ myst:

# TypeScript

```{versionadded} 17.0.0-alpha.27
```

TypeScript support has been added to Volto core.
ESlint has been configured in order to accept code base written both in JavaScript and in TypeScript.
TypeScript in projects and add-ons has been supported since Volto 14.
It is now supported in the project generator by default.

## TypeScript in core

The internal policy for TypeScript support in Volto core will be as follows.

- No existing code has been migrated.
Volto 17.0.0 has no TypeScript code present.
Only *support* for TypeScript has been added.
- Code in core can be written in either JavaScript or TypeScript, or both.
- You are not forced to migrate existing code to TypeScript.
It's your choice which one to use.
- If you need to backport code to a version of Volto before 17.0.0, you must make the code compatible without TypeScript.

## TypeScript learning resources

- [TypeScript Official Handbook](https://www.typescriptlang.org/docs/handbook/intro.html)

- [TotalTypeScript React with TypeScript Free course](https://www.totaltypescript.com/tutorials/react-with-typescript)

- [TotalTypeScript Beginner's TypeScript Free course](https://www.totaltypescript.com/tutorials/beginners-typescript)

## TypeScript in projects and add-ons

You can enable TypeScript support when developing your project in Volto.
If you use the Volto generator, TypeScript is enabled by default, and you can already start using TypeScript in it.

### Enable it in your Volto 17 project

If you already use Volto 17 in your projects, using a boilerplate generated before Volto 17.0.0-alpha.27 and the generator 7.0.0-alpha.7, you can enable TypeScript support as follows:

Edit your {file}`package.json`:

```diff
- "lint": "./node_modules/eslint/bin/eslint.js --max-warnings=0 'src/**/*.{js,jsx}'",
- "lint:fix": "./node_modules/eslint/bin/eslint.js --max-warnings=0 --fix 'src/**/*.{js,jsx}'",
- "lint:ci": "./node_modules/eslint/bin/eslint.js --max-warnings=0 -f checkstyle 'src/**/*.{js,jsx}' > eslint.xml",
+ "lint": "./node_modules/eslint/bin/eslint.js --max-warnings=0 'src/**/*.{js,jsx,ts,tsx,json}'",
+ "lint:fix": "./node_modules/eslint/bin/eslint.js --fix 'src/**/*.{js,jsx,ts,tsx,json}'",
+ "lint:ci": "./node_modules/eslint/bin/eslint.js --max-warnings=0 -f checkstyle 'src/**/*.{js,jsx,ts,tsx,json}' > eslint.xml",
```

```diff
"devDependencies": {
+ "@plone/scripts": ^3.0.0,
+ "@typescript-eslint/eslint-plugin": "6.7.0",
+ "@typescript-eslint/parser": "6.7.0",
+ "stylelint-prettier": "1.1.2",
+ "ts-jest": "^26.4.2",
+ "ts-loader": "9.4.4",
+ "typescript": "5.2.2"
}
```

```{note}
This feature is available since Volto 14. Please note that TypeScript is *not* allowed in Volto core, that's why it's not enabled in the core by default. This feature enables the use of TypeScript (as opt-in) in projects and in add-ons.
After making this change, you might experience hoisting problems and some packages can't be found on start.
In that case, make sure you reset your `yarn.lock` by deleting it and start with a clean environment.
```

To use TypeScript in your projects, you'll need to introduce a TypeScript configuration file {file}`tsconfig.json`, and remove the existing file {file}`jsconfig.json`.
You can use the one provided by the generator as a template, or use your own:

```json
{
"compilerOptions": {
"target": "ESNext",
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"module": "commonjs",
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "Node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
"paths": {},
"baseUrl": "src"
},
"include": ["src"],
"exclude": [
"node_modules",
"build",
"public",
"coverage",
"src/**/*.test.{js,jsx,ts,tsx}",
"src/**/*.spec.{js,jsx,ts,tsx}",
"src/**/*.stories.{js,jsx,ts,tsx}"
]
}
```

If you use `mrs-developer` in your project, update the command in {file}`Makefile`:

```diff
--- a/Makefile
+++ b/Makefile
@@ -59,7 +59,8 @@ preinstall: ## Preinstall task, checks if missdev (mrs-developer) is present and runs it

.PHONY: develop
develop: ## Runs missdev in the local project (mrs.developer.json should be present)
- npx -p mrs-developer missdev --config=jsconfig.json --output=addons --fetch-https
+ if [ -f $$(pwd)/jsconfig.json ]; then npx -p mrs-developer missdev --config=jsconfig.json --output=addons --fetch-https; fi
+ if [ ! -f $$(pwd)/jsconfig.json ]; then npx -p mrs-developer missdev --output=addons --fetch-https; fi
```

````{note}
After editing your {file}`Makefile`, run `mrs-developer` with the following command, so the configuration gets in the right place ({file}`tsconfig.json`).
```shell
make develop
```
````

It is possible to enable TypeScript support when developing you project with Volto.
Volto itself is not written in TypeScript, but it is ready to use it if you want.
### Enable it in a project not using Volto 17 yet

In order to enable TypeScript, you need to install these additional dependencies in your project:
To use TypeScript for an existing project in Volto versions 14.x-16.x, you need to install these additional dependencies in your project:

```shell
yarn add --dev typescript @typescript-eslint/parser @typescript-eslint/eslint-plugin @types/react @types/react-dom concurrently
Expand Down
114 changes: 114 additions & 0 deletions docs/source/upgrade-guide/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,120 @@ or use Webpack plugins, you might need to make adjustments.
Razzle has been upgraded to version `4.2.18`.
It is recommended that you update your project's dependency on Razzle to this version in order to avoid duplication.

### TypeScript support in Volto

```{versionadded} 17.0.0-alpha.27
```

We added full support of TypeScript in Volto core.

No existing code has been migrated.
You may write code in either JavaScript or TypeScript.
The choice is yours.

Previously developers had the option to support TypeScript only in their Volto add-ons.
Now it's available in Volto projects, as long as you upgrade your project dependencies.

To support TypeScript in your projects, you must update your project as follows.

Edit your {file}`package.json`:

```diff
"scripts": {
- "lint": "./node_modules/eslint/bin/eslint.js --max-warnings=0 'src/**/*.{js,jsx}'",
- "lint:fix": "./node_modules/eslint/bin/eslint.js --max-warnings=0 --fix 'src/**/*.{js,jsx}'",
- "lint:ci": "./node_modules/eslint/bin/eslint.js --max-warnings=0 -f checkstyle 'src/**/*.{js,jsx}' > eslint.xml",
+ "lint": "./node_modules/eslint/bin/eslint.js --max-warnings=0 'src/**/*.{js,jsx,ts,tsx,json}'",
+ "lint:fix": "./node_modules/eslint/bin/eslint.js --fix 'src/**/*.{js,jsx,ts,tsx,json}'",
+ "lint:ci": "./node_modules/eslint/bin/eslint.js --max-warnings=0 -f checkstyle 'src/**/*.{js,jsx,ts,tsx,json}' > eslint.xml",
}
```

```diff
"devDependencies": {
+ "@plone/scripts": ^3.0.0,
+ "@typescript-eslint/eslint-plugin": "6.7.0",
+ "@typescript-eslint/parser": "6.7.0",
+ "stylelint-prettier": "1.1.2",
+ "ts-jest": "^26.4.2",
+ "ts-loader": "9.4.4",
+ "typescript": "5.2.2"
}
```

```{note}
After making this change, you might experience hoisting problems and some packages can't be found on start.
In that case, make sure you reset your `yarn.lock` by deleting it and start with a clean environment.
```

To use TypeScript in your projects, you'll need to introduce a TypeScript configuration file {file}`tsconfig.json`, and remove the existing file {file}`jsconfig.json`.
You can use the one provided by the generator as a template, or use your own:

```json
{
"compilerOptions": {
"target": "ESNext",
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"module": "commonjs",
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "Node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
"paths": {},
"baseUrl": "src"
},
"include": ["src"],
"exclude": [
"node_modules",
"build",
"public",
"coverage",
"src/**/*.test.{js,jsx,ts,tsx}",
"src/**/*.spec.{js,jsx,ts,tsx}",
"src/**/*.stories.{js,jsx,ts,tsx}"
]
}
```

If you use `mrs-developer` in your project, update the command in {file}`Makefile`:

```diff
--- a/Makefile
+++ b/Makefile
preinstall: ## Preinstall task, checks if missdev (mrs-developer) is present and runs it

.PHONY: develop
develop: ## Runs missdev in the local project (mrs.developer.json should be present)
- npx -p mrs-developer missdev --config=jsconfig.json --output=addons --fetch-https
+ if [ -f $$(pwd)/jsconfig.json ]; then npx -p mrs-developer missdev --config=jsconfig.json --output=addons --fetch-https; fi
+ if [ ! -f $$(pwd)/jsconfig.json ]; then npx -p mrs-developer missdev --output=addons --fetch-https; fi
```

````{note}
After editing your {file}`Makefile`, run `mrs-developer` with the following command, so the configuration gets in the right place ({file}`tsconfig.json`).
```shell
make develop
```
````

### Upgrade ESlint and use `@babel/eslint-parser`

```{versionchanged} 17.0.0-alpha.27
```

ESlint uses a library to parse the language under analysis.
The one used was long deprecated and didn't supported both TypeScript and JavaScript.
We upgraded the ESlint parser to use `@babel/eslint-parser`.
This means when you upgrade your project, some new violations may appear.
Once upgraded, run the linters again to make sure that your code is free of violations.

### `BlockChooser` component now uses `popperjs` internally

Technically not a breaking, the API nor the component contract has changed, but it's worth noting this change in here.
Expand Down
1 change: 1 addition & 0 deletions news/4662.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TypeScript support in core @sneridagh @ninanoleto
Loading

0 comments on commit 3f03d9f

Please sign in to comment.