diff --git a/bin/jsx b/bin/jsx index e0f6247a39a..ee893af2e95 100755 --- a/bin/jsx +++ b/bin/jsx @@ -12,13 +12,19 @@ require('commoner').version( }).option( '--harmony', 'Turns on JS transformations such as ES6 Classes etc.' +).option( + '--use-single-quotes', + 'Uses single quotes for transform output.' ).process(function(id, source) { // This is where JSX, ES6, etc. desugaring happens. var visitorList; + if (this.options.harmony) { visitorList = visitors.getAllVisitors(); } else { visitorList = visitors.transformVisitors.react; } - return transform(visitorList, source).code; + return transform(visitorList, source, { + useSingleQuotes: this.options.useSingleQuotes + }).code; }); diff --git a/vendor/fbtransform/transforms/react.js b/vendor/fbtransform/transforms/react.js index c79eaa85f56..fb494852eeb 100644 --- a/vendor/fbtransform/transforms/react.js +++ b/vendor/fbtransform/transforms/react.js @@ -92,7 +92,7 @@ function visitReactTag(traverse, object, path, state) { var isLast = index === attributesObject.length - 1; utils.catchup(attr.range[0], state, trimLeft); - utils.append(quoteAttrName(name), state); + utils.append(quoteAttrName(name, state.g.opts.useSingleQuotes), state); utils.append(': ', state); if (!attr.value) { diff --git a/vendor/fbtransform/transforms/reactDisplayName.js b/vendor/fbtransform/transforms/reactDisplayName.js index 6bc784c6e0b..31d3ea488e1 100644 --- a/vendor/fbtransform/transforms/reactDisplayName.js +++ b/vendor/fbtransform/transforms/reactDisplayName.js @@ -18,6 +18,7 @@ var Syntax = require('esprima-fb').Syntax; var utils = require('jstransform/src/utils'); +var doubleOrSingleQuotes = require('./xjs').doubleOrSingleQuotes; function addDisplayName(displayName, object, state) { if (object && @@ -40,7 +41,10 @@ function addDisplayName(displayName, object, state) { if (safe) { utils.catchup(object['arguments'][0].range[0] + 1, state); - utils.append("displayName: '" + displayName + "',", state); + utils.append( + 'displayName: ' + doubleOrSingleQuotes(displayName, state) + ',', + state + ); } } } diff --git a/vendor/fbtransform/transforms/xjs.js b/vendor/fbtransform/transforms/xjs.js index 66a8fb13cb2..5a1b92725b0 100644 --- a/vendor/fbtransform/transforms/xjs.js +++ b/vendor/fbtransform/transforms/xjs.js @@ -190,9 +190,12 @@ function renderXJSLiteral(object, isLast, state, start, end) { if (trimmedLine || isLastNonEmptyLine) { utils.append( - JSON.stringify(trimmedLine) + + state.g.opts.useSingleQuotes ? swapQuotes( + JSON.stringify(swapQuotes(trimmedLine)) + ) : JSON.stringify(trimmedLine) + (!isLastNonEmptyLine ? " + ' ' +" : ''), - state); + state + ); if (isLastNonEmptyLine) { if (end) { @@ -234,10 +237,23 @@ function renderXJSExpressionContainer(traverse, object, isLast, path, state) { return false; } -function quoteAttrName(attr) { +function doubleOrSingleQuotes(value, state) { + if (state && state.g.opts.useSingleQuotes) { + return '\'' + value + '\''; + } + return '"' + value + '"'; +} + +function swapQuotes(str) { + return str.replace(/['"]/g, function(m) { + return m === '"' ? '\'' : '"'; + }); +} + +function quoteAttrName(attr, state) { // Quote invalid JS identifiers. if (!/^[a-z_$][a-z\d_$]*$/i.test(attr)) { - return "'" + attr + "'"; + return doubleOrSingleQuotes(attr, state); } return attr; } @@ -250,4 +266,5 @@ exports.knownTags = knownTags; exports.renderXJSExpressionContainer = renderXJSExpressionContainer; exports.renderXJSLiteral = renderXJSLiteral; exports.quoteAttrName = quoteAttrName; +exports.doubleOrSingleQuotes = doubleOrSingleQuotes; exports.trimLeft = trimLeft;