diff --git a/crates/oxc_syntax/src/identifier.rs b/crates/oxc_syntax/src/identifier.rs index dfa757eb8deba0..9b1bc14fd72f43 100644 --- a/crates/oxc_syntax/src/identifier.rs +++ b/crates/oxc_syntax/src/identifier.rs @@ -28,6 +28,9 @@ pub const VT: char = '\u{b}'; /// U+000C FORM FEED, abbreviated ``. pub const FF: char = '\u{c}'; +/// U+0020 SPACE, abbreviated ``. +pub const SP: char = '\u{20}'; + /// U+00A0 NON-BREAKING SPACE, abbreviated ``. pub const NBSP: char = '\u{a0}'; @@ -39,6 +42,26 @@ pub fn is_irregular_whitespace(c: char) -> bool { ) } +const NEL: char = '\u{85}'; +const OGHAM_SPACE_MARK: char = '\u{1680}'; +const EN_QUAD: char = '\u{2000}'; +const ZWSP: char = '\u{200b}'; + +// Narrow No-Break Space +const NNBSP: char = '\u{202f}'; + +// Medium Mathematical Space +const MMSP: char = '\u{205f}'; +const IDEOGRAPHIC_SPACE: char = '\u{3000}'; + +// https://github.com/microsoft/TypeScript/blob/b8e4ed8aeb0b228f544c5736908c31f136a9f7e3/src/compiler/scanner.ts#L556 +pub fn is_white_space_single_line(c: char) -> bool { + // Note: nextLine is in the Zs space, and should be considered to be a whitespace. + // It is explicitly not a line-break as it isn't in the exact set specified by EcmaScript. + matches!(c, |SP| TAB | VT | FF | NBSP | NEL | OGHAM_SPACE_MARK | EN_QUAD + ..=ZWSP | NNBSP | MMSP | IDEOGRAPHIC_SPACE | ZWNBSP) +} + // 11.3 Line Terminators /// U+000A LINE FEED, abbreviated in the spec as ``. diff --git a/crates/oxc_transformer/src/react/jsx.rs b/crates/oxc_transformer/src/react/jsx.rs index c61c9083667601..a236579eb9d469 100644 --- a/crates/oxc_transformer/src/react/jsx.rs +++ b/crates/oxc_transformer/src/react/jsx.rs @@ -93,7 +93,7 @@ use oxc_ast::{ast::*, AstBuilder, NONE}; use oxc_ecmascript::PropName; use oxc_span::{Atom, GetSpan, Span, SPAN}; use oxc_syntax::{ - identifier::{is_irregular_whitespace, is_line_terminator}, + identifier::{is_line_terminator, is_white_space_single_line}, reference::ReferenceFlags, symbol::SymbolFlags, xml_entities::XML_ENTITIES, @@ -909,7 +909,7 @@ impl<'a, 'ctx> ReactJsx<'a, 'ctx> { acc = Some(Self::add_line_of_jsx_text(acc, &text[first..last])); } first_non_whitespace = None; - } else if c != ' ' && !is_irregular_whitespace(c) { + } else if !is_white_space_single_line(c) { last_non_whitespace = Some(index + c.len_utf8()); if first_non_whitespace.is_none() { first_non_whitespace.replace(index);