@samitouri / QOS-React-2 / commits / f69112cb3f

JSX: Respect original spacing and newlines better

Fixes #335. Now this JSX: ``` /** @jsx React.DOM */ var HelloMessage = React.createClass({ render: function() { return <div> Look! <a href= "http://www.facebook.com/">Facebook </a> </div>; } }); ``` produces ``` /** @jsx React.DOM */ var HelloMessage = React.createClass({displayName: 'HelloMessage', render: function() { return React.DOM.div(null, " Look! ", React.DOM.a( {href: "http://www.facebook.com/"}, "Facebook " ) ); } }); ``` rather than the less-desirable ``` /** @jsx React.DOM */ var HelloMessage = React.createClass({displayName: 'HelloMessage', render: function() { return React.DOM.div(null, " Look! ", React.DOM.a( {href:"http://www.facebook.com/"}, "Facebook " ), ); } }); ```

Ben Alpert committed Sep 10, 2013 at 17:14 UTC f69112cb3f080fc92ddb6543cca58282fd5e6c0b
2 files changed +22 -17
vendor/fbtransform/transforms/react.js
+15 -12
@@ -19,6 +19,7 @@
19 var Syntax = require('esprima-fb').Syntax;
20
21 var catchup = require('jstransform/src/utils').catchup;
22 +var catchupWhiteSpace = require('jstransform/src/utils').catchupWhiteSpace;
23 var append = require('jstransform/src/utils').append;
24 var move = require('jstransform/src/utils').move;
25 var getDocblock = require('jstransform/src/utils').getDocblock;
@@ -110,19 +111,21 @@ function visitReactTag(traverse, object, path, state) {
111 if (!isLast) {
112 append(',', state);
113 }
113 - } else if (JSX_ATTRIBUTE_TRANSFORMS[attr.name.name]) {
114 - move(attr.value.range[0], state);
115 - append(JSX_ATTRIBUTE_TRANSFORMS[attr.name.name](attr), state);
116 - move(attr.value.range[1], state);
117 - if (!isLast) {
118 - append(',', state);
119 - }
120 - } else if (attr.value.type === Syntax.Literal) {
121 - move(attr.value.range[0], state);
122 - renderXJSLiteral(attr.value, isLast, state);
114 } else {
124 - move(attr.value.range[0], state);
125 - renderXJSExpressionContainer(traverse, attr.value, isLast, path, state);
115 + move(attr.name.range[1], state);
116 + // Use catchupWhiteSpace to skip over the '=' in the attribute
117 + catchupWhiteSpace(attr.value.range[0], state);
118 + if (JSX_ATTRIBUTE_TRANSFORMS[attr.name.name]) {
119 + append(JSX_ATTRIBUTE_TRANSFORMS[attr.name.name](attr), state);
120 + move(attr.value.range[1], state);
121 + if (!isLast) {
122 + append(',', state);
123 + }
124 + } else if (attr.value.type === Syntax.Literal) {
125 + renderXJSLiteral(attr.value, isLast, state);
126 + } else {
127 + renderXJSExpressionContainer(traverse, attr.value, isLast, path, state);
128 + }
129 }
130
131 if (isLast) {
vendor/fbtransform/transforms/xjs.js
+7 -5
@@ -172,6 +172,7 @@ function trimWithSingleSpace(string) {
172 function renderXJSLiteral(object, isLast, state, start, end) {
173 /** Added blank check filtering and triming*/
174 var trimmedChildValue = safeTrim(object.value);
175 + var hasFinalNewLine = false;
176
177 if (trimmedChildValue) {
178 // head whitespace
@@ -191,7 +192,7 @@ function renderXJSLiteral(object, isLast, state, start, end) {
192 });
193
194 var hasInitialNewLine = initialLines[0] !== lines[0];
194 - var hasFinalNewLine =
195 + hasFinalNewLine =
196 initialLines[initialLines.length - 1] !== lines[lines.length - 1];
197
198 var numLines = lines.length;
@@ -203,20 +204,18 @@ function renderXJSLiteral(object, isLast, state, start, end) {
204 } else {
205 var preString = '';
206 var postString = '';
206 - var leading = '';
207 + var leading = line.match(/^[ \t]*/)[0];
208
209 if (ii === 0) {
210 if (hasInitialNewLine) {
211 preString = ' ';
211 - leading = '\n';
212 + leading = '\n' + leading;
213 }
214 if (trimmedChildValueWithSpace.substring(0, 1) === ' ') {
215 // If this is the first line, and the original content starts with
216 // whitespace, place a single space at the beginning.
217 preString = ' ';
218 }
218 - } else {
219 - leading = line.match(/^[ \t]*/)[0];
219 }
220 if (!lastLine || trimmedChildValueWithSpace.substr(
221 trimmedChildValueWithSpace.length - 1, 1) === ' ' ||
@@ -256,6 +255,9 @@ function renderXJSLiteral(object, isLast, state, start, end) {
255 }
256
257 // tail whitespace
258 + if (hasFinalNewLine) {
259 + append('\n', state);
260 + }
261 append(object.value.match(/[ \t]*$/)[0], state);
262 move(object.range[1], state);
263 }