diff --git a/packages/core/integration-tests/test/integration/vue-ts-template/App.vue b/packages/core/integration-tests/test/integration/vue-ts-template/App.vue new file mode 100644 index 00000000000..859cda55e0e --- /dev/null +++ b/packages/core/integration-tests/test/integration/vue-ts-template/App.vue @@ -0,0 +1,7 @@ + + + diff --git a/packages/core/integration-tests/test/vue.js b/packages/core/integration-tests/test/vue.js index 03096229731..0cfcd4b192e 100644 --- a/packages/core/integration-tests/test/vue.js +++ b/packages/core/integration-tests/test/vue.js @@ -113,4 +113,12 @@ describe('vue', function () { assert.equal(typeof output.render, 'function'); assert.equal(typeof output.setup, 'function'); }); + it('should process template with TS when script is TS', async function () { + let b = await bundle( + path.join(__dirname, '/integration/vue-ts-template/App.vue'), + ); + let output = (await run(b)).default; + assert.equal(typeof output.render, 'function'); + assert.equal(typeof output.setup, 'function'); + }); }); diff --git a/packages/transformers/vue/src/VueTransformer.js b/packages/transformers/vue/src/VueTransformer.js index 4d5bf8f2aef..968ede917c6 100644 --- a/packages/transformers/vue/src/VueTransformer.js +++ b/packages/transformers/vue/src/VueTransformer.js @@ -199,6 +199,47 @@ function createDiagnostic(err, filePath) { return diagnostic; } +function getScriptType(script) { + if (!script) { + return 'js'; + } + + if (script.src) { + script.lang = extname(script.src).slice(1); + } + let type; + switch (script.lang || 'js') { + case 'javascript': + case 'js': + type = 'js'; + break; + case 'jsx': + type = 'jsx'; + break; + case 'typescript': + case 'ts': + type = 'ts'; + break; + case 'tsx': + type = 'tsx'; + break; + case 'coffeescript': + case 'coffee': + type = 'coffee'; + break; + default: + // TODO: codeframe + throw new ThrowableDiagnostic({ + diagnostic: { + message: md`Unknown script language: "${script.lang}"`, + origin: '@parcel/transformer-vue', + }, + }); + } + + return type; +} + async function processPipeline({ asset, template, @@ -244,6 +285,14 @@ async function processPipeline({ } content = await preprocessor.render(content, options); } + + // if using TS, support TS syntax in template expressions + const expressionPlugins = config.compilerOptions?.expressionPlugins || []; + const type = getScriptType(script); + if (type === 'ts') { + expressionPlugins.push('typescript'); + } + let templateComp = compiler.compileTemplate({ filename: asset.filePath, source: content, @@ -253,6 +302,7 @@ async function processPipeline({ compilerOptions: { ...config.compilerOptions, bindingMetadata: script ? script.bindings : undefined, + expressionPlugins, }, isProd: options.mode === 'production', id, @@ -265,7 +315,7 @@ async function processPipeline({ }); } let templateAsset: TransformerResult = { - type: 'js', + type, uniqueKey: asset.id + '-template', ...(!template.src && asset.env.sourceMap && { @@ -295,35 +345,7 @@ ${ ).toString(); script.lang = extname(script.src).slice(1); } - let type; - switch (script.lang || 'js') { - case 'javascript': - case 'js': - type = 'js'; - break; - case 'jsx': - type = 'jsx'; - break; - case 'typescript': - case 'ts': - type = 'ts'; - break; - case 'tsx': - type = 'tsx'; - break; - case 'coffeescript': - case 'coffee': - type = 'coffee'; - break; - default: - // TODO: codeframe - throw new ThrowableDiagnostic({ - diagnostic: { - message: md`Unknown script language: "${script.lang}"`, - origin: '@parcel/transformer-vue', - }, - }); - } + let type = getScriptType(script); let scriptAsset = { type, uniqueKey: asset.id + '-script',