From 7dd7417f1248e10f3fe84fdc471d6da58cb5ce5c Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 11 Mar 2020 17:47:18 -0600 Subject: [PATCH] Enable support for TypeScript in components Includes: compilation, translations, IDE support (use .tsx not .ts), typings, and other build tools. TypeScript component have to import PropTypes and React with `import * as React from 'react';` --- package.json | 3 ++- scripts/gen-i18n.js | 2 +- scripts/reskindex.js | 11 +++++++---- src/utils/replaceableComponent.ts | 2 +- tsconfig.json | 3 ++- yarn.lock | 18 ++++++++++++++++++ 6 files changed, 31 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 26e6a6bf2e..e9bd23b58a 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "rethemendex": "res/css/rethemendex.sh", "clean": "rimraf lib", "build": "yarn clean && git rev-parse HEAD > git-revision.txt && yarn build:compile && yarn build:types", - "build:compile": "yarn reskindex && babel -d lib --verbose --extensions \".ts,.js\" src", + "build:compile": "yarn reskindex && babel -d lib --verbose --extensions \".ts,.js,.tsx\" src", "build:types": "tsc --emitDeclarationOnly", "start": "echo THIS IS FOR LEGACY PURPOSES ONLY. && yarn start:all", "start:all": "concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n build,reskindex \"yarn start:build\" \"yarn reskindex:watch\"", @@ -118,6 +118,7 @@ "@babel/preset-typescript": "^7.7.4", "@babel/register": "^7.7.4", "@peculiar/webcrypto": "^1.0.22", + "@types/react": "16.9", "babel-eslint": "^10.0.3", "babel-jest": "^24.9.0", "chokidar": "^3.3.1", diff --git a/scripts/gen-i18n.js b/scripts/gen-i18n.js index 3d3d5af116..a4d53aea2f 100755 --- a/scripts/gen-i18n.js +++ b/scripts/gen-i18n.js @@ -237,7 +237,7 @@ const walkOpts = { const fullPath = path.join(root, fileStats.name); let trs; - if (fileStats.name.endsWith('.js')) { + if (fileStats.name.endsWith('.js') || fileStats.name.endsWith('.tsx')) { trs = getTranslationsJs(fullPath); } else if (fileStats.name.endsWith('.html')) { trs = getTranslationsOther(fullPath); diff --git a/scripts/reskindex.js b/scripts/reskindex.js index 81ab111f46..9fb0e1a7c0 100755 --- a/scripts/reskindex.js +++ b/scripts/reskindex.js @@ -8,11 +8,14 @@ var chokidar = require('chokidar'); var componentIndex = path.join('src', 'component-index.js'); var componentIndexTmp = componentIndex+".tmp"; var componentsDir = path.join('src', 'components'); -var componentGlob = '**/*.js'; +var componentJsGlob = '**/*.js'; +var componentTsGlob = '**/*.tsx'; var prevFiles = []; function reskindex() { - var files = glob.sync(componentGlob, {cwd: componentsDir}).sort(); + var jsFiles = glob.sync(componentJsGlob, {cwd: componentsDir}).sort(); + var tsFiles = glob.sync(componentTsGlob, {cwd: componentsDir}).sort(); + var files = [...tsFiles, ...jsFiles]; if (!filesHaveChanged(files, prevFiles)) { return; } @@ -36,7 +39,7 @@ function reskindex() { strm.write("let components = {};\n"); for (var i = 0; i < files.length; ++i) { - var file = files[i].replace('.js', ''); + var file = files[i].replace('.js', '').replace('.tsx', ''); var moduleName = (file.replace(/\//g, '.')); var importName = moduleName.replace(/\./g, "$"); @@ -79,7 +82,7 @@ if (!args.w) { } var watchDebouncer = null; -chokidar.watch(path.join(componentsDir, componentGlob)).on('all', (event, path) => { +chokidar.watch(path.join(componentsDir, componentJsGlob)).on('all', (event, path) => { if (path === componentIndex) return; if (watchDebouncer) clearTimeout(watchDebouncer); watchDebouncer = setTimeout(reskindex, 1000); diff --git a/src/utils/replaceableComponent.ts b/src/utils/replaceableComponent.ts index 9f617b27f3..8c29fdf037 100644 --- a/src/utils/replaceableComponent.ts +++ b/src/utils/replaceableComponent.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React from 'react'; +import * as React from 'react'; import * as sdk from '../index'; /** diff --git a/tsconfig.json b/tsconfig.json index ec1531e429..ecb524e22e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,7 +10,8 @@ "outDir": "./lib", "declaration": true, "types": [ - "node" + "node", + "react" ] }, "include": [ diff --git a/yarn.lock b/yarn.lock index f6c4915a84..8056f3d435 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1217,6 +1217,19 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-13.7.6.tgz#cb734a7c191472ae6a2b3a502b4dfffcea974113" integrity sha512-eyK7MWD0R1HqVTp+PtwRgFeIsemzuj4gBFSQxfPHY5iMjS7474e5wq+VFgTcdpyHeNxyKSaetYAjdMLJlKoWqA== +"@types/prop-types@*": + version "15.7.3" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" + integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw== + +"@types/react@16.9": + version "16.9.23" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.23.tgz#1a66c6d468ba11a8943ad958a8cb3e737568271c" + integrity sha512-SsGVT4E7L2wLN3tPYLiF20hmZTPGuzaayVunfgXzUn1x4uHVsKH6QDJQ/TdpHqwsTLd4CwrmQ2vOgxN7gE24gw== + dependencies: + "@types/prop-types" "*" + csstype "^2.2.0" + "@types/stack-utils@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" @@ -2664,6 +2677,11 @@ cssstyle@^1.0.0: dependencies: cssom "0.3.x" +csstype@^2.2.0: + version "2.6.9" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.9.tgz#05141d0cd557a56b8891394c1911c40c8a98d098" + integrity sha512-xz39Sb4+OaTsULgUERcCk+TJj8ylkL4aSVDQiX/ksxbELSqwkgt4d4RD7fovIdgJGSuNYqwZEiVjYY5l0ask+Q== + currently-unhandled@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"