-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from ericclemmons/1-release
First Release
- Loading branch information
Showing
39 changed files
with
672 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"presets": ["es2015", "stage-0"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
v5.6.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
# react-transform-functional-hmr | ||
# babel-plugin-react-pure-to-class | ||
https://github.com/gaearon/babel-plugin-react-transform/issues/57#issuecomment-167652102 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
{ | ||
"name": "example", | ||
"version": "1.0.0", | ||
"description": "", | ||
"main": "index.js", | ||
"scripts": { | ||
"start": "webpack-dev-server --content-base src/public --hot --inline", | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"keywords": [], | ||
"author": "", | ||
"license": "MIT", | ||
"devDependencies": { | ||
"babel-loader": "6.2.2", | ||
"babel-plugin-react-transform": "2.0.0", | ||
"babel-preset-es2015": "6.5.0", | ||
"babel-preset-react": "6.5.0", | ||
"babel-preset-stage-0": "6.5.0", | ||
"react-transform-hmr": "1.0.2", | ||
"webpack": "1.12.13", | ||
"webpack-dev-server": "1.14.1" | ||
}, | ||
"dependencies": { | ||
"react": "0.14.7", | ||
"react-dom": "0.14.7" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import React from "react"; | ||
import DOM from "react-dom"; | ||
|
||
import App from "./components/App"; | ||
|
||
DOM.render(( | ||
<App />, | ||
), document.getElementById("app")); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
const App = (props) => ( | ||
<h1>Howdy!</h1> | ||
); | ||
|
||
export default App; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<title>babel-plugin-functional-hmr Example</title> | ||
<link href="https://maxcdn.bootstrapcdn.com/bootswatch/3.3.6/cerulean/bootstrap.min.css" rel="stylesheet" integrity="sha256-Ucf/ylcKTNevYP6l7VNUhGLDRZPQs1+LsbbxuzMxUJM= sha512-FW2XqnqMwERwg0LplG7D64h8zA1BsxvxrDseWpHLq8Dg8kOBmLs19XNa9oAajN/ToJRRklfDJ398sOU+7LcjZA==" crossorigin="anonymous"> | ||
</head> | ||
<body> | ||
<div id="app"> | ||
Loading… | ||
</div> | ||
|
||
<script> | ||
document.write("The time is: " + new Date().toString()); | ||
</script> | ||
|
||
<script src="/client.js"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import path from "path"; | ||
|
||
export default { | ||
entry: { | ||
client: [ | ||
"./src/client.js", | ||
] | ||
}, | ||
|
||
module: { | ||
loaders: [ | ||
{ | ||
test: /\.js$/, | ||
loader: "babel", | ||
query: { | ||
babelrc: false, | ||
cacheDirectory: true, | ||
passPerPreset: true, | ||
presets: [ | ||
// Convert pure to Class | ||
{ plugins: ["../src/plugin.js"] }, | ||
// Enhance Classes | ||
{ plugins: [ | ||
["react-transform", { | ||
transforms: [{ | ||
transform: "react-transform-hmr", | ||
imports: ["react"], | ||
locals: ["module"], | ||
}], | ||
}], | ||
]}, | ||
// Convert to ES5 | ||
"react", | ||
"es2015", | ||
"stage-0", | ||
], | ||
}, | ||
exclude: /node_modules/, | ||
}, | ||
], | ||
}, | ||
|
||
output: { | ||
chunkFilename: "[id].[hash:5]-[chunkhash:7].js", | ||
devtoolModuleFilenameTemplate: "[absolute-resource-path]", | ||
filename: "[name].js", | ||
libraryTarget: "var", | ||
path: path.join(__dirname, "build/client"), | ||
publicPath: "/", | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
{ | ||
"name": "babel-plugin-react-pure-to-class", | ||
"version": "1.0.0", | ||
"description": "Convert Functional Components to React Classes for Hot Module Replacement (HMR) & Transforms.", | ||
"main": "dist/plugin.js", | ||
"scripts": { | ||
"build": "babel src -d dist", | ||
"clean": "rimraf dist", | ||
"test": "mocha --compilers js:babel-register", | ||
"watch": "npm test -- --bail --watch" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/ericclemmons/babel-plugin-react-pure-to-class.git" | ||
}, | ||
"keywords": [ | ||
"babel-plugin", | ||
"hmr", | ||
"react", | ||
"functional", | ||
"components" | ||
], | ||
"author": "Eric Clemmons <eric@smarterspam.com>", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/ericclemmons/babel-plugin-react-pure-to-class/issues" | ||
}, | ||
"homepage": "https://github.com/ericclemmons/babel-plugin-react-pure-to-class#readme", | ||
"devDependencies": { | ||
"babel-cli": "6.5.1", | ||
"babel-core": "6.5.1", | ||
"babel-plugin-react-transform": "2.0.0", | ||
"babel-plugin-syntax-jsx": "6.5.0", | ||
"babel-preset-es2015": "6.5.0", | ||
"babel-preset-stage-0": "6.5.0", | ||
"babel-register": "6.5.1", | ||
"expect": "1.14.0", | ||
"mocha": "2.4.5", | ||
"react-transform-hmr": "1.0.2", | ||
"rimraf": "2.5.2" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,203 @@ | ||
export default function({ types: t, template }) { | ||
const declareParam = (param, i) => { | ||
if (t.isIdentifier(param)) { | ||
return t.variableDeclaration( | ||
"const", | ||
[ | ||
t.variableDeclarator( | ||
t.identifier(param.name), | ||
t.memberExpression( | ||
t.thisExpression(), | ||
t.identifier(param.name), | ||
), | ||
), | ||
], | ||
); | ||
} | ||
|
||
if (t.isObjectPattern(param)) { | ||
return t.variableDeclaration( | ||
"const", | ||
[ | ||
t.variableDeclarator( | ||
param, | ||
t.memberExpression( | ||
t.thisExpression(), | ||
t.identifier(i === 0 ? "props" : "context"), | ||
), | ||
), | ||
], | ||
) | ||
} | ||
}; | ||
|
||
const declareParams = (params) => params.map(declareParam); | ||
|
||
const functionToClass = (id, path, { file }) => { | ||
const React = findReact(file); | ||
|
||
const superClass = t.memberExpression( | ||
t.identifier("React"), | ||
t.identifier("Component"), | ||
); | ||
|
||
const decorators = []; | ||
const body = getClassBody(path); | ||
|
||
const Component = t.classDeclaration( | ||
id, | ||
superClass, | ||
body, | ||
decorators, | ||
); | ||
|
||
return Component; | ||
}; | ||
|
||
const getClassBody = (path) => { | ||
const body = (t.isBlockStatement(path.node.body)) | ||
? path.node.body.body : [t.returnStatement(path.node.body)] | ||
; | ||
|
||
const name = t.identifier("render"); | ||
const args = []; | ||
|
||
const render = t.classMethod( | ||
"method", | ||
name, | ||
args, | ||
t.blockStatement([ | ||
...declareParams(path.node.params), | ||
...body, | ||
], []) | ||
); | ||
|
||
return t.classBody([ | ||
render, | ||
]); | ||
}; | ||
|
||
const hasJSX = (path) => { | ||
const state = { jsx: false }; | ||
|
||
path.traverse({ | ||
JSXElement(path) { | ||
this.jsx = true; | ||
path.stop(); | ||
}, | ||
}, state); | ||
|
||
return state.jsx; | ||
}; | ||
|
||
const findReact = (file) => { | ||
const existing = file.path.node.body | ||
.filter((path) => t.isImportDeclaration(path)) | ||
.map((path) => path.specifiers | ||
.filter((path) => t.isImportDefaultSpecifier(path)) | ||
.map((path) => path.local) | ||
.filter((id) => id.name === "React") | ||
.shift() | ||
) | ||
.shift() | ||
; | ||
|
||
if (existing) { | ||
return existing; | ||
} | ||
|
||
const React = t.importDeclaration( | ||
[t.importDefaultSpecifier(t.identifier("React"))], | ||
t.stringLiteral("react"), | ||
); | ||
|
||
file.path.node.body.unshift(React); | ||
|
||
return React; | ||
} | ||
|
||
const isCapitalized = (name) => name.match(/^[A-Z]\w+$/); | ||
|
||
const FunctionExpression = (path, { file }) => { | ||
if (t.isCallExpression(path.parent)) { | ||
FunctionDeclaration(path, { file }); | ||
return; | ||
} | ||
|
||
const variable = path.parent; | ||
|
||
if (!t.isVariableDeclarator(variable)) { | ||
return; | ||
} | ||
|
||
const declaration = path.parentPath.parentPath; | ||
|
||
if (!t.isVariableDeclaration(declaration)) { | ||
return; | ||
} | ||
|
||
if (!declaration.kind === "const") { | ||
return; | ||
} | ||
|
||
const { name } = variable.id; | ||
|
||
if (!isCapitalized(name)) { | ||
return; | ||
} | ||
|
||
if (!hasJSX(path)) { | ||
return; | ||
} | ||
|
||
const id = t.identifier(name); | ||
const Component = functionToClass(id, path, { file }); | ||
|
||
declaration.replaceWith(Component); | ||
}; | ||
|
||
const FunctionDeclaration = (path, { file }) => { | ||
const { id } = path.node; | ||
|
||
if (!id) { | ||
return; | ||
} | ||
|
||
if (!isCapitalized(id.name)) { | ||
return; | ||
} | ||
|
||
if (!hasJSX(path)) { | ||
return; | ||
} | ||
|
||
const Component = functionToClass(id, path, { file }); | ||
|
||
if (t.isExportDefaultDeclaration(path.parent)) { | ||
path.parentPath.replaceWith(Component); | ||
path.parentPath.insertAfter(t.exportDefaultDeclaration(id)); | ||
} else if (t.isCallExpression(path.parent)) { | ||
if (t.isExportDefaultDeclaration(path.parentPath.parentPath)) { | ||
path.replaceWith(id); | ||
path.parentPath.parentPath.insertBefore(Component); | ||
} | ||
} else if (t.isExportNamedDeclaration(path.parent)) { | ||
path.replaceWith(Component); | ||
} else if (t.isProgram(path.parent)) { | ||
path.replaceWith(Component); | ||
} | ||
}; | ||
|
||
return { | ||
visitor: { | ||
// const Component = () => {} | ||
ArrowFunctionExpression: FunctionExpression, | ||
|
||
// function Component(...) | ||
FunctionDeclaration, | ||
|
||
// const Component = function(...) | ||
FunctionExpression, | ||
} | ||
} | ||
} |
Oops, something went wrong.