mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Remove whitespace_transformer package
This was a one-time use thing, let's get rid of it. If we ever need to push an update, we'll do it from the 0.9-stable branch.
This commit is contained in:
@@ -1 +0,0 @@
|
||||
node_modules
|
||||
@@ -1,40 +0,0 @@
|
||||
# JSX Whitespace Transformer
|
||||
|
||||
React 0.9 changes the way whitespace is parsed from JSX.
|
||||
|
||||
Take this example block:
|
||||
|
||||
```js
|
||||
<div>
|
||||
Monkeys:
|
||||
<input type="text" /> <button />
|
||||
</div>
|
||||
```
|
||||
|
||||
In 0.8 and below, this would be transformed to the following:
|
||||
|
||||
```js
|
||||
React.DOM.div(null,
|
||||
" Monkeys: ",
|
||||
React.DOM.input( {type:"text"} ), React.DOM.button(null )
|
||||
)
|
||||
```
|
||||
|
||||
In 0.9, this will instead be transformed the following:
|
||||
|
||||
```js
|
||||
React.DOM.div(null,
|
||||
"Monkeys:",
|
||||
React.DOM.input( {type:"text"} ), " ", React.DOM.button(null )
|
||||
)
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
The `jsx_whitespace_transformer` module ships an executable which transforms a file or directory of files. It looks for the `@jsx React.DOM` trigger, the same as the `jsx` transformer works. Files will be modified in place, so be sure you are prepared for that.
|
||||
|
||||
```sh
|
||||
$ npm -g install jsx_whitespace_transformer
|
||||
$ jsx_whitespace_tranformer <path_to_file_or_files>
|
||||
```
|
||||
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"name": "jsx_whitespace_transformer",
|
||||
"description": "A utility to update your JSX to behave identically in React 0.8 and React 0.9.",
|
||||
"version": "1.0.1",
|
||||
"main": "run.js",
|
||||
"dependencies": {
|
||||
"esprima-fb": "~2001.1001.0-dev-harmony-fb",
|
||||
"graceful-fs": "~2.0.0",
|
||||
"jstransform": "~2.0.1",
|
||||
"node-find-files": "0.0.2",
|
||||
"optimist": "~0.6.0"
|
||||
},
|
||||
"bin": {
|
||||
"jsx_whitespace_transformer": "./run.js"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"preferGlobal": true
|
||||
}
|
||||
@@ -1,170 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var esprima = require('esprima-fb');
|
||||
var FileFinder = require('node-find-files');
|
||||
var fs = require('graceful-fs');
|
||||
var jstransform = require('jstransform');
|
||||
var path = require('path');
|
||||
var visitReactTag = require('./transforms/react').visitReactTag;
|
||||
|
||||
var S = esprima.Syntax;
|
||||
|
||||
var USAGE =
|
||||
'Read a file (or directory of files) from disk, transform it so that ' +
|
||||
'React 0.9 will render it the same way as React 0.8 (whitespace-wise), and ' +
|
||||
'write the result back to disk.';
|
||||
|
||||
function _visitFbt(node, path, state) {
|
||||
return false;
|
||||
}
|
||||
_visitFbt.test = function(node, path, state) {
|
||||
return node.type === S.XJSElement
|
||||
&& node.openingElement.name.name === 'fbt';
|
||||
};
|
||||
|
||||
var VISITORS_LIST = [
|
||||
_visitFbt,
|
||||
visitReactTag
|
||||
];
|
||||
|
||||
function _transformSource(source) {
|
||||
return jstransform.transform(VISITORS_LIST, source).code;
|
||||
}
|
||||
|
||||
function transformDir(dirPath, exclude) {
|
||||
var finder = new FileFinder({
|
||||
rootFolder: dirPath,
|
||||
filterFunction: function(path, stat) {
|
||||
return /\.jsx?$/.test(path) && (!exclude || !exclude.test(path));
|
||||
}
|
||||
});
|
||||
|
||||
var numTransforms = 0;
|
||||
var completeTransforms = 0;
|
||||
var findingComplete = false;
|
||||
function _printProgress() {
|
||||
process.stdout.clearLine();
|
||||
process.stdout.cursorTo(0);
|
||||
process.stdout.write(
|
||||
completeTransforms + '/' + numTransforms + ' transforms complete'
|
||||
);
|
||||
|
||||
if (findingComplete && completeTransforms === numTransforms) {
|
||||
console.log('\ndone!');
|
||||
}
|
||||
}
|
||||
|
||||
finder.on('match', function(pathStr, stat) {
|
||||
fs.readFile(pathStr, 'utf8', function(err, data) {
|
||||
if (err) {
|
||||
err.message = err.message + ' (' + pathStr + ')';
|
||||
throw err;
|
||||
}
|
||||
|
||||
if (/@jsx React\.DOM/.test(data)) {
|
||||
numTransforms++;
|
||||
_printProgress();
|
||||
|
||||
var transformedData;
|
||||
try {
|
||||
transformedData = _transformSource(data);
|
||||
} catch (e) {
|
||||
e.message = e.message + ' (' + pathStr + ')';
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (transformedData !== data) {
|
||||
fs.writeFile(pathStr, transformedData, function(err) {
|
||||
if (err) {
|
||||
err.message = err.message + ' (' + pathStr + ')';
|
||||
throw err;
|
||||
}
|
||||
completeTransforms++;
|
||||
_printProgress();
|
||||
});
|
||||
} else {
|
||||
completeTransforms++;
|
||||
_printProgress();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
finder.on('error', function(err) {
|
||||
console.log('\nError: ', err.stack);
|
||||
throw err;
|
||||
});
|
||||
|
||||
finder.on('complete', function() {
|
||||
findingComplete = true;
|
||||
});
|
||||
|
||||
finder.startSearch();
|
||||
}
|
||||
|
||||
function transformFile(pathStr) {
|
||||
fs.readFile(pathStr, 'utf8', function(err, data) {
|
||||
if (err) {
|
||||
err.message = err.message + ' (' + pathStr + ')';
|
||||
throw err;
|
||||
}
|
||||
|
||||
if (/@jsx React\.DOM/.test(data)) {
|
||||
var transformedData;
|
||||
try {
|
||||
transformedData = _transformSource(data);
|
||||
} catch (e) {
|
||||
e.message = e.message + ' (' + pathStr + ')';
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (transformedData !== data) {
|
||||
fs.writeFile(pathStr, transformedData, function(err) {
|
||||
if (err) {
|
||||
err.message = err.message + ' (' + pathStr + ')';
|
||||
throw err;
|
||||
}
|
||||
console.log('done!');
|
||||
});
|
||||
} else {
|
||||
console.log('done!');
|
||||
}
|
||||
} else {
|
||||
console.error(pathStr + ' is not a JSX file!');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
var argv = require('optimist')
|
||||
.usage(USAGE)
|
||||
.argv;
|
||||
|
||||
if (argv._.length === 0) {
|
||||
throw new Error(
|
||||
'Please specify a file or directory path as the first arg!'
|
||||
);
|
||||
}
|
||||
|
||||
argv._.forEach(function(arg) {
|
||||
var absPath = path.resolve(arg);
|
||||
|
||||
fs.stat(absPath, function(err, stat) {
|
||||
if (err) throw err;
|
||||
|
||||
if (stat.isFile()) {
|
||||
transformFile(absPath);
|
||||
} else if (stat.isDirectory()) {
|
||||
var exclude = null;
|
||||
if (argv.exclude) {
|
||||
exclude = new RegExp(argv.exclude);
|
||||
}
|
||||
transformDir(absPath, exclude);
|
||||
} else {
|
||||
throw new Error('Unknown filesystem node type: ' + absPath);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.transformDir = transformDir;
|
||||
-143
@@ -1,143 +0,0 @@
|
||||
/**
|
||||
* Copyright 2013-2014 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*global exports:true*/
|
||||
"use strict";
|
||||
var Syntax = require('esprima-fb').Syntax;
|
||||
var utils = require('jstransform/src/utils');
|
||||
|
||||
function visitReactTag(traverse, object, path, state) {
|
||||
object.attributes.forEach(function(attr, index) {
|
||||
if (attr.value) {
|
||||
traverse(attr.value, path, state);
|
||||
}
|
||||
});
|
||||
|
||||
object.children.forEach(function(child, index) {
|
||||
if (child.type === Syntax.Literal) {
|
||||
codemodXJSLiteral(child, state);
|
||||
} else if (child.type === Syntax.XJSExpressionContainer) {
|
||||
var isNotAfterLiteral =
|
||||
index == 0 ||
|
||||
object.children[index - 1].type !== Syntax.Literal;
|
||||
|
||||
var isNotBeforeLiteral =
|
||||
index == object.children.length - 1 ||
|
||||
object.children[index + 1].type !== Syntax.Literal;
|
||||
|
||||
codemodXJSExpressionContainer(
|
||||
traverse,
|
||||
child,
|
||||
isNotAfterLiteral,
|
||||
isNotBeforeLiteral,
|
||||
path,
|
||||
state
|
||||
);
|
||||
} else {
|
||||
traverse(child, path, state);
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
visitReactTag.test = function(object, path, state) {
|
||||
// only run react when react @jsx namespace is specified in docblock
|
||||
var jsx = utils.getDocblock(state).jsx;
|
||||
return object.type === Syntax.XJSElement && jsx && jsx.length;
|
||||
};
|
||||
|
||||
function codemodXJSLiteral(object, state) {
|
||||
var value = object.raw;
|
||||
|
||||
utils.catchup(object.range[0], state);
|
||||
|
||||
/*
|
||||
This can be used to "annotate spaces" inserted by this transformation,
|
||||
so that they can be more easily recognized as such in the final code
|
||||
|
||||
{' '}
|
||||
{'\\x20'}
|
||||
{(' ')}
|
||||
{' '||0}
|
||||
{' '||AnyTextYouLike}
|
||||
{' '||'AnyTextYouLike'}
|
||||
{GlobalVariableWithASpace}
|
||||
*/
|
||||
|
||||
var space = "{' '}";
|
||||
|
||||
/*
|
||||
· space
|
||||
¬ newline
|
||||
{expr} = <tag>
|
||||
|
||||
Old whitespace rules:
|
||||
{1}··Aaa··Bbb··{2}··{3} → {1}·Aaa··Bbb·{2}{3}
|
||||
{1}¬¬Aaa¬¬Bbb¬¬{2}¬¬{3} → {1}·Aaa·Bbb·{2}{3}
|
||||
|
||||
New whitespace rules:
|
||||
{1}··Aaa··Bbb··{2}··{3} → {1}··Aaa··Bbb··{2}··{3}
|
||||
{1}¬¬Aaa¬¬Bbb¬¬{2}¬¬{3} → {1}Aaa·Bbb{2}{3}
|
||||
|
||||
Required transformation:
|
||||
{1}··{2} = {1}··{2} → {1}{2}
|
||||
{1}··Aaa··{2} = {1}··Aaa··{2} → {1}·Aaa·{2}
|
||||
{1}¬¬Aaa¬¬{2} = {1}Aaa{2} → {1}·Aaa·{2}
|
||||
*/
|
||||
|
||||
// {1}··{2} = {1}··{2} → {1}{2}
|
||||
value = value.replace(/^[ \t]+$/, '');
|
||||
|
||||
// {1}··Aaa··{2} = {1}··Aaa··{2} → {1}·Aaa·{2}
|
||||
value = value.replace(/^[ \t]+([^ \t\r\n])/, " $1");
|
||||
value = value.replace(/([^ \t\r\n])[ \t]+$/, "$1 ");
|
||||
|
||||
// {1}¬¬Aaa¬¬{2} = {1}Aaa{2} → {1}·Aaa·{2}
|
||||
value = value.replace(/^([ \t]*[\r\n][ \t\r\n]*)([^ \t\r\n].*)/, "$1" + space + "$2");
|
||||
value = value.replace(/([^ \t\r\n])([ \t]*[\r\n][ \t\r\n]*)$/, "$1" + space + "$2");
|
||||
|
||||
// Rendered whitespace tabs are replaced with spaces
|
||||
value = value.replace(/[^ \t\r\n][ ]*[\t][ \t]*[^ \t\r\n]/, function(match) {
|
||||
return match.replace(/\t/g, ' ');
|
||||
});
|
||||
|
||||
utils.append(value, state);
|
||||
utils.move(object.range[1], state);
|
||||
}
|
||||
|
||||
function codemodXJSExpressionContainer(
|
||||
traverse,
|
||||
object,
|
||||
isNotAfterLiteral,
|
||||
isNotBeforeLiteral,
|
||||
path,
|
||||
state) {
|
||||
utils.catchup(object.range[0], state);
|
||||
traverse(object.expression, path, state);
|
||||
|
||||
// Unbox the previously required {' '}-workaround
|
||||
var raw = object.expression.raw;
|
||||
var isSpace = raw === "' '" || raw === '" "';
|
||||
|
||||
if (isNotAfterLiteral && isNotBeforeLiteral && isSpace) {
|
||||
utils.append(' ', state);
|
||||
utils.move(object.range[1], state);
|
||||
} else {
|
||||
utils.catchup(object.range[1], state);
|
||||
}
|
||||
}
|
||||
|
||||
exports.visitReactTag = visitReactTag;
|
||||
@@ -1,103 +0,0 @@
|
||||
/**
|
||||
* Copyright 2013-2014 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*global exports:true*/
|
||||
"use strict";
|
||||
var Syntax = require('esprima-fb').Syntax;
|
||||
var utils = require('jstransform/src/utils');
|
||||
|
||||
function renderXJSLiteral(object, state) {
|
||||
var value = object.raw;
|
||||
|
||||
utils.catchup(object.range[0], state);
|
||||
|
||||
/*
|
||||
This can be used to "annotate spaces" inserted by this transformation,
|
||||
so that they can be more easily recognized as such in the final code
|
||||
|
||||
{' '}
|
||||
{'\\x20'}
|
||||
{(' ')}
|
||||
{' '||0}
|
||||
{' '||AnyTextYouLike}
|
||||
{' '||'AnyTextYouLike'}
|
||||
{GlobalVariableWithASpace}
|
||||
*/
|
||||
|
||||
var space = "{' '}";
|
||||
|
||||
/*
|
||||
· space
|
||||
¬ newline
|
||||
{expr} = <tag>
|
||||
|
||||
Old whitespace rules:
|
||||
{1}··Aaa··Bbb··{2}··{3} → {1}·Aaa··Bbb·{2}{3}
|
||||
{1}¬¬Aaa¬¬Bbb¬¬{2}¬¬{3} → {1}·Aaa·Bbb·{2}{3}
|
||||
|
||||
New whitespace rules:
|
||||
{1}··Aaa··Bbb··{2}··{3} → {1}··Aaa··Bbb··{2}··{3}
|
||||
{1}¬¬Aaa¬¬Bbb¬¬{2}¬¬{3} → {1}Aaa·Bbb{2}{3}
|
||||
|
||||
Required transformation:
|
||||
{1}··{2} = {1}··{2} → {1}{2}
|
||||
{1}··Aaa··{2} = {1}··Aaa··{2} → {1}·Aaa·{2}
|
||||
{1}¬¬Aaa¬¬{2} = {1}Aaa{2} → {1}·Aaa·{2}
|
||||
*/
|
||||
|
||||
// {1}··{2} = {1}··{2} → {1}{2}
|
||||
value = value.replace(/^[ \t]+$/, '');
|
||||
|
||||
// {1}··Aaa··{2} = {1}··Aaa··{2} → {1}·Aaa·{2}
|
||||
value = value.replace(/^[ \t]+([^ \t\r\n])/, " $1");
|
||||
value = value.replace(/([^ \t\r\n])[ \t]+$/, "$1 ");
|
||||
|
||||
// {1}¬¬Aaa¬¬{2} = {1}Aaa{2} → {1}·Aaa·{2}
|
||||
value = value.replace(/^([ \t]*[\r\n][ \t\r\n]*)([^ \t\r\n].*)/, "$1" + space + "$2");
|
||||
value = value.replace(/([^ \t\r\n])([ \t]*[\r\n][ \t\r\n]*)$/, "$1" + space + "$2");
|
||||
|
||||
// Rendered whitespace tabs are replaced with spaces
|
||||
value = value.replace(/[^ \t\r\n][ ]*[\t][ \t]*[^ \t\r\n]/, function(match) {
|
||||
return match.replace(/\t/g, ' ');
|
||||
});
|
||||
|
||||
utils.append(value, state);
|
||||
utils.move(object.range[1], state);
|
||||
}
|
||||
|
||||
function renderXJSExpressionContainer(
|
||||
traverse, object,
|
||||
isNotAfterLiteral,
|
||||
isNotBeforeLiteral,
|
||||
path, state)
|
||||
{
|
||||
utils.catchup(object.range[0], state);
|
||||
|
||||
// Unbox the previously required {' '}-workaround
|
||||
var raw = object.expression.raw;
|
||||
var isSpace = (raw === "' '" || raw === '" "');
|
||||
|
||||
if (isNotAfterLiteral && isNotBeforeLiteral && isSpace) {
|
||||
utils.append(' ', state);
|
||||
utils.move(object.range[1], state);
|
||||
} else {
|
||||
utils.catchup(object.range[1], state);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
exports.renderXJSExpressionContainer = renderXJSExpressionContainer;
|
||||
exports.renderXJSLiteral = renderXJSLiteral;
|
||||
Reference in New Issue
Block a user