New boilerplate

This commit is contained in:
Christian Alfoni
2014-10-27 15:28:16 +01:00
parent 54bbfd3ce2
commit 633e48461c
29 changed files with 2609 additions and 29544 deletions

View File

@@ -1,38 +1,31 @@
## React FLUX Boilerplate ## React FLUX Boilerplate
Based on the architecture suggestions from Facebook, this boilerplate will help you deal with it. It has included the Based on the architecture suggestions from Facebook, this boilerplate will help you deal with it. It has included the flux-react extension to React JS, [flux-react](https://github.com/christianalfoni/flux-react).
flux-react extension to React JS. Read more about FLUX over at [Facebook Flux](http://facebook.github.io/flux/) and I wrote a post about it too: [React JS and FLUX](http://christianalfoni.github.io/javascript/2014/08/20/react-js-and-flux.html).
Read more about FLUX over at [Facebook Flux](http://facebook.github.io/flux/) and I wrote a post about it too: [React JS and FLUX](http://christianalfoni.github.io/javascript/2014/08/20/react-js-and-flux.html).
### How to use ### How to use
* Clone the repo * Clone the repo
* Run `npm install` * Run `npm install`
* Open `dev/index.html`, run `python -m SimpleHTTPServer` in the `dev` folder or set up your own server * Open `build/index.html`, run `python -m SimpleHTTPServer` in the `build` folder or set up your own server
### Development ### Development
* Run `gulp` * Run `gulp`
* Any changes to `app` or `styles` folder will automatically rebuild to `dev` folder * Any changes to `app` folder will automatically rebuild to `build` folder
### Tests
* Run `gulp test -'./tests/App-test.js'
* Open `test.html`
* Any changes done to the test file or files in `app` folder will autoreload the browser
### Run all tests with Karma ### Run all tests with Karma
* Run `npm test` * Run `npm test`
Karma will launch PhantomJS and run the tests once. If you need to run tests in a GUI browser, either change `karma.conf.js` to use Chrome or Firefox, or manually start it with: Karma will launch PhantomJS and run the tests once. If you need to run tests in a normal browser change karma.conf.js to use 'Chrome' as browser. You can also keep running the tests as you write them. Set `autoWatch: true` and `singleRun: false`.
`./node_modules/karma/bin/karma start --single-run --browsers Chrome`
### Minify the code, ready for production ### Minify the code, ready for production
* Run `gulp deploy` * Run `gulp deploy` to deploy to `dist` folder
### Directory ### Directory
* **app/**: Where you develop the application * **app/**: Where you develop the application
* **dev/**: Where your automatically builds to. This is where you launch your app in development * **build/**: Where your automatically builds to. This is where you launch your app in development
* **dist/**: Where the deployed code exists, ready for production * **dist/**: Where the deployed code exists, ready for production
* **utils/**: Gulp tasks and other utils
* **styles/**: Where you put your css files
* **tests/**: Where you put your test files * **tests/**: Where you put your test files
* **gulpfile**: Gulp configuration * **gulpfile**: Gulp configuration
* **karma.conf.js**: Karma configuration * **karma.conf.js**: Karma configuration

BIN
app/.DS_Store vendored

Binary file not shown.

View File

@@ -1,5 +1,5 @@
/** @jsx React.DOM */ /** @jsx React.DOM */
var React = require('flux-react'); var React = require('react');
var Checkboxes = require('./components/Checkboxes.js'); var Checkboxes = require('./components/Checkboxes.js');
var NameThrower = require('./components/NameThrower.js'); var NameThrower = require('./components/NameThrower.js');
@@ -8,8 +8,12 @@ var App = React.createClass({
return ( return (
<div> <div>
<h1>Hello world!</h1> <h1>Hello world!</h1>
<Checkboxes/> <div>
<NameThrower/> <Checkboxes/>
</div>
<div>
<NameThrower/>
</div>
</div> </div>
); );
} }

View File

@@ -1,3 +0,0 @@
module.exports = {
EVENT_CHANGE: 'change'
};

5
app/actions.js Normal file
View File

@@ -0,0 +1,5 @@
module.exports = flux.createActions([
'checkAll',
'uncheckAll',
'check'
]);

View File

@@ -1,5 +0,0 @@
module.exports = {
'CHECK_ALL': 'check all',
'UNCHECK_ALL': 'uncheck all',
'CHECK': 'check'
};

View File

@@ -1,8 +1,8 @@
/** @jsx React.DOM */ /** @jsx React.DOM */
var React = require('flux-react'); var React = require('react');
var Constants = require('../Constants.js'); var flux = require('flux-react');
var actions = require('./../actions.js');
var ColoredCheckbox = require('./Checkboxes/ColoredCheckbox.js'); var ColoredCheckbox = require('./Checkboxes/ColoredCheckbox.js');
var CheckboxActions = require('../actions/CheckboxActions.js');
var CheckboxStore = require('../stores/CheckboxStore.js'); var CheckboxStore = require('../stores/CheckboxStore.js');
var Checkboxes = React.createClass({ var Checkboxes = React.createClass({
@@ -12,36 +12,44 @@ var Checkboxes = React.createClass({
checkboxes: CheckboxStore.getCheckboxes() checkboxes: CheckboxStore.getCheckboxes()
}; };
}, },
storesDidUpdate: function () { componentWillMount: function () {
CheckboxStore.addChangeListener(this.update);
},
componentWillUnmount: function () {
CheckboxStore.removeChangeListener(this.update);
},
update: function () {
this.setState({ this.setState({
checkboxes: CheckboxStore.getCheckboxes() checkboxes: CheckboxStore.getCheckboxes()
}); });
}, },
check: function (color) { check: function (color) {
React.dispatch({ actions.check(color);
type: CheckboxActions.CHECK,
color: color
})
}, },
checkAll: function () { checkAll: function () {
React.dispatch({ actions.checkAll();
type: CheckboxActions.CHECK_ALL
});
}, },
uncheckAll: function () { uncheckAll: function () {
React.dispatch({ actions.uncheckAll();
type: CheckboxActions.UNCHECK_ALL },
}); renderCheckbox: function (checkbox, index) {
return <ColoredCheckbox
key={index}
color={checkbox.color}
checked={checkbox.checked}
onChange={this.check}/>
}, },
render: function() { render: function() {
var checkboxes = this.state.checkboxes.map(function (checkbox, index) { var checkboxes = this.state.checkboxes.map(this.renderCheckbox);
return <ColoredCheckbox key={index} color={checkbox.color} checked={checkbox.checked} onChange={this.check}/>
}, this);
return ( return (
<div> <div>
{checkboxes} <div>
<button onClick={this.checkAll}>Check all</button> {checkboxes}
<button onClick={this.uncheckAll}>Uncheck all</button> </div>
<div>
<button onClick={this.checkAll}>Check all</button>
<button onClick={this.uncheckAll}>Uncheck all</button>
</div>
</div> </div>
); );
} }

View File

@@ -1,7 +1,10 @@
/** @jsx React.DOM */ /** @jsx React.DOM */
var React = require('flux-react'); var React = require('react');
var ColoredCheckbox = React.createClass({ var ColoredCheckbox = React.createClass({
changeColor: function () {
this.props.onChange(this.props.color);
},
render: function() { render: function() {
var style = { var style = {
backgroundColor: this.props.color, backgroundColor: this.props.color,
@@ -10,7 +13,7 @@ var ColoredCheckbox = React.createClass({
return ( return (
<span key={this.props.key} style={style}> <span key={this.props.key} style={style}>
<input type="checkbox" <input type="checkbox"
onChange={this.props.onChange.bind(null, this.props.color)} onChange={this.changeColor}
checked={this.props.checked}/> checked={this.props.checked}/>
</span> </span>
); );

View File

@@ -1,35 +1,44 @@
/** @jsx React.DOM */ /** @jsx React.DOM */
var React = require('flux-react'); var React = require('react');
var Constants = require('../Constants.js');
var CheckboxStore = require('../stores/CheckboxStore.js'); var CheckboxStore = require('../stores/CheckboxStore.js');
var NameThrower = React.createClass({ var NameThrower = React.createClass({
stores: [CheckboxStore],
getInitialState: function () { getInitialState: function () {
return { return {
name: '', name: '',
colors: CheckboxStore.getColors() colors: CheckboxStore.getColors()
}; };
}, },
storesDidUpdate: function () { componentWillMount: function () {
CheckboxStore.addChangeListener(this.update);
},
componentWillUnmount: function () {
CheckboxStore.removeChangeListener(this.update);
},
update: function () {
this.setState({ this.setState({
colors: CheckboxStore.getColors() colors: CheckboxStore.getColors()
}); });
}, },
updateName: function () { updateName: function (event) {
this.setState({ this.setState({
name: this.refs.input.getDOMNode().value name: event.target.value
}); });
}, },
render: function() { renderColors: function (color, index) {
var names = this.state.colors.map(function (color, index) {
var style = {color: color}; var style = {color: color};
return <div key={index} style={style}>{this.state.name}</div> return <div key={index} style={style}>{this.state.name}</div>
}, this); },
render: function() {
var names = this.state.colors.map(this.renderColors);
return ( return (
<div> <div>
<input ref="input" type="text" value={this.state.name} onChange={this.updateName}/> <div>
{names} <input type="text" value={this.state.name} onChange={this.updateName}/>
</div>
<div>
{names}
</div>
</div> </div>
); );
} }

View File

@@ -1,6 +1,8 @@
/** @jsx React.DOM */ /** @jsx React.DOM */
var React = require('flux-react'); var React = require('react');
React.debug(); var flux = require('flux-react');
var App = require('./App.js'); var App = require('./App.js');
flux.debug();
React.renderComponent(<App/>, document.body); React.renderComponent(<App/>, document.body);

View File

@@ -1,63 +1,60 @@
var React = require('flux-react'); var flux = require('flux-react');
var merge = require('react/lib/merge'); var actions = require('./../actions.js');
var CheckboxActions = require('../actions/CheckboxActions.js');
var mergeInto = require('react/lib/mergeInto');
var Constants = require('../Constants.js');
var checkboxes = [{ var CheckboxStore = flux.createStore({
color: 'red', getInitialState: function () {
checked: false return {
}, { checkboxes: [{
color: 'blue', color: 'red',
checked: false checked: false
}, { }, {
color: 'green', color: 'blue',
checked: false checked: false
}]; }, {
color: 'green',
var CheckboxStore = React.createStore({ checked: false
}]
getCheckboxes: function () { };
return checkboxes.map(function (checkbox) {
var checkboxCopy = {};
mergeInto(checkboxCopy, checkbox); // Create a copy to make it impossible to mutate store
return checkboxCopy;
});
}, },
getColors: function () { actions: [
return checkboxes.map(function (checkbox) { actions.checkAll,
if (checkbox.checked) { actions.uncheckAll,
return checkbox.color; actions.check
} else { ],
return 'black'; checkAll: function () {
this.state.checkboxes.forEach(function (checkbox) {
checkbox.checked = true;
});
this.emitChange();
},
uncheckAll: function () {
this.state.checkboxes.forEach(function (checkbox) {
checkbox.checked = false;
});
this.emitChange();
},
check: function (color) {
this.state.checkboxes.forEach(function (checkbox) {
if (checkbox.color === color) {
checkbox.checked = !checkbox.checked;
} }
}); });
this.emitChange();
}, },
dispatch: function (payload) { exports: {
switch (payload.type) { getCheckboxes: function () {
case CheckboxActions.CHECK_ALL: return this.checkboxes;
checkboxes.forEach(function (checkbox) { },
checkbox.checked = true; getColors: function () {
}); return this.checkboxes.map(function (checkbox) {
break; if (checkbox.checked) {
return checkbox.color;
case CheckboxActions.UNCHECK_ALL: } else {
checkboxes.forEach(function (checkbox) { return 'black';
checkbox.checked = false;
});
break;
case CheckboxActions.CHECK:
checkboxes.forEach(function (checkbox) {
if (checkbox.color === payload.color) {
checkbox.checked = !checkbox.checked;
} }
}); });
break;
} }
this.flush();
} }
}); });
module.exports = CheckboxStore; module.exports = CheckboxStore;

15
build/index.html Normal file
View File

@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<style>
div {
margin-bottom: 10px;
}
</style>
</head>
<body>
<script src="vendors.js"></script>
<script src="main.js"></script>
</body>
</html>

239
build/main.js Executable file

File diff suppressed because one or more lines are too long

3549
dev/main.js → build/vendors.js Normal file → Executable file

File diff suppressed because one or more lines are too long

View File

@@ -1,14 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<link rel="stylesheet" href="main.css"/>
<script>
window.DEBUG = true;
</script>
</head>
<body>
<div id="app"></div>
<script src="main.js"></script>
</body>
</html>

View File

@@ -1,4 +0,0 @@
body {
background-color: #EAEAEA;
zoom: 150%;
}

27776
dev/test.js

File diff suppressed because one or more lines are too long

15
dist/index.html vendored Executable file
View File

@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<style>
div {
margin-bottom: 10px;
}
</style>
</head>
<body>
<script src="vendors.js"></script>
<script src="main.js"></script>
</body>
</html>

1
dist/main.js vendored Executable file
View File

@@ -0,0 +1 @@
!function e(t,o,c){function n(s,a){if(!o[s]){if(!t[s]){var i="function"==typeof require&&require;if(!a&&i)return i(s,!0);if(r)return r(s,!0);var l=new Error("Cannot find module '"+s+"'");throw l.code="MODULE_NOT_FOUND",l}var h=o[s]={exports:{}};t[s][0].call(h.exports,function(e){var o=t[s][1][e];return n(o?o:e)},h,h.exports,e,t,o,c)}return o[s].exports}for(var r="function"==typeof require&&require,s=0;s<c.length;s++)n(c[s]);return n}({"./app/main.js":[function(e){var t=e("react"),o=e("flux-react");o.debug(),o.createActions(["checkAll","uncheckAll","check"]);var c=e("./App.js");t.renderComponent(c(null),document.body)},{"./App.js":"/Users/christianalfoni/Documents/dev/flux-react-boilerplate/app/App.js","flux-react":"flux-react",react:"react"}],"/Users/christianalfoni/Documents/dev/flux-react-boilerplate/app/App.js":[function(e,t){var o=e("react"),c=e("./components/Checkboxes.js"),n=e("./components/NameThrower.js"),r=o.createClass({displayName:"App",render:function(){return o.DOM.div(null,o.DOM.h1(null,"Hello world!"),o.DOM.div(null,c(null)),o.DOM.div(null,n(null)))}});t.exports=r},{"./components/Checkboxes.js":"/Users/christianalfoni/Documents/dev/flux-react-boilerplate/app/components/Checkboxes.js","./components/NameThrower.js":"/Users/christianalfoni/Documents/dev/flux-react-boilerplate/app/components/NameThrower.js",react:"react"}],"/Users/christianalfoni/Documents/dev/flux-react-boilerplate/app/components/Checkboxes.js":[function(e,t){var o=e("react"),c=e("flux-react"),n=e("./Checkboxes/ColoredCheckbox.js"),r=e("../stores/CheckboxStore.js"),s=o.createClass({displayName:"Checkboxes",stores:[r],getInitialState:function(){return{checkboxes:r.getCheckboxes()}},componentWillMount:function(){r.addChangeListener(this.update)},componentWillUnmount:function(){r.removeChangeListener(this.update)},update:function(){this.setState({checkboxes:r.getCheckboxes()})},check:function(e){c.action.check(e)},checkAll:function(){c.action.checkAll()},uncheckAll:function(){c.action.uncheckAll()},renderCheckbox:function(e,t){return n({key:t,color:e.color,checked:e.checked,onChange:this.check})},render:function(){var e=this.state.checkboxes.map(this.renderCheckbox);return o.DOM.div(null,o.DOM.div(null,e),o.DOM.div(null,o.DOM.button({onClick:this.checkAll},"Check all"),o.DOM.button({onClick:this.uncheckAll},"Uncheck all")))}});t.exports=s},{"../stores/CheckboxStore.js":"/Users/christianalfoni/Documents/dev/flux-react-boilerplate/app/stores/CheckboxStore.js","./Checkboxes/ColoredCheckbox.js":"/Users/christianalfoni/Documents/dev/flux-react-boilerplate/app/components/Checkboxes/ColoredCheckbox.js","flux-react":"flux-react",react:"react"}],"/Users/christianalfoni/Documents/dev/flux-react-boilerplate/app/components/Checkboxes/ColoredCheckbox.js":[function(e,t){var o=e("react"),c=o.createClass({displayName:"ColoredCheckbox",changeColor:function(){this.props.onChange(this.props.color)},render:function(){var e={backgroundColor:this.props.color,padding:"5px"};return o.DOM.span({key:this.props.key,style:e},o.DOM.input({type:"checkbox",onChange:this.changeColor,checked:this.props.checked}))}});t.exports=c},{react:"react"}],"/Users/christianalfoni/Documents/dev/flux-react-boilerplate/app/components/NameThrower.js":[function(e,t){var o=e("react"),c=e("../stores/CheckboxStore.js"),n=o.createClass({displayName:"NameThrower",getInitialState:function(){return{name:"",colors:c.getColors()}},componentWillMount:function(){c.addChangeListener(this.update)},componentWillUnmount:function(){c.removeChangeListener(this.update)},update:function(){this.setState({colors:c.getColors()})},updateName:function(e){this.setState({name:e.target.value})},renderColors:function(e,t){var c={color:e};return o.DOM.div({key:t,style:c},this.state.name)},render:function(){var e=this.state.colors.map(this.renderColors);return o.DOM.div(null,o.DOM.div(null,o.DOM.input({type:"text",value:this.state.name,onChange:this.updateName})),o.DOM.div(null,e))}});t.exports=n},{"../stores/CheckboxStore.js":"/Users/christianalfoni/Documents/dev/flux-react-boilerplate/app/stores/CheckboxStore.js",react:"react"}],"/Users/christianalfoni/Documents/dev/flux-react-boilerplate/app/stores/CheckboxStore.js":[function(e,t){var o=e("flux-react"),c=o.createStore({getInitialState:function(){return{checkboxes:[{color:"red",checked:!1},{color:"blue",checked:!1},{color:"green",checked:!1}]}},actions:["checkAll","uncheckAll","check"],checkAll:function(){this.state.checkboxes.forEach(function(e){e.checked=!0}),this.emitChange()},uncheckAll:function(){this.state.checkboxes.forEach(function(e){e.checked=!1}),this.emitChange()},check:function(e){this.state.checkboxes.forEach(function(t){t.color===e&&(t.checked=!t.checked)}),this.emitChange()},exports:{getCheckboxes:function(){return this.checkboxes},getColors:function(){return this.checkboxes.map(function(e){return e.checked?e.color:"black"})}}});t.exports=c},{"flux-react":"flux-react"}]},{},["./app/main.js"]);

6
dist/vendors.js vendored Executable file

File diff suppressed because one or more lines are too long

View File

@@ -1,49 +1,132 @@
// Gulp dependencies
var gulp = require('gulp'); var gulp = require('gulp');
var browserify = require('browserify');
var watchify = require('watchify');
var source = require('vinyl-source-stream');
var reactify = require('reactify');
var gulpif = require('gulp-if');
var uglify = require('gulp-uglify');
var streamify = require('gulp-streamify');
var notify = require('gulp-notify');
var gutil = require('gulp-util'); var gutil = require('gulp-util');
var shell = require('gulp-shell');
var browserify = require('./utils/browserify.js'); var appOptions = {
var css = require('./utils/css.js');
/*
* DIRECTORIES
*/
// Where your app lives
appDir: './app',
// Where your production version is deployed
distDir: './dist',
// Where you bundled development version will run from
buildDir: './build',
/*
* BUNDLE FILES
*/
// The name of your main app file
entryFile: 'main.js',
// The name of your bundled vendors
vendorsFile: 'vendors.js',
/*
* VENDORS
*/
// Add other vendors here, if any
vendors: [
'react',
'flux-react'
]
var DEFAULT_OPTIONS = {
browserify: {
src: './app/main.js',
isTest: false,
dest: './dev/',
watch: true,
uglify: false
},
css: {
src: './styles/**/*.css',
dest: './dev/',
watch: true
}
}; };
gulp.task('browserify', function () { // The task that handles both development and deployment
return browserify(DEFAULT_OPTIONS.browserify); var browserifyTask = function (bundleOptions) {
});
gulp.task('css', function () { // This bundle only runs when you start to develop,
return css(DEFAULT_OPTIONS.css); // it is needed to prevent rebundling external deps
}); // on project changes
var vendorBundler = browserify({
debug: bundleOptions.debug,
require: appOptions.vendors
});
gulp.task('default', ['browserify', 'css']); // This bundle is for the application
var appBundler = browserify({
entries: [appOptions.appDir + '/' + appOptions.entryFile],
debug: bundleOptions.debug,
// These options are needed by Watchify
cache: {},
packageCache: {},
fullPaths: true
});
// Add reactify transformer
appBundler.transform(reactify);
// Add vendors as externals
appOptions.vendors.forEach(function (vendor) {
appBundler.external(vendor);
});
// The rebundle process
var rebundle = function () {
var start = Date.now();
appBundler.bundle()
.on('error', gutil.log)
.pipe(source(appOptions.entryFile))
.pipe(gulpif(bundleOptions.uglify, streamify(uglify())))
.pipe(gulp.dest(bundleOptions.dest))
.pipe(notify(function () {
console.log('Built in ' + (Date.now() - start) + 'ms');
}));
};
// Fire up Watchify when developing
if (bundleOptions.watch) {
appBundler = watchify(appBundler);
appBundler.on('update', rebundle);
}
// Run the vendor bundle when the default Gulp task starts
vendorBundler.bundle()
.on('error', gutil.log)
.pipe(source(appOptions.vendorsFile))
.pipe(gulpif(bundleOptions.uglify, streamify(uglify())))
.pipe(gulp.dest(bundleOptions.dest));
return rebundle();
};
gulp.task('default', function () {
browserifyTask({
watch: true,
dest: appOptions.buildDir,
uglify: false,
debug: true
});
});
gulp.task('deploy', function () { gulp.task('deploy', function () {
DEFAULT_OPTIONS.browserify.dest = './dist/';
DEFAULT_OPTIONS.browserify.watch = false;
DEFAULT_OPTIONS.browserify.uglify = true;
browserify(DEFAULT_OPTIONS.browserify);
DEFAULT_OPTIONS.css.dest = './dist/'; browserifyTask({
DEFAULT_OPTIONS.css.watch = false; watch: false,
css(DEFAULT_OPTIONS.css); dest: appOptions.distDir,
}); uglify: true,
debug: false
});
gulp.task('test', function () {
var src = '.' + gutil.env[''][''];
DEFAULT_OPTIONS.browserify.src = src;
DEFAULT_OPTIONS.browserify.isTest = true;
return browserify(DEFAULT_OPTIONS.browserify);
}); });

View File

@@ -12,9 +12,8 @@ module.exports = function(config) {
// list of files / patterns to load in the browser // list of files / patterns to load in the browser
files: [ files: [
'utils/es5-shim.js', 'es5-shim.js',
'tests/**/*.js' 'tests/**/*.js'
// 'server/**/*.js'
], ],
@@ -27,7 +26,6 @@ module.exports = function(config) {
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: { preprocessors: {
'tests/**/*.js': ['browserify'] 'tests/**/*.js': ['browserify']
// 'server/**/*.js': ['browserify']
}, },
@@ -57,7 +55,7 @@ module.exports = function(config) {
// enable / disable watching file and executing tests whenever any file changes // enable / disable watching file and executing tests whenever any file changes
autoWatch: false, autoWatch: true,
// start these browsers // start these browsers
@@ -68,6 +66,6 @@ module.exports = function(config) {
// Continuous Integration mode // Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits // if true, Karma captures browsers, runs the tests and exits
singleRun: true singleRun: false
}); });
}; };

View File

@@ -1,6 +1,6 @@
{ {
"name": "flux-react-boilerplate", "name": "flux-react-boilerplate",
"version": "1.0.0", "version": "2.0.0",
"description": "React flux architecture boilerplate", "description": "React flux architecture boilerplate",
"main": "gulp", "main": "gulp",
"scripts": { "scripts": {
@@ -11,28 +11,25 @@
"devDependencies": { "devDependencies": {
"browserify": "^5.9.3", "browserify": "^5.9.3",
"chai": "^1.9.1", "chai": "^1.9.1",
"es6-promise": "^1.0.0", "flux-react": "^2.1.0",
"flux-react": "^1.3.2",
"gulp": "^3.8.7", "gulp": "^3.8.7",
"gulp-concat": "^2.3.4",
"gulp-cssmin": "^0.1.6",
"gulp-if": "^1.2.4", "gulp-if": "^1.2.4",
"gulp-livereload": "^2.1.0", "gulp-livereload": "^2.1.0",
"gulp-notify": "^1.4.2", "gulp-notify": "^1.4.2",
"gulp-shell": "^0.2.10",
"gulp-streamify": "0.0.5", "gulp-streamify": "0.0.5",
"gulp-uglify": "^0.3.1", "gulp-uglify": "^0.3.1",
"gulp-util": "^3.0.0", "gulp-util": "^3.0.0",
"react": "^0.11.1",
"reactify": "^0.14.0",
"vinyl-source-stream": "^0.1.1",
"watchify": "^1.0.2",
"karma": "^0.12.21", "karma": "^0.12.21",
"karma-bro": "^0.6.2", "karma-bro": "^0.6.2",
"karma-chrome-launcher": "^0.1.4", "karma-chrome-launcher": "^0.1.4",
"karma-firefox-launcher": "^0.1.3", "karma-firefox-launcher": "^0.1.3",
"karma-mocha": "^0.1.7", "karma-mocha": "^0.1.7",
"karma-phantomjs-launcher": "^0.1.4", "karma-phantomjs-launcher": "^0.1.4",
"mocha": "^1.21.4", "mocha": "^1.21.4"
"react": "^0.11.1",
"react-tools": "^0.11.1",
"reactify": "^0.14.0",
"vinyl-source-stream": "^0.1.1",
"watchify": "^1.0.2"
} }
} }

View File

@@ -1,4 +0,0 @@
body {
background-color: #EAEAEA;
zoom: 150%;
}

View File

@@ -15,4 +15,4 @@ describe('App', function() {
expect(h1.getDOMNode().textContent).to.equal('Hello world!'); expect(h1.getDOMNode().textContent).to.equal('Hello world!');
}); });
}); });

View File

@@ -1,69 +0,0 @@
/**
Use Browserify to bundle up our tests.
gulp test --watch --tests './tests/checkboxWithLabel-test.js'
Thanks to - http://blog.avisi.nl/2014/04/25/how-to-keep-a-fast-build-with-browserify-and-reactjs/
*/
var gulp = require('gulp');
var source = require('vinyl-source-stream');
var browserify = require('browserify');
var watchify = require('watchify');
var reactify = require('reactify');
var livereload = require('gulp-livereload');
var gulpif = require('gulp-if');
var path = require('path');
var uglify = require('gulp-uglify');
var streamify = require('gulp-streamify');
var notify = require('gulp-notify');
var handleError = require('./handleError');
var getTimeStamp = function () {
var date = new Date();
var hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours();
var minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes();
return hours + ':' + minutes;
};
var runBrowserify = function (options) {
var bundler = browserify({
entries: [options.src],
transform: [reactify],
debug: true,
standalone: 'ReactDispatcher',
cache: {}, packageCache: {}, fullPaths: true
});
var rebundle = function() {
console.log('[' + getTimeStamp() + '] Building');
var start = Date.now();
var fileName = options.uglify ? 'ReactDispatcher.min.js' : path.basename(options.src);
bundler.bundle()
.on('error', handleError('Browserify'))
.pipe(source(options.isTest ? 'test.js' : fileName))
.pipe(gulpif(options.uglify, streamify(uglify())))
.pipe(gulp.dest(options.dest))
.pipe(gulpif(options.isTest, livereload()))
.pipe(notify(function () {
console.log('[' + getTimeStamp() + '] Built in ' + (Date.now() - start) + 'ms');
}));
};
if (options.isTest) {
livereload.listen();
}
if (options.watch) {
bundler = watchify(bundler);
bundler.on('update', rebundle);
}
bundler.transform(reactify);
return rebundle();
};
module.exports = runBrowserify;

View File

@@ -1,24 +0,0 @@
var gulp = require('gulp');
var concat = require('gulp-concat');
var cssmin = require('gulp-cssmin');
var handleError = require('./handleError');
var runCss = function (options) {
if (options.watch) {
return gulp.watch(options.src, function () {
return gulp.src(options.src)
.pipe(concat('main.css'))
.pipe(gulp.dest(options.dest));
});
} else {
return gulp.src(options.src)
.pipe(concat('main.css'))
.pipe(cssmin())
.pipe(gulp.dest(options.dest));
}
};
module.exports = runCss;

View File

@@ -1,12 +0,0 @@
var gutil = require('gulp-util');
var notify = require('gulp-notify');
module.exports = function (task) {
return function(err) {
gutil.log(gutil.colors.red(err));
notify.onError(task + ' failed, check the logs..')(err);
// Keep gulp or browserify from hanging on this task
this.emit('end');
};
};