feat(napi/transform): add jsx: 'preserve' option (#7965)

closes #7958
This commit is contained in:
Boshen 2024-12-17 13:49:50 +00:00
parent 111dc52f62
commit c16a85176d
4 changed files with 69 additions and 10 deletions

View file

@ -109,6 +109,20 @@ pub struct JsxOptions {
impl Default for JsxOptions {
fn default() -> Self {
Self::enable()
}
}
impl JsxOptions {
pub fn conform(&mut self) {
if self.development {
self.jsx_plugin = true;
self.jsx_self_plugin = true;
self.jsx_source_plugin = true;
}
}
pub fn enable() -> Self {
Self {
jsx_plugin: true,
display_name_plugin: true,
@ -126,14 +140,23 @@ impl Default for JsxOptions {
refresh: None,
}
}
}
impl JsxOptions {
pub fn conform(&mut self) {
if self.development {
self.jsx_plugin = true;
self.jsx_self_plugin = true;
self.jsx_source_plugin = true;
pub fn disable() -> Self {
Self {
jsx_plugin: false,
display_name_plugin: false,
jsx_self_plugin: false,
jsx_source_plugin: false,
runtime: JsxRuntime::default(),
development: false,
throw_if_namespace: false,
pure: false,
import_source: None,
pragma: None,
pragma_frag: None,
use_built_ins: None,
use_spread: None,
refresh: None,
}
}
}

View file

@ -259,7 +259,7 @@ export interface TransformOptions {
/** Configure how TypeScript is transformed. */
typescript?: TypeScriptOptions
/** Configure how TSX and JSX are transformed. */
jsx?: JsxOptions
jsx?: 'preserve' | JsxOptions
/**
* Sets the target environment for the generated JavaScript.
*

View file

@ -106,7 +106,8 @@ pub struct TransformOptions {
pub typescript: Option<TypeScriptOptions>,
/// Configure how TSX and JSX are transformed.
pub jsx: Option<JsxOptions>,
#[napi(ts_type = "'preserve' | JsxOptions")]
pub jsx: Option<Either<String, JsxOptions>>,
/// Sets the target environment for the generated JavaScript.
///
@ -150,7 +151,17 @@ impl TryFrom<TransformOptions> for oxc::transformer::TransformOptions {
.typescript
.map(oxc::transformer::TypeScriptOptions::from)
.unwrap_or_default(),
jsx: options.jsx.map(Into::into).unwrap_or_default(),
jsx: match options.jsx {
Some(Either::A(s)) => {
if s == "preserve" {
oxc::transformer::JsxOptions::disable()
} else {
return Err(format!("Invalid jsx option: `{s}`."));
}
}
Some(Either::B(options)) => oxc::transformer::JsxOptions::from(options),
None => oxc::transformer::JsxOptions::enable(),
},
env,
helper_loader: options
.helpers

View file

@ -140,6 +140,31 @@ import bar = require('bar')
});
});
describe('jsx', () => {
const code = `const foo: Foo = <div/>`;
it('enables jsx transform by default', () => {
const ret = transform('test.tsx', code);
expect(ret.code).toEqual('import { jsx as _jsx } from "react/jsx-runtime";\nconst foo = _jsx("div", {});\n');
});
it('configures jsx', () => {
const ret = transform('test.tsx', code, {
jsx: {
importSource: 'xxx',
},
});
expect(ret.code).toEqual('import { jsx as _jsx } from "xxx/jsx-runtime";\nconst foo = _jsx("div", {});\n');
});
it('can preserve jsx transform', () => {
const ret = transform('test.tsx', code, {
jsx: 'preserve',
});
expect(ret.code).toEqual('const foo = <div />;\n');
});
});
describe('react refresh plugin', () => {
const code = `import { useState } from "react";
export const App = () => {