From e053a5ec93b7f907b681f2ffc64c1b7878c93b1b Mon Sep 17 00:00:00 2001 From: Hugo Alliaume Date: Fri, 7 Feb 2020 22:07:39 +0100 Subject: [PATCH 1/7] fix(fixtures): use "better" syntax for TypeScript import/export --- fixtures/js/index.ts | 4 ++-- fixtures/js/render.ts | 2 +- fixtures/js/render2.tsx | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fixtures/js/index.ts b/fixtures/js/index.ts index 7ff32dcf..a9f060b6 100644 --- a/fixtures/js/index.ts +++ b/fixtures/js/index.ts @@ -1,3 +1,3 @@ -import render = require('./render'); +import render from './render'; -render(); \ No newline at end of file +render(); diff --git a/fixtures/js/render.ts b/fixtures/js/render.ts index 1a3c83f2..f8783a21 100644 --- a/fixtures/js/render.ts +++ b/fixtures/js/render.ts @@ -2,4 +2,4 @@ function render() { document.getElementById('app').innerHTML = "

Welcome to Your TypeScript App

"; } -export = render; \ No newline at end of file +export default render; diff --git a/fixtures/js/render2.tsx b/fixtures/js/render2.tsx index 1a3c83f2..f8783a21 100644 --- a/fixtures/js/render2.tsx +++ b/fixtures/js/render2.tsx @@ -2,4 +2,4 @@ function render() { document.getElementById('app').innerHTML = "

Welcome to Your TypeScript App

"; } -export = render; \ No newline at end of file +export default render; From 2e21d4f2b22e54f8e8f4ff42e7beaef8cb79fbc6 Mon Sep 17 00:00:00 2001 From: Hugo Alliaume Date: Fri, 7 Feb 2020 22:08:20 +0100 Subject: [PATCH 2/7] chore(deps-dev): install Babel TypeScript preset, with class properties plugin --- package.json | 2 + yarn.lock | 160 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+) diff --git a/package.json b/package.json index 72e76002..ec008e23 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,9 @@ }, "devDependencies": { "@babel/plugin-transform-react-jsx": "^7.0.0", + "@babel/plugin-proposal-class-properties": "^7.0.0", "@babel/preset-react": "^7.0.0", + "@babel/preset-typescript": "^7.0.0", "@vue/babel-helper-vue-jsx-merge-props": "^1.0.0-beta.3", "@vue/babel-preset-jsx": "^1.0.0-beta.3", "autoprefixer": "^8.5.0", diff --git a/yarn.lock b/yarn.lock index 88a87f49..4749a534 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9,6 +9,13 @@ dependencies: "@babel/highlight" "^7.0.0" +"@babel/code-frame@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e" + integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g== + dependencies: + "@babel/highlight" "^7.8.3" + "@babel/core@^7.4.0": version "7.6.2" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.6.2.tgz#069a776e8d5e9eefff76236bc8845566bd31dd91" @@ -39,6 +46,16 @@ lodash "^4.17.13" source-map "^0.5.0" +"@babel/generator@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.4.tgz#35bbc74486956fe4251829f9f6c48330e8d0985e" + integrity sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA== + dependencies: + "@babel/types" "^7.8.3" + jsesc "^2.5.1" + lodash "^4.17.13" + source-map "^0.5.0" + "@babel/helper-annotate-as-pure@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz#323d39dd0b50e10c7c06ca7d7638e6864d8c5c32" @@ -71,6 +88,18 @@ "@babel/traverse" "^7.4.4" "@babel/types" "^7.4.4" +"@babel/helper-create-class-features-plugin@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.8.3.tgz#5b94be88c255f140fd2c10dd151e7f98f4bff397" + integrity sha512-qmp4pD7zeTxsv0JNecSBsEmG1ei2MqwJq4YQcK3ZWm/0t07QstWfvuV/vm3Qt5xNMFETn2SZqpMx2MQzbtq+KA== + dependencies: + "@babel/helper-function-name" "^7.8.3" + "@babel/helper-member-expression-to-functions" "^7.8.3" + "@babel/helper-optimise-call-expression" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-replace-supers" "^7.8.3" + "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/helper-define-map@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.5.5.tgz#3dec32c2046f37e09b28c93eb0b103fd2a25d369" @@ -97,6 +126,15 @@ "@babel/template" "^7.1.0" "@babel/types" "^7.0.0" +"@babel/helper-function-name@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz#eeeb665a01b1f11068e9fb86ad56a1cb1a824cca" + integrity sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA== + dependencies: + "@babel/helper-get-function-arity" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/types" "^7.8.3" + "@babel/helper-get-function-arity@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3" @@ -104,6 +142,13 @@ dependencies: "@babel/types" "^7.0.0" +"@babel/helper-get-function-arity@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz#b894b947bd004381ce63ea1db9f08547e920abd5" + integrity sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA== + dependencies: + "@babel/types" "^7.8.3" + "@babel/helper-hoist-variables@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz#0298b5f25c8c09c53102d52ac4a98f773eb2850a" @@ -118,6 +163,13 @@ dependencies: "@babel/types" "^7.5.5" +"@babel/helper-member-expression-to-functions@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz#659b710498ea6c1d9907e0c73f206eee7dadc24c" + integrity sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA== + dependencies: + "@babel/types" "^7.8.3" + "@babel/helper-module-imports@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d" @@ -144,11 +196,23 @@ dependencies: "@babel/types" "^7.0.0" +"@babel/helper-optimise-call-expression@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz#7ed071813d09c75298ef4f208956006b6111ecb9" + integrity sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ== + dependencies: + "@babel/types" "^7.8.3" + "@babel/helper-plugin-utils@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== +"@babel/helper-plugin-utils@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz#9ea293be19babc0f52ff8ca88b34c3611b208670" + integrity sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ== + "@babel/helper-regex@^7.0.0", "@babel/helper-regex@^7.4.4": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.5.5.tgz#0aa6824f7100a2e0e89c1527c23936c152cab351" @@ -177,6 +241,16 @@ "@babel/traverse" "^7.5.5" "@babel/types" "^7.5.5" +"@babel/helper-replace-supers@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.8.3.tgz#91192d25f6abbcd41da8a989d4492574fb1530bc" + integrity sha512-xOUssL6ho41U81etpLoT2RTdvdus4VfHamCuAm4AHxGr+0it5fnwoVdwUJ7GFEqCsQYzJUhcbsN9wB9apcYKFA== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.8.3" + "@babel/helper-optimise-call-expression" "^7.8.3" + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" + "@babel/helper-simple-access@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz#65eeb954c8c245beaa4e859da6188f39d71e585c" @@ -192,6 +266,13 @@ dependencies: "@babel/types" "^7.4.4" +"@babel/helper-split-export-declaration@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz#31a9f30070f91368a7182cf05f831781065fc7a9" + integrity sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA== + dependencies: + "@babel/types" "^7.8.3" + "@babel/helper-wrap-function@^7.1.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz#c4e0012445769e2815b55296ead43a958549f6fa" @@ -220,11 +301,25 @@ esutils "^2.0.2" js-tokens "^4.0.0" +"@babel/highlight@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.8.3.tgz#28f173d04223eaaa59bc1d439a3836e6d1265797" + integrity sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg== + dependencies: + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^4.0.0" + "@babel/parser@^7.0.0", "@babel/parser@^7.6.0", "@babel/parser@^7.6.2": version "7.6.2" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.2.tgz#205e9c95e16ba3b8b96090677a67c9d6075b70a1" integrity sha512-mdFqWrSPCmikBoaBYMuBulzTIKuXVPtEISFbRRVNwMWpCms/hmE2kRq0bblUHaNRKrjRlmVbx1sDHmjmRgD2Xg== +"@babel/parser@^7.8.3", "@babel/parser@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.4.tgz#d1dbe64691d60358a974295fa53da074dd2ce8e8" + integrity sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw== + "@babel/plugin-proposal-async-generator-functions@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz#b289b306669dce4ad20b0252889a15768c9d417e" @@ -234,6 +329,14 @@ "@babel/helper-remap-async-to-generator" "^7.1.0" "@babel/plugin-syntax-async-generators" "^7.2.0" +"@babel/plugin-proposal-class-properties@^7.0.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.8.3.tgz#5e06654af5cd04b608915aada9b2a6788004464e" + integrity sha512-EqFhbo7IosdgPgZggHaNObkmO1kNUe3slaKu54d5OWvy+p9QIKOzK1GAEpAIsZtWVtPXUHSMcT4smvDrCfY4AA== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-proposal-dynamic-import@^7.5.0": version "7.5.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.5.0.tgz#e532202db4838723691b10a67b8ce509e397c506" @@ -317,6 +420,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-syntax-typescript@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.8.3.tgz#c1f659dda97711a569cef75275f7e15dcaa6cabc" + integrity sha512-GO1MQ/SGGGoiEXY0e0bSpHimJvxqB7lktLLIq2pv8xG7WZ8IMEle74jIe1FhprHBWjwjZtXHkycDLZXIWM5Wfg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-transform-arrow-functions@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz#9aeafbe4d6ffc6563bf8f8372091628f00779550" @@ -586,6 +696,15 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-typescript@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.8.3.tgz#be6f01a7ef423be68e65ace1f04fc407e6d88917" + integrity sha512-Ebj230AxcrKGZPKIp4g4TdQLrqX95TobLUWKd/CwG7X1XHUH1ZpkpFvXuXqWbtGRWb7uuEWNlrl681wsOArAdQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-typescript" "^7.8.3" + "@babel/plugin-transform-unicode-regex@^7.6.2": version "7.6.2" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.6.2.tgz#b692aad888a7e8d8b1b214be6b9dc03d5031f698" @@ -662,6 +781,14 @@ "@babel/plugin-transform-react-jsx-self" "^7.0.0" "@babel/plugin-transform-react-jsx-source" "^7.0.0" +"@babel/preset-typescript@^7.0.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.8.3.tgz#90af8690121beecd9a75d0cc26c6be39d1595d13" + integrity sha512-qee5LgPGui9zQ0jR1TeU5/fP9L+ovoArklEqY12ek8P/wV5ZeM/VYSQYwICeoT6FfpJTekG9Ilay5PhwsOpMHA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-transform-typescript" "^7.8.3" + "@babel/template@^7.1.0", "@babel/template@^7.4.4", "@babel/template@^7.6.0": version "7.6.0" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.6.0.tgz#7f0159c7f5012230dad64cca42ec9bdb5c9536e6" @@ -671,6 +798,15 @@ "@babel/parser" "^7.6.0" "@babel/types" "^7.6.0" +"@babel/template@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.3.tgz#e02ad04fe262a657809327f578056ca15fd4d1b8" + integrity sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/parser" "^7.8.3" + "@babel/types" "^7.8.3" + "@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.4.4", "@babel/traverse@^7.5.5", "@babel/traverse@^7.6.2": version "7.6.2" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.6.2.tgz#b0e2bfd401d339ce0e6c05690206d1e11502ce2c" @@ -686,6 +822,21 @@ globals "^11.1.0" lodash "^4.17.13" +"@babel/traverse@^7.8.3": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.4.tgz#f0845822365f9d5b0e312ed3959d3f827f869e3c" + integrity sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.8.4" + "@babel/helper-function-name" "^7.8.3" + "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/parser" "^7.8.4" + "@babel/types" "^7.8.3" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.13" + "@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.3.0", "@babel/types@^7.4.4", "@babel/types@^7.5.5", "@babel/types@^7.6.0": version "7.6.1" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.6.1.tgz#53abf3308add3ac2a2884d539151c57c4b3ac648" @@ -695,6 +846,15 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" +"@babel/types@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.3.tgz#5a383dffa5416db1b73dedffd311ffd0788fb31c" + integrity sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg== + dependencies: + esutils "^2.0.2" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + "@types/events@*": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" From 66067a07b8913d23a884034bb4474fef302de522 Mon Sep 17 00:00:00 2001 From: Hugo Alliaume Date: Fri, 7 Feb 2020 22:10:42 +0100 Subject: [PATCH 3/7] test: add test for TypeScript "compilation" with Babel --- fixtures/js/tsconfig.json | 6 ++++-- test/functional.js | 44 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/fixtures/js/tsconfig.json b/fixtures/js/tsconfig.json index 4ee3592b..34cf7dd5 100644 --- a/fixtures/js/tsconfig.json +++ b/fixtures/js/tsconfig.json @@ -1,3 +1,5 @@ { - "compilerOptions": {} -} \ No newline at end of file + "compilerOptions": { + "allowSyntheticDefaultImports": true + } +} diff --git a/test/functional.js b/test/functional.js index 8e83c4bc..b0aab7a1 100644 --- a/test/functional.js +++ b/test/functional.js @@ -1321,6 +1321,50 @@ module.exports = { }).to.throw('wrong `tsconfig` path in fork plugin configuration (should be a relative or absolute path)'); }); + it('TypeScript can be compiled by Babel', (done) => { + const config = createWebpackConfig('www/build', 'dev'); + config.setPublicPath('/build'); + config.addEntry('main', ['./js/render.ts', './js/index.ts']); + config.configureBabel(function(config) { + config.presets = [ + ['@babel/preset-env', { + 'targets': { + 'chrome': 52, + }, + }], + '@babel/typescript', // required preset + ]; + // not required, but recommended + config.plugins = ['@babel/proposal-class-properties']; + }); + + config.configureLoaderRule('javascript', loader => { + loader.test = /.(j|t)sx?$/; // let Babel to run over .tsx? files too + }); + + testSetup.runWebpack(config, (webpackAssert) => { + // check that babel-loader transformed the ts file + webpackAssert.assertOutputFileContains( + 'main.js', + 'document.getElementById(\'app\').innerHTML =', + ); + + testSetup.requestTestPage( + path.join(config.getContext(), 'www'), + [ + 'build/runtime.js', + 'build/main.js', + ], + (browser) => { + + // assert that the ts module rendered + browser.assert.text('#app h1', 'Welcome to Your TypeScript App'); + done(); + }, + ); + }); + }); + it('When configured, Handlebars is compiled', (done) => { const config = createWebpackConfig('www/build', 'dev'); config.setPublicPath('/build'); From 8238c3260ee730c6500b712c496e9ed6950eb8d8 Mon Sep 17 00:00:00 2001 From: Hugo Alliaume Date: Thu, 13 Feb 2020 22:05:44 +0100 Subject: [PATCH 4/7] fixture: add code that only works in TypeScript --- fixtures/js/render.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fixtures/js/render.ts b/fixtures/js/render.ts index f8783a21..db797835 100644 --- a/fixtures/js/render.ts +++ b/fixtures/js/render.ts @@ -1,5 +1,6 @@ function render() { - document.getElementById('app').innerHTML = "

Welcome to Your TypeScript App

"; + const html: string = "

Welcome to Your TypeScript App

"; + document.getElementById('app').innerHTML = html; } export default render; From 6f992b0e7450eece443f8d35707ec85a7943aa95 Mon Sep 17 00:00:00 2001 From: Hugo Alliaume Date: Fri, 20 Mar 2020 23:52:12 +0100 Subject: [PATCH 5/7] feat: prepare method "enableBabelTypeScriptPreset" --- index.js | 38 +++++++++++++++++++++++++++++++++++++- lib/WebpackConfig.js | 20 ++++++++++++++++++++ test/WebpackConfig.js | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 3c7e7906..630d5ead 100644 --- a/index.js +++ b/index.js @@ -980,7 +980,7 @@ class Encore { /** * If enabled, a Preact preset will be applied to - * the generated Webpack configuration. + * the generated Webpack and Babel configuration. * * ``` * Encore.enablePreactPreset() @@ -1044,6 +1044,42 @@ class Encore { return this; } + + /** + * If enabled, a TypeScript preset will be applied to + * the generated Webpack and Babel configuration. + * + * ``` + * Encore.enableBabelTypeScriptPreset() + * ``` + * + * This method let Babel handle your TypeScript code + * and can not be used with `Encore.enableTypeScriptLoader()` + * or `Encore.enableForkedTypeScriptTypesChecking()`. + * + * Since all types are removed by Babel, + * you must run `tsc --noEmit` yourself for types checking. + * + * The Babel TypeScript preset can be configured, + * see https://babeljs.io/docs/en/babel-preset-typescript#options + * for available options. + * + * For example: + * ``` + * Encore.enableBabelTypeScriptPreset({ + * isTSX: true + * }) + * ``` + * + * @param {object} options + * @returns {Encore} + */ + enableBabelTypeScriptPreset(options) { + webpackConfig.enableBabelTypeScriptPreset(options); + + return this; + } + /** * If enabled, the Vue.js loader is enabled. * diff --git a/lib/WebpackConfig.js b/lib/WebpackConfig.js index 308a2217..4d67cbd9 100644 --- a/lib/WebpackConfig.js +++ b/lib/WebpackConfig.js @@ -109,6 +109,7 @@ class WebpackConfig { this.useEslintLoader = false; this.useTypeScriptLoader = false; this.useForkedTypeScriptTypeChecking = false; + this.useBabelTypeScriptPreset = false; this.useWebpackNotifier = false; this.useHandlebarsLoader = false; @@ -647,6 +648,10 @@ class WebpackConfig { } enableTypeScriptLoader(callback = () => {}) { + if (this.useBabelTypeScriptPreset) { + throw new Error('Encore.enableTypeScriptLoader() can not be called when Encore.enableBabelTypeScriptPreset() has been called.'); + } + this.useTypeScriptLoader = true; if (typeof callback !== 'function') { @@ -657,6 +662,9 @@ class WebpackConfig { } enableForkedTypeScriptTypesChecking(forkedTypeScriptTypesCheckOptionsCallback = () => {}) { + if (this.useBabelTypeScriptPreset) { + throw new Error('Encore.enableBabelTypeScriptPreset() can not be called when Encore.enableForkedTypeScriptTypesChecking() has been called.'); + } if (typeof forkedTypeScriptTypesCheckOptionsCallback !== 'function') { throw new Error('Argument 1 to enableForkedTypeScriptTypesChecking() must be a callback function.'); @@ -667,6 +675,18 @@ class WebpackConfig { forkedTypeScriptTypesCheckOptionsCallback; } + enableBabelTypeScriptPreset(options = {}) { + if (this.useTypeScriptLoader) { + throw new Error('Encore.enableBabelTypeScriptPreset() can not be called when Encore.enableTypeScriptLoader() has been called.'); + } + + if (this.useForkedTypeScriptTypeChecking) { + throw new Error('Encore.enableBabelTypeScriptPreset() can not be called when Encore.enableForkedTypeScriptTypesChecking() has been called.'); + } + + this.useBabelTypeScriptPreset = true; + } + enableVueLoader(vueLoaderOptionsCallback = () => {}, vueOptions = {}) { this.useVueLoader = true; diff --git a/test/WebpackConfig.js b/test/WebpackConfig.js index b2311fbb..e2b1438e 100644 --- a/test/WebpackConfig.js +++ b/test/WebpackConfig.js @@ -872,6 +872,15 @@ describe('WebpackConfig object', () => { config.enableTypeScriptLoader('FOO'); }).to.throw('must be a callback function'); }); + + it('TypeScript can not be compiled by ts-loader is Babel is already handling TypeScript', () => { + const config = createConfig(); + config.enableBabelTypeScriptPreset(); + + expect(function() { + config.enableTypeScriptLoader(); + }).to.throw('Encore.enableTypeScriptLoader() can not be called when Encore.enableBabelTypeScriptPreset() has been called.'); + }); }); describe('enableForkedTypeScriptTypesChecking', () => { @@ -891,8 +900,37 @@ describe('WebpackConfig object', () => { config.enableForkedTypeScriptTypesChecking('FOO'); }).to.throw('must be a callback function'); }); + + it('TypeScript can not be compiled by Babel if forked types checking is enabled', () => { + const config = createConfig(); + config.enableForkedTypeScriptTypesChecking(); + + expect(function() { + config.enableBabelTypeScriptPreset(); + }).to.throw('Encore.enableBabelTypeScriptPreset() can not be called when Encore.enableForkedTypeScriptTypesChecking() has been called.'); + }); }); + describe('enableBabelTypeScriptPreset', () => { + it('TypeScript can not be compiled by Babel if ts-loader is already enabled', () => { + const config = createConfig(); + config.enableTypeScriptLoader(); + + expect(function() { + config.enableBabelTypeScriptPreset(); + }).to.throw('Encore.enableBabelTypeScriptPreset() can not be called when Encore.enableTypeScriptLoader() has been called.'); + }); + + it('TypeScript can not be compiled by Babel if ts-loader is already enabled', () => { + const config = createConfig(); + config.enableForkedTypeScriptTypesChecking(); + + expect(function() { + config.enableBabelTypeScriptPreset(); + }).to.throw('Encore.enableBabelTypeScriptPreset() can not be called when Encore.enableForkedTypeScriptTypesChecking() has been called.'); + }); + }) + describe('enableVueLoader', () => { it('Call with no config', () => { const config = createConfig(); From 96a666b7f8b21296c68d52c0a541a51e86b13afe Mon Sep 17 00:00:00 2001 From: Hugo Alliaume Date: Sat, 21 Mar 2020 08:34:19 +0100 Subject: [PATCH 6/7] feat: implement Encore.enableBabelTypeScriptPreset() --- lib/WebpackConfig.js | 2 ++ lib/config-generator.js | 3 +-- lib/features.js | 9 +++++++++ lib/loaders/babel.js | 23 +++++++++++++++++++++++ test/WebpackConfig.js | 11 ++++++++++- test/config-generator.js | 14 +++++++------- test/functional.js | 17 +---------------- test/loaders/babel.js | 37 +++++++++++++++++++++++++++++++++++++ 8 files changed, 90 insertions(+), 26 deletions(-) diff --git a/lib/WebpackConfig.js b/lib/WebpackConfig.js index 4d67cbd9..87fd3825 100644 --- a/lib/WebpackConfig.js +++ b/lib/WebpackConfig.js @@ -131,6 +131,7 @@ class WebpackConfig { useBuiltIns: false, corejs: null, }; + this.babelTypeScriptPresetOptions = {}; this.vueOptions = { useJsx: false, }; @@ -685,6 +686,7 @@ class WebpackConfig { } this.useBabelTypeScriptPreset = true; + this.babelTypeScriptPresetOptions = options; } enableVueLoader(vueLoaderOptionsCallback = () => {}, vueOptions = {}) { diff --git a/lib/config-generator.js b/lib/config-generator.js index 087080c8..5ded1555 100644 --- a/lib/config-generator.js +++ b/lib/config-generator.js @@ -250,8 +250,7 @@ class ConfigGenerator { let rules = [ applyRuleConfigurationCallback('javascript', { - // match .js and .jsx - test: /\.jsx?$/, + test: babelLoaderUtil.getTest(this.webpackConfig), exclude: this.webpackConfig.babelOptions.exclude, use: babelLoaderUtil.getLoaders(this.webpackConfig) }), diff --git a/lib/features.js b/lib/features.js index d8a27fe1..dd100af4 100644 --- a/lib/features.js +++ b/lib/features.js @@ -78,6 +78,15 @@ const features = { ], description: 'check TypeScript types in a separate process' }, + 'typescript-babel': { + method: 'enableBabelTypeScriptPreset', + packages: [ + { name: 'typescript' }, + { name: '@babel/preset-typescript', enforce_version: true }, + { name: '@babel/plugin-proposal-class-properties', enforce_version: true }, + ], + description: 'process TypeScript files with Babel' + }, vue: { method: 'enableVueLoader()', // vue is needed so the end-user can do things diff --git a/lib/loaders/babel.js b/lib/loaders/babel.js index d5a16892..10e124cf 100644 --- a/lib/loaders/babel.js +++ b/lib/loaders/babel.js @@ -58,6 +58,13 @@ module.exports = { plugins: ['@babel/plugin-syntax-dynamic-import'] }); + if (webpackConfig.useBabelTypeScriptPreset) { + loaderFeatures.ensurePackagesExistAndAreCorrectVersion('typescript-babel'); + + babelConfig.presets.push(['@babel/preset-typescript', webpackConfig.babelTypeScriptPresetOptions]); + babelConfig.plugins.push('@babel/plugin-proposal-class-properties'); + } + if (webpackConfig.useReact) { loaderFeatures.ensurePackagesExistAndAreCorrectVersion('react'); @@ -95,5 +102,21 @@ module.exports = { options: babelConfig } ]; + }, + + /** + * @param {WebpackConfig} webpackConfig + * @return {RegExp} to use for eslint-loader `test` rule + */ + getTest(webpackConfig) { + const extensions = [ + 'jsx?', // match .js and .jsx + ]; + + if (webpackConfig.useBabelTypeScriptPreset) { + extensions.push('tsx?'); // match .ts and .tsx + } + + return new RegExp(`\\.(${extensions.join('|')})$`); } }; diff --git a/test/WebpackConfig.js b/test/WebpackConfig.js index e2b1438e..f998419e 100644 --- a/test/WebpackConfig.js +++ b/test/WebpackConfig.js @@ -929,7 +929,16 @@ describe('WebpackConfig object', () => { config.enableBabelTypeScriptPreset(); }).to.throw('Encore.enableBabelTypeScriptPreset() can not be called when Encore.enableForkedTypeScriptTypesChecking() has been called.'); }); - }) + + it('Options should be defined', () => { + const config = createConfig(); + const options = { isTSX: true }; + + config.enableBabelTypeScriptPreset(options); + + expect(config.babelTypeScriptPresetOptions).to.equal(options); + }); + }); describe('enableVueLoader', () => { it('Call with no config', () => { diff --git a/test/config-generator.js b/test/config-generator.js index 2e5a80f8..7afcc284 100644 --- a/test/config-generator.js +++ b/test/config-generator.js @@ -520,7 +520,7 @@ describe('The config-generator function', () => { const actualConfig = configGenerator(config); - const jsRule = findRule(/\.jsx?$/, actualConfig.module.rules); + const jsRule = findRule(/\.(jsx?)$/, actualConfig.module.rules); // check for the default env preset only expect(JSON.stringify(jsRule.use[0].options.presets)).contains('@babel/preset-env'); @@ -932,7 +932,7 @@ describe('The config-generator function', () => { const actualConfig = configGenerator(config); - const jsRule = findRule(/\.jsx?$/, actualConfig.module.rules); + const jsRule = findRule(/\.(jsx?)$/, actualConfig.module.rules); expect(String(jsRule.exclude)).to.equal(String(/(node_modules|bower_components)/)); const babelLoader = jsRule.use.find(loader => loader.loader === 'babel-loader'); @@ -951,7 +951,7 @@ describe('The config-generator function', () => { const actualConfig = configGenerator(config); - const jsRule = findRule(/\.jsx?$/, actualConfig.module.rules); + const jsRule = findRule(/\.(jsx?)$/, actualConfig.module.rules); expect(String(jsRule.exclude)).to.equal(String(/foo/)); }); @@ -966,7 +966,7 @@ describe('The config-generator function', () => { const actualConfig = configGenerator(config); - const jsRule = findRule(/\.jsx?$/, actualConfig.module.rules); + const jsRule = findRule(/\.(jsx?)$/, actualConfig.module.rules); expect(jsRule.exclude).to.be.a('Function'); expect(jsRule.exclude(path.join('test', 'node_modules', 'foo', 'index.js'))).to.be.false; expect(jsRule.exclude(path.join('test', 'node_modules', 'bar', 'index.js'))).to.be.true; @@ -984,7 +984,7 @@ describe('The config-generator function', () => { const actualConfig = configGenerator(config); - const jsRule = findRule(/\.jsx?$/, actualConfig.module.rules); + const jsRule = findRule(/\.(jsx?)$/, actualConfig.module.rules); const babelLoader = jsRule.use.find(loader => loader.loader === 'babel-loader'); const babelEnvPreset = babelLoader.options.presets.find(([name]) => name === '@babel/preset-env'); expect(babelEnvPreset[1].useBuiltIns).to.equal('usage'); @@ -1001,7 +1001,7 @@ describe('The config-generator function', () => { const actualConfig = configGenerator(config); - const jsRule = findRule(/\.jsx?$/, actualConfig.module.rules); + const jsRule = findRule(/\.(jsx?)$/, actualConfig.module.rules); const babelLoader = jsRule.use.find(loader => loader.loader === 'babel-loader'); const babelEnvPreset = babelLoader.options.presets.find(([name]) => name === '@babel/preset-env'); expect(babelEnvPreset[1].useBuiltIns).to.equal(false); @@ -1018,7 +1018,7 @@ describe('The config-generator function', () => { const actualConfig = configGenerator(config); - const jsRule = findRule(/\.jsx?$/, actualConfig.module.rules); + const jsRule = findRule(/\.(jsx?)$/, actualConfig.module.rules); const babelLoader = jsRule.use.find(loader => loader.loader === 'babel-loader'); const babelEnvPreset = babelLoader.options.presets.find(([name]) => name === '@babel/preset-env'); expect(babelEnvPreset[1].useBuiltIns).to.equal('usage'); diff --git a/test/functional.js b/test/functional.js index b0aab7a1..008865ec 100644 --- a/test/functional.js +++ b/test/functional.js @@ -1325,22 +1325,7 @@ module.exports = { const config = createWebpackConfig('www/build', 'dev'); config.setPublicPath('/build'); config.addEntry('main', ['./js/render.ts', './js/index.ts']); - config.configureBabel(function(config) { - config.presets = [ - ['@babel/preset-env', { - 'targets': { - 'chrome': 52, - }, - }], - '@babel/typescript', // required preset - ]; - // not required, but recommended - config.plugins = ['@babel/proposal-class-properties']; - }); - - config.configureLoaderRule('javascript', loader => { - loader.test = /.(j|t)sx?$/; // let Babel to run over .tsx? files too - }); + config.enableBabelTypeScriptPreset(); testSetup.runWebpack(config, (webpackAssert) => { // check that babel-loader transformed the ts file diff --git a/test/loaders/babel.js b/test/loaders/babel.js index c4fea571..33691cda 100644 --- a/test/loaders/babel.js +++ b/test/loaders/babel.js @@ -166,4 +166,41 @@ describe('loaders/babel', () => { expect(actualLoaders[0].options.presets[0][1].corejs).to.equal(3); expect(actualLoaders[0].options.presets[0][1].include).to.have.members(['bar']); }); + + it('getLoaders() with TypeScript', () => { + const config = createConfig(); + const presetTypeScriptOptions = { isTSX: true }; + + config.enableBabelTypeScriptPreset(presetTypeScriptOptions); + + config.configureBabel(function(babelConfig) { + babelConfig.plugins.push('foo'); + }); + + const actualLoaders = babelLoader.getLoaders(config); + + expect(actualLoaders[0].options.presets[0][0]).to.equal('@babel/preset-env'); + expect(actualLoaders[0].options.presets[1][0]).to.equal('@babel/preset-typescript'); + expect(actualLoaders[0].options.presets[1][1]).to.equal(presetTypeScriptOptions); + expect(actualLoaders[0].options.plugins).to.deep.include.members([ + '@babel/plugin-syntax-dynamic-import', + '@babel/plugin-proposal-class-properties', + 'foo' + ]); + }); + + it('getTest() base behavior', () => { + const config = createConfig(); + + const actualTest = babelLoader.getTest(config); + expect(actualTest.toString()).to.equals(/\.(jsx?)$/.toString()); + }); + + it('getTest() with TypeScript', () => { + const config = createConfig(); + config.enableBabelTypeScriptPreset(); + + const actualTest = babelLoader.getTest(config); + expect(actualTest.toString()).to.equals(/\.(jsx?|tsx?)$/.toString()); + }); }); From bdd553aa086c1dc6209b3a1b3077e029c2f86ae4 Mon Sep 17 00:00:00 2001 From: Hugo Alliaume Date: Sat, 21 Mar 2020 13:21:53 +0100 Subject: [PATCH 7/7] chore: typo --- lib/WebpackConfig.js | 2 +- test/WebpackConfig.js | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/WebpackConfig.js b/lib/WebpackConfig.js index 87fd3825..1b8be906 100644 --- a/lib/WebpackConfig.js +++ b/lib/WebpackConfig.js @@ -664,7 +664,7 @@ class WebpackConfig { enableForkedTypeScriptTypesChecking(forkedTypeScriptTypesCheckOptionsCallback = () => {}) { if (this.useBabelTypeScriptPreset) { - throw new Error('Encore.enableBabelTypeScriptPreset() can not be called when Encore.enableForkedTypeScriptTypesChecking() has been called.'); + throw new Error('Encore.enableForkedTypeScriptTypesChecking() can not be called when Encore.enableBabelTypeScriptPreset() has been called.'); } if (typeof forkedTypeScriptTypesCheckOptionsCallback !== 'function') { diff --git a/test/WebpackConfig.js b/test/WebpackConfig.js index f998419e..017e7a86 100644 --- a/test/WebpackConfig.js +++ b/test/WebpackConfig.js @@ -873,7 +873,7 @@ describe('WebpackConfig object', () => { }).to.throw('must be a callback function'); }); - it('TypeScript can not be compiled by ts-loader is Babel is already handling TypeScript', () => { + it('TypeScript can not be compiled by ts-loader if Babel is already handling TypeScript', () => { const config = createConfig(); config.enableBabelTypeScriptPreset(); @@ -903,11 +903,11 @@ describe('WebpackConfig object', () => { it('TypeScript can not be compiled by Babel if forked types checking is enabled', () => { const config = createConfig(); - config.enableForkedTypeScriptTypesChecking(); + config.enableBabelTypeScriptPreset(); expect(function() { - config.enableBabelTypeScriptPreset(); - }).to.throw('Encore.enableBabelTypeScriptPreset() can not be called when Encore.enableForkedTypeScriptTypesChecking() has been called.'); + config.enableForkedTypeScriptTypesChecking(); + }).to.throw('Encore.enableForkedTypeScriptTypesChecking() can not be called when Encore.enableBabelTypeScriptPreset() has been called.'); }); });