diff --git a/src/core/__tests__/ReactRenderDocument-test.js b/src/core/__tests__/ReactRenderDocument-test.js
index 350c0356b7b..04e3d30525f 100644
--- a/src/core/__tests__/ReactRenderDocument-test.js
+++ b/src/core/__tests__/ReactRenderDocument-test.js
@@ -67,7 +67,7 @@ describe('rendering React components at document', function() {
React.renderComponentToString(, function(markup) {
testDocument = getTestDocument(markup);
var component = React.renderComponent(, testDocument);
- expect(testDocument.body.innerHTML).toBe(' Hello world ');
+ expect(testDocument.body.innerHTML).toBe('Hello world');
var componentID = ReactMount.getReactRootID(testDocument);
expect(componentID).toBe(component._rootNodeID);
@@ -95,13 +95,13 @@ describe('rendering React components at document', function() {
React.renderComponentToString(, function(markup) {
testDocument = getTestDocument(markup);
React.renderComponent(, testDocument);
- expect(testDocument.body.innerHTML).toBe(' Hello world ');
+ expect(testDocument.body.innerHTML).toBe('Hello world');
expect(function() {
React.unmountComponentAtNode(testDocument);
}).toThrow(UNMOUNT_INVARIANT_MESSAGE);
- expect(testDocument.body.innerHTML).toBe(' Hello world ');
+ expect(testDocument.body.innerHTML).toBe('Hello world');
});
});
@@ -143,14 +143,14 @@ describe('rendering React components at document', function() {
React.renderComponent(, testDocument);
- expect(testDocument.body.innerHTML).toBe(' Hello world ');
+ expect(testDocument.body.innerHTML).toBe('Hello world');
// Reactive update
expect(function() {
React.renderComponent(, testDocument);
}).toThrow(UNMOUNT_INVARIANT_MESSAGE);
- expect(testDocument.body.innerHTML).toBe(' Hello world ');
+ expect(testDocument.body.innerHTML).toBe('Hello world');
});
});
diff --git a/vendor/fbtransform/transforms/react.js b/vendor/fbtransform/transforms/react.js
index af5aa7dbedc..0c217c7c718 100644
--- a/vendor/fbtransform/transforms/react.js
+++ b/vendor/fbtransform/transforms/react.js
@@ -68,10 +68,6 @@ function visitReactTag(traverse, object, path, state) {
utils.move(object.name.range[1], state);
- var childrenToRender = object.children.filter(function(child) {
- return !(child.type === Syntax.Literal && !child.value.match(/\S/));
- });
-
// if we don't have any attributes, pass in null
if (object.attributes.length === 0) {
utils.append('null', state);
@@ -131,16 +127,18 @@ function visitReactTag(traverse, object, path, state) {
}
// filter out whitespace
+ var childrenToRender = object.children.filter(function(child) {
+ return !(child.type === Syntax.Literal &&
+ child.value.match(/^[ \t]*[\r\n][ \t\r\n]*$/));
+ });
+
if (childrenToRender.length > 0) {
utils.append(', ', state);
- object.children.forEach(function(child) {
- if (child.type === Syntax.Literal && !child.value.match(/\S/)) {
- return;
- }
+ childrenToRender.forEach(function(child, index) {
utils.catchup(child.range[0], state);
- var isLast = child === childrenToRender[childrenToRender.length - 1];
+ var isLast = index === childrenToRender.length - 1;
if (child.type === Syntax.Literal) {
renderXJSLiteral(child, isLast, state);
diff --git a/vendor/fbtransform/transforms/xjs.js b/vendor/fbtransform/transforms/xjs.js
index faa9fb40f33..97b4f0432c1 100644
--- a/vendor/fbtransform/transforms/xjs.js
+++ b/vendor/fbtransform/transforms/xjs.js
@@ -149,118 +149,65 @@ var knownTags = {
wbr: true
};
-function safeTrim(string) {
- return string.replace(/^[ \t]+/, '').replace(/[ \t]+$/, '');
-}
-
-// Replace all trailing whitespace characters with a single space character
-function trimWithSingleSpace(string) {
- return string.replace(/^[ \t\xA0]{2,}/, ' ').
- replace(/[ \t\xA0]{2,}$/, ' ').replace(/^\s+$/, '');
-}
-
-/**
- * Special handling for multiline string literals
- * print lines:
- *
- * line
- * line
- *
- * as:
- *
- * "line "+
- * "line"
- */
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
- utils.append(object.value.match(/^[\t ]*/)[0], state);
- if (start) {
- utils.append(start, state);
+ var lines = object.value.split(/\r\n|\n|\r/);
+
+ if (start) {
+ utils.append(start, state);
+ }
+
+ var lastNonEmptyLine = 0;
+
+ lines.forEach(function (line, index) {
+ if (line.match(/[^ \t]/)) {
+ lastNonEmptyLine = index;
}
-
- var trimmedChildValueWithSpace = trimWithSingleSpace(object.value);
-
- /**
- */
- var initialLines = trimmedChildValue.split(/\r\n|\n|\r/);
-
- var lines = initialLines.filter(function(line) {
- return safeTrim(line).length > 0;
- });
-
- var hasInitialNewLine = initialLines[0] !== lines[0];
- hasFinalNewLine =
- initialLines[initialLines.length - 1] !== lines[lines.length - 1];
-
- var numLines = lines.length;
- lines.forEach(function (line, ii) {
- var lastLine = ii === numLines - 1;
- var trimmedLine = safeTrim(line);
- if (trimmedLine === '' && !lastLine) {
- utils.append(line, state);
- } else {
- var preString = '';
- var postString = '';
- var leading = line.match(/^[ \t]*/)[0];
-
- if (ii === 0) {
- if (hasInitialNewLine) {
- preString = ' ';
- 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 = ' ';
- }
+ });
+
+ lines.forEach(function (line, index) {
+ var isFirstLine = index === 0;
+ var isLastLine = index === lines.length - 1;
+ var isLastNonEmptyLine = index === lastNonEmptyLine;
+
+ // replace rendered whitespace tabs with spaces
+ var trimmedLine = line.replace(/\t/g, ' ');
+
+ // trim whitespace touching a newline
+ if (!isFirstLine) {
+ trimmedLine = trimmedLine.replace(/^[ ]+/, '');
+ }
+ if (!isLastLine) {
+ trimmedLine = trimmedLine.replace(/[ ]+$/, '');
+ }
+
+ utils.append(line.match(/^[ \t]*/)[0], state);
+
+ if (trimmedLine || isLastNonEmptyLine) {
+ utils.append(
+ JSON.stringify(trimmedLine) +
+ (!isLastNonEmptyLine ? "+' '+" : ''),
+ state);
+
+ if (isLastNonEmptyLine) {
+ if (end) {
+ utils.append(end, state);
}
- if (!lastLine || trimmedChildValueWithSpace.substr(
- trimmedChildValueWithSpace.length - 1, 1) === ' ' ||
- hasFinalNewLine
- ) {
- // If either not on the last line, or the original content ends with
- // whitespace, place a single character at the end.
- postString = ' ';
+ if (!isLast) {
+ utils.append(',', state);
}
-
- utils.append(
- leading +
- JSON.stringify(
- preString + trimmedLine + postString
- ) +
- (lastLine ? '' : '+') +
- line.match(/[ \t]*$/)[0],
- state);
}
- if (!lastLine) {
- utils.append('\n', state);
+
+ // only restore tail whitespace if line had literals
+ if (trimmedLine) {
+ utils.append(line.match(/[ \t]*$/)[0], state);
}
- });
- } else {
- if (start) {
- utils.append(start, state);
}
- utils.append('""', state);
- }
- if (end) {
- utils.append(end, state);
- }
-
- // add comma before trailing whitespace
- if (!isLast) {
- utils.append(',', state);
- }
-
- // tail whitespace
- if (hasFinalNewLine) {
- utils.append('\n', state);
- }
- utils.append(object.value.match(/[ \t]*$/)[0], state);
+
+ if (!isLastLine) {
+ utils.append('\n', state);
+ }
+ });
+
utils.move(object.range[1], state);
}