From f5eb177f50a0bf37bc6bd9d87b447c73a53b6ea5 Mon Sep 17 00:00:00 2001 From: Kitson Kelly Date: Tue, 9 Nov 2021 12:26:39 +1100 Subject: feat(cli): support React 17 JSX transforms (#12631) Closes #8440 --- cli/config_file.rs | 55 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 6 deletions(-) (limited to 'cli/config_file.rs') diff --git a/cli/config_file.rs b/cli/config_file.rs index 3a71d41a9..20e254dd0 100644 --- a/cli/config_file.rs +++ b/cli/config_file.rs @@ -1,7 +1,9 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. use crate::fs_util::canonicalize_path; + use deno_core::error::anyhow; +use deno_core::error::custom_error; use deno_core::error::AnyError; use deno_core::error::Context; use deno_core::serde::Deserialize; @@ -17,6 +19,9 @@ use std::fmt; use std::path::Path; use std::path::PathBuf; +pub(crate) type MaybeImportsResult = + Result)>>, AnyError>; + /// The transpile options that are significant out of a user provided tsconfig /// file, that we want to deserialize out of the final config for a transpile. #[derive(Debug, Deserialize)] @@ -31,6 +36,7 @@ pub struct EmitConfigOptions { pub jsx: String, pub jsx_factory: String, pub jsx_fragment_factory: String, + pub jsx_import_source: Option, } /// There are certain compiler options that can impact what modules are part of @@ -38,6 +44,8 @@ pub struct EmitConfigOptions { #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CompilerOptions { + pub jsx: Option, + pub jsx_import_source: Option, pub types: Option>, } @@ -404,15 +412,50 @@ impl ConfigFile { /// If the configuration file contains "extra" modules (like TypeScript /// `"types"`) options, return them as imports to be added to a module graph. - pub fn to_maybe_imports( - &self, - ) -> Option)>> { + pub fn to_maybe_imports(&self) -> MaybeImportsResult { + let mut imports = Vec::new(); + let compiler_options_value = + if let Some(value) = self.json.compiler_options.as_ref() { + value + } else { + return Ok(None); + }; + let compiler_options: CompilerOptions = + serde_json::from_value(compiler_options_value.clone())?; + let referrer = ModuleSpecifier::from_file_path(&self.path) + .map_err(|_| custom_error("TypeError", "bad config file specifier"))?; + if let Some(types) = compiler_options.types { + imports.extend(types); + } + if compiler_options.jsx == Some("react-jsx".to_string()) { + imports.push(format!( + "{}/jsx-runtime", + compiler_options.jsx_import_source.ok_or_else(|| custom_error("TypeError", "Compiler option 'jsx' set to 'react-jsx', but no 'jsxImportSource' defined."))? + )); + } else if compiler_options.jsx == Some("react-jsxdev".to_string()) { + imports.push(format!( + "{}/jsx-dev-runtime", + compiler_options.jsx_import_source.ok_or_else(|| custom_error("TypeError", "Compiler option 'jsx' set to 'react-jsxdev', but no 'jsxImportSource' defined."))? + )); + } + if !imports.is_empty() { + Ok(Some(vec![(referrer, imports)])) + } else { + Ok(None) + } + } + + /// Based on the compiler options in the configuration file, return the + /// implied JSX import source module. + pub fn to_maybe_jsx_import_source_module(&self) -> Option { let compiler_options_value = self.json.compiler_options.as_ref()?; let compiler_options: CompilerOptions = serde_json::from_value(compiler_options_value.clone()).ok()?; - let referrer = ModuleSpecifier::from_file_path(&self.path).ok()?; - let types = compiler_options.types?; - Some(vec![(referrer, types)]) + match compiler_options.jsx.as_deref() { + Some("react-jsx") => Some("jsx-runtime".to_string()), + Some("react-jsxdev") => Some("jsx-dev-runtime".to_string()), + _ => None, + } } pub fn to_fmt_config(&self) -> Result, AnyError> { -- cgit v1.2.3