Skip to content

Commit 3166950

Browse files
author
Andy Hanson
committed
Comment code and remember to add a space before the last part
1 parent 88d0560 commit 3166950

File tree

5 files changed

+61
-11
lines changed

5 files changed

+61
-11
lines changed

src/compiler/transformers/jsx.ts

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -162,37 +162,58 @@ namespace ts {
162162
* on the same line as the closing tag. See examples in
163163
* tests/cases/conformance/jsx/tsxReactEmitWhitespace.tsx
164164
* 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+
* An equivalent algorithm would be:
167+
* - If there is only one line, return it.
168+
* - If there is only whitespace (but multiple lines), return `undefined`.
169+
* - Split the text into lines.
170+
* - 'trimRight' the first line, 'trimLeft' the last line, 'trim' middle lines.
171+
* - Decode entities on each line (individually).
172+
* - Remove empty lines and join the rest with " ".
165173
*/
166174
function fixupWhitespaceAndDecodeEntities(text: string): string | undefined {
167175
let acc: string | undefined;
176+
// First non-whitespace character on this line.
168177
let firstNonWhitespace = 0;
178+
// Last non-whitespace character on this line.
169179
let lastNonWhitespace = -1;
180+
// These initial values are special because the first line is:
181+
// firstNonWhitespace = 0 to indicate that we want leading whitsepace,
182+
// but lastNonWhitespace = -1 as a special flag to indicate that we *don't* include the line if it's all whitespace.
170183

171184
for (let i = 0; i < text.length; i++) {
172185
const c = text.charCodeAt(i);
173186
if (isLineBreak(c)) {
174-
if (firstNonWhitespace !== -1 && (lastNonWhitespace - firstNonWhitespace + 1 > 0)) {
175-
const part = decodeEntities(text.substr(firstNonWhitespace, lastNonWhitespace - firstNonWhitespace + 1));
176-
acc = acc === undefined ? part : acc + " " + part;
187+
// If we've seen any non-whitespace characters on this line, add the 'trim' of the line.
188+
// (lastNonWhitespace === -1 is a special flag to detect whether the first line is all whitespace.)
189+
if (firstNonWhitespace !== -1 && lastNonWhitespace !== -1) {
190+
acc = addLineOfJsxText(acc, text.substr(firstNonWhitespace, lastNonWhitespace - firstNonWhitespace + 1));
177191
}
178192

193+
// Reset firstNonWhitespace for the next line.
194+
// Don't bother to reset lastNonWhitespace because we ignore it if firstNonWhitespace = -1.
179195
firstNonWhitespace = -1;
180196
}
181-
else if (!isWhiteSpace(c)) {
197+
else if (!isWhiteSpaceSingleLine(c)) {
182198
lastNonWhitespace = i;
183199
if (firstNonWhitespace === -1) {
184200
firstNonWhitespace = i;
185201
}
186202
}
187203
}
188204

189-
if (firstNonWhitespace !== -1) {
190-
const lastPart = decodeEntities(text.substr(firstNonWhitespace));
191-
return acc ? acc + lastPart : lastPart;
192-
}
193-
else {
194-
return acc;
195-
}
205+
return firstNonWhitespace !== -1
206+
// Last line had a non-whitespace character. Emit the 'trimLeft', meaning keep trailing whitespace.
207+
? addLineOfJsxText(acc, text.substr(firstNonWhitespace))
208+
// Last line was all whitespace, so ignore it
209+
: acc;
210+
}
211+
212+
function addLineOfJsxText(acc: string | undefined, trimmedLine: string): string {
213+
// We do not escape the string here as that is handled by the printer
214+
// when it emits the literal. We do, however, need to decode JSX entities.
215+
const decoded = decodeEntities(trimmedLine);
216+
return acc === undefined ? decoded : acc + " " + decoded;
196217
}
197218

198219
/**

tests/baselines/reference/tsxReactEmitWhitespace.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ var p = 0;
5757

5858
world
5959
</div>;
60+
61+
// Emit " a b c d "
62+
<div> a
63+
b c
64+
d </div>;
6065

6166

6267
//// [file.js]
@@ -86,3 +91,5 @@ React.createElement("div", null);
8691
React.createElement("div", null, "foo bar");
8792
// Emit "hello\\ world"
8893
React.createElement("div", null, "hello\\ world");
94+
// Emit " a b c d "
95+
React.createElement("div", null, " a b c d ");

tests/baselines/reference/tsxReactEmitWhitespace.symbols

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,11 @@ world
100100
</div>;
101101
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
102102

103+
// Emit " a b c d "
104+
<div> a
105+
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
106+
107+
b c
108+
d </div>;
109+
>div : Symbol(JSX.IntrinsicElements, Decl(file.tsx, 1, 22))
110+

tests/baselines/reference/tsxReactEmitWhitespace.types

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,12 @@ world
111111
</div>;
112112
>div : any
113113

114+
// Emit " a b c d "
115+
<div> a
116+
><div> a b c d </div> : JSX.Element
117+
>div : any
118+
119+
b c
120+
d </div>;
121+
>div : any
122+

tests/cases/conformance/jsx/tsxReactEmitWhitespace.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,8 @@ var p = 0;
5858

5959
world
6060
</div>;
61+
62+
// Emit " a b c d "
63+
<div> a
64+
b c
65+
d </div>;

0 commit comments

Comments
 (0)