diff --git a/README.rst b/README.rst index d4bc758f4..e7e044bcd 100644 --- a/README.rst +++ b/README.rst @@ -157,6 +157,14 @@ You may create a `.env.private` with any overrides of the environment settings c **Note: .env.private should be added to your project's .gitignore so it does not get checked in.** +Local module configuration for TypeScript +----------------------------------------- + +#. Copy tsconfig.json into the root of the module +#. Set "rootDir" to the root of the source code folders +#. Set "include" to wildcard patterns specifying the subdirectories/files under rootDir where source code can be found +#. Include any wildcards under rootDir that should be excluded using "exclude" + Development ----------- diff --git a/config/jest.config.js b/config/jest.config.js index ae08b706f..716c0e10c 100644 --- a/config/jest.config.js +++ b/config/jest.config.js @@ -1,5 +1,6 @@ const path = require('path'); const fs = require('fs'); +const { jsWithTs: tsjPreset } = require('ts-jest/presets'); const presets = require('../lib/presets'); @@ -33,11 +34,12 @@ module.exports = { '/node_modules/(?!@edx)', ], transform: { - '^.+\\.[t|j]sx?$': [ + '^.+\\.jsx?$': [ 'babel-jest', { configFile: presets.babel.resolvedFilepath, }, ], + ...tsjPreset.transform, }, }; diff --git a/config/webpack.common.config.js b/config/webpack.common.config.js index 62c3aa348..8490a665c 100644 --- a/config/webpack.common.config.js +++ b/config/webpack.common.config.js @@ -17,6 +17,6 @@ module.exports = { // the application being built. 'env.config': false, }, - extensions: ['.js', '.jsx'], + extensions: ['.js', '.jsx', '.ts', '.tsx'], }, }; diff --git a/config/webpack.prod.config.js b/config/webpack.prod.config.js index 8634a4f9a..2db9ba5b1 100644 --- a/config/webpack.prod.config.js +++ b/config/webpack.prod.config.js @@ -71,12 +71,12 @@ module.exports = merge(commonConfig, { // The babel-loader transforms newer ES2015+ syntax to older ES5 for older browsers. // Babel is configured with the .babelrc file at the root of the project. { - test: /\.(js|jsx)$/, + test: /\.(js|jsx|ts|tsx)$/, exclude: /node_modules\/(?!@edx)/, use: { loader: 'babel-loader', options: { - configFile: presets.babel.resolvedFilepath, + configFile: presets['babel-typescript'].resolvedFilepath, }, }, }, diff --git a/example/src/App.jsx b/example/src/App.jsx index 2f1346339..8ef1e4417 100644 --- a/example/src/App.jsx +++ b/example/src/App.jsx @@ -1,4 +1,5 @@ import config from 'env.config'; +import Image from './Image'; import appleUrl, { ReactComponent as Apple } from './apple.svg'; import appleImg from './apple.jpg'; @@ -19,6 +20,8 @@ export default function App() {

JSX parsing tests

+

TSX parsing tests

+ appleFromTsx

Asset import tests

