mirror of
https://github.com/wassname/generator-react-webpack.git
synced 2026-08-20 12:20:27 +08:00
Added changes for version 2.0
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"env": {
|
||||
"browser": false,
|
||||
"amd": false,
|
||||
"es6": true,
|
||||
"node": true,
|
||||
"mocha": true
|
||||
},
|
||||
"rules": {
|
||||
"comma-dangle": 1,
|
||||
"quotes": [ 1, "single" ],
|
||||
"no-undef": 1,
|
||||
"global-strict": 0,
|
||||
"no-extra-semi": 1,
|
||||
"no-underscore-dangle": 0,
|
||||
"no-console": 0,
|
||||
"no-unused-vars": 1,
|
||||
"no-trailing-spaces": [1, { "skipBlankLines": true }],
|
||||
"no-unreachable": 1,
|
||||
"no-alert": 0
|
||||
}
|
||||
}
|
||||
@@ -13,4 +13,3 @@ $RECYCLE.BIN/
|
||||
node_modules/
|
||||
npm-debug.log
|
||||
.idea/
|
||||
/test/temp-test
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"node": true,
|
||||
"esnext": true,
|
||||
"bitwise": true,
|
||||
"camelcase": true,
|
||||
"curly": true,
|
||||
"eqeqeq": true,
|
||||
"immed": true,
|
||||
"indent": 2,
|
||||
"latedef": true,
|
||||
"newcap": true,
|
||||
"noarg": true,
|
||||
"quotmark": "single",
|
||||
"regexp": true,
|
||||
"undef": true,
|
||||
"unused": true,
|
||||
"strict": true,
|
||||
"trailing": true,
|
||||
"smarttabs": true,
|
||||
"white": true
|
||||
}
|
||||
@@ -1,359 +1,76 @@
|
||||
# generator-react-webpack [](https://travis-ci.org/newtriks/generator-react-webpack) [](http://gruntjs.com/)
|
||||
# generator-react-webpack V2.0 [](https://travis-ci.org/newtriks/generator-react-webpack) [](http://gruntjs.com/)
|
||||
|
||||
> Yeoman generator for [ReactJS](http://facebook.github.io/react/) - lets you quickly set up a project including karma test runner and [Webpack](http://webpack.github.io/) module system.
|
||||
|
||||
# About
|
||||
Generator-React-Webpack will help you build new Reactprojects using modern technologies.
|
||||
|
||||
## Usage
|
||||
Out of the box it comes with support for:
|
||||
- Webpack
|
||||
- ES2015 via Babel-Loader
|
||||
- Different supported style languages (sass, scss, less, stylus)
|
||||
- Automatic code linting via esLint
|
||||
- Ability to unit test components via Karma and Mocha/Chai
|
||||
|
||||
Install `generator-react-webpack`:
|
||||
```
|
||||
npm install -g generator-react-webpack
|
||||
```
|
||||
## Subgenerators
|
||||
This generator is also the base project for some other generators that depend on it:
|
||||
### Generator-React-Webpack-Alt
|
||||
(https://github.com/weblogixx/generator-react-webpack-alt)
|
||||
Generator based on generator-react-webpack, providing support for Alt.js.
|
||||
|
||||
Make a new directory, and `cd` into it:
|
||||
```
|
||||
mkdir my-new-project && cd $_
|
||||
```
|
||||
---
|
||||
|
||||
Run `yo react-webpack`, optionally passing an app name:
|
||||
```
|
||||
yo react-webpack [app-name]
|
||||
```
|
||||
|
||||
Run `grunt build` for building and `grunt serve` for preview in the browser at [localhost](http://localhost:8000).
|
||||
|
||||
## Generators
|
||||
|
||||
Available generators:
|
||||
|
||||
* [react-webpack](#app) (aka [react-webpack:app](#app))
|
||||
* [react-webpack:component](#component)
|
||||
|
||||
and for **Flux** or **Reflux** :
|
||||
* [react-webpack:action](#action)
|
||||
* [react-webpack:store](#store)
|
||||
|
||||
|
||||
### App
|
||||
|
||||
Sets up a new ReactJS app, generating all the boilerplate you need to get started. The app generator also facilitates the following:
|
||||
|
||||
1. Configures a Gruntfile to run the app on a local server.
|
||||
2. Configures Webpack to modularise the app enabling [loading of various file formats](http://webpack.github.io/docs/loader-list.html) e.g. JSON, CSS, PNG, etc.
|
||||
3. Configures [Karma](http://karma-runner.github.io) to run all tests.
|
||||
4. Watches for changes and recompiles JS and refreshes the browser.
|
||||
|
||||
Example:
|
||||
## Installation
|
||||
```bash
|
||||
npm install -g yo
|
||||
npm install generator-react-webpack
|
||||
```
|
||||
|
||||
## Setting up projects
|
||||
```bash
|
||||
# Create a new directory, and `cd` into it:
|
||||
mkdir my-new-project && cd my-new-project
|
||||
|
||||
# Run the generator
|
||||
yo react-webpack
|
||||
```
|
||||
|
||||
### Component
|
||||
Please make sure to edit your newly generated `package.json` file to set description, author information and the like.
|
||||
|
||||
Generates a [JSX](http://facebook.github.io/react/docs/jsx-in-depth.html) component in `src/components`, its corresponding test in `test/spec/components` and its style in `src/styles`.
|
||||
|
||||
Example:
|
||||
## Generating new components
|
||||
```bash
|
||||
yo react-webpack:component foo //or just: yo react-webpack:c foo
|
||||
# After setup of course :)
|
||||
# cd my-new-project
|
||||
yo react-webpack:component my/namespaced/components/name
|
||||
```
|
||||
|
||||
Produces `src/components/Foo.js` (*javascript - JSX*):
|
||||
```js
|
||||
'use strict';
|
||||
The above command will create a new component, as well as its stylesheet and a basic testcase.
|
||||
|
||||
var React = require('react/addons');
|
||||
|
||||
require('styles/componentName.css'); //or .sass,.less etc...
|
||||
|
||||
var Foo = React.createClass({
|
||||
render: function () {
|
||||
return (
|
||||
<div>
|
||||
<p>Content for Foo</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Foo;
|
||||
```
|
||||
|
||||
And `test/spec/components/Foo.js` (*javascript - jasmine, as seen on http://simonsmith.io/unit-testing-react-components-without-a-dom/*):
|
||||
```js
|
||||
'use strict';
|
||||
|
||||
// Uncomment the following lines to use the react test utilities
|
||||
// import React from 'react/addons';
|
||||
// const TestUtils = React.addons.TestUtils;
|
||||
|
||||
import createComponent from 'helpers/createComponent';
|
||||
import Foo from 'components/Foo.js';
|
||||
|
||||
describe('Foo', () => {
|
||||
|
||||
let FooComponent;
|
||||
|
||||
beforeEach(() => {
|
||||
FooComponent = createComponent(Foo);
|
||||
});
|
||||
|
||||
it('should have its component name as default className', () => {
|
||||
expect(FooComponent._store.props.className).toBe('Foo');
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
And `src/styles/Foo.css` (or .sass, .less etc...) :
|
||||
```css
|
||||
.Foo {
|
||||
border: 1px dashed #f00;
|
||||
}
|
||||
```
|
||||
|
||||
### rich flag
|
||||
|
||||
For all you lazy programmers out there, we've added another shortcut - `rich` flag:
|
||||
## Usage
|
||||
The following commands are available in your project:
|
||||
```bash
|
||||
yo react-webpack:c foofoo --rich
|
||||
# Start for development
|
||||
npm start # or
|
||||
npm run serve
|
||||
|
||||
# Start the dev-server with the dist version
|
||||
npm run serve:dist
|
||||
|
||||
# Just build the dist version and copy static files
|
||||
npm run dist
|
||||
|
||||
# Run unit tests
|
||||
npm test
|
||||
|
||||
# Lint all files in src (also automatically done AFTER tests are run)
|
||||
npm run lint
|
||||
|
||||
# Clean up the dist directory
|
||||
npm run clean
|
||||
|
||||
# Just copy the static assets
|
||||
npm run copy
|
||||
```
|
||||
This will give you all of react component's most common stuff :
|
||||
```js
|
||||
var React = require('react/addons');
|
||||
|
||||
require('styles/Foofoo.sass');
|
||||
|
||||
var Foofoo = React.createClass({
|
||||
mixins: [],
|
||||
getInitialState: function() {
|
||||
return {};
|
||||
},
|
||||
getDefaultProps: function() {},
|
||||
componentWillMount: function() {},
|
||||
componentDidMount: function() {},
|
||||
shouldComponentUpdate: function() {},
|
||||
componentDidUpdate: function() {},
|
||||
componentWillUnmount: function() {},
|
||||
|
||||
render: function () {
|
||||
return (
|
||||
<div>
|
||||
<p>Content for Foofoo</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Foofoo;
|
||||
```
|
||||
|
||||
Just remove those you don't need, then fill and space out the rest.
|
||||
|
||||
### Action
|
||||
|
||||
When using Flux or Reflux architecture, it generates an actionCreator in `src/actions` and it's corresponding test in `src/spec/actions`.
|
||||
|
||||
Example:
|
||||
```bash
|
||||
yo react-webpack:action bar //or just: yo react-webpack:a bar
|
||||
```
|
||||
Will create a file - `src/actions/BarActionCreators.js`
|
||||
|
||||
if 'architecture' is **Flux**, it Produces :
|
||||
```js
|
||||
'use strict';
|
||||
|
||||
var BarActionCreators = {
|
||||
|
||||
}
|
||||
|
||||
module.exports = BarActionCreators;
|
||||
```
|
||||
And if it's **Reflux**:
|
||||
```js
|
||||
'use strict';
|
||||
|
||||
var Reflux = require('reflux');
|
||||
|
||||
var BarActionCreators = Reflux.createActions([
|
||||
|
||||
]);
|
||||
|
||||
|
||||
module.exports = BarActionCreators;
|
||||
```
|
||||
|
||||
and same test for both architectures:
|
||||
```js
|
||||
'use strict';
|
||||
|
||||
describe('BarActionCreators', () => {
|
||||
let action;
|
||||
|
||||
beforeEach(function() {
|
||||
action = require('actions/BarActionCreators.js');
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(action).toBeDefined();
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### Store
|
||||
|
||||
When using Flux or Reflux architecture, it generates a store in `src/stores` and it's corresponding test in `src/spec/stores`.
|
||||
|
||||
Example:
|
||||
```bash
|
||||
yo react-webpack:store baz //or just: yo react-webpack:s baz
|
||||
```
|
||||
Will create a file - `src/stores/BazStore.js`
|
||||
|
||||
if 'architecture' is **Flux**, it Produces :
|
||||
```js
|
||||
'use strict';
|
||||
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var assign = require('object-assign');
|
||||
var MainAppDispatcher = require('../dispatcher/MainAppDispatcher');
|
||||
|
||||
var BazStore = assign({}, EventEmitter.prototype, {
|
||||
|
||||
});
|
||||
|
||||
BazStore.dispatchToken = MainAppDispatcher.register(function(action) {
|
||||
|
||||
switch(action.type) {
|
||||
default:
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
module.exports = BazStore;
|
||||
```
|
||||
And if it's **Reflux**:
|
||||
```js
|
||||
'use strict';
|
||||
|
||||
var Reflux = require('reflux');
|
||||
//var Actions = require('actions/..');
|
||||
|
||||
|
||||
var BazStore = Reflux.createStore({
|
||||
listenables: Actions,
|
||||
|
||||
|
||||
});
|
||||
|
||||
module.exports = BazStore;
|
||||
```
|
||||
|
||||
and same test for both architectures:
|
||||
```js
|
||||
'use strict';
|
||||
|
||||
describe('BazStore', () => {
|
||||
let store;
|
||||
|
||||
beforeEach(() => {
|
||||
store = require('stores/BazStore.js');
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(store).toBeDefined();
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## Options
|
||||
Options are available as additional installs to the initial application generation phase.
|
||||
|
||||
### [ReactRouter](https://github.com/rackt/react-router)
|
||||
|
||||
A complete routing library for React. This option only adds the basic hooks to get started with [react router](https://github.com/rackt/react-router).
|
||||
|
||||
### styles language
|
||||
|
||||
css, sass, scss, less or stylus
|
||||
|
||||
Sets the style file's template and extension
|
||||
|
||||
### component suffix
|
||||
|
||||
js or jsx
|
||||
|
||||
Sets the file suffix for generated components. Defaults to "js". Please note that you need to require files *including* the file ending when using jsx as suffix. Example:
|
||||
|
||||
```js
|
||||
var MyJSComponent = require('./MyJSComponent');
|
||||
var MyJSX = require('./MyJSX.jsx');
|
||||
```
|
||||
|
||||
### architecture
|
||||
|
||||
[flux](https://facebook.github.io/flux/) or [reflux](https://github.com/spoike/refluxjs)
|
||||
|
||||
### es6
|
||||
|
||||
If you are using `es6`, and want to use its export functionality (and not webpack's), just add `--es6` flag when you create a component, action or store.
|
||||
|
||||
|
||||
## Testing
|
||||
|
||||
Running `grunt test` will run the unit tests with karma. Tests are written using [Jasmine](http://jasmine.github.io/) by default.
|
||||
|
||||
## Further Information
|
||||
|
||||
### Project Structure
|
||||
|
||||
The react-webpack generator automates the setup of a [ReactJS](http://facebook.github.io/react/) project using the specific structure detailed below:
|
||||
|
||||
```
|
||||
project
|
||||
- src
|
||||
-components
|
||||
MainApp.js
|
||||
Foo.js
|
||||
AnotherComponent.js
|
||||
|
||||
//for flux/reflux
|
||||
-actions
|
||||
BarActionCreators.js
|
||||
-stores
|
||||
BazStore.js
|
||||
//for flux
|
||||
-dispatcher
|
||||
FooAppDispatcher
|
||||
|
||||
- styles
|
||||
main.css
|
||||
index.html
|
||||
- test
|
||||
- spec
|
||||
- components
|
||||
MainApp.js
|
||||
Foo.js
|
||||
AnotherComponent.js
|
||||
|
||||
//for flux/reflux
|
||||
-actions
|
||||
BarActionCreators.js
|
||||
-stores
|
||||
BazStore.js
|
||||
|
||||
- helpers
|
||||
- react
|
||||
addons.js
|
||||
phantomjs-shims.js
|
||||
Gruntfile.js
|
||||
karma.conf.js
|
||||
package.json
|
||||
webpack.config.js
|
||||
webpack.dist.config.js
|
||||
```
|
||||
|
||||
I have tried to keep the project structure as simple as possible and understand it may not suit everyone.
|
||||
|
||||
### Naming Components
|
||||
|
||||
@@ -363,27 +80,6 @@ I have opted to follow [@floydophone](https://twitter.com/floydophone) conventio
|
||||
|
||||
Each component is a module and can be required using the [Webpack](http://webpack.github.io/) module system. [Webpack](http://webpack.github.io/) uses [Loaders](http://webpack.github.io/docs/loaders.html) which means you can also require CSS and a host of other file types. Read the [Webpack documentation](http://webpack.github.io/docs/home.html) to find out more.
|
||||
|
||||
### Grunt
|
||||
|
||||
Out the box the [Gruntfile](http://gruntjs.com/api/grunt.file) is configured with the following:
|
||||
|
||||
1. **webpack**: uses the [grunt-webpack](https://github.com/webpack/grunt-webpack) plugin to load all required modules and output to a single JS file `src/main.js`. This is included in the `src/index.html` file by default and will reload in the browser as and when it is recompiled.
|
||||
2. **webpack-dev-server**: uses the [webpack-dev-server](https://github.com/webpack/webpack-dev-server) to watch for file changes and also serve the webpack app in development.
|
||||
3. **connect**: uses the [grunt-connect](https://github.com/gruntjs/grunt-contrib-connect) plugin to start a webserver at [localhost](http://localhost:8000).
|
||||
4. **karma**: uses the [grunt-karma](https://github.com/karma-runner/grunt-karma) plugin to load the Karma configuration file `karma.conf.js` located in the project root. This will run all tests using [PhantomJS](http://phantomjs.org/) by default but supports many other browsers. Please note that karma-launchers other than PhantomJS must be installed separately and configured in `karma.conf.js`.
|
||||
|
||||
### CSS
|
||||
|
||||
Included in the project is the [normalize.css](http://necolas.github.io/normalize.css/) script. There is also a `src/styles/main.css` script that's required by the core `src/components/App.js` component using Webpack.
|
||||
|
||||
### Linting
|
||||
|
||||
Webpack is automatically configured to run esLint (http://eslint.org) on every file change or build. The configuration can be found in `PROJECTROOT/.eslintrc`. There are plugins for different editors that use this tool directly:
|
||||
- linter-eslint for Atom
|
||||
- Sublime-Linter-eslint for Sublime
|
||||
|
||||
You could also use jsxhint, the corresponding rules file is located in `PROJECTROOT/.jshintrc`. However, the support for jsxhint is planned to be dropped in a later release and only available for backwards compatibility.
|
||||
|
||||
## Props
|
||||
|
||||
Thanks to all who contributed to [generator-angular](https://github.com/yeoman/generator-angular) as the majority of code here has been shamelessy sourced from that repos.
|
||||
@@ -396,7 +92,7 @@ Contributions are welcomed. When submitting a bugfix, write a test that exposes
|
||||
|
||||
### Running Tests
|
||||
|
||||
`node node_modules/.bin/mocha`
|
||||
`npm test` or `node node_modules/.bin/mocha`
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
module.exports = require('../action');
|
||||
@@ -1,39 +0,0 @@
|
||||
'use strict';
|
||||
var util = require('util');
|
||||
var ScriptBase = require('../script-base.js');
|
||||
|
||||
var ActionGenerator = module.exports = function ActionGenerator(args, options, config) {
|
||||
if (!args[0]) console.log('\n Please specify a name for this action creator \n');
|
||||
else {
|
||||
args[0] += 'ActionCreators';
|
||||
ScriptBase.apply(this, arguments)
|
||||
}
|
||||
};
|
||||
|
||||
util.inherits(ActionGenerator, ScriptBase);
|
||||
|
||||
ActionGenerator.prototype.createActionFile = function createActionFile() {
|
||||
this.option('es6');
|
||||
this.es6 = this.options.es6;
|
||||
|
||||
var actionTemplate;
|
||||
switch (this.architecture){
|
||||
case 'flux':
|
||||
actionTemplate = 'FluxAction';
|
||||
break;
|
||||
case 'reflux':
|
||||
actionTemplate = 'RefluxAction';
|
||||
break;
|
||||
case 'alt':
|
||||
actionTemplate = 'AltAction';
|
||||
break;
|
||||
}
|
||||
|
||||
console.log('Creating ' + this.architecture + ' action');
|
||||
|
||||
this.generateSourceAndTest(
|
||||
actionTemplate,
|
||||
'spec/Action',
|
||||
'actions'
|
||||
);
|
||||
};
|
||||
-164
@@ -1,164 +0,0 @@
|
||||
'use strict';
|
||||
var util = require('util');
|
||||
var path = require('path');
|
||||
var yeoman = require('yeoman-generator');
|
||||
var generalUtils = require('../util.js');
|
||||
|
||||
var ReactWebpackGenerator = module.exports = function ReactWebpackGenerator(args, options, config) {
|
||||
yeoman.generators.Base.apply(this, arguments);
|
||||
this.option('es6');
|
||||
|
||||
this.argument('appname', { type: String, required: false });
|
||||
this.appname = this.appname || path.basename(process.cwd());
|
||||
this.appname = this._.camelize(this._.slugify(this._.humanize(this.appname)));
|
||||
this.scriptAppName = this._.capitalize(this.appname) + generalUtils.appName(this);
|
||||
|
||||
this.config.set('app-name', this.appname);
|
||||
|
||||
|
||||
if (typeof this.options.appPath === 'undefined') {
|
||||
this.options.appPath = this.options.appPath || 'src';
|
||||
}
|
||||
|
||||
this.appPath = this.options.appPath;
|
||||
|
||||
args = [this.scriptAppName];
|
||||
|
||||
this.composeWith('react-webpack:common', {
|
||||
args: args
|
||||
});
|
||||
|
||||
this.composeWith('react-webpack:main', {
|
||||
args: args
|
||||
});
|
||||
|
||||
this.on('end', function () {
|
||||
this.installDependencies({ skipInstall: options['skip-install'], bower: false });
|
||||
});
|
||||
|
||||
|
||||
this.pkg = JSON.parse(this.readFileAsString(path.join(__dirname, '../package.json')));
|
||||
|
||||
this.config.save();
|
||||
};
|
||||
|
||||
util.inherits(ReactWebpackGenerator, yeoman.generators.Base);
|
||||
|
||||
ReactWebpackGenerator.prototype.welcome = function welcome() {
|
||||
// welcome message
|
||||
if (!this.options['skip-welcome-message']) {
|
||||
console.log(this.yeoman);
|
||||
console.log(
|
||||
'Out of the box I include Webpack and some default React components.\n'
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
ReactWebpackGenerator.prototype.askForReactRouter = function () {
|
||||
var done = this.async();
|
||||
this.prompt({
|
||||
type : 'confirm',
|
||||
name : 'reactRouter',
|
||||
message : 'Would you like to include react-router?',
|
||||
default : true
|
||||
}, function (props) {
|
||||
this.env.options.reactRouter = props.reactRouter;
|
||||
done();
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
ReactWebpackGenerator.prototype.askForArchitecture = function() {
|
||||
var done = this.async();
|
||||
this.prompt({
|
||||
type : 'list',
|
||||
name : 'architecture',
|
||||
message : 'Would you like to use one of these architectures?',
|
||||
choices: [
|
||||
{name:'No need for that, thanks',value:false},
|
||||
{name:'Flux',value:'flux'},
|
||||
{name:'ReFlux',value:'reflux'},
|
||||
{name:'Alt',value:'alt'}
|
||||
],
|
||||
default : false
|
||||
}, function(props) {
|
||||
this.env.options.architecture = props.architecture;
|
||||
this.config.set('architecture', props.architecture);
|
||||
done();
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
ReactWebpackGenerator.prototype.askForStylesLanguage = function () {
|
||||
var done = this.async();
|
||||
this.prompt({
|
||||
type : 'list',
|
||||
name : 'stylesLanguage',
|
||||
message : 'Which styles language you want to use?',
|
||||
choices: [
|
||||
{name: 'CSS', value: 'css'},
|
||||
{name: 'SASS', value: 'sass'},
|
||||
{name: 'SCSS', value: 'scss'},
|
||||
{name: 'LESS', value: 'less'},
|
||||
{name: 'Stylus', value: 'stylus'}
|
||||
],
|
||||
default : 'css'
|
||||
}, function (props) {
|
||||
this.env.options.stylesLanguage = props.stylesLanguage;
|
||||
this.config.set('styles-language', props.stylesLanguage);
|
||||
done();
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
// Allow to set the generated files suffix for the project when using components
|
||||
// @see https://github.com/newtriks/generator-react-webpack/issues/99
|
||||
ReactWebpackGenerator.prototype.askForComponentSuffix = function() {
|
||||
var done = this.async();
|
||||
this.prompt({
|
||||
type: 'list',
|
||||
name: 'componentSuffix',
|
||||
message: 'Which file suffix do you want to use for components?',
|
||||
choices: [
|
||||
{ name: '.js (default)', value: 'js' },
|
||||
{ name: '.jsx (deprecated)', value: 'jsx' }
|
||||
],
|
||||
default: 'js'
|
||||
}, function (props) {
|
||||
this.env.options.componentSuffix = props.componentSuffix;
|
||||
this.config.set('component-suffix', props.componentSuffix);
|
||||
done();
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
ReactWebpackGenerator.prototype.readIndex = function readIndex() {
|
||||
this.indexFile = this.engine(this.read('../../templates/common/index.html'), this);
|
||||
};
|
||||
|
||||
ReactWebpackGenerator.prototype.createIndexHtml = function createIndexHtml() {
|
||||
this.indexFile = this.indexFile.replace(/'/g, "'");
|
||||
this.write(path.join(this.appPath, 'index.html'), this.indexFile);
|
||||
};
|
||||
|
||||
ReactWebpackGenerator.prototype.packageFiles = function () {
|
||||
this.es6 = this.options.es6;
|
||||
this.reactRouter = this.env.options.reactRouter;
|
||||
this.architecture = this.env.options.architecture;
|
||||
this.stylesLanguage = this.env.options.stylesLanguage;
|
||||
this.template('../../templates/common/_package.json', 'package.json');
|
||||
this.template('../../templates/common/_webpack.config.js', 'webpack.config.js');
|
||||
this.template('../../templates/common/_webpack.dist.config.js', 'webpack.dist.config.js');
|
||||
this.copy('../../templates/common/Gruntfile.js', 'Gruntfile.js');
|
||||
this.copy('../../templates/common/gitignore', '.gitignore');
|
||||
};
|
||||
|
||||
ReactWebpackGenerator.prototype.styleFiles = function styleFiles() {
|
||||
var mainFile = 'main.css';
|
||||
this.copy('styles/' + mainFile, 'src/styles/' + mainFile);
|
||||
};
|
||||
|
||||
ReactWebpackGenerator.prototype.imageFiles = function () {
|
||||
this.sourceRoot(path.join(__dirname, 'templates'));
|
||||
this.directory('images', 'src/images', true);
|
||||
};
|
||||
|
||||
ReactWebpackGenerator.prototype.karmaFiles = function () {
|
||||
this.copy('../../templates/common/karma.conf.js', 'karma.conf.js');
|
||||
};
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 13 KiB |
@@ -1,41 +0,0 @@
|
||||
/* Stiziles */
|
||||
|
||||
html, body {
|
||||
background: #222222;
|
||||
}
|
||||
|
||||
/* main */
|
||||
|
||||
.main {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #222222;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.main img {
|
||||
width: 103px;
|
||||
height: 89px;
|
||||
margin-bottom: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* transitions */
|
||||
|
||||
.fade-enter {
|
||||
opacity: 0.01;
|
||||
transition: opacity .5s ease-in;
|
||||
}
|
||||
|
||||
.fade-enter.fade-enter-active {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.fade-leave {
|
||||
opacity: 1;
|
||||
transition: opacity .5s ease-in;
|
||||
}
|
||||
|
||||
.fade-leave.fade-leave-active {
|
||||
opacity: 0.01;
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
module.exports = require('../component');
|
||||
@@ -1,17 +0,0 @@
|
||||
'use strict';
|
||||
var path = require('path');
|
||||
var util = require('util');
|
||||
var yeoman = require('yeoman-generator');
|
||||
|
||||
var CommonGenerator = module.exports = function CommonGenerator(args, options, config) {
|
||||
yeoman.generators.NamedBase.apply(this, arguments);
|
||||
};
|
||||
|
||||
util.inherits(CommonGenerator, yeoman.generators.NamedBase);
|
||||
|
||||
CommonGenerator.prototype.setupEnv = function setupEnv() {
|
||||
// Copies the contents of the generator `templates`
|
||||
// directory into your users new application path
|
||||
this.sourceRoot(path.join(__dirname, '../templates/common'));
|
||||
this.directory('root', '.', true);
|
||||
};
|
||||
@@ -1,25 +0,0 @@
|
||||
'use strict';
|
||||
var util = require('util');
|
||||
var ScriptBase = require('../script-base.js');
|
||||
|
||||
var ComponentGenerator = module.exports = function ComponentGenerator(args, options, config) {
|
||||
ScriptBase.apply(this, arguments);
|
||||
};
|
||||
|
||||
util.inherits(ComponentGenerator, ScriptBase);
|
||||
|
||||
ComponentGenerator.prototype.createComponentFile = function createComponentFile() {
|
||||
this.option('es6');
|
||||
this.option('rich');
|
||||
|
||||
this.es6 = this.options.es6;
|
||||
this.rich = this.options.rich;
|
||||
|
||||
this.generateComponentTestAndStyle(
|
||||
'Component',
|
||||
'spec/Component',
|
||||
'styles/Component',
|
||||
'components',
|
||||
true
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,124 @@
|
||||
'use strict';
|
||||
let generator = require('yeoman-generator');
|
||||
let utils = require('../../utils/all');
|
||||
let prompts = require('./prompts');
|
||||
let path = require('path');
|
||||
let fs = require('fs');
|
||||
|
||||
// Set the base root directory for our files
|
||||
let baseRootPath = path.join(__dirname, '../../node_modules/react-webpack-template');
|
||||
|
||||
module.exports = generator.Base.extend({
|
||||
|
||||
constructor: function() {
|
||||
generator.Base.apply(this, arguments);
|
||||
|
||||
// Make options available
|
||||
this.option('skip-welcome-message', {
|
||||
desc: 'Skip the welcome message',
|
||||
type: Boolean,
|
||||
defaults: false
|
||||
});
|
||||
this.option('skip-install');
|
||||
|
||||
// Use our plain template as source
|
||||
this.sourceRoot(baseRootPath);
|
||||
|
||||
this.config.save();
|
||||
},
|
||||
|
||||
initializing: function() {
|
||||
if(!this.options['skip-welcome-message']) {
|
||||
this.log(require('yeoman-welcome'));
|
||||
this.log('Out of the box I include Webpack and some default React components.\n');
|
||||
}
|
||||
},
|
||||
|
||||
prompting: function() {
|
||||
let done = this.async();
|
||||
this.prompt(prompts, function(props) {
|
||||
|
||||
// Make sure to get the correct app name if it is not the default
|
||||
if(props.appName !== utils.yeoman.getAppName()) {
|
||||
props.appName = utils.yeoman.getAppName(props.appName);
|
||||
}
|
||||
|
||||
// Set needed global vars for yo
|
||||
this.appName = props.appName;
|
||||
this.style = props.style;
|
||||
|
||||
// Set needed keys into config
|
||||
this.config.set('appName', this.appName);
|
||||
this.config.set('appPath', this.appPath);
|
||||
this.config.set('style', this.style);
|
||||
|
||||
done();
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
configuring: function() {
|
||||
|
||||
// Generate our package.json. Make sure to also include the required dependencies for styles
|
||||
let defaultSettings = this.fs.readJSON(path.join(baseRootPath, 'package.json'));
|
||||
let packageSettings = {
|
||||
name: this.appName,
|
||||
private: true,
|
||||
version: '0.0.1',
|
||||
description: 'YOUR DESCRIPTION - Generated by generator-react-webpack',
|
||||
main: '',
|
||||
scripts: defaultSettings.scripts,
|
||||
repository: '',
|
||||
keywords: [],
|
||||
author: 'Your name here',
|
||||
devDependencies: defaultSettings.devDependencies,
|
||||
dependencies: defaultSettings.dependencies
|
||||
};
|
||||
|
||||
// Add needed loaders if we have special styles
|
||||
let styleConfig = utils.config.getChoiceByKey('style', this.style);
|
||||
if(styleConfig && styleConfig.packages) {
|
||||
|
||||
for(let dependency of styleConfig.packages) {
|
||||
packageSettings.dependencies[dependency.name] = dependency.version;
|
||||
}
|
||||
}
|
||||
|
||||
this.fs.writeJSON(this.destinationPath('package.json'), packageSettings);
|
||||
},
|
||||
|
||||
writing: function() {
|
||||
|
||||
let excludeList = [
|
||||
'LICENCE',
|
||||
'README.md',
|
||||
'node_modules',
|
||||
'package.json'
|
||||
];
|
||||
|
||||
// Get all files in our repo and copy the ones we should
|
||||
fs.readdir(this.sourceRoot(), (err, items) => {
|
||||
|
||||
for(let item of items) {
|
||||
|
||||
// Skip the item if it is in our exclude list
|
||||
if(excludeList.indexOf(item) !== -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Copy all items to our root
|
||||
let fullPath = path.join(baseRootPath, item);
|
||||
if(fs.lstatSync(fullPath).isDirectory()) {
|
||||
this.bulkDirectory(item, item);
|
||||
} else {
|
||||
this.copy(item, item);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
install: function() {
|
||||
if(!this.options['skip-install']) {
|
||||
this.installDependencies({ bower: false });
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,18 @@
|
||||
'use strict';
|
||||
let utils = require('../../utils/all');
|
||||
|
||||
module.exports = [
|
||||
{
|
||||
type: 'input',
|
||||
name: 'appName',
|
||||
message: 'Please choose your application name',
|
||||
default: utils.yeoman.getAppName()
|
||||
},
|
||||
{
|
||||
type: 'list',
|
||||
name: 'style',
|
||||
message: 'Which styles language you want to use?',
|
||||
choices: utils.config.getChoices('style'),
|
||||
default: utils.config.getDefaultChoice('style')
|
||||
}
|
||||
];
|
||||
@@ -0,0 +1,36 @@
|
||||
'use strict';
|
||||
let generator = require('yeoman-generator');
|
||||
let utils = require('../../utils/all');
|
||||
|
||||
module.exports = generator.NamedBase.extend({
|
||||
|
||||
constructor: function() {
|
||||
generator.NamedBase.apply(this, arguments);
|
||||
},
|
||||
|
||||
writing: function() {
|
||||
|
||||
let settings = utils.yeoman.getAllSettingsFromComponentName(this.name, this.config.get('style'));
|
||||
|
||||
// Create the style template
|
||||
this.fs.copyTpl(
|
||||
this.templatePath(`styles/Component${settings.style.suffix}`),
|
||||
this.destinationPath(settings.style.path + settings.style.fileName),
|
||||
settings
|
||||
);
|
||||
|
||||
// Create the component
|
||||
this.fs.copyTpl(
|
||||
this.templatePath('components/Base.js'),
|
||||
this.destinationPath(settings.component.path + settings.component.fileName),
|
||||
settings
|
||||
);
|
||||
|
||||
// Create the unit test
|
||||
this.fs.copyTpl(
|
||||
this.templatePath('tests/Base.js'),
|
||||
this.destinationPath(settings.test.path + settings.test.fileName),
|
||||
settings
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,21 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react/addons';
|
||||
|
||||
require('<%= style.webpackPath %>');
|
||||
|
||||
class <%= component.className %> extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<div className="<%= style.className %>">
|
||||
Please edit <%= component.path %>/<%= component.fileName %> to update this component!
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Uncomment properties you need
|
||||
// <%= component.className %>.propTypes = {};
|
||||
// <%= component.className %>.defaultProps = {};
|
||||
|
||||
export default <%= component.className %>;
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
.<%= classedName %> {
|
||||
.<%= style.className %> {
|
||||
border: 1px dashed #f00;
|
||||
}
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
.<%= classedName %> {
|
||||
.<%= style.className %> {
|
||||
border: 1px dashed #f00;
|
||||
}
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
.<%= classedName %>
|
||||
.<%= style.className %>
|
||||
border: 1px dashed #f00
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
.<%= classedName %> {
|
||||
.<%= style.className %> {
|
||||
border: 1px dashed #f00;
|
||||
}
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
.<%= classedName %>
|
||||
.<%= style.className %>
|
||||
border 1px dashed #f00
|
||||
@@ -0,0 +1,23 @@
|
||||
/*eslint-env node, mocha */
|
||||
/*global expect */
|
||||
/*eslint no-console: 0*/
|
||||
'use strict';
|
||||
|
||||
// Uncomment the following lines to use the react test utilities
|
||||
// import React from 'react/addons';
|
||||
// const TestUtils = React.addons.TestUtils;
|
||||
import createComponent from 'helpers/shallowRenderHelper';
|
||||
|
||||
import <%= component.className %> from '<%= component.webpackPath %>';
|
||||
|
||||
describe('<%= component.className %>', () => {
|
||||
let component;
|
||||
|
||||
beforeEach(() => {
|
||||
component = createComponent(<%= component.className %>);
|
||||
});
|
||||
|
||||
it('should have its component name as default className', () => {
|
||||
expect(component._store.props.className).to.equal('<%= style.className %>');
|
||||
});
|
||||
});
|
||||
@@ -1,35 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var util = require('util');
|
||||
var ScriptBase = require('../script-base.js');
|
||||
|
||||
var MainGenerator = module.exports = function MainGenerator(args, options, config) {
|
||||
ScriptBase.apply(this, arguments);
|
||||
};
|
||||
|
||||
util.inherits(MainGenerator, ScriptBase);
|
||||
|
||||
MainGenerator.prototype.createAppFile = function createAppFile(scriptAppName) {
|
||||
this.reactRouter = this.env.options.reactRouter;
|
||||
this.scriptAppName = scriptAppName;
|
||||
this.appTemplate('App', 'components/' + scriptAppName);
|
||||
this.testTemplate('spec/App', 'components/' + scriptAppName);
|
||||
};
|
||||
|
||||
MainGenerator.prototype.createMainFile = function createMainFile() {
|
||||
if(this.env.options.reactRouter) {
|
||||
this.appTemplate('main', 'components/main');
|
||||
}
|
||||
};
|
||||
|
||||
MainGenerator.prototype.createDispatcher = function createDispatcher() {
|
||||
if(this.env.options.architecture=='flux') {
|
||||
this.appTemplate('Dispatcher', 'dispatcher/' + this.scriptAppName + 'Dispatcher');
|
||||
}
|
||||
};
|
||||
|
||||
MainGenerator.prototype.createAltjsFile = function createAltjsFile() {
|
||||
if(this.env.options.architecture=='alt') {
|
||||
this.appTemplate('alt', 'alt');
|
||||
}
|
||||
};
|
||||
+17
-16
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "generator-react-webpack",
|
||||
"version": "1.2.13",
|
||||
"version": "1.2.23",
|
||||
"description": "Yeoman generator for ReactJS and Webpack",
|
||||
"keywords": [
|
||||
"yeoman-generator",
|
||||
@@ -19,7 +19,14 @@
|
||||
"email": "simon@newtriks.com",
|
||||
"url": "https://github.com/newtriks"
|
||||
},
|
||||
"main": "app/index.js",
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Christian Schilling",
|
||||
"email": "cs@weblogixx.de",
|
||||
"url": "https://github.com/weblogixx"
|
||||
}
|
||||
],
|
||||
"main": "generators/app/index.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/newtriks/generator-react-webpack.git"
|
||||
@@ -28,24 +35,18 @@
|
||||
"test": "mocha"
|
||||
},
|
||||
"dependencies": {
|
||||
"yeoman-generator": "^0.17.6"
|
||||
"react-webpack-template": "^0.1.0",
|
||||
"underscore.string": "^3.2.2",
|
||||
"yeoman-generator": "^0.20.3",
|
||||
"yeoman-welcome": "^1.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mocha": "^1.21.4",
|
||||
"underscore.string": "^2.3.3",
|
||||
"grunt": "^0.4.5",
|
||||
"grunt-cli": "^0.1.13"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"yo": ">=1.2.0"
|
||||
"chai": "^3.2.0",
|
||||
"mocha": "^2.3.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0",
|
||||
"node": ">=4.0.0",
|
||||
"iojs": ">=1.1.0"
|
||||
},
|
||||
"licenses": [
|
||||
{
|
||||
"type": "MIT"
|
||||
}
|
||||
]
|
||||
"license": "MIT"
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
module.exports = require('../store');
|
||||
-118
@@ -1,118 +0,0 @@
|
||||
'use strict';
|
||||
var util = require('util');
|
||||
var path = require('path');
|
||||
var yeoman = require('yeoman-generator');
|
||||
var generalUtils = require('./util.js');
|
||||
|
||||
var Generator = module.exports = function Generator() {
|
||||
yeoman.generators.NamedBase.apply(this, arguments);
|
||||
|
||||
// Add capitalize mixin
|
||||
this._.mixin({ 'capitalize': generalUtils.capitalize });
|
||||
this._.mixin({ 'capitalizeFile': generalUtils.capitalizeFile });
|
||||
this._.mixin({ 'capitalizeClass': generalUtils.capitalizeClass });
|
||||
this._.mixin({ 'lowercase': generalUtils.lowercase });
|
||||
|
||||
this.appname = path.basename(process.cwd());
|
||||
|
||||
this.appname = this._.slugify(this._.humanize(this.appname));
|
||||
this.scriptAppName = this._.camelize(this._.capitalize(this.appname)) + generalUtils.appName(this);
|
||||
this.classedFileName = this._.capitalizeFile(this.name);
|
||||
this.classedName = this._.capitalizeClass(this.name);
|
||||
this.stylesLanguage = this.config.get('styles-language');
|
||||
this.architecture = this.config.get('architecture');
|
||||
|
||||
if (typeof this.options.appPath === 'undefined') {
|
||||
this.options.appPath = this.options.appPath || 'src';
|
||||
}
|
||||
|
||||
if (typeof this.options.testPath === 'undefined') {
|
||||
this.options.testPath = this.options.testPath || 'test/spec';
|
||||
}
|
||||
|
||||
if (typeof this.options.stylesPath === 'undefined') {
|
||||
this.options.stylesPath = this.options.stylesPath || 'src/styles';
|
||||
}
|
||||
|
||||
var sourceRoot = '/templates/';
|
||||
this.scriptSuffix = '.js';
|
||||
this.reactSuffix = '.js';
|
||||
|
||||
// Add support for generated file legacy fallback
|
||||
// @see https://github.com/newtriks/generator-react-webpack/issues/99
|
||||
this.reactComponentSuffix = this.config.get('component-suffix');
|
||||
switch(this.reactComponentSuffix) {
|
||||
case 'jsx':
|
||||
this.reactComponentSuffix = '.jsx';
|
||||
break;
|
||||
default:
|
||||
this.reactComponentSuffix = '.js';
|
||||
}
|
||||
|
||||
this.stylesSuffix = '.css';
|
||||
|
||||
switch(this.stylesLanguage) {
|
||||
case 'sass':
|
||||
this.stylesSuffix = '.sass';
|
||||
break;
|
||||
case 'scss':
|
||||
this.stylesSuffix = '.scss';
|
||||
break;
|
||||
case 'less':
|
||||
this.stylesSuffix = '.less';
|
||||
break;
|
||||
case 'stylus':
|
||||
this.stylesSuffix = '.styl';
|
||||
break;
|
||||
}
|
||||
|
||||
this.sourceRoot(path.join(__dirname, sourceRoot));
|
||||
};
|
||||
|
||||
util.inherits(Generator, yeoman.generators.NamedBase);
|
||||
|
||||
Generator.prototype.appTemplate = function (src, dest) {
|
||||
yeoman.generators.Base.prototype.template.apply(this, [
|
||||
path.join('javascript', src + this.scriptSuffix),
|
||||
path.join(this.options.appPath, dest) + this.scriptSuffix
|
||||
]);
|
||||
};
|
||||
|
||||
Generator.prototype.reactComponentTemplate = function (src, dest) {
|
||||
yeoman.generators.Base.prototype.template.apply(this, [
|
||||
path.join('javascript', src + this.reactSuffix),
|
||||
path.join(this.options.appPath, dest) + this.reactComponentSuffix
|
||||
]);
|
||||
};
|
||||
|
||||
Generator.prototype.testTemplate = function (src, dest) {
|
||||
yeoman.generators.Base.prototype.template.apply(this, [
|
||||
src + this.scriptSuffix,
|
||||
path.join(this.options.testPath, dest) + this.scriptSuffix
|
||||
]);
|
||||
};
|
||||
|
||||
Generator.prototype.stylesTemplate = function (src, dest) {
|
||||
yeoman.generators.Base.prototype.template.apply(this, [
|
||||
src + this.stylesSuffix,
|
||||
path.join(this.options.stylesPath, dest) + this.stylesSuffix
|
||||
]);
|
||||
};
|
||||
|
||||
Generator.prototype.htmlTemplate = function (src, dest) {
|
||||
yeoman.generators.Base.prototype.template.apply(this, [
|
||||
src,
|
||||
path.join(this.options.appPath, dest.toLowerCase())
|
||||
]);
|
||||
};
|
||||
|
||||
Generator.prototype.generateSourceAndTest = function (appTemplate, testTemplate, targetDirectory) {
|
||||
this.appTemplate(appTemplate, path.join(targetDirectory, this._.capitalizeFile(this.name)));
|
||||
this.testTemplate(testTemplate, path.join(targetDirectory, this._.capitalizeFile(this.name)));
|
||||
};
|
||||
|
||||
Generator.prototype.generateComponentTestAndStyle = function (componentTemplate, testTemplate, stylesTemplate, targetDirectory) {
|
||||
this.reactComponentTemplate(componentTemplate, path.join(targetDirectory, this._.capitalizeFile(this.name)));
|
||||
this.testTemplate(testTemplate, path.join(targetDirectory, this._.capitalizeFile(this.name)));
|
||||
this.stylesTemplate(stylesTemplate, path.join(this._.capitalizeFile(this.name)));
|
||||
};
|
||||
@@ -1,42 +0,0 @@
|
||||
'use strict';
|
||||
var util = require('util');
|
||||
var ScriptBase = require('../script-base.js');
|
||||
|
||||
var StoreGenerator = module.exports = function StoreGenerator(args, options, config) {
|
||||
if (!args[0]) console.log('\n Please specify a name for this store \n');
|
||||
else {
|
||||
args[0] += 'Store';
|
||||
ScriptBase.apply(this, arguments)
|
||||
}
|
||||
};
|
||||
|
||||
util.inherits(StoreGenerator, ScriptBase);
|
||||
|
||||
StoreGenerator .prototype.createStoreFile = function createStoreFile() {
|
||||
this.option('es6');
|
||||
|
||||
this.es6 = this.options.es6;
|
||||
|
||||
var storeTemplate;
|
||||
switch (this.architecture){
|
||||
case 'flux':
|
||||
storeTemplate = 'FluxStore';
|
||||
this.dispatcherName = this._.capitalizeFile(this.config.get('app-name')) + 'AppDispatcher';
|
||||
break;
|
||||
case 'reflux':
|
||||
storeTemplate = 'RefluxStore';
|
||||
break;
|
||||
case 'alt':
|
||||
storeTemplate = 'AltStore';
|
||||
break;
|
||||
}
|
||||
|
||||
console.log('Creating ' + this.architecture + ' store');
|
||||
|
||||
|
||||
this.generateSourceAndTest(
|
||||
storeTemplate,
|
||||
'spec/Store',
|
||||
'stores'
|
||||
);
|
||||
};
|
||||
@@ -1,125 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var mountFolder = function (connect, dir) {
|
||||
return connect.static(require('path').resolve(dir));
|
||||
};
|
||||
|
||||
var webpackDistConfig = require('./webpack.dist.config.js'),
|
||||
webpackDevConfig = require('./webpack.config.js');
|
||||
|
||||
module.exports = function (grunt) {
|
||||
// Let *load-grunt-tasks* require everything
|
||||
require('load-grunt-tasks')(grunt);
|
||||
|
||||
// Read configuration from package.json
|
||||
var pkgConfig = grunt.file.readJSON('package.json');
|
||||
|
||||
grunt.initConfig({
|
||||
pkg: pkgConfig,
|
||||
|
||||
webpack: {
|
||||
options: webpackDistConfig,
|
||||
dist: {
|
||||
cache: false
|
||||
}
|
||||
},
|
||||
|
||||
'webpack-dev-server': {
|
||||
options: {
|
||||
hot: true,
|
||||
port: 8000,
|
||||
webpack: webpackDevConfig,
|
||||
publicPath: '/assets/',
|
||||
contentBase: './<%= pkg.src %>/'
|
||||
},
|
||||
|
||||
start: {
|
||||
keepAlive: true
|
||||
}
|
||||
},
|
||||
|
||||
connect: {
|
||||
options: {
|
||||
port: 8000
|
||||
},
|
||||
|
||||
dist: {
|
||||
options: {
|
||||
keepalive: true,
|
||||
middleware: function (connect) {
|
||||
return [
|
||||
mountFolder(connect, pkgConfig.dist)
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
open: {
|
||||
options: {
|
||||
delay: 500
|
||||
},
|
||||
dev: {
|
||||
path: 'http://localhost:<%= connect.options.port %>/webpack-dev-server/'
|
||||
},
|
||||
dist: {
|
||||
path: 'http://localhost:<%= connect.options.port %>/'
|
||||
}
|
||||
},
|
||||
|
||||
karma: {
|
||||
unit: {
|
||||
configFile: 'karma.conf.js'
|
||||
}
|
||||
},
|
||||
|
||||
copy: {
|
||||
dist: {
|
||||
files: [
|
||||
// includes files within path
|
||||
{
|
||||
flatten: true,
|
||||
expand: true,
|
||||
src: ['<%= pkg.src %>/*'],
|
||||
dest: '<%= pkg.dist %>/',
|
||||
filter: 'isFile'
|
||||
},
|
||||
{
|
||||
flatten: true,
|
||||
expand: true,
|
||||
src: ['<%= pkg.src %>/images/*'],
|
||||
dest: '<%= pkg.dist %>/images/'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
clean: {
|
||||
dist: {
|
||||
files: [{
|
||||
dot: true,
|
||||
src: [
|
||||
'<%= pkg.dist %>'
|
||||
]
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
grunt.registerTask('serve', function (target) {
|
||||
if (target === 'dist') {
|
||||
return grunt.task.run(['build', 'open:dist', 'connect:dist']);
|
||||
}
|
||||
|
||||
grunt.task.run([
|
||||
'open:dev',
|
||||
'webpack-dev-server'
|
||||
]);
|
||||
});
|
||||
|
||||
grunt.registerTask('test', ['karma']);
|
||||
|
||||
grunt.registerTask('build', ['clean', 'copy', 'webpack']);
|
||||
|
||||
grunt.registerTask('default', []);
|
||||
};
|
||||
@@ -1,52 +0,0 @@
|
||||
{
|
||||
"name": "<%= _.slugify(appname) %>",
|
||||
"version": "0.0.0",
|
||||
"description": "",
|
||||
"repository": "",
|
||||
"private": true,
|
||||
"src": "src",
|
||||
"test": "test",
|
||||
"dist": "dist",
|
||||
"mainInput": "<% if (reactRouter) { %>main<% } else { %><%= scriptAppName %><% } %>",
|
||||
"mainOutput": "main",
|
||||
"dependencies": {<% if (reactRouter) { %>
|
||||
"react-router": "0.13.x",<% } if (architecture === 'flux') { %>
|
||||
"flux": "^2.0.1",
|
||||
"events": "^1.0.2",
|
||||
"object-assign": "^2.0.0", <% } if (architecture === 'reflux') {%>
|
||||
"reflux": "^0.2.7", <% } if (architecture === 'alt') { %>
|
||||
"alt": "^0.16.5", <% } %>
|
||||
"react": "0.13.x",
|
||||
"normalize.css": "~3.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel": "^5.0.0",
|
||||
"babel-loader": "^5.0.0",
|
||||
"grunt": "~0.4.5",
|
||||
"eslint": "^0.21.2",
|
||||
"eslint-loader": "^0.11.2",
|
||||
"eslint-plugin-react": "^2.4.0",
|
||||
"load-grunt-tasks": "~0.6.0",
|
||||
"grunt-contrib-connect": "~0.8.0",
|
||||
"grunt-webpack": "~1.0.8",
|
||||
"jasmine-core": "^2.3.4",
|
||||
"karma": "~0.13.9",
|
||||
"karma-jasmine": "^0.3.5",
|
||||
"karma-phantomjs-launcher": "~0.2.1",
|
||||
"karma-script-launcher": "~0.1.0",
|
||||
"karma-webpack": "^1.7.0",
|
||||
"style-loader": "~0.8.0",
|
||||
"url-loader": "~0.5.5",
|
||||
"css-loader": "~0.9.0",
|
||||
"grunt-karma": "~0.12.1",
|
||||
"grunt-open": "~0.2.3",
|
||||
"grunt-contrib-copy": "~0.5.0",
|
||||
"grunt-contrib-clean": "~0.6.0",<% if (stylesLanguage.match(/s[ac]ss/)) { %>
|
||||
"sass-loader": "^1.0.1",<% } %><% if (stylesLanguage === 'less') { %>
|
||||
"less-loader": "^2.0.0",<% } %><% if (stylesLanguage === 'stylus') { %>
|
||||
"stylus-loader": "^0.5.0",<% } %>
|
||||
"react-hot-loader": "^1.0.7",
|
||||
"webpack": "~1.10.0",
|
||||
"webpack-dev-server": "~1.10.0"
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Webpack development server configuration
|
||||
*
|
||||
* This file is set up for serving the webpack-dev-server, which will watch for changes and recompile as required if
|
||||
* the subfolder /webpack-dev-server/ is visited. Visiting the root will not automatically reload.
|
||||
*/
|
||||
'use strict';
|
||||
var webpack = require('webpack');
|
||||
|
||||
module.exports = {
|
||||
|
||||
output: {
|
||||
filename: 'main.js',
|
||||
publicPath: '/assets/'
|
||||
},
|
||||
|
||||
cache: true,
|
||||
debug: true,
|
||||
devtool: 'sourcemap',
|
||||
entry: [
|
||||
'webpack/hot/only-dev-server',
|
||||
'./src/components/<% if (reactRouter) { %>main<% } else { %><%= scriptAppName %><% } %>.js'
|
||||
],
|
||||
|
||||
stats: {
|
||||
colors: true,
|
||||
reasons: true
|
||||
},
|
||||
|
||||
resolve: {
|
||||
extensions: ['', '.js', '.jsx'],
|
||||
alias: {
|
||||
'styles': __dirname + '/src/styles',
|
||||
'mixins': __dirname + '/src/mixins',
|
||||
'components': __dirname + '/src/components/'<% if(architecture==='flux'||architecture=='reflux') { %>,
|
||||
'stores': __dirname + '/src/stores/',
|
||||
'actions': __dirname + '/src/actions/'<% } %>
|
||||
}
|
||||
},
|
||||
module: {
|
||||
preLoaders: [{
|
||||
test: /\.(js|jsx)$/,
|
||||
exclude: /node_modules/,
|
||||
loader: 'eslint-loader'
|
||||
}],
|
||||
loaders: [{
|
||||
test: /\.(js|jsx)$/,
|
||||
exclude: /node_modules/,
|
||||
loader: 'react-hot!babel-loader'
|
||||
},<% if (stylesLanguage === 'sass') { %> {
|
||||
test: /\.sass/,
|
||||
loader: 'style-loader!css-loader!sass-loader?outputStyle=expanded&indentedSyntax'
|
||||
},<% } %><% if (stylesLanguage === 'scss') { %> {
|
||||
test: /\.scss/,
|
||||
loader: 'style-loader!css-loader!sass-loader?outputStyle=expanded'
|
||||
},<% } %><% if (stylesLanguage === 'less') { %> {
|
||||
test: /\.less/,
|
||||
loader: 'style-loader!css-loader!less-loader'
|
||||
},<% } %><% if (stylesLanguage === 'stylus') { %> {
|
||||
test: /\.styl/,
|
||||
loader: 'style-loader!css-loader!stylus-loader'
|
||||
},<% } %> {
|
||||
test: /\.css$/,
|
||||
loader: 'style-loader!css-loader'
|
||||
}, {
|
||||
test: /\.(png|jpg|woff|woff2)$/,
|
||||
loader: 'url-loader?limit=8192'
|
||||
}]
|
||||
},
|
||||
|
||||
plugins: [
|
||||
new webpack.HotModuleReplacementPlugin()
|
||||
]
|
||||
|
||||
};
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Webpack distribution configuration
|
||||
*
|
||||
* This file is set up for serving the distribution version. It will be compiled to dist/ by default
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var webpack = require('webpack');
|
||||
|
||||
module.exports = {
|
||||
|
||||
output: {
|
||||
publicPath: '/assets/',
|
||||
path: 'dist/assets/',
|
||||
filename: 'main.js'
|
||||
},
|
||||
|
||||
debug: false,
|
||||
devtool: false,
|
||||
entry: './src/components/<% if (reactRouter) { %>main<% } else { %><%= scriptAppName %><% } %>.js',
|
||||
|
||||
stats: {
|
||||
colors: true,
|
||||
reasons: false
|
||||
},
|
||||
|
||||
plugins: [
|
||||
new webpack.optimize.DedupePlugin(),
|
||||
new webpack.optimize.UglifyJsPlugin(),
|
||||
new webpack.optimize.OccurenceOrderPlugin(),
|
||||
new webpack.optimize.AggressiveMergingPlugin(),
|
||||
new webpack.NoErrorsPlugin()
|
||||
],
|
||||
|
||||
resolve: {
|
||||
extensions: ['', '.js', '.jsx'],
|
||||
alias: {
|
||||
'styles': __dirname + '/src/styles',
|
||||
'mixins': __dirname + '/src/mixins',
|
||||
'components': __dirname + '/src/components/'<% if(architecture==='flux'||architecture=='reflux') { %>,
|
||||
'stores': __dirname + '/src/stores/',
|
||||
'actions': __dirname + '/src/actions/'<% } %>
|
||||
}
|
||||
},
|
||||
|
||||
module: {
|
||||
preLoaders: [{
|
||||
test: /\.(js|jsx)$/,
|
||||
exclude: /node_modules/,
|
||||
loader: 'eslint-loader'
|
||||
}],
|
||||
loaders: [{
|
||||
test: /\.(js|jsx)$/,
|
||||
exclude: /node_modules/,
|
||||
loader: 'babel-loader'
|
||||
}, {
|
||||
test: /\.css$/,
|
||||
loader: 'style-loader!css-loader'
|
||||
},<% if (stylesLanguage === 'sass') { %> {
|
||||
test: /\.sass/,
|
||||
loader: 'style-loader!css-loader!sass-loader?outputStyle=expanded&indentedSyntax'
|
||||
},<% } %><% if (stylesLanguage === 'scss') { %> {
|
||||
test: /\.scss/,
|
||||
loader: 'style-loader!css-loader!sass-loader?outputStyle=expanded'
|
||||
},<% } %><% if (stylesLanguage === 'less') { %> {
|
||||
test: /\.less/,
|
||||
loader: 'style-loader!css-loader!less-loader'
|
||||
},<% } %><% if (stylesLanguage === 'stylus') { %> {
|
||||
test: /\.styl/,
|
||||
loader: 'style-loader!css-loader!stylus-loader'
|
||||
},<% } %> {
|
||||
test: /\.(png|jpg|woff|woff2)$/,
|
||||
loader: 'url-loader?limit=8192'
|
||||
}]
|
||||
}
|
||||
};
|
||||
@@ -1,33 +0,0 @@
|
||||
### SublimeText ###
|
||||
*.sublime-workspace
|
||||
|
||||
### OSX ###
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
Icon
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear on external disk
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
|
||||
### Windows ###
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# App specific
|
||||
|
||||
node_modules/
|
||||
.tmp
|
||||
dist
|
||||
/src/main.js
|
||||
@@ -1,23 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<title></title>
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
</head>
|
||||
<body>
|
||||
<!--[if lt IE 8]>
|
||||
<p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
|
||||
<![endif]-->
|
||||
<div id="content">
|
||||
<h1>If you can see this, something is broken (or JS is not enabled)!!.</h1>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__
|
||||
</script>
|
||||
<script type="text/javascript" src="assets/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,93 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var path = require('path');
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
basePath: '',
|
||||
frameworks: ['jasmine'],
|
||||
files: [
|
||||
'test/helpers/pack/**/*.js',
|
||||
'test/helpers/react/**/*.js',
|
||||
'test/spec/components/**/*.js'<% if(architecture === 'flux'||architecture === 'reflux') { %>,
|
||||
'test/spec/stores/**/*.js',
|
||||
'test/spec/actions/**/*.js'<% } %>
|
||||
],
|
||||
preprocessors: {
|
||||
'test/helpers/createComponent.js': ['webpack'],
|
||||
'test/spec/components/**/*.js': ['webpack'],
|
||||
'test/spec/components/**/*.jsx': ['webpack']<% if(architecture === 'flux'||architecture === 'reflux') { %>,
|
||||
'test/spec/stores/**/*.js': ['webpack'],
|
||||
'test/spec/actions/**/*.js': ['webpack']<% } %>
|
||||
},
|
||||
webpack: {
|
||||
cache: true,
|
||||
module: {
|
||||
loaders: [{
|
||||
test: /\.gif/,
|
||||
loader: 'url-loader?limit=10000&mimetype=image/gif'
|
||||
}, {
|
||||
test: /\.jpg/,
|
||||
loader: 'url-loader?limit=10000&mimetype=image/jpg'
|
||||
}, {
|
||||
test: /\.png/,
|
||||
loader: 'url-loader?limit=10000&mimetype=image/png'
|
||||
}, {
|
||||
test: /\.(js|jsx)$/,
|
||||
loader: 'babel-loader',
|
||||
exclude: /node_modules/
|
||||
},<% if (stylesLanguage === 'sass') { %> {
|
||||
test: /\.sass/,
|
||||
loader: 'style-loader!css-loader!sass-loader?outputStyle=expanded'
|
||||
},<% } %><% if (stylesLanguage === 'scss') { %> {
|
||||
test: /\.scss/,
|
||||
loader: 'style-loader!css-loader!sass-loader?outputStyle=expanded'
|
||||
},<% } %><% if (stylesLanguage === 'less') { %> {
|
||||
test: /\.less/,
|
||||
loader: 'style-loader!css-loader!less-loader'
|
||||
},<% } %><% if (stylesLanguage === 'stylus') { %> {
|
||||
test: /\.styl/,
|
||||
loader: 'style-loader!css-loader!stylus-loader'
|
||||
},<% } %> {
|
||||
test: /\.css$/,
|
||||
loader: 'style-loader!css-loader'
|
||||
}, {
|
||||
test: /\.woff/,
|
||||
loader: 'url-loader?limit=10000&mimetype=application/font-woff'
|
||||
}, {
|
||||
test: /\.woff2/,
|
||||
loader: 'url-loader?limit=10000&mimetype=application/font-woff2'
|
||||
}]
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'styles': path.join(process.cwd(), './src/styles/'),
|
||||
'components': path.join(process.cwd(), './src/components/')<% if(architecture === 'flux'||architecture === 'reflux') { %>,
|
||||
'stores': '../../../src/stores/',
|
||||
'actions': '../../../src/actions/'<% } %>,
|
||||
'helpers': path.join(process.cwd(), './test/helpers/')
|
||||
}
|
||||
}
|
||||
},
|
||||
webpackMiddleware: {
|
||||
noInfo: true,
|
||||
stats: {
|
||||
colors: true
|
||||
}
|
||||
},
|
||||
exclude: [],
|
||||
port: 8080,
|
||||
logLevel: config.LOG_INFO,
|
||||
colors: true,
|
||||
autoWatch: false,
|
||||
browsers: ['PhantomJS'],
|
||||
reporters: ['dots'],
|
||||
captureTimeout: 60000,
|
||||
singleRun: true,
|
||||
plugins: [
|
||||
require('karma-webpack'),
|
||||
require('karma-jasmine'),
|
||||
require('karma-phantomjs-launcher')
|
||||
]
|
||||
});
|
||||
};
|
||||
@@ -1,13 +0,0 @@
|
||||
# http://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"plugins": [
|
||||
"react"
|
||||
],
|
||||
"ecmaFeatures": {
|
||||
"jsx": true,
|
||||
"modules": true
|
||||
},
|
||||
"env": {
|
||||
"browser": true,
|
||||
"amd": true,
|
||||
"es6": true
|
||||
},
|
||||
"rules": {
|
||||
"quotes": [ 1, "single" ],
|
||||
"no-undef": false,
|
||||
"global-strict": false,
|
||||
"no-extra-semi": 1,
|
||||
"no-underscore-dangle": false
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
{
|
||||
"node": true,
|
||||
"browser": true,
|
||||
"esnext": true,
|
||||
"bitwise": true,
|
||||
"camelcase": false,
|
||||
"curly": true,
|
||||
"eqeqeq": true,
|
||||
"immed": true,
|
||||
"indent": 2,
|
||||
"latedef": true,
|
||||
"newcap": true,
|
||||
"noarg": true,
|
||||
"quotmark": "false",
|
||||
"regexp": true,
|
||||
"undef": true,
|
||||
"unused": false,
|
||||
"strict": true,
|
||||
"trailing": true,
|
||||
"smarttabs": true,
|
||||
"white": true,
|
||||
"newcap": false,
|
||||
"globals": {
|
||||
"React": true
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 4.2 KiB |
@@ -1,40 +0,0 @@
|
||||
{
|
||||
"node": true,
|
||||
"browser": true,
|
||||
"esnext": true,
|
||||
"bitwise": true,
|
||||
"camelcase": false,
|
||||
"curly": true,
|
||||
"eqeqeq": true,
|
||||
"immed": true,
|
||||
"indent": 2,
|
||||
"latedef": true,
|
||||
"newcap": true,
|
||||
"noarg": true,
|
||||
"quotmark": "false",
|
||||
"regexp": true,
|
||||
"undef": true,
|
||||
"unused": false,
|
||||
"strict": true,
|
||||
"trailing": true,
|
||||
"smarttabs": true,
|
||||
"white": true,
|
||||
"newcap": false,
|
||||
"globals": {
|
||||
"after": false,
|
||||
"afterEach": false,
|
||||
"react": false,
|
||||
"before": false,
|
||||
"beforeEach": false,
|
||||
"browser": false,
|
||||
"describe": false,
|
||||
"expect": false,
|
||||
"inject": false,
|
||||
"it": false,
|
||||
"spyOn": false,
|
||||
"jasmine": false,
|
||||
"spyOnConstructor": false,
|
||||
"React": true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
/**
|
||||
* Function to get the shallow output for a given component
|
||||
* As we are using phantom.js, we also need to include the fn.proto.bind shim!
|
||||
*
|
||||
* @see http://simonsmith.io/unit-testing-react-components-without-a-dom/
|
||||
* @author somonsmith
|
||||
*/
|
||||
|
||||
// Add missing methods to phantom.js
|
||||
import './pack/phantomjs-shims';
|
||||
|
||||
import React from 'react/addons';
|
||||
const TestUtils = React.addons.TestUtils;
|
||||
|
||||
/**
|
||||
* Get the shallow rendered component
|
||||
*
|
||||
* @param {Object} component The component to return the output for
|
||||
* @param {Object} props [optional] The components properties
|
||||
* @param {Mixed} ...children [optional] List of children
|
||||
* @return {Object} Shallow rendered output
|
||||
*/
|
||||
export default function createComponent(component, props = {}, ...children) {
|
||||
const shallowRenderer = TestUtils.createRenderer();
|
||||
shallowRenderer.render(React.createElement(component, props, children.length > 1 ? children : children[0]));
|
||||
return shallowRenderer.getRenderOutput();
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
(function() {
|
||||
|
||||
var Ap = Array.prototype;
|
||||
var slice = Ap.slice;
|
||||
var Fp = Function.prototype;
|
||||
|
||||
if (!Fp.bind) {
|
||||
// PhantomJS doesn't support Function.prototype.bind natively, so
|
||||
// polyfill it whenever this module is required.
|
||||
Fp.bind = function(context) {
|
||||
var func = this;
|
||||
var args = slice.call(arguments, 1);
|
||||
|
||||
function bound() {
|
||||
var invokedAsConstructor = func.prototype && (this instanceof func);
|
||||
return func.apply(
|
||||
// Ignore the context parameter when invoking the bound function
|
||||
// as a constructor. Note that this includes not only constructor
|
||||
// invocations using the new keyword but also calls to base class
|
||||
// constructors such as BaseClass.call(this, ...) or super(...).
|
||||
!invokedAsConstructor && context || this,
|
||||
args.concat(slice.call(arguments))
|
||||
);
|
||||
}
|
||||
|
||||
// The bound function must share the .prototype of the unbound
|
||||
// function so that any object created by one constructor will count
|
||||
// as an instance of both constructors.
|
||||
bound.prototype = func.prototype;
|
||||
|
||||
return bound;
|
||||
};
|
||||
}
|
||||
})();
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,11 +0,0 @@
|
||||
var alt = require('../alt');
|
||||
|
||||
<% if (es6) { %>class <%= classedName %> {
|
||||
|
||||
}; <% }
|
||||
else { %>var <%= classedName %> = alt.createActions(function () {
|
||||
|
||||
}); <% } %>
|
||||
|
||||
<% if (es6) { %>export default alt.createActions(<%= classedName %>); <% }
|
||||
else { %>module.exports = <%= classedName %>; <% } %>
|
||||
@@ -1,21 +0,0 @@
|
||||
var alt = require('../alt');
|
||||
|
||||
<% if (es6) { %>class <%= classedName %> {
|
||||
constructor() {
|
||||
|
||||
this.bindListeners({
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
} <% }
|
||||
else { %>var <%= classedName %> = alt.createStore({
|
||||
|
||||
bindListeners: {
|
||||
|
||||
}
|
||||
|
||||
}); <% } %>
|
||||
|
||||
<% if (es6) { %>export default alt.createStore(<%= classedName %>, '<%= classedName %>'); <% }
|
||||
else { %>module.exports = <%= classedName %>; <% } %>
|
||||
@@ -1,26 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var React = require('react/addons');
|
||||
var ReactTransitionGroup = React.addons.TransitionGroup;
|
||||
|
||||
// CSS
|
||||
require('normalize.css');
|
||||
require('../styles/main.css');
|
||||
|
||||
var imageURL = require('../images/yeoman.png');
|
||||
|
||||
var <%= scriptAppName %> = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div className="main">
|
||||
<ReactTransitionGroup transitionName="fade">
|
||||
<img src={imageURL} />
|
||||
</ReactTransitionGroup>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
<% if (!reactRouter) {
|
||||
%>React.render(<<%= scriptAppName %> />, document.getElementById('content')); // jshint ignore:line
|
||||
<% } %>
|
||||
module.exports = <%= scriptAppName %>;
|
||||
@@ -1,36 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var React = require('react/addons');<% if(rich && architecture === 'reflux'){%>
|
||||
var Reflux = require('Reflux');<%}%>
|
||||
<% if(rich && architecture === 'flux' || architecture === 'reflux'){%>
|
||||
//var Actions = require('actions/xxx')<%}%>
|
||||
|
||||
<% if (stylesLanguage === 'css') { %>require('styles/<%= classedFileName %>.css');<% } %><%
|
||||
if (stylesLanguage === 'sass') { %>require('styles/<%= classedFileName %>.sass');<% } %><%
|
||||
if (stylesLanguage === 'scss') { %>require('styles/<%= classedFileName %>.scss');<% } %><%
|
||||
if (stylesLanguage === 'less') { %>require('styles/<%= classedFileName %>.less');<% } %><%
|
||||
if (stylesLanguage === 'stylus') { %>require('styles/<%= classedFileName %>.styl');<% } %>
|
||||
|
||||
var <%= classedName %> = React.createClass({<% if(rich){%>
|
||||
mixins: [<% if(architecture === 'reflux'){%>Reflux.ListenerMixin<%}%>],
|
||||
getInitialState: function() {
|
||||
return {};
|
||||
},
|
||||
getDefaultProps: function() {},
|
||||
componentWillMount: function() {},
|
||||
componentDidMount: function() {},
|
||||
shouldComponentUpdate: function() {},
|
||||
componentDidUpdate: function() {},
|
||||
componentWillUnmount: function() {},<%}%>
|
||||
|
||||
render: function () {
|
||||
return (
|
||||
<div className="<%= classedName %>">
|
||||
<p>Content for <%= classedName %></p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
<% if (es6) { %>export default <%= classedName %>;<% }
|
||||
else { %>module.exports = <%= classedName %>;<% } %>
|
||||
@@ -1,3 +0,0 @@
|
||||
var Dispatcher = require('flux').Dispatcher;
|
||||
|
||||
module.exports = new Dispatcher();
|
||||
@@ -1,8 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var <%= classedName %> = {
|
||||
|
||||
};
|
||||
|
||||
<% if (es6) { %> export default <%= classedName %>; <% }
|
||||
else { %>module.exports = <%= classedName %>; <% } %>
|
||||
@@ -1,20 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var assign = require('object-assign');
|
||||
var <%= dispatcherName %> = require('../dispatcher/<%= dispatcherName %>');
|
||||
|
||||
var <%= classedName %> = assign({}, EventEmitter.prototype, {
|
||||
|
||||
});
|
||||
|
||||
<%= classedName %>.dispatchToken = <%= dispatcherName %>.register(function(action) {
|
||||
|
||||
switch(action.type) {
|
||||
default:
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
<% if (es6) { %> export default <%= classedName %>; <% }
|
||||
else { %>module.exports = <%= classedName %>; <% } %>
|
||||
@@ -1,11 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var Reflux = require('reflux');
|
||||
|
||||
var <%= classedName %> = Reflux.createActions([
|
||||
|
||||
]);
|
||||
|
||||
|
||||
<% if (es6) { %> export default <%= classedName %>; <% }
|
||||
else { %>module.exports = <%= classedName %>; <% } %>
|
||||
@@ -1,14 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var Reflux = require('reflux');
|
||||
//var Actions = require('actions/..');
|
||||
|
||||
|
||||
var <%= classedName %> = Reflux.createStore({
|
||||
listenables: Actions,
|
||||
|
||||
|
||||
});
|
||||
|
||||
<% if (es6) { %> export default <%= classedName %>; <% }
|
||||
else { %>module.exports = <%= classedName %>; <% } %>
|
||||
@@ -1,4 +0,0 @@
|
||||
var Alt = require('alt');
|
||||
var alt = new Alt();
|
||||
|
||||
module.exports = alt;
|
||||
@@ -1,18 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var <%= scriptAppName %> = require('./<%= scriptAppName %>');
|
||||
var React = require('react');
|
||||
var Router = require('react-router');
|
||||
var Route = Router.Route;
|
||||
|
||||
var content = document.getElementById('content');
|
||||
|
||||
var Routes = (
|
||||
<Route handler={<%= scriptAppName %>}>
|
||||
<Route name="/" handler={<%= scriptAppName %>}/>
|
||||
</Route>
|
||||
);
|
||||
|
||||
Router.run(Routes, function (Handler) {
|
||||
React.render(<Handler/>, content);
|
||||
});
|
||||
@@ -1,13 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
describe('<%= classedName %>', () => {
|
||||
let action;
|
||||
|
||||
beforeEach(() => {
|
||||
action = require('actions/<%= classedFileName %>.js');
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(action).toBeDefined();
|
||||
});
|
||||
});
|
||||
@@ -1,19 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
describe('<%= classedName %>', () => {
|
||||
let React = require('react/addons');
|
||||
let <%= scriptAppName %>, component;
|
||||
|
||||
beforeEach(() => {
|
||||
let container = document.createElement('div');
|
||||
container.id = 'content';
|
||||
document.body.appendChild(container);
|
||||
|
||||
<%= scriptAppName %> = require('components/<%= scriptAppName %>.js');
|
||||
component = React.createElement(<%= scriptAppName %>);
|
||||
});
|
||||
|
||||
it('should create a new instance of <%= scriptAppName %>', () => {
|
||||
expect(component).toBeDefined();
|
||||
});
|
||||
});
|
||||
@@ -1,20 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
// Uncomment the following lines to use the react test utilities
|
||||
// import React from 'react/addons';
|
||||
// const TestUtils = React.addons.TestUtils;
|
||||
|
||||
import createComponent from 'helpers/createComponent';
|
||||
import <%= classedName %> from 'components/<%= classedFileName %><%= reactComponentSuffix %>';
|
||||
|
||||
describe('<%= classedName %>', () => {
|
||||
let <%= classedName %>Component;
|
||||
|
||||
beforeEach(() => {
|
||||
<%= classedName %>Component = createComponent(<%= classedName %>);
|
||||
});
|
||||
|
||||
it('should have its component name as default className', () => {
|
||||
expect(<%= classedName %>Component._store.props.className).toBe('<%= classedName %>');
|
||||
});
|
||||
});
|
||||
@@ -1,13 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
describe('<%= classedName %>', () => {
|
||||
let store;
|
||||
|
||||
beforeEach(() => {
|
||||
store = require('stores/<%= classedFileName %>.js');
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(store).toBeDefined();
|
||||
});
|
||||
});
|
||||
@@ -1,14 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
describe('main', () => {
|
||||
let main, component;
|
||||
|
||||
beforeEach(() => {
|
||||
main = require('components/main.jsx');
|
||||
component = main();
|
||||
});
|
||||
|
||||
it('should create a new instance of main', () => {
|
||||
expect(component).toBeDefined();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,97 @@
|
||||
'use strict';
|
||||
let path = require('path');
|
||||
let expect = require('chai').expect;
|
||||
let assert = require('yeoman-generator').assert;
|
||||
let helpers = require('yeoman-generator').test
|
||||
|
||||
describe('react-webpack:app', () => {
|
||||
|
||||
let defaultPrompts = require('../../../generators/app/prompts.js');
|
||||
let prompts = {};
|
||||
for(let p of defaultPrompts) {
|
||||
prompts[p.name] = p.default;
|
||||
}
|
||||
|
||||
let generator;
|
||||
let generatorBase = path.join(__dirname, '../../../generators/app');
|
||||
|
||||
before((done) => {
|
||||
|
||||
helpers.run(generatorBase)
|
||||
.inTmpDir()
|
||||
.withOptions({
|
||||
'skip-welcome-message': true,
|
||||
'skip-install': true
|
||||
})
|
||||
.withPrompts(prompts)
|
||||
.on('ready', (instance) => {
|
||||
generator = instance;
|
||||
})
|
||||
.on('end', done);
|
||||
});
|
||||
|
||||
describe('#config', () => {
|
||||
|
||||
it('should use "css" as default style language', () => {
|
||||
expect(generator.config.get('style')).to.equal('css');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#createFiles', () => {
|
||||
|
||||
it('should generate dot files', () => {
|
||||
|
||||
assert.file([
|
||||
'.editorconfig',
|
||||
'.eslintrc',
|
||||
'.npmignore',
|
||||
'.yo-rc.json'
|
||||
]);
|
||||
});
|
||||
|
||||
it('should generate project configuration files', () => {
|
||||
|
||||
assert.file([
|
||||
'LICENSE',
|
||||
'package.json'
|
||||
]);
|
||||
});
|
||||
|
||||
it('should generate the webpack configuration', () => {
|
||||
|
||||
assert.file([
|
||||
'cfg/base.js',
|
||||
'cfg/dev.js',
|
||||
'cfg/dist.js',
|
||||
'cfg/test.js',
|
||||
'server.js',
|
||||
'webpack.config.js'
|
||||
]);
|
||||
});
|
||||
|
||||
it('should generate required source files', () => {
|
||||
|
||||
assert.file([
|
||||
'src/actions/README.md',
|
||||
'src/components/Main.js',
|
||||
'src/components/run.js',
|
||||
'src/favicon.ico',
|
||||
'src/images/yeoman.png',
|
||||
'src/index.html',
|
||||
'src/sources/README.md',
|
||||
'src/stores/README.md',
|
||||
'src/styles/App.css'
|
||||
]);
|
||||
});
|
||||
|
||||
it('should generate test configuration and basic tests', () => {
|
||||
|
||||
assert.file([
|
||||
'karma.conf.js',
|
||||
'test/components/MainTest.js',
|
||||
'test/helpers/shallowRenderHelper.js',
|
||||
'test/loadtests.js'
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,283 @@
|
||||
'use strict';
|
||||
let path = require('path');
|
||||
let assert = require('yeoman-generator').assert;
|
||||
let helpers = require('yeoman-generator').test
|
||||
|
||||
describe('react-webpack:component', () => {
|
||||
|
||||
let generatorComponent = path.join(__dirname, '../../../generators/component');
|
||||
|
||||
/**
|
||||
* Return a newly generated component with given name and style
|
||||
* @param {String} name
|
||||
* @param {String} styleType
|
||||
* @param {Function} callback
|
||||
*/
|
||||
function createGeneratedComponent(name, styleType, callback) {
|
||||
helpers.run(generatorComponent)
|
||||
.withArguments([name])
|
||||
.on('ready', (instance) => {
|
||||
instance.config.set('style', styleType);
|
||||
})
|
||||
.on('end', callback);
|
||||
}
|
||||
|
||||
describe('When using style type "css"', () => {
|
||||
|
||||
describe('Setup', () => {
|
||||
|
||||
it('should create the react component, its stylesheet and test file', (done) => {
|
||||
createGeneratedComponent('mycomponent', 'css', () => {
|
||||
|
||||
assert.file([
|
||||
'src/components/MycomponentComponent.js',
|
||||
'src/styles/Mycomponent.css',
|
||||
'test/components/MycomponentComponentTest.js'
|
||||
]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Component', () => {
|
||||
|
||||
it('should require the created css file', (done) => {
|
||||
createGeneratedComponent('mycomponent', 'css', () => {
|
||||
assert.fileContent('src/components/MycomponentComponent.js', 'require(\'styles//Mycomponent.css\');');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Style', () => {
|
||||
|
||||
it('should add the components css class to the stylesheet', (done) => {
|
||||
createGeneratedComponent('mycomponent', 'css', () => {
|
||||
assert.fileContent('src/styles/Mycomponent.css', '.mycomponent-component');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Test', () => {
|
||||
|
||||
it('should import the react component', (done) => {
|
||||
createGeneratedComponent('mycomponent', 'css', () => {
|
||||
assert.fileContent('test/components/MycomponentComponentTest.js', 'import MycomponentComponent from \'components//MycomponentComponent.js\';');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
}); // End css
|
||||
|
||||
describe('When creating a component in a subfolder', () => {
|
||||
|
||||
describe('Setup', () => {
|
||||
|
||||
it('should create the react component, its stylesheet and test file', (done) => {
|
||||
createGeneratedComponent('my/little !special/test', 'css', () => {
|
||||
|
||||
assert.file([
|
||||
'src/components/my/littleSpecial/TestComponent.js',
|
||||
'src/styles/my/littleSpecial/Test.css',
|
||||
'test/components/my/littleSpecial/TestComponentTest.js'
|
||||
]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
}); // End css (subfolder)
|
||||
|
||||
describe('When using style type "sass"', () => {
|
||||
|
||||
describe('Setup', () => {
|
||||
|
||||
it('should create the react component, its stylesheet and test file', (done) => {
|
||||
createGeneratedComponent('mycomponent', 'sass', () => {
|
||||
|
||||
assert.file([
|
||||
'src/components/MycomponentComponent.js',
|
||||
'src/styles/Mycomponent.sass',
|
||||
'test/components/MycomponentComponentTest.js'
|
||||
]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Component', () => {
|
||||
|
||||
it('should require the created sass file', (done) => {
|
||||
createGeneratedComponent('mycomponent', 'sass', () => {
|
||||
assert.fileContent('src/components/MycomponentComponent.js', 'require(\'styles//Mycomponent.sass\');');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Style', () => {
|
||||
|
||||
it('should add the components sass class to the stylesheet', (done) => {
|
||||
createGeneratedComponent('mycomponent', 'sass', () => {
|
||||
assert.fileContent('src/styles/Mycomponent.sass', '.mycomponent-component');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Test', () => {
|
||||
|
||||
it('should import the react component', (done) => {
|
||||
createGeneratedComponent('mycomponent', 'sass', () => {
|
||||
assert.fileContent('test/components/MycomponentComponentTest.js', 'import MycomponentComponent from \'components//MycomponentComponent.js\';');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
}); // End sass
|
||||
|
||||
describe('When using style type "scss"', () => {
|
||||
|
||||
describe('Setup', () => {
|
||||
|
||||
it('should create the react component, its stylesheet and test file', (done) => {
|
||||
createGeneratedComponent('mycomponent', 'scss', () => {
|
||||
|
||||
assert.file([
|
||||
'src/components/MycomponentComponent.js',
|
||||
'src/styles/Mycomponent.scss',
|
||||
'test/components/MycomponentComponentTest.js'
|
||||
]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Component', () => {
|
||||
|
||||
it('should require the created scss file', (done) => {
|
||||
createGeneratedComponent('mycomponent', 'scss', () => {
|
||||
assert.fileContent('src/components/MycomponentComponent.js', 'require(\'styles//Mycomponent.scss\');');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Style', () => {
|
||||
|
||||
it('should add the components scss class to the stylesheet', (done) => {
|
||||
createGeneratedComponent('mycomponent', 'scss', () => {
|
||||
assert.fileContent('src/styles/Mycomponent.scss', '.mycomponent-component');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Test', () => {
|
||||
|
||||
it('should import the react component', (done) => {
|
||||
createGeneratedComponent('mycomponent', 'scss', () => {
|
||||
assert.fileContent('test/components/MycomponentComponentTest.js', 'import MycomponentComponent from \'components//MycomponentComponent.js\';');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
}); // End scss
|
||||
|
||||
describe('When using style type "less"', () => {
|
||||
|
||||
describe('Setup', () => {
|
||||
|
||||
it('should create the react component, its stylesheet and test file', (done) => {
|
||||
createGeneratedComponent('mycomponent', 'less', () => {
|
||||
|
||||
assert.file([
|
||||
'src/components/MycomponentComponent.js',
|
||||
'src/styles/Mycomponent.less',
|
||||
'test/components/MycomponentComponentTest.js'
|
||||
]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Component', () => {
|
||||
|
||||
it('should require the created less file', (done) => {
|
||||
createGeneratedComponent('mycomponent', 'less', () => {
|
||||
assert.fileContent('src/components/MycomponentComponent.js', 'require(\'styles//Mycomponent.less\');');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Style', () => {
|
||||
|
||||
it('should add the components less class to the stylesheet', (done) => {
|
||||
createGeneratedComponent('mycomponent', 'less', () => {
|
||||
assert.fileContent('src/styles/Mycomponent.less', '.mycomponent-component');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Test', () => {
|
||||
|
||||
it('should import the react component', (done) => {
|
||||
createGeneratedComponent('mycomponent', 'less', () => {
|
||||
assert.fileContent('test/components/MycomponentComponentTest.js', 'import MycomponentComponent from \'components//MycomponentComponent.js\';');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
}); // End less
|
||||
|
||||
describe('When using style type "stylus"', () => {
|
||||
|
||||
describe('Setup', () => {
|
||||
|
||||
it('should create the react component, its stylesheet and test file', (done) => {
|
||||
createGeneratedComponent('mycomponent', 'stylus', () => {
|
||||
|
||||
assert.file([
|
||||
'src/components/MycomponentComponent.js',
|
||||
'src/styles/Mycomponent.styl',
|
||||
'test/components/MycomponentComponentTest.js'
|
||||
]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Component', () => {
|
||||
|
||||
it('should require the created stylus file', (done) => {
|
||||
createGeneratedComponent('mycomponent', 'stylus', () => {
|
||||
assert.fileContent('src/components/MycomponentComponent.js', 'require(\'styles//Mycomponent.styl\');');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Style', () => {
|
||||
|
||||
it('should add the components stylus class to the stylesheet', (done) => {
|
||||
createGeneratedComponent('mycomponent', 'stylus', () => {
|
||||
assert.fileContent('src/styles/Mycomponent.styl', '.mycomponent-component');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Test', () => {
|
||||
|
||||
it('should import the react component', (done) => {
|
||||
createGeneratedComponent('mycomponent', 'less', () => {
|
||||
assert.fileContent('test/components/MycomponentComponentTest.js', 'import MycomponentComponent from \'components//MycomponentComponent.js\';');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
}); // End stylus
|
||||
|
||||
});
|
||||
@@ -0,0 +1,2 @@
|
||||
--reporter spec
|
||||
--recursive
|
||||
@@ -1,342 +0,0 @@
|
||||
/*global describe, beforeEach, it*/
|
||||
'use strict';
|
||||
|
||||
var path = require('path');
|
||||
var helpers = require('yeoman-generator').test;
|
||||
var assert = require('yeoman-generator').assert;
|
||||
var _ = require('underscore.string');
|
||||
|
||||
describe('react-webpack generator', function() {
|
||||
var react;
|
||||
var expected = [
|
||||
'src/favicon.ico',
|
||||
'src/styles/main.css',
|
||||
'src/index.html',
|
||||
'Gruntfile.js',
|
||||
'webpack.config.js',
|
||||
'karma.conf.js',
|
||||
'package.json'
|
||||
];
|
||||
var mockPrompts = {};
|
||||
var genOptions = {
|
||||
'appPath': 'src',
|
||||
'skip-install': true,
|
||||
'skip-welcome-message': true,
|
||||
'skip-message': true
|
||||
};
|
||||
var deps = [
|
||||
'../../app',
|
||||
'../../common',
|
||||
'../../component',
|
||||
'../../main'
|
||||
];
|
||||
|
||||
beforeEach(function(done) {
|
||||
helpers.testDirectory(path.join(__dirname, 'temp-test'), function(err) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
react = helpers.createGenerator('react-webpack:app', deps, false, genOptions);
|
||||
helpers.mockPrompt(react, mockPrompts);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('App files', function() {
|
||||
it('should generate dotfiles', function(done) {
|
||||
react.run({}, function() {
|
||||
helpers.assertFile([].concat(expected, [
|
||||
'.yo-rc.json',
|
||||
'.editorconfig',
|
||||
'.gitignore',
|
||||
'.jshintrc'
|
||||
]));
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should generate app files', function(done) {
|
||||
react.run({}, function() {
|
||||
// TODO: Hack, no time to work out why generated
|
||||
// files not present at point of test...
|
||||
setTimeout(function() {
|
||||
helpers.assertFile(expected);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should generate expected JS files', function(done) {
|
||||
react.run({}, function() {
|
||||
setTimeout(function() {
|
||||
helpers.assertFile([].concat(expected, [
|
||||
'src/components/TempTestApp.js',
|
||||
'src/components/main.js'
|
||||
]));
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should generate expected test JS files', function(done) {
|
||||
react.run({}, function() {
|
||||
// TODO: Hack, no time to work out why generated
|
||||
// files not present at point of test...
|
||||
setTimeout(function() {
|
||||
helpers.assertFile([].concat(expected, [
|
||||
'test/helpers/pack/phantomjs-shims.js',
|
||||
'test/helpers/createComponent.js',
|
||||
'test/helpers/react/addons.js',
|
||||
'test/spec/components/TempTestApp.js'
|
||||
]));
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should use HMR webpack API inside of configs', function (done) {
|
||||
react.run({}, function() {
|
||||
assert.fileContent([
|
||||
['package.json', /react-hot-loader/],
|
||||
['Gruntfile.js', /hot:\s*true/],
|
||||
['webpack.config.js', /react-hot/],
|
||||
['webpack.config.js', /webpack\.HotModuleReplacementPlugin/],
|
||||
['webpack.config.js', /webpack\/hot\/only-dev-server/]
|
||||
]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should generate JS config with aliases', function(done) {
|
||||
react.run({}, function() {
|
||||
assert.fileContent([
|
||||
// style aliases
|
||||
['webpack.config.js', /resolve[\S\s]+alias[\S\s]+styles/m],
|
||||
['karma.conf.js', /resolve[\S\s]+alias[\S\s]+styles/m],
|
||||
['webpack.dist.config.js', /resolve[\S\s]+alias[\S\s]+styles/m],
|
||||
// script/components aliases
|
||||
['webpack.config.js', /resolve[\S\s]+alias[\S\s]+components/m],
|
||||
['karma.conf.js', /resolve[\S\s]+alias[\S\s]+components/m],
|
||||
['webpack.dist.config.js', /resolve[\S\s]+alias[\S\s]+components/m]
|
||||
]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not have any flux assets configured', function(done) {
|
||||
react.run({}, function() {
|
||||
assert.noFileContent([
|
||||
['package.json', /flux/],
|
||||
['package.json', /events/],
|
||||
['package.json', /object-assign/],
|
||||
['karma.conf.js', /resolve[\S\s]+alias[\S\s]+stores/m],
|
||||
['webpack.config.js', /resolve[\S\s]+alias[\S\s]+stores/m],
|
||||
['webpack.dist.config.js', /resolve[\S\s]+alias[\S\s]+stores/m]
|
||||
]);
|
||||
|
||||
assert.noFile('src/dispatcher/TempTestAppDispatcher.js');
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Generator', function () {
|
||||
|
||||
it('should contain info about used style lang', function (done) {
|
||||
react.run({}, function() {
|
||||
assert.ok(react.config.get('styles-language'));
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('by default should use css style lang', function (done) {
|
||||
react.run({}, function() {
|
||||
assert.equal(react.config.get('styles-language'), 'css');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
var assertStyle = function (lang, done) {
|
||||
helpers.mockPrompt(react, {
|
||||
stylesLanguage: lang
|
||||
});
|
||||
react.run({}, function() {
|
||||
assert.equal(react.config.get('styles-language'), lang);
|
||||
done();
|
||||
});
|
||||
};
|
||||
|
||||
it('should use sass style lang', function (done) {
|
||||
assertStyle('sass', done);
|
||||
});
|
||||
|
||||
it('should use scss style lang', function (done) {
|
||||
assertStyle('scss', done);
|
||||
});
|
||||
|
||||
it('should use less style lang', function (done) {
|
||||
assertStyle('less', done);
|
||||
});
|
||||
|
||||
it('should use stylus style lang', function (done) {
|
||||
assertStyle('stylus', done);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('When using Flux', function() {
|
||||
|
||||
beforeEach(function(done) {
|
||||
helpers.mockPrompt(react, {
|
||||
architecture: 'flux'
|
||||
});
|
||||
|
||||
react.run({}, function() {
|
||||
done();
|
||||
})
|
||||
});
|
||||
|
||||
it('should add flux, events, and object-assign packages', function(done) {
|
||||
assert.fileContent([
|
||||
['package.json', /flux/],
|
||||
['package.json', /events/],
|
||||
['package.json', /object-assign/]
|
||||
]);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
it('should add stores and actions alias to karma config', function(done) {
|
||||
assert.fileContent([
|
||||
['karma.conf.js', /resolve[\S\s]+alias[\S\s]+stores/m]
|
||||
]);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
it('should add stores and actions alias to webpack configs', function(done) {
|
||||
assert.fileContent([
|
||||
['webpack.config.js', /resolve[\S\s]+alias[\S\s]+stores/m],
|
||||
['webpack.dist.config.js', /resolve[\S\s]+alias[\S\s]+stores/m]
|
||||
]);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
it('should have a Dispatcher generated', function(done) {
|
||||
setTimeout(function(){
|
||||
assert.file('src/dispatcher/TempTestAppDispatcher.js');
|
||||
|
||||
done();
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
describe('When generating a Component', function() {
|
||||
var generatorTest = function(name, generatorType, specType, targetDirectory, scriptNameFn, specNameFn, suffix, done) {
|
||||
var deps = [path.join('../..', generatorType)];
|
||||
genOptions.appPath = 'src';
|
||||
|
||||
var reactGenerator = helpers.createGenerator('react-webpack:' + generatorType, deps, [name], genOptions);
|
||||
|
||||
react.run([], function() {
|
||||
reactGenerator.run([], function() {
|
||||
helpers.assertFileContent([
|
||||
[path.join('src', targetDirectory, name + '.js'), new RegExp('var ' + scriptNameFn(name) + suffix, 'g')],
|
||||
[path.join('src', targetDirectory, name + '.js'), new RegExp('require\\(\'styles\\/' + name + suffix + '\\.[^\']+' + '\'\\)', 'g')],
|
||||
[path.join('test/spec', targetDirectory, 'TempTestApp' + '.js'), new RegExp('require\\(\'components\\/' + 'TempTestApp' + suffix + '\\.[^\']+' + '\'\\)', 'g')],
|
||||
[path.join('test/spec', targetDirectory, name + '.js'), new RegExp('import ' + scriptNameFn(name) + ' from \'components\/Foo', 'g')],
|
||||
[path.join('test/spec', targetDirectory, name + '.js'), new RegExp('describe\\(\'' + specNameFn(name) + suffix + '\'', 'g')]
|
||||
]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
it('should generate a new component', function(done) {
|
||||
react.run({}, function() {
|
||||
generatorTest('Foo', 'component', 'component', 'components', _.capitalize, _.capitalize, '', done);
|
||||
});
|
||||
});
|
||||
|
||||
it('should generate a subcomponent', function(done) {
|
||||
react.run({}, function() {
|
||||
var subComponentNameFn = function () { return 'Bar'; };
|
||||
generatorTest('Foo/Bar', 'component', 'component', 'components', subComponentNameFn, subComponentNameFn, '', done);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('When generating an Action', function() {
|
||||
|
||||
beforeEach(function(done){
|
||||
helpers.mockPrompt(react, {
|
||||
architecture: 'flux'
|
||||
});
|
||||
|
||||
react.run({}, function() {
|
||||
var generator =
|
||||
helpers.createGenerator(
|
||||
'react-webpack:action',
|
||||
[path.join('../../action')],
|
||||
['Test'],
|
||||
{ appPath: 'src' }
|
||||
);
|
||||
|
||||
react.run([], function() {
|
||||
generator.run([], function() {
|
||||
done();
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should generate a new action with tests', function(done) {
|
||||
assert.fileContent([
|
||||
['src/actions/TestActionCreators.js', /var TestActionCreators/g],
|
||||
['test/spec/actions/TestActionCreators.js', /require\('actions\/TestActionCreators.js'\)/g],
|
||||
['test/spec/actions/TestActionCreators.js', /describe\('TestActionCreators'/g]
|
||||
]);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('When generating a Store', function() {
|
||||
|
||||
beforeEach(function(done) {
|
||||
helpers.mockPrompt(react, {
|
||||
architecture: 'flux'
|
||||
});
|
||||
|
||||
react.run({}, function() {
|
||||
var generator =
|
||||
helpers.createGenerator(
|
||||
'react-webpack:store',
|
||||
[path.join('../../store')],
|
||||
['Test'],
|
||||
{ appPath: 'src' }
|
||||
);
|
||||
|
||||
react.run([], function() {
|
||||
generator.run([], function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should generate a new store with tests', function(done) {
|
||||
assert.fileContent([
|
||||
['src/stores/TestStore.js', /var TestStore/g],
|
||||
['test/spec/stores/TestStore.js', /require\('stores\/TestStore.js'\)/g],
|
||||
['test/spec/stores/TestStore.js', /describe\('TestStore'/g]
|
||||
]);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,65 @@
|
||||
'use strict';
|
||||
let expect = require('chai').expect;
|
||||
|
||||
let utils = require('../../utils/config');
|
||||
let originalSettings = require('../../utils/configopts.json');
|
||||
|
||||
describe('Utilities:Config', () => {
|
||||
|
||||
describe('#getSetting', () => {
|
||||
|
||||
it('should return "null" if the key could not be found', () => {
|
||||
expect(utils.getSetting('bogus')).to.be.null;
|
||||
});
|
||||
|
||||
it('should return a settings object if it exists', () => {
|
||||
|
||||
let result = utils.getSetting('style');
|
||||
expect(result).to.be.an.object;
|
||||
expect(result).to.deep.equal(originalSettings.style);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getChoices', () => {
|
||||
|
||||
it('should return "null" if the key could not be found', () => {
|
||||
expect(utils.getChoices('bogus')).to.be.null;
|
||||
});
|
||||
|
||||
it('should return an array of choices when queried correctly', () => {
|
||||
|
||||
let result = utils.getChoices('style');
|
||||
expect(result).to.be.an.array;
|
||||
expect(result).to.deep.equal(originalSettings.style.options);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getChoiceByKey', () => {
|
||||
|
||||
it('should return "null" if the key or the setting could not be found', () => {
|
||||
|
||||
expect(utils.getChoiceByKey('bogus', 'unknown')).to.be.null;
|
||||
expect(utils.getChoiceByKey('style', 'unknown')).to.be.null;
|
||||
});
|
||||
|
||||
it('should return the configured object when it can be found', () => {
|
||||
|
||||
expect(utils.getChoiceByKey('style', 'css')).to.equal(originalSettings.style.options[0]);
|
||||
expect(utils.getChoiceByKey('style', 'less')).to.equal(originalSettings.style.options[3]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getDefaultChoice', () => {
|
||||
|
||||
it('should return "null" if the key could not be found', () => {
|
||||
expect(utils.getDefaultChoice('bogus')).to.be.null;
|
||||
});
|
||||
|
||||
it('should return the default choice when queried correctly', () => {
|
||||
|
||||
let result = utils.getDefaultChoice('style');
|
||||
expect(result).to.equal(originalSettings.style.default);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,97 @@
|
||||
'use strict';
|
||||
let expect = require('chai').expect;
|
||||
let path = require('path');
|
||||
|
||||
let utils = require('../../utils/yeoman');
|
||||
let baseDir = path.basename(process.cwd());
|
||||
|
||||
describe('Utilities:Yeoman', () => {
|
||||
|
||||
describe('#getBaseDir', () => {
|
||||
|
||||
it('should return the current run directory', () => {
|
||||
expect(utils.getBaseDir()).to.equal(baseDir);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getCleanedPathName', () => {
|
||||
|
||||
it('should return normalized paths', () => {
|
||||
|
||||
let tests = {
|
||||
'my/full œ!/path!': 'my/full/path',
|
||||
'Test': 'test',
|
||||
'I am a Test Component!': 'iAmATestComponent',
|
||||
'A very\^specialChary!@componentName with !!!': 'aVerySpecialCharyComponentNameWith'
|
||||
};
|
||||
|
||||
for(let test in tests) {
|
||||
expect(utils.getCleanedPathName(test)).to.be.equal(tests[test]);
|
||||
expect(utils.getCleanedPathName(test, 'suffix')).to.be.equal(tests[test] + 'Suffix');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getAppName', () => {
|
||||
|
||||
it('should return a js friendly application name', () => {
|
||||
let result = utils.getAppName('this is a test using % special / chars!');
|
||||
expect(result).to.be.equal('thisIsATestUsingSpecialChars');
|
||||
});
|
||||
|
||||
it('should use the current path for creating the appName if the argument is omitted', () => {
|
||||
|
||||
let resultWithoutArgs = utils.getAppName();
|
||||
let resultWithArgs = utils.getAppName(baseDir);
|
||||
|
||||
expect(resultWithoutArgs).to.be.equal(resultWithArgs);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getComponentStyleName', () => {
|
||||
|
||||
it('should return a components css className', () => {
|
||||
|
||||
let tests = {
|
||||
'my/full œ!/path!': 'path-component',
|
||||
'Test': 'test-component',
|
||||
'I am a Test Component!': 'i-am-a-test-component-component',
|
||||
'A very\^specialChary!@componentName with !!!': 'a-very-specialchary-componentname-with-component'
|
||||
};
|
||||
|
||||
for(let test in tests) {
|
||||
expect(utils.getComponentStyleName(test)).to.be.equal(tests[test]);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getAllSettingsFromComponentName', () => {
|
||||
|
||||
it('should get all required information for component creation from the components name', () => {
|
||||
|
||||
let expection = {
|
||||
style: {
|
||||
webpackPath: 'styles/my/component/Test.css',
|
||||
path: 'src/styles/my/component/',
|
||||
fileName: 'Test.css',
|
||||
className: 'test-component',
|
||||
suffix: '.css'
|
||||
},
|
||||
component: {
|
||||
webpackPath: 'components/my/component/TestComponent.js',
|
||||
path: 'src/components/my/component/',
|
||||
fileName: 'TestComponent.js',
|
||||
className: 'TestComponent',
|
||||
suffix: '.js'
|
||||
},
|
||||
test: {
|
||||
path: 'test/components/my/component/',
|
||||
fileName: 'TestComponentTest.js'
|
||||
}
|
||||
};
|
||||
|
||||
expect(utils.getAllSettingsFromComponentName('my/component/test')).to.deep.equal(expection);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,95 +0,0 @@
|
||||
'use strict';
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
|
||||
|
||||
module.exports = {
|
||||
rewrite: rewrite,
|
||||
rewriteFile: rewriteFile,
|
||||
appName: appName,
|
||||
capitalize: capitalize,
|
||||
capitalizeClass: capitalizeClass,
|
||||
capitalizeFile: capitalizeFile
|
||||
};
|
||||
|
||||
function rewriteFile (args) {
|
||||
args.path = args.path || process.cwd();
|
||||
var fullPath = path.join(args.path, args.file);
|
||||
|
||||
args.haystack = fs.readFileSync(fullPath, 'utf8');
|
||||
var body = rewrite(args);
|
||||
|
||||
fs.writeFileSync(fullPath, body);
|
||||
}
|
||||
|
||||
function escapeRegExp (str) {
|
||||
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
|
||||
}
|
||||
|
||||
function rewrite (args) {
|
||||
// check if splicable is already in the body text
|
||||
var re = new RegExp(args.splicable.map(function (line) {
|
||||
return '\s*' + escapeRegExp(line);
|
||||
}).join('\n'));
|
||||
|
||||
if (re.test(args.haystack)) {
|
||||
return args.haystack;
|
||||
}
|
||||
|
||||
var lines = args.haystack.split('\n');
|
||||
|
||||
var otherwiseLineIndex = 0;
|
||||
lines.forEach(function (line, i) {
|
||||
if (line.indexOf(args.needle) !== -1) {
|
||||
otherwiseLineIndex = i;
|
||||
}
|
||||
});
|
||||
|
||||
var spaces = 0;
|
||||
while (lines[otherwiseLineIndex].charAt(spaces) === ' ') {
|
||||
spaces += 1;
|
||||
}
|
||||
|
||||
var spaceStr = '';
|
||||
while ((spaces -= 1) >= 0) {
|
||||
spaceStr += ' ';
|
||||
}
|
||||
|
||||
lines.splice(otherwiseLineIndex, 0, args.splicable.map(function (line) {
|
||||
return spaceStr + line;
|
||||
}).join('\n'));
|
||||
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
function capitalize(str) {
|
||||
str = String(str);
|
||||
return str[0].toUpperCase() + str.substr(1, str.length);
|
||||
}
|
||||
|
||||
function capitalizeClass(string) {
|
||||
var words = string.split('/');
|
||||
words.push(capitalize(words.pop()));
|
||||
return words.pop();
|
||||
}
|
||||
|
||||
function capitalizeFile(string) {
|
||||
var words = string.split('/');
|
||||
words.push(capitalize(words.pop()));
|
||||
return words.join('/');
|
||||
}
|
||||
|
||||
function appName(self) {
|
||||
var counter = 0, suffix = self.options['app-suffix'];
|
||||
// Have to check this because of generator bug #386
|
||||
process.argv.forEach(function (val) {
|
||||
if (val.indexOf('--app-suffix') > -1) {
|
||||
counter++;
|
||||
}
|
||||
});
|
||||
if (counter === 0 || (typeof suffix === 'boolean' && suffix)) {
|
||||
suffix = 'App';
|
||||
}
|
||||
return suffix ? self._.classify(suffix) : '';
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
let config = require('./config');
|
||||
let yeoman = require('./yeoman');
|
||||
|
||||
module.exports = {
|
||||
config: config,
|
||||
yeoman: yeoman
|
||||
};
|
||||
@@ -0,0 +1,68 @@
|
||||
'use strict';
|
||||
let opts = require('./configopts.json');
|
||||
|
||||
/**
|
||||
* Get a setting
|
||||
* @param {String} setting
|
||||
* @return {Mixed} setting or null if not found
|
||||
*/
|
||||
let getSetting = (setting) => {
|
||||
return opts[setting] !== undefined ? opts[setting] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get choices for a given setting
|
||||
* @param {String} setting
|
||||
* @return {Mixed} Result or null if nothing was found
|
||||
*/
|
||||
let getChoices = function getChoices(setting) {
|
||||
|
||||
let config = getSetting(setting);
|
||||
return config && Array.isArray(config.options) ? config.options : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the wanted choice by key
|
||||
* @param {String} setting
|
||||
* @param {String} key
|
||||
* @return {Object}
|
||||
*/
|
||||
let getChoiceByKey = (setting, key) => {
|
||||
|
||||
let choices = getChoices(setting);
|
||||
if(!choices) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let result = null;
|
||||
|
||||
for(let choice of choices) {
|
||||
|
||||
if(choice.name === key) {
|
||||
result = choice;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default choice for a config setting
|
||||
* @param {String} setting
|
||||
* @return {Mixed}
|
||||
*/
|
||||
let getDefaultChoice = (setting) => {
|
||||
let config = getSetting(setting);
|
||||
return config && config.default !== undefined && config.default.length > 0 ? config.default : null;
|
||||
}
|
||||
|
||||
// getChoices
|
||||
// getDefault
|
||||
|
||||
module.exports = {
|
||||
getSetting: getSetting,
|
||||
getChoices: getChoices,
|
||||
getChoiceByKey: getChoiceByKey,
|
||||
getDefaultChoice: getDefaultChoice
|
||||
};
|
||||
@@ -0,0 +1,84 @@
|
||||
{
|
||||
"path": {
|
||||
"options": [
|
||||
{
|
||||
"name": "base",
|
||||
"path": "src"
|
||||
},
|
||||
{
|
||||
"name": "action",
|
||||
"path": "src/actions"
|
||||
},
|
||||
{
|
||||
"name": "component",
|
||||
"path": "src/components"
|
||||
},
|
||||
{
|
||||
"name": "image",
|
||||
"path": "src/images"
|
||||
},
|
||||
{
|
||||
"name": "source",
|
||||
"path": "src/sources"
|
||||
},
|
||||
{
|
||||
"name": "store",
|
||||
"path": "src/stores"
|
||||
},
|
||||
{
|
||||
"name": "style",
|
||||
"path": "src/styles"
|
||||
},
|
||||
{
|
||||
"name": "test",
|
||||
"path": "test"
|
||||
},
|
||||
{
|
||||
"name": "dist",
|
||||
"path": "dist"
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"options": [
|
||||
{
|
||||
"name": "css",
|
||||
"value": "css",
|
||||
"suffix": ".css"
|
||||
},
|
||||
{
|
||||
"name": "sass",
|
||||
"value": "sass",
|
||||
"suffix": ".sass",
|
||||
"packages": [
|
||||
{ "name": "sass-loader", "version": "^1.0.1" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "scss",
|
||||
"value": "scss",
|
||||
"suffix": ".scss",
|
||||
"packages": [
|
||||
{ "name": "sass-loader", "version": "^1.0.1" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "less",
|
||||
"value": "less",
|
||||
"suffix": ".less",
|
||||
"packages": [
|
||||
{ "name": "less-loader", "version": "^2.0.0" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "stylus",
|
||||
"value": "stylus",
|
||||
"suffix": ".styl",
|
||||
"packages": [
|
||||
{ "name": "stylus-loader", "version": "^0.5.0" }
|
||||
]
|
||||
}
|
||||
],
|
||||
"default": "css"
|
||||
}
|
||||
}
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
'use strict';
|
||||
|
||||
let path = require('path');
|
||||
let configUtils = require('./config');
|
||||
let _ = require('underscore.string');
|
||||
|
||||
// Needed directory paths
|
||||
const baseName = path.basename(process.cwd());
|
||||
|
||||
/**
|
||||
* Get the base directory
|
||||
* @return {String}
|
||||
*/
|
||||
let getBaseDir = () => {
|
||||
return baseName;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get all settings (paths and the like) from components name
|
||||
* @param {String} componentName The components name
|
||||
* @param {String} style Style language to use [optional]
|
||||
* @return {Object} Component settings
|
||||
*/
|
||||
let getAllSettingsFromComponentName = (componentName, style) => {
|
||||
|
||||
if(!style) {
|
||||
style = 'css';
|
||||
}
|
||||
|
||||
// Clean up the path and pull it to parts
|
||||
let cleanedPaths = getCleanedPathName(componentName);
|
||||
let componentParts = cleanedPaths.split('/');
|
||||
let componentBaseName = _.capitalize(componentParts.pop());
|
||||
let componentPartPath = componentParts.join('/');
|
||||
|
||||
// Configure Styles
|
||||
let stylePaths = configUtils.getChoiceByKey('path', 'style');
|
||||
let styleSettings = configUtils.getChoiceByKey('style', style);
|
||||
|
||||
// Configure components
|
||||
let componentPath = configUtils.getChoiceByKey('path', 'component');
|
||||
|
||||
// Configure tests
|
||||
let testPath = configUtils.getChoiceByKey('path', 'test');
|
||||
|
||||
let settings = {
|
||||
style: {
|
||||
webpackPath: `styles/${componentPartPath}/${componentBaseName}${styleSettings.suffix}`,
|
||||
path: `${stylePaths.path}/${componentPartPath}/`,
|
||||
fileName: `${componentBaseName}${styleSettings.suffix}`,
|
||||
className: getComponentStyleName(componentBaseName),
|
||||
suffix: styleSettings.suffix
|
||||
},
|
||||
component: {
|
||||
webpackPath: `components/${componentPartPath}/${componentBaseName}Component.js`,
|
||||
path: `${componentPath.path}/${componentPartPath}/`,
|
||||
fileName: `${componentBaseName}Component.js`,
|
||||
className: `${componentBaseName}Component`,
|
||||
suffix: '.js'
|
||||
},
|
||||
test: {
|
||||
path: `${testPath.path}/components/${componentPartPath}/`,
|
||||
fileName: `${componentBaseName}ComponentTest.js`
|
||||
}
|
||||
};
|
||||
|
||||
return settings;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a cleaned path name for a given path
|
||||
* @param {String} path
|
||||
* @param {String} suffix [optional]
|
||||
* @return {String}
|
||||
*/
|
||||
let getCleanedPathName = (path, suffix) => {
|
||||
|
||||
if(!suffix) {
|
||||
suffix = '';
|
||||
}
|
||||
|
||||
// If we have filesystem separators, use them to build the full path
|
||||
let pathArray = path.split('/');
|
||||
|
||||
// Build the full components name
|
||||
return pathArray.map((path) => {
|
||||
return _.camelize(_.slugify(_.humanize(path)));
|
||||
}).join('/') + _.capitalize(suffix);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the css/less/whatever style name to use
|
||||
* @param {String} path
|
||||
* @return {String}
|
||||
*/
|
||||
let getComponentStyleName = (path) => {
|
||||
let fileName = path.split('/').pop().toLowerCase();
|
||||
return _.slugify(_.humanize(fileName)) + '-component';
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a js friendly application name
|
||||
* @param {String} appName The input application name [optional]
|
||||
* @return {String}
|
||||
*/
|
||||
let getAppName = (appName) => {
|
||||
|
||||
// If appName is not given, use the current directory
|
||||
if(appName === undefined) {
|
||||
appName = getBaseDir();
|
||||
}
|
||||
|
||||
return _.camelize(_.slugify(_.humanize(appName)));
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
getBaseDir: getBaseDir,
|
||||
getAllSettingsFromComponentName: getAllSettingsFromComponentName,
|
||||
getAppName: getAppName,
|
||||
getCleanedPathName: getCleanedPathName,
|
||||
getComponentStyleName: getComponentStyleName
|
||||
};
|
||||
Reference in New Issue
Block a user