@samitouri / QOS-React-2 / commits / 60d7a02d44

Normalize whitespace for transformed JSX code

Andreas Svensson committed Jan 24, 2014 at 21:46 UTC 60d7a02d44d8ce893e338f0ff6ae4812c9b5331a
2 files changed +40 -32
vendor/fbtransform/transforms/react.js
+25 -25
@@ -25,6 +25,8 @@ var renderXJSExpressionContainer =
25 var renderXJSLiteral = require('./xjs').renderXJSLiteral;
26 var quoteAttrName = require('./xjs').quoteAttrName;
27
28 +var trimLeft = require('./xjs').trimLeft;
29 +
30 /**
31 * Customized desugar processor.
32 *
@@ -53,7 +55,7 @@ function visitReactTag(traverse, object, path, state) {
55 var nameObject = openingElement.name;
56 var attributesObject = openingElement.attributes;
57
56 - utils.catchup(openingElement.range[0], state);
58 + utils.catchup(openingElement.range[0], state, trimLeft);
59
60 if (nameObject.namespace) {
61 throw new Error(
@@ -68,44 +70,43 @@ function visitReactTag(traverse, object, path, state) {
70
71 utils.move(nameObject.range[1], state);
72
73 + var hasAttributes = attributesObject.length;
74 +
75 // if we don't have any attributes, pass in null
72 - if (attributesObject.length === 0) {
76 + if (hasAttributes) {
77 + utils.append('{', state);
78 + } else {
79 utils.append('null', state);
80 }
81
82 // write attributes
83 attributesObject.forEach(function(attr, index) {
78 - utils.catchup(attr.range[0], state);
84 if (attr.name.namespace) {
85 throw new Error(
86 'Namespace attributes are not supported. ReactJSX is not XML.');
87 }
88 var name = attr.name.name;
84 - var isFirst = index === 0;
89 var isLast = index === attributesObject.length - 1;
90
87 - if (isFirst) {
88 - utils.append('{', state);
89 - }
90 -
91 + utils.catchup(attr.range[0], state, trimLeft);
92 utils.append(quoteAttrName(name), state);
92 - utils.append(':', state);
93 + utils.append(': ', state);
94
95 if (!attr.value) {
96 state.g.buffer += 'true';
97 state.g.position = attr.name.range[1];
98 if (!isLast) {
98 - utils.append(',', state);
99 + utils.append(', ', state);
100 }
101 } else {
102 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);
105 if (JSX_ATTRIBUTE_TRANSFORMS.hasOwnProperty(attr.name.name)) {
106 utils.append(JSX_ATTRIBUTE_TRANSFORMS[attr.name.name](attr), state);
107 utils.move(attr.value.range[1], state);
108 if (!isLast) {
108 - utils.append(',', state);
109 + utils.append(', ', state);
110 }
111 } else if (attr.value.type === Syntax.Literal) {
112 renderXJSLiteral(attr.value, isLast, state);
@@ -114,18 +115,18 @@ function visitReactTag(traverse, object, path, state) {
115 }
116 }
117
117 - if (isLast) {
118 - utils.append('}', state);
119 - }
120 -
121 - utils.catchup(attr.range[1], state);
118 + utils.catchup(attr.range[1], state, trimLeft);
119 });
120
121 if (!openingElement.selfClosing) {
125 - utils.catchup(openingElement.range[1] - 1, state);
122 + utils.catchup(openingElement.range[1] - 1, state, trimLeft);
123 utils.move(openingElement.range[1], state);
124 }
125
126 + if (hasAttributes) {
127 + utils.append('}', state);
128 + }
129 +
130 // filter out whitespace
131 var childrenToRender = object.children.filter(function(child) {
132 return !(child.type === Syntax.Literal
@@ -147,7 +148,7 @@ function visitReactTag(traverse, object, path, state) {
148 }
149
150 childrenToRender.forEach(function(child, index) {
150 - utils.catchup(child.range[0], state);
151 + utils.catchup(child.range[0], state, trimLeft);
152
153 var isLast = index >= lastRenderableIndex;
154
@@ -158,22 +159,21 @@ function visitReactTag(traverse, object, path, state) {
159 } else {
160 traverse(child, path, state);
161 if (!isLast) {
161 - utils.append(',', state);
162 - state.g.buffer = state.g.buffer.replace(/(\s*),$/, ',$1');
162 + utils.append(', ', state);
163 }
164 }
165
166 - utils.catchup(child.range[1], state);
166 + utils.catchup(child.range[1], state, trimLeft);
167 });
168 }
169
170 if (openingElement.selfClosing) {
171 // everything up to />
172 - utils.catchup(openingElement.range[1] - 2, state);
172 + utils.catchup(openingElement.range[1] - 2, state, trimLeft);
173 utils.move(openingElement.range[1], state);
174 } else {
175 // everything up to </ sdflksjfd>
176 - utils.catchup(object.closingElement.range[0], state);
176 + utils.catchup(object.closingElement.range[0], state, trimLeft);
177 utils.move(object.closingElement.range[1], state);
178 }
179
vendor/fbtransform/transforms/xjs.js
+15 -7
@@ -180,12 +180,14 @@ function renderXJSLiteral(object, isLast, state, start, end) {
180 trimmedLine = trimmedLine.replace(/[ ]+$/, '');
181 }
182
183 - utils.append(line.match(/^[ \t]*/)[0], state);
183 + if (!isFirstLine) {
184 + utils.append(line.match(/^[ \t]*/)[0], state);
185 + }
186
187 if (trimmedLine || isLastNonEmptyLine) {
188 utils.append(
189 JSON.stringify(trimmedLine) +
188 - (!isLastNonEmptyLine ? "+' '+" : ''),
190 + (!isLastNonEmptyLine ? " + ' ' +" : ''),
191 state);
192
193 if (isLastNonEmptyLine) {
@@ -193,12 +195,12 @@ function renderXJSLiteral(object, isLast, state, start, end) {
195 utils.append(end, state);
196 }
197 if (!isLast) {
196 - utils.append(',', state);
198 + utils.append(', ', state);
199 }
200 }
201
202 // only restore tail whitespace if line had literals
201 - if (trimmedLine) {
203 + if (trimmedLine && !isLastLine) {
204 utils.append(line.match(/[ \t]*$/)[0], state);
205 }
206 }
@@ -215,14 +217,15 @@ function renderXJSExpressionContainer(traverse, object, isLast, path, state) {
217 // Plus 1 to skip `{`.
218 utils.move(object.range[0] + 1, state);
219 traverse(object.expression, path, state);
220 +
221 if (!isLast && object.expression.type !== Syntax.XJSEmptyExpression) {
222 // If we need to append a comma, make sure to do so after the expression.
220 - utils.catchup(object.expression.range[1], state);
221 - utils.append(',', state);
223 + utils.catchup(object.expression.range[1], state, trimLeft);
224 + utils.append(', ', state);
225 }
226
227 // Minus 1 to skip `}`.
225 - utils.catchup(object.range[1] - 1, state);
228 + utils.catchup(object.range[1] - 1, state, trimLeft);
229 utils.move(object.range[1], state);
230 return false;
231 }
@@ -235,7 +238,12 @@ function quoteAttrName(attr) {
238 return attr;
239 }
240
241 +function trimLeft(value) {
242 + return value.replace(/^[ ]+/, '');
243 +}
244 +
245 exports.knownTags = knownTags;
246 exports.renderXJSExpressionContainer = renderXJSExpressionContainer;
247 exports.renderXJSLiteral = renderXJSLiteral;
248 exports.quoteAttrName = quoteAttrName;
249 +exports.trimLeft = trimLeft;