apple apple diff --git a/example/src/Image.tsx b/example/src/Image.tsx new file mode 100644 index 000000000..a8e7531e1 --- /dev/null +++ b/example/src/Image.tsx @@ -0,0 +1,11 @@ +import React, { CSSProperties } from "react"; + +type ImageProps = { + src: string; + alt?: string; + style?: CSSProperties; +}; + +export default function Image(props:ImageProps) { + return ; +} diff --git a/example/src/__snapshots__/App.test.jsx.snap b/example/src/__snapshots__/App.test.jsx.snap index 5666dd15d..551869852 100644 --- a/example/src/__snapshots__/App.test.jsx.snap +++ b/example/src/__snapshots__/App.test.jsx.snap @@ -39,6 +39,18 @@ exports[`Basic test should render 1`] = ` } } /> +

+ TSX parsing tests +

+ appleFromTsx

Asset import tests

diff --git a/package-lock.json b/package-lock.json index 4c520dd03..cc5410d64 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,9 +19,11 @@ "@babel/preset-react": "7.18.6", "@edx/eslint-config": "3.1.1", "@edx/new-relic-source-map-webpack-plugin": "1.0.2", + "@edx/typescript-config": "^1.0.0", "@fullhuman/postcss-purgecss": "^5.0.0", "@pmmmwh/react-refresh-webpack-plugin": "0.5.10", "@svgr/webpack": "6.5.1", + "@types/jest": "^26.0.0", "autoprefixer": "10.4.14", "babel-jest": "26.6.3", "babel-loader": "9.1.2", @@ -57,6 +59,8 @@ "sharp": "^0.31.0", "source-map-loader": "^4.0.1", "style-loader": "3.3.2", + "ts-jest": "^26.5.0", + "typescript": "^4.9.4", "url-loader": "4.1.1", "webpack": "5.76.0", "webpack-bundle-analyzer": "4.5.0", @@ -1949,6 +1953,16 @@ "@newrelic/publish-sourcemap": "^5.0.1" } }, + "node_modules/@edx/typescript-config": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@edx/typescript-config/-/typescript-config-1.0.0.tgz", + "integrity": "sha512-4Iip/UZyJ/Kn6fMbtzjpltTEssRdaeseYQAxiCeFOp3l5I6/Kt54UTQSYFYZtd8KtKSYNfXNXe1PqsZjYQf55w==", + "peerDependencies": { + "@types/jest": "^26.0.0", + "ts-jest": "^26.5.0", + "typescript": "^4.9.4" + } + }, "node_modules/@eslint/eslintrc": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", @@ -3471,6 +3485,15 @@ "@types/istanbul-lib-report": "*" } }, + "node_modules/@types/jest": { + "version": "26.0.24", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.24.tgz", + "integrity": "sha512-E/X5Vib8BWqZNRlDxj9vYXhsDwPYbPINqKF9BsnSoon4RQ0D9moEuLD8txgyypFLH7J4+Lho9Nr/c8H0Fi+17w==", + "dependencies": { + "jest-diff": "^26.0.0", + "pretty-format": "^26.0.0" + } + }, "node_modules/@types/json-schema": { "version": "7.0.11", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", @@ -4870,8 +4893,6 @@ "version": "0.2.6", "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", - "optional": true, - "peer": true, "dependencies": { "fast-json-stable-stringify": "2.x" }, @@ -11756,9 +11777,7 @@ "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "optional": true, - "peer": true + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" }, "node_modules/makeerror": { "version": "1.0.12", @@ -16160,8 +16179,6 @@ "version": "26.5.6", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.5.6.tgz", "integrity": "sha512-rua+rCP8DxpA8b4DQD/6X2HQS8Zy/xzViVYfEs2OQu68tkCuKLV0Md8pmX55+W24uRIyAsf/BajRfxOs+R2MKA==", - "optional": true, - "peer": true, "dependencies": { "bs-logger": "0.x", "buffer-from": "1.x", @@ -16189,8 +16206,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "optional": true, - "peer": true, "dependencies": { "yallist": "^4.0.0" }, @@ -16202,8 +16217,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "optional": true, - "peer": true, "bin": { "mkdirp": "bin/cmd.js" }, @@ -16215,8 +16228,6 @@ "version": "7.3.8", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "optional": true, - "peer": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -16230,9 +16241,7 @@ "node_modules/ts-jest/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "optional": true, - "peer": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/tsconfig-paths": { "version": "3.14.1", diff --git a/package.json b/package.json index efb719985..4a8c990a2 100644 --- a/package.json +++ b/package.json @@ -35,9 +35,11 @@ "@babel/preset-react": "7.18.6", "@edx/eslint-config": "3.1.1", "@edx/new-relic-source-map-webpack-plugin": "1.0.2", + "@edx/typescript-config": "^1.0.0", "@fullhuman/postcss-purgecss": "^5.0.0", "@pmmmwh/react-refresh-webpack-plugin": "0.5.10", "@svgr/webpack": "6.5.1", + "@types/jest": "^26.0.0", "autoprefixer": "10.4.14", "babel-jest": "26.6.3", "babel-loader": "9.1.2", @@ -73,6 +75,8 @@ "sharp": "^0.31.0", "source-map-loader": "^4.0.1", "style-loader": "3.3.2", + "ts-jest": "^26.5.0", + "typescript": "^4.9.4", "url-loader": "4.1.1", "webpack": "5.76.0", "webpack-bundle-analyzer": "4.5.0", diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..d603a1dbf --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "@edx/typescript-config", + "compilerOptions": { + "rootDir": "example", + "outDir": "dist" + }, + "include": ["example/**/*"], + "exclude": ["example/dist/*", "example/node_modules/*'"] +}