@@ -151,28 +151,29 @@ namespace ts {
151151 }
152152 }
153153
154- function visitJsxText ( node : JsxText ) {
155- const text = getTextOfNode ( node , /*includeTrivia*/ true ) ;
156- let parts : Expression [ ] ;
154+ function visitJsxText ( node : JsxText ) : StringLiteral | undefined {
155+ const fixed = fixupWhitespaceAndDecodeEntities ( getTextOfNode ( node , /*includeTrivia*/ true ) ) ;
156+ return fixed !== undefined && createLiteral ( fixed ) ;
157+ }
158+
159+ /**
160+ * JSX trims whitespace at the end and beginning of lines, except that the
161+ * start/end of a tag is considered a start/end of a line only if that line is
162+ * on the same line as the closing tag. See examples in
163+ * tests/cases/conformance/jsx/tsxReactEmitWhitespace.tsx
164+ * See also https://www.w3.org/TR/html4/struct/text.html#h-9.1 and https://www.w3.org/TR/CSS2/text.html#white-space-model
165+ */
166+ function fixupWhitespaceAndDecodeEntities ( text : string ) : string | undefined {
167+ let acc : string | undefined ;
157168 let firstNonWhitespace = 0 ;
158169 let lastNonWhitespace = - 1 ;
159170
160- // JSX trims whitespace at the end and beginning of lines, except that the
161- // start/end of a tag is considered a start/end of a line only if that line is
162- // on the same line as the closing tag. See examples in
163- // tests/cases/conformance/jsx/tsxReactEmitWhitespace.tsx
164171 for ( let i = 0 ; i < text . length ; i ++ ) {
165172 const c = text . charCodeAt ( i ) ;
166173 if ( isLineBreak ( c ) ) {
167174 if ( firstNonWhitespace !== - 1 && ( lastNonWhitespace - firstNonWhitespace + 1 > 0 ) ) {
168- const part = text . substr ( firstNonWhitespace , lastNonWhitespace - firstNonWhitespace + 1 ) ;
169- if ( ! parts ) {
170- parts = [ ] ;
171- }
172-
173- // We do not escape the string here as that is handled by the printer
174- // when it emits the literal. We do, however, need to decode JSX entities.
175- parts . push ( createLiteral ( decodeEntities ( part ) ) ) ;
175+ const part = decodeEntities ( text . substr ( firstNonWhitespace , lastNonWhitespace - firstNonWhitespace + 1 ) ) ;
176+ acc = acc === undefined ? part : acc + " " + part ;
176177 }
177178
178179 firstNonWhitespace = - 1 ;
@@ -186,28 +187,12 @@ namespace ts {
186187 }
187188
188189 if ( firstNonWhitespace !== - 1 ) {
189- const part = text . substr ( firstNonWhitespace ) ;
190- if ( ! parts ) {
191- parts = [ ] ;
192- }
193-
194- // We do not escape the string here as that is handled by the printer
195- // when it emits the literal. We do, however, need to decode JSX entities.
196- parts . push ( createLiteral ( decodeEntities ( part ) ) ) ;
190+ const lastPart = decodeEntities ( text . substr ( firstNonWhitespace ) ) ;
191+ return acc ? acc + lastPart : lastPart ;
197192 }
198-
199- if ( parts ) {
200- return reduceLeft ( parts , aggregateJsxTextParts ) ;
193+ else {
194+ return acc ;
201195 }
202-
203- return undefined ;
204- }
205-
206- /**
207- * Aggregates two expressions by interpolating them with a whitespace literal.
208- */
209- function aggregateJsxTextParts ( left : Expression , right : Expression ) {
210- return createAdd ( createAdd ( left , createLiteral ( " " ) ) , right ) ;
211196 }
212197
213198 /**
0 commit comments