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 "      ),
    );
  }
});
```
This commit is contained in:
Ben Alpert
2013-09-10 17:14:36 -07:00
parent 63b58cf6b5
commit f69112cb3f
2 changed files with 22 additions and 17 deletions
+15 -12
View File
@@ -19,6 +19,7 @@
var Syntax = require('esprima-fb').Syntax;
var catchup = require('jstransform/src/utils').catchup;
var catchupWhiteSpace = require('jstransform/src/utils').catchupWhiteSpace;
var append = require('jstransform/src/utils').append;
var move = require('jstransform/src/utils').move;
var getDocblock = require('jstransform/src/utils').getDocblock;
@@ -110,19 +111,21 @@ function visitReactTag(traverse, object, path, state) {
if (!isLast) {
append(',', state);
}
} else if (JSX_ATTRIBUTE_TRANSFORMS[attr.name.name]) {
move(attr.value.range[0], state);
append(JSX_ATTRIBUTE_TRANSFORMS[attr.name.name](attr), state);
move(attr.value.range[1], state);
if (!isLast) {
append(',', state);
}
} else if (attr.value.type === Syntax.Literal) {
move(attr.value.range[0], state);
renderXJSLiteral(attr.value, isLast, state);
} else {
move(attr.value.range[0], state);
renderXJSExpressionContainer(traverse, attr.value, isLast, path, state);
move(attr.name.range[1], state);
// Use catchupWhiteSpace to skip over the '=' in the attribute
catchupWhiteSpace(attr.value.range[0], state);
if (JSX_ATTRIBUTE_TRANSFORMS[attr.name.name]) {
append(JSX_ATTRIBUTE_TRANSFORMS[attr.name.name](attr), state);
move(attr.value.range[1], state);
if (!isLast) {
append(',', state);
}
} else if (attr.value.type === Syntax.Literal) {
renderXJSLiteral(attr.value, isLast, state);
} else {
renderXJSExpressionContainer(traverse, attr.value, isLast, path, state);
}
}
if (isLast) {
+7 -5
View File
@@ -172,6 +172,7 @@ function trimWithSingleSpace(string) {
function renderXJSLiteral(object, isLast, state, start, end) {
/** Added blank check filtering and triming*/
var trimmedChildValue = safeTrim(object.value);
var hasFinalNewLine = false;
if (trimmedChildValue) {
// head whitespace
@@ -191,7 +192,7 @@ function renderXJSLiteral(object, isLast, state, start, end) {
});
var hasInitialNewLine = initialLines[0] !== lines[0];
var hasFinalNewLine =
hasFinalNewLine =
initialLines[initialLines.length - 1] !== lines[lines.length - 1];
var numLines = lines.length;
@@ -203,20 +204,18 @@ function renderXJSLiteral(object, isLast, state, start, end) {
} else {
var preString = '';
var postString = '';
var leading = '';
var leading = line.match(/^[ \t]*/)[0];
if (ii === 0) {
if (hasInitialNewLine) {
preString = ' ';
leading = '\n';
leading = '\n' + leading;
}
if (trimmedChildValueWithSpace.substring(0, 1) === ' ') {
// If this is the first line, and the original content starts with
// whitespace, place a single space at the beginning.
preString = ' ';
}
} else {
leading = line.match(/^[ \t]*/)[0];
}
if (!lastLine || trimmedChildValueWithSpace.substr(
trimmedChildValueWithSpace.length - 1, 1) === ' ' ||
@@ -256,6 +255,9 @@ function renderXJSLiteral(object, isLast, state, start, end) {
}
// tail whitespace
if (hasFinalNewLine) {
append('\n', state);
}
append(object.value.match(/[ \t]*$/)[0], state);
move(object.range[1], state);
}