Skip to content

Commit 9c2b9b1

Browse files
Jeff MorrisonJeff Morrison
authored andcommitted
Merge pull request #970 from syranide/jsxws
Normalize whitespace for transformed JSX code
2 parents 0617696 + 60d7a02 commit 9c2b9b1

File tree

2 files changed

+40
-32
lines changed

2 files changed

+40
-32
lines changed

vendor/fbtransform/transforms/react.js

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ var renderXJSExpressionContainer =
2525
var renderXJSLiteral = require('./xjs').renderXJSLiteral;
2626
var quoteAttrName = require('./xjs').quoteAttrName;
2727

28+
var trimLeft = require('./xjs').trimLeft;
29+
2830
/**
2931
* Customized desugar processor.
3032
*
@@ -53,7 +55,7 @@ function visitReactTag(traverse, object, path, state) {
5355
var nameObject = openingElement.name;
5456
var attributesObject = openingElement.attributes;
5557

56-
utils.catchup(openingElement.range[0], state);
58+
utils.catchup(openingElement.range[0], state, trimLeft);
5759

5860
if (nameObject.namespace) {
5961
throw new Error(
@@ -68,44 +70,43 @@ function visitReactTag(traverse, object, path, state) {
6870

6971
utils.move(nameObject.range[1], state);
7072

73+
var hasAttributes = attributesObject.length;
74+
7175
// if we don't have any attributes, pass in null
72-
if (attributesObject.length === 0) {
76+
if (hasAttributes) {
77+
utils.append('{', state);
78+
} else {
7379
utils.append('null', state);
7480
}
7581

7682
// write attributes
7783
attributesObject.forEach(function(attr, index) {
78-
utils.catchup(attr.range[0], state);
7984
if (attr.name.namespace) {
8085
throw new Error(
8186
'Namespace attributes are not supported. ReactJSX is not XML.');
8287
}
8388
var name = attr.name.name;
84-
var isFirst = index === 0;
8589
var isLast = index === attributesObject.length - 1;
8690

87-
if (isFirst) {
88-
utils.append('{', state);
89-
}
90-
91+
utils.catchup(attr.range[0], state, trimLeft);
9192
utils.append(quoteAttrName(name), state);
92-
utils.append(':', state);
93+
utils.append(': ', state);
9394

9495
if (!attr.value) {
9596
state.g.buffer += 'true';
9697
state.g.position = attr.name.range[1];
9798
if (!isLast) {
98-
utils.append(',', state);
99+
utils.append(', ', state);
99100
}
100101
} else {
101102
utils.move(attr.name.range[1], state);
102-
// Use catchupWhiteSpace to skip over the '=' in the attribute
103-
utils.catchupWhiteSpace(attr.value.range[0], state);
103+
// Use catchupNewlines to skip over the '=' in the attribute
104+
utils.catchupNewlines(attr.value.range[0], state);
104105
if (JSX_ATTRIBUTE_TRANSFORMS.hasOwnProperty(attr.name.name)) {
105106
utils.append(JSX_ATTRIBUTE_TRANSFORMS[attr.name.name](attr), state);
106107
utils.move(attr.value.range[1], state);
107108
if (!isLast) {
108-
utils.append(',', state);
109+
utils.append(', ', state);
109110
}
110111
} else if (attr.value.type === Syntax.Literal) {
111112
renderXJSLiteral(attr.value, isLast, state);
@@ -114,18 +115,18 @@ function visitReactTag(traverse, object, path, state) {
114115
}
115116
}
116117

117-
if (isLast) {
118-
utils.append('}', state);
119-
}
120-
121-
utils.catchup(attr.range[1], state);
118+
utils.catchup(attr.range[1], state, trimLeft);
122119
});
123120

124121
if (!openingElement.selfClosing) {
125-
utils.catchup(openingElement.range[1] - 1, state);
122+
utils.catchup(openingElement.range[1] - 1, state, trimLeft);
126123
utils.move(openingElement.range[1], state);
127124
}
128125

126+
if (hasAttributes) {
127+
utils.append('}', state);
128+
}
129+
129130
// filter out whitespace
130131
var childrenToRender = object.children.filter(function(child) {
131132
return !(child.type === Syntax.Literal
@@ -147,7 +148,7 @@ function visitReactTag(traverse, object, path, state) {
147148
}
148149

149150
childrenToRender.forEach(function(child, index) {
150-
utils.catchup(child.range[0], state);
151+
utils.catchup(child.range[0], state, trimLeft);
151152

152153
var isLast = index >= lastRenderableIndex;
153154

@@ -158,22 +159,21 @@ function visitReactTag(traverse, object, path, state) {
158159
} else {
159160
traverse(child, path, state);
160161
if (!isLast) {
161-
utils.append(',', state);
162-
state.g.buffer = state.g.buffer.replace(/(\s*),$/, ',$1');
162+
utils.append(', ', state);
163163
}
164164
}
165165

166-
utils.catchup(child.range[1], state);
166+
utils.catchup(child.range[1], state, trimLeft);
167167
});
168168
}
169169

170170
if (openingElement.selfClosing) {
171171
// everything up to />
172-
utils.catchup(openingElement.range[1] - 2, state);
172+
utils.catchup(openingElement.range[1] - 2, state, trimLeft);
173173
utils.move(openingElement.range[1], state);
174174
} else {
175175
// everything up to </ sdflksjfd>
176-
utils.catchup(object.closingElement.range[0], state);
176+
utils.catchup(object.closingElement.range[0], state, trimLeft);
177177
utils.move(object.closingElement.range[1], state);
178178
}
179179

vendor/fbtransform/transforms/xjs.js

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -181,25 +181,27 @@ function renderXJSLiteral(object, isLast, state, start, end) {
181181
trimmedLine = trimmedLine.replace(/[ ]+$/, '');
182182
}
183183

184-
utils.append(line.match(/^[ \t]*/)[0], state);
184+
if (!isFirstLine) {
185+
utils.append(line.match(/^[ \t]*/)[0], state);
186+
}
185187

186188
if (trimmedLine || isLastNonEmptyLine) {
187189
utils.append(
188190
JSON.stringify(trimmedLine) +
189-
(!isLastNonEmptyLine ? "+' '+" : ''),
191+
(!isLastNonEmptyLine ? " + ' ' +" : ''),
190192
state);
191193

192194
if (isLastNonEmptyLine) {
193195
if (end) {
194196
utils.append(end, state);
195197
}
196198
if (!isLast) {
197-
utils.append(',', state);
199+
utils.append(', ', state);
198200
}
199201
}
200202

201203
// only restore tail whitespace if line had literals
202-
if (trimmedLine) {
204+
if (trimmedLine && !isLastLine) {
203205
utils.append(line.match(/[ \t]*$/)[0], state);
204206
}
205207
}
@@ -216,14 +218,15 @@ function renderXJSExpressionContainer(traverse, object, isLast, path, state) {
216218
// Plus 1 to skip `{`.
217219
utils.move(object.range[0] + 1, state);
218220
traverse(object.expression, path, state);
221+
219222
if (!isLast && object.expression.type !== Syntax.XJSEmptyExpression) {
220223
// If we need to append a comma, make sure to do so after the expression.
221-
utils.catchup(object.expression.range[1], state);
222-
utils.append(',', state);
224+
utils.catchup(object.expression.range[1], state, trimLeft);
225+
utils.append(', ', state);
223226
}
224227

225228
// Minus 1 to skip `}`.
226-
utils.catchup(object.range[1] - 1, state);
229+
utils.catchup(object.range[1] - 1, state, trimLeft);
227230
utils.move(object.range[1], state);
228231
return false;
229232
}
@@ -236,7 +239,12 @@ function quoteAttrName(attr) {
236239
return attr;
237240
}
238241

242+
function trimLeft(value) {
243+
return value.replace(/^[ ]+/, '');
244+
}
245+
239246
exports.knownTags = knownTags;
240247
exports.renderXJSExpressionContainer = renderXJSExpressionContainer;
241248
exports.renderXJSLiteral = renderXJSLiteral;
242249
exports.quoteAttrName = quoteAttrName;
250+
exports.trimLeft = trimLeft;

0 commit comments

Comments
 (0)