Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 30 additions & 7 deletions crates/oxc_transformer/src/jsx/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion napi/transform/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
15 changes: 13 additions & 2 deletions napi/transform/src/transformer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand Down Expand Up @@ -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
Expand Down
25 changes: 25 additions & 0 deletions napi/transform/test/transform.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = () => {
Expand Down
Loading