From 023d9378779be9d29ef7503f023a98aefb94ff6b Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 21 Sep 2015 20:45:57 +0200 Subject: [PATCH] Added changes for version 2.0 --- .eslintrc | 22 + .gitignore | 1 - .jshintrc | 21 - README.md | 416 +- a/index.js | 1 - action/index.js | 39 - app/index.js | 164 - app/templates/images/yeoman.png | Bin 13501 -> 0 bytes app/templates/styles/main.css | 41 - c/index.js | 1 - common/index.js | 17 - component/index.js | 25 - generators/app/index.js | 124 + generators/app/prompts.js | 18 + generators/component/index.js | 36 + .../component/templates/components/Base.js | 21 + .../component/templates}/styles/Component.css | 2 +- .../templates}/styles/Component.less | 2 +- .../templates}/styles/Component.sass | 2 +- .../templates}/styles/Component.scss | 2 +- .../templates}/styles/Component.styl | 2 +- generators/component/templates/tests/Base.js | 23 + main/index.js | 35 - package.json | 33 +- s/index.js | 1 - script-base.js | 118 - store/index.js | 42 - templates/common/Gruntfile.js | 125 - templates/common/_package.json | 52 - templates/common/_webpack.config.js | 75 - templates/common/_webpack.dist.config.js | 77 - templates/common/gitignore | 33 - templates/common/index.html | 23 - templates/common/karma.conf.js | 93 - templates/common/root/.editorconfig | 13 - templates/common/root/.eslintrc | 21 - templates/common/root/.jshintrc | 27 - templates/common/root/src/favicon.ico | Bin 4286 -> 0 bytes templates/common/root/test/.jshintrc | 40 - .../root/test/helpers/createComponent.js | 27 - .../root/test/helpers/pack/phantomjs-shims.js | 34 - .../common/root/test/helpers/react/addons.js | 16336 ---------------- templates/javascript/AltAction.js | 11 - templates/javascript/AltStore.js | 21 - templates/javascript/App.js | 26 - templates/javascript/Component.js | 36 - templates/javascript/Dispatcher.js | 3 - templates/javascript/FluxAction.js | 8 - templates/javascript/FluxStore.js | 20 - templates/javascript/RefluxAction.js | 11 - templates/javascript/RefluxStore.js | 14 - templates/javascript/alt.js | 4 - templates/javascript/main.js | 18 - templates/spec/Action.js | 13 - templates/spec/App.js | 19 - templates/spec/Component.js | 20 - templates/spec/Store.js | 13 - templates/spec/main.js | 14 - test/generators/app/indexTest.js | 97 + test/generators/component/indexTest.js | 283 + test/mocha.opts | 2 + test/test-creation.js | 342 - test/utils/configTest.js | 65 + test/utils/yeomanTest.js | 97 + util.js | 95 - utils/all.js | 9 + utils/config.js | 68 + utils/configopts.json | 84 + utils/yeoman.js | 122 + 69 files changed, 1149 insertions(+), 18551 deletions(-) create mode 100644 .eslintrc delete mode 100644 .jshintrc delete mode 100644 a/index.js delete mode 100644 action/index.js delete mode 100644 app/index.js delete mode 100644 app/templates/images/yeoman.png delete mode 100644 app/templates/styles/main.css delete mode 100644 c/index.js delete mode 100644 common/index.js delete mode 100644 component/index.js create mode 100644 generators/app/index.js create mode 100644 generators/app/prompts.js create mode 100644 generators/component/index.js create mode 100644 generators/component/templates/components/Base.js rename {templates => generators/component/templates}/styles/Component.css (52%) rename {templates => generators/component/templates}/styles/Component.less (52%) rename {templates => generators/component/templates}/styles/Component.sass (52%) rename {templates => generators/component/templates}/styles/Component.scss (52%) rename {templates => generators/component/templates}/styles/Component.styl (51%) create mode 100644 generators/component/templates/tests/Base.js delete mode 100644 main/index.js delete mode 100644 s/index.js delete mode 100644 script-base.js delete mode 100644 store/index.js delete mode 100644 templates/common/Gruntfile.js delete mode 100644 templates/common/_package.json delete mode 100644 templates/common/_webpack.config.js delete mode 100644 templates/common/_webpack.dist.config.js delete mode 100644 templates/common/gitignore delete mode 100644 templates/common/index.html delete mode 100644 templates/common/karma.conf.js delete mode 100644 templates/common/root/.editorconfig delete mode 100644 templates/common/root/.eslintrc delete mode 100644 templates/common/root/.jshintrc delete mode 100644 templates/common/root/src/favicon.ico delete mode 100644 templates/common/root/test/.jshintrc delete mode 100644 templates/common/root/test/helpers/createComponent.js delete mode 100644 templates/common/root/test/helpers/pack/phantomjs-shims.js delete mode 100755 templates/common/root/test/helpers/react/addons.js delete mode 100644 templates/javascript/AltAction.js delete mode 100644 templates/javascript/AltStore.js delete mode 100644 templates/javascript/App.js delete mode 100644 templates/javascript/Component.js delete mode 100644 templates/javascript/Dispatcher.js delete mode 100644 templates/javascript/FluxAction.js delete mode 100644 templates/javascript/FluxStore.js delete mode 100644 templates/javascript/RefluxAction.js delete mode 100644 templates/javascript/RefluxStore.js delete mode 100644 templates/javascript/alt.js delete mode 100644 templates/javascript/main.js delete mode 100644 templates/spec/Action.js delete mode 100644 templates/spec/App.js delete mode 100644 templates/spec/Component.js delete mode 100644 templates/spec/Store.js delete mode 100644 templates/spec/main.js create mode 100644 test/generators/app/indexTest.js create mode 100644 test/generators/component/indexTest.js create mode 100644 test/mocha.opts delete mode 100644 test/test-creation.js create mode 100644 test/utils/configTest.js create mode 100644 test/utils/yeomanTest.js delete mode 100644 util.js create mode 100644 utils/all.js create mode 100644 utils/config.js create mode 100644 utils/configopts.json create mode 100644 utils/yeoman.js diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..e7822e5 --- /dev/null +++ b/.eslintrc @@ -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 + } +} diff --git a/.gitignore b/.gitignore index 17d340a..7e8a112 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,3 @@ $RECYCLE.BIN/ node_modules/ npm-debug.log .idea/ -/test/temp-test diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index da64b6e..0000000 --- a/.jshintrc +++ /dev/null @@ -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 -} diff --git a/README.md b/README.md index 88b7e58..a763b10 100644 --- a/README.md +++ b/README.md @@ -1,359 +1,76 @@ -# generator-react-webpack [![Build Status](https://secure.travis-ci.org/newtriks/generator-react-webpack.png?branch=master)](https://travis-ci.org/newtriks/generator-react-webpack) [![Built with Grunt](https://cdn.gruntjs.com/builtwith.png)](http://gruntjs.com/) +# generator-react-webpack V2.0 [![Build Status](https://secure.travis-ci.org/newtriks/generator-react-webpack.png?branch=master)](https://travis-ci.org/newtriks/generator-react-webpack) [![Built with Grunt](https://cdn.gruntjs.com/builtwith.png)](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 ( -
-

Content for Foo

-
- ) - } -}); - -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 ( -
-

Content for Foofoo

-
- ); - } - }); - - 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 diff --git a/a/index.js b/a/index.js deleted file mode 100644 index eeffccf..0000000 --- a/a/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('../action'); diff --git a/action/index.js b/action/index.js deleted file mode 100644 index 228642b..0000000 --- a/action/index.js +++ /dev/null @@ -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' - ); -}; diff --git a/app/index.js b/app/index.js deleted file mode 100644 index 2fa6982..0000000 --- a/app/index.js +++ /dev/null @@ -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'); -}; diff --git a/app/templates/images/yeoman.png b/app/templates/images/yeoman.png deleted file mode 100644 index 92497addf96c5c009ac24007f55eb989f3bf74c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13501 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 diff --git a/app/templates/styles/main.css b/app/templates/styles/main.css deleted file mode 100644 index 321e9a1..0000000 --- a/app/templates/styles/main.css +++ /dev/null @@ -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; -} diff --git a/c/index.js b/c/index.js deleted file mode 100644 index d61f628..0000000 --- a/c/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('../component'); diff --git a/common/index.js b/common/index.js deleted file mode 100644 index 0452f1a..0000000 --- a/common/index.js +++ /dev/null @@ -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); -}; diff --git a/component/index.js b/component/index.js deleted file mode 100644 index 28223e5..0000000 --- a/component/index.js +++ /dev/null @@ -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 - ); -}; diff --git a/generators/app/index.js b/generators/app/index.js new file mode 100644 index 0000000..54de5ab --- /dev/null +++ b/generators/app/index.js @@ -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 }); + } + } +}); diff --git a/generators/app/prompts.js b/generators/app/prompts.js new file mode 100644 index 0000000..5c447ea --- /dev/null +++ b/generators/app/prompts.js @@ -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') + } +]; diff --git a/generators/component/index.js b/generators/component/index.js new file mode 100644 index 0000000..93fae40 --- /dev/null +++ b/generators/component/index.js @@ -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 + ); + } +}); diff --git a/generators/component/templates/components/Base.js b/generators/component/templates/components/Base.js new file mode 100644 index 0000000..27f20e6 --- /dev/null +++ b/generators/component/templates/components/Base.js @@ -0,0 +1,21 @@ +'use strict'; + +import React from 'react/addons'; + +require('<%= style.webpackPath %>'); + +class <%= component.className %> extends React.Component { + render() { + return ( +
+ Please edit <%= component.path %>/<%= component.fileName %> to update this component! +
+ ); + } +} + +// Uncomment properties you need +// <%= component.className %>.propTypes = {}; +// <%= component.className %>.defaultProps = {}; + +export default <%= component.className %>; diff --git a/templates/styles/Component.css b/generators/component/templates/styles/Component.css similarity index 52% rename from templates/styles/Component.css rename to generators/component/templates/styles/Component.css index 912c840..0a1af92 100644 --- a/templates/styles/Component.css +++ b/generators/component/templates/styles/Component.css @@ -1,3 +1,3 @@ -.<%= classedName %> { +.<%= style.className %> { border: 1px dashed #f00; } diff --git a/templates/styles/Component.less b/generators/component/templates/styles/Component.less similarity index 52% rename from templates/styles/Component.less rename to generators/component/templates/styles/Component.less index 912c840..0a1af92 100644 --- a/templates/styles/Component.less +++ b/generators/component/templates/styles/Component.less @@ -1,3 +1,3 @@ -.<%= classedName %> { +.<%= style.className %> { border: 1px dashed #f00; } diff --git a/templates/styles/Component.sass b/generators/component/templates/styles/Component.sass similarity index 52% rename from templates/styles/Component.sass rename to generators/component/templates/styles/Component.sass index 9811abb..9e9d772 100644 --- a/templates/styles/Component.sass +++ b/generators/component/templates/styles/Component.sass @@ -1,2 +1,2 @@ -.<%= classedName %> +.<%= style.className %> border: 1px dashed #f00 diff --git a/templates/styles/Component.scss b/generators/component/templates/styles/Component.scss similarity index 52% rename from templates/styles/Component.scss rename to generators/component/templates/styles/Component.scss index 912c840..0a1af92 100644 --- a/templates/styles/Component.scss +++ b/generators/component/templates/styles/Component.scss @@ -1,3 +1,3 @@ -.<%= classedName %> { +.<%= style.className %> { border: 1px dashed #f00; } diff --git a/templates/styles/Component.styl b/generators/component/templates/styles/Component.styl similarity index 51% rename from templates/styles/Component.styl rename to generators/component/templates/styles/Component.styl index 4cc329f..f37b496 100644 --- a/templates/styles/Component.styl +++ b/generators/component/templates/styles/Component.styl @@ -1,2 +1,2 @@ -.<%= classedName %> +.<%= style.className %> border 1px dashed #f00 diff --git a/generators/component/templates/tests/Base.js b/generators/component/templates/tests/Base.js new file mode 100644 index 0000000..4282623 --- /dev/null +++ b/generators/component/templates/tests/Base.js @@ -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 %>'); + }); +}); diff --git a/main/index.js b/main/index.js deleted file mode 100644 index 0317a5e..0000000 --- a/main/index.js +++ /dev/null @@ -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'); - } -}; diff --git a/package.json b/package.json index dcef9c6..06dc699 100644 --- a/package.json +++ b/package.json @@ -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" } diff --git a/s/index.js b/s/index.js deleted file mode 100644 index 4b2cf54..0000000 --- a/s/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('../store'); diff --git a/script-base.js b/script-base.js deleted file mode 100644 index 6d16036..0000000 --- a/script-base.js +++ /dev/null @@ -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))); -}; diff --git a/store/index.js b/store/index.js deleted file mode 100644 index 98db828..0000000 --- a/store/index.js +++ /dev/null @@ -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' - ); -}; diff --git a/templates/common/Gruntfile.js b/templates/common/Gruntfile.js deleted file mode 100644 index 0f61f8a..0000000 --- a/templates/common/Gruntfile.js +++ /dev/null @@ -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', []); -}; diff --git a/templates/common/_package.json b/templates/common/_package.json deleted file mode 100644 index 573c48d..0000000 --- a/templates/common/_package.json +++ /dev/null @@ -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" - } -} diff --git a/templates/common/_webpack.config.js b/templates/common/_webpack.config.js deleted file mode 100644 index 84d8810..0000000 --- a/templates/common/_webpack.config.js +++ /dev/null @@ -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() - ] - -}; diff --git a/templates/common/_webpack.dist.config.js b/templates/common/_webpack.dist.config.js deleted file mode 100644 index c502608..0000000 --- a/templates/common/_webpack.dist.config.js +++ /dev/null @@ -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' - }] - } -}; diff --git a/templates/common/gitignore b/templates/common/gitignore deleted file mode 100644 index ce592cc..0000000 --- a/templates/common/gitignore +++ /dev/null @@ -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 diff --git a/templates/common/index.html b/templates/common/index.html deleted file mode 100644 index 7d321af..0000000 --- a/templates/common/index.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - -
-

If you can see this, something is broken (or JS is not enabled)!!.

-
- - - - - diff --git a/templates/common/karma.conf.js b/templates/common/karma.conf.js deleted file mode 100644 index 5e0f0e4..0000000 --- a/templates/common/karma.conf.js +++ /dev/null @@ -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') - ] - }); -}; diff --git a/templates/common/root/.editorconfig b/templates/common/root/.editorconfig deleted file mode 100644 index c308ed0..0000000 --- a/templates/common/root/.editorconfig +++ /dev/null @@ -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 diff --git a/templates/common/root/.eslintrc b/templates/common/root/.eslintrc deleted file mode 100644 index 94df36a..0000000 --- a/templates/common/root/.eslintrc +++ /dev/null @@ -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 - } -} diff --git a/templates/common/root/.jshintrc b/templates/common/root/.jshintrc deleted file mode 100644 index 2f22258..0000000 --- a/templates/common/root/.jshintrc +++ /dev/null @@ -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 - } -} - diff --git a/templates/common/root/src/favicon.ico b/templates/common/root/src/favicon.ico deleted file mode 100644 index 6527905307f19ba00762f9241f7eb535fa84a2f9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4286 zcmchaPe@cz6vpqQW1y54B@{_hhFD-kWPgyXjSGVaf);_51TESOlSPOdvy}@W5Q+** zs6~RrtlR}7(V|sCkP&1f7!5{Hixw@4+x@+HXSm*Z^WGalm2d8S=brO@=iGm9MyZ7P zPo)%}YN|=8W~EfSfibDm2H3qnGq$y%h@zqVv#zn@@WvhIGJ8*ECePe@roq(*vwGys z4?Q;bI~MRIM&jXu6Yg@wqQ#8&8x#z55E}ONd3<&rw_h!5AbBx{CcZ%&z736jHxFa0 zsBLqly3+dQ%MZGH{QU}GW6bsq=@$a@sXtac^<8>8uP>*+d!Qdtv&&mnKlvE_T-+SC z*QNCVwcvq%+&DDc+T}Uf(2_FavDN{-&hCpIs?aW=A$mcrzyD+9(025i1~K&uVf&w4 zItQLK9T{7k?s@bnU*&p+<^UI*aHA1aH+Fo^PAzM|xjNK09?2V(Cme7IFB(BP?7#at z(>DB3w`AUFS~=(LUBdZ>v-SG4J~%Mrfj&05Z)oj13l5tbEq4x>8+;FC0Dvr zbJY#7PS$+yE_Cf7gxqQEC@RoZX5J^}71l+`Q~qnOF4D za`lhjUuqZa-sj)EHDleV2i|mc!Ly-@7IwzPM{?pBUt(+@IHi8HTz#Iq9)9h|hrL3) zfOT#@|5$JCxmRjsOj>&kUt(m8*57|W(FoE`CX*8edYv%j=3sR5>!hvglJ#@8K6j$g z&IuUbRC_{)p}sbyx%UD6Fki;t6nDk0gT5&6Q_at7FbVVOu?4VK{oR#!kyYbCc;<4+LITzoZ8-~O5L+9MiLHL4NyME>! z;Ky7<)UR!gN_~GXhMvPMHNB;EmmIK}eHD&~cRx89jth}IM#tU%ablw0|GxfE9IjRR zl-)b-IvC#UD!IewzPL77SI>R+?}<2ERr|R2o~zCC8rJUR8>DI5*0O$6+k~wZ)Mt;b z(Hul-OFl+F))}lK&&Yi*+S2kJmHDbdBWOQnaSA6S|#* 1 ? children : children[0])); - return shallowRenderer.getRenderOutput(); -} diff --git a/templates/common/root/test/helpers/pack/phantomjs-shims.js b/templates/common/root/test/helpers/pack/phantomjs-shims.js deleted file mode 100644 index 7da307d..0000000 --- a/templates/common/root/test/helpers/pack/phantomjs-shims.js +++ /dev/null @@ -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; - }; -} -})(); diff --git a/templates/common/root/test/helpers/react/addons.js b/templates/common/root/test/helpers/react/addons.js deleted file mode 100755 index 0bf44fe..0000000 --- a/templates/common/root/test/helpers/react/addons.js +++ /dev/null @@ -1,16336 +0,0 @@ -/** - * React (with addons) v0.9.0-alpha - */ -!function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.React=e():"undefined"!=typeof global?global.React=e():"undefined"!=typeof self&&(self.React=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o -1; -} - -var CSSCore = { - - /** - * Adds the class passed in to the element if it doesn't already have it. - * - * @param {DOMElement} element the element to set the class on - * @param {string} className the CSS className - * @return {DOMElement} the element passed in - */ - addClass: function(element, className) { - ("production" !== "development" ? invariant( - !/\s/.test(className), - 'CSSCore.addClass takes only a single class name. "%s" contains ' + - 'multiple classes.', className - ) : invariant(!/\s/.test(className))); - - if (className) { - if (element.classList) { - element.classList.add(className); - } else if (!hasClass(element, className)) { - element.className = element.className + ' ' + className; - } - } - return element; - }, - - /** - * Removes the class passed in from the element - * - * @param {DOMElement} element the element to set the class on - * @param {string} className the CSS className - * @return {DOMElement} the element passed in - */ - removeClass: function(element, className) { - ("production" !== "development" ? invariant( - !/\s/.test(className), - 'CSSCore.removeClass takes only a single class name. "%s" contains ' + - 'multiple classes.', className - ) : invariant(!/\s/.test(className))); - - if (className) { - if (element.classList) { - element.classList.remove(className); - } else if (hasClass(element, className)) { - element.className = element.className - .replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)', 'g'), '$1') - .replace(/\s+/g, ' ') // multiple spaces to one - .replace(/^\s*|\s*$/g, ''); // trim the ends - } - } - return element; - }, - - /** - * Helper to add or remove a class from an element based on a condition. - * - * @param {DOMElement} element the element to set the class on - * @param {string} className the CSS className - * @param {*} bool condition to whether to add or remove the class - * @return {DOMElement} the element passed in - */ - conditionClass: function(element, className, bool) { - return (bool ? CSSCore.addClass : CSSCore.removeClass)(element, className); - } -}; - -module.exports = CSSCore; - -},{"./invariant":113}],3:[function(require,module,exports){ -/** - * Copyright 2013 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @providesModule CSSProperty - */ - -"use strict"; - -/** - * CSS properties which accept numbers but are not in units of "px". - */ -var isUnitlessNumber = { - fillOpacity: true, - fontWeight: true, - lineHeight: true, - opacity: true, - orphans: true, - zIndex: true, - zoom: true -}; - -/** - * Most style properties can be unset by doing .style[prop] = '' but IE8 - * doesn't like doing that with shorthand properties so for the properties that - * IE8 breaks on, which are listed here, we instead unset each of the - * individual properties. See http://bugs.jquery.com/ticket/12385. - * The 4-value 'clock' properties like margin, padding, border-width seem to - * behave without any problems. Curiously, list-style works too without any - * special prodding. - */ -var shorthandPropertyExpansions = { - background: { - backgroundImage: true, - backgroundPosition: true, - backgroundRepeat: true, - backgroundColor: true - }, - border: { - borderWidth: true, - borderStyle: true, - borderColor: true - }, - borderBottom: { - borderBottomWidth: true, - borderBottomStyle: true, - borderBottomColor: true - }, - borderLeft: { - borderLeftWidth: true, - borderLeftStyle: true, - borderLeftColor: true - }, - borderRight: { - borderRightWidth: true, - borderRightStyle: true, - borderRightColor: true - }, - borderTop: { - borderTopWidth: true, - borderTopStyle: true, - borderTopColor: true - }, - font: { - fontStyle: true, - fontVariant: true, - fontWeight: true, - fontSize: true, - lineHeight: true, - fontFamily: true - } -}; - -var CSSProperty = { - isUnitlessNumber: isUnitlessNumber, - shorthandPropertyExpansions: shorthandPropertyExpansions -}; - -module.exports = CSSProperty; - -},{}],4:[function(require,module,exports){ -/** - * Copyright 2013 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @providesModule CSSPropertyOperations - * @typechecks static-only - */ - -"use strict"; - -var CSSProperty = require("./CSSProperty"); - -var dangerousStyleValue = require("./dangerousStyleValue"); -var escapeTextForBrowser = require("./escapeTextForBrowser"); -var hyphenate = require("./hyphenate"); -var memoizeStringOnly = require("./memoizeStringOnly"); - -var processStyleName = memoizeStringOnly(function(styleName) { - return escapeTextForBrowser(hyphenate(styleName)); -}); - -/** - * Operations for dealing with CSS properties. - */ -var CSSPropertyOperations = { - - /** - * Serializes a mapping of style properties for use as inline styles: - * - * > createMarkupForStyles({width: '200px', height: 0}) - * "width:200px;height:0;" - * - * Undefined values are ignored so that declarative programming is easier. - * - * @param {object} styles - * @return {?string} - */ - createMarkupForStyles: function(styles) { - var serialized = ''; - for (var styleName in styles) { - if (!styles.hasOwnProperty(styleName)) { - continue; - } - var styleValue = styles[styleName]; - if (styleValue != null) { - serialized += processStyleName(styleName) + ':'; - serialized += dangerousStyleValue(styleName, styleValue) + ';'; - } - } - return serialized || null; - }, - - /** - * Sets the value for multiple styles on a node. If a value is specified as - * '' (empty string), the corresponding style property will be unset. - * - * @param {DOMElement} node - * @param {object} styles - */ - setValueForStyles: function(node, styles) { - var style = node.style; - for (var styleName in styles) { - if (!styles.hasOwnProperty(styleName)) { - continue; - } - var styleValue = dangerousStyleValue(styleName, styles[styleName]); - if (styleValue) { - style[styleName] = styleValue; - } else { - var expansion = CSSProperty.shorthandPropertyExpansions[styleName]; - if (expansion) { - // Shorthand property that IE8 won't like unsetting, so unset each - // component to placate it - for (var individualStyleName in expansion) { - style[individualStyleName] = ''; - } - } else { - style[styleName] = ''; - } - } - } - } - -}; - -module.exports = CSSPropertyOperations; - -},{"./CSSProperty":3,"./dangerousStyleValue":97,"./escapeTextForBrowser":99,"./hyphenate":112,"./memoizeStringOnly":121}],5:[function(require,module,exports){ -/** - * Copyright 2013 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @providesModule CallbackRegistry - * @typechecks static-only - */ - -"use strict"; - -var listenerBank = {}; - -/** - * Stores "listeners" by `registrationName`/`id`. There should be at most one - * "listener" per `registrationName`/`id` in the `listenerBank`. - * - * Access listeners via `listenerBank[registrationName][id]`. - * - * @class CallbackRegistry - * @internal - */ -var CallbackRegistry = { - - /** - * Stores `listener` at `listenerBank[registrationName][id]`. Is idempotent. - * - * @param {string} id ID of the DOM element. - * @param {string} registrationName Name of listener (e.g. `onClick`). - * @param {?function} listener The callback to store. - */ - putListener: function(id, registrationName, listener) { - var bankForRegistrationName = - listenerBank[registrationName] || (listenerBank[registrationName] = {}); - bankForRegistrationName[id] = listener; - }, - - /** - * @param {string} id ID of the DOM element. - * @param {string} registrationName Name of listener (e.g. `onClick`). - * @return {?function} The stored callback. - */ - getListener: function(id, registrationName) { - var bankForRegistrationName = listenerBank[registrationName]; - return bankForRegistrationName && bankForRegistrationName[id]; - }, - - /** - * Deletes a listener from the registration bank. - * - * @param {string} id ID of the DOM element. - * @param {string} registrationName Name of listener (e.g. `onClick`). - */ - deleteListener: function(id, registrationName) { - var bankForRegistrationName = listenerBank[registrationName]; - if (bankForRegistrationName) { - delete bankForRegistrationName[id]; - } - }, - - /** - * Deletes all listeners for the DOM element with the supplied ID. - * - * @param {string} id ID of the DOM element. - */ - deleteAllListeners: function(id) { - for (var registrationName in listenerBank) { - delete listenerBank[registrationName][id]; - } - }, - - /** - * This is needed for tests only. Do not use! - */ - __purge: function() { - listenerBank = {}; - } - -}; - -module.exports = CallbackRegistry; - -},{}],6:[function(require,module,exports){ -/** - * Copyright 2013 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @providesModule ChangeEventPlugin - */ - -"use strict"; - -var EventConstants = require("./EventConstants"); -var EventPluginHub = require("./EventPluginHub"); -var EventPropagators = require("./EventPropagators"); -var ExecutionEnvironment = require("./ExecutionEnvironment"); -var SyntheticEvent = require("./SyntheticEvent"); - -var isEventSupported = require("./isEventSupported"); -var isTextInputElement = require("./isTextInputElement"); -var keyOf = require("./keyOf"); - -var topLevelTypes = EventConstants.topLevelTypes; - -var eventTypes = { - change: { - phasedRegistrationNames: { - bubbled: keyOf({onChange: null}), - captured: keyOf({onChangeCapture: null}) - } - } -}; - -/** - * For IE shims - */ -var activeElement = null; -var activeElementID = null; -var activeElementValue = null; -var activeElementValueProp = null; - -/** - * SECTION: handle `change` event - */ -function shouldUseChangeEvent(elem) { - return ( - elem.nodeName === 'SELECT' || - (elem.nodeName === 'INPUT' && elem.type === 'file') - ); -} - -var doesChangeEventBubble = false; -if (ExecutionEnvironment.canUseDOM) { - // See `handleChange` comment below - doesChangeEventBubble = isEventSupported('change') && ( - !('documentMode' in document) || document.documentMode > 8 - ); -} - -function manualDispatchChangeEvent(nativeEvent) { - var event = SyntheticEvent.getPooled( - eventTypes.change, - activeElementID, - nativeEvent - ); - EventPropagators.accumulateTwoPhaseDispatches(event); - - // If change bubbled, we'd just bind to it like all the other events - // and have it go through ReactEventTopLevelCallback. Since it doesn't, we - // manually listen for the change event and so we have to enqueue and - // process the abstract event manually. - EventPluginHub.enqueueEvents(event); - EventPluginHub.processEventQueue(); -} - -function startWatchingForChangeEventIE8(target, targetID) { - activeElement = target; - activeElementID = targetID; - activeElement.attachEvent('onchange', manualDispatchChangeEvent); -} - -function stopWatchingForChangeEventIE8() { - if (!activeElement) { - return; - } - activeElement.detachEvent('onchange', manualDispatchChangeEvent); - activeElement = null; - activeElementID = null; -} - -function getTargetIDForChangeEvent( - topLevelType, - topLevelTarget, - topLevelTargetID) { - if (topLevelType === topLevelTypes.topChange) { - return topLevelTargetID; - } -} -function handleEventsForChangeEventIE8( - topLevelType, - topLevelTarget, - topLevelTargetID) { - if (topLevelType === topLevelTypes.topFocus) { - // stopWatching() should be a noop here but we call it just in case we - // missed a blur event somehow. - stopWatchingForChangeEventIE8(); - startWatchingForChangeEventIE8(topLevelTarget, topLevelTargetID); - } else if (topLevelType === topLevelTypes.topBlur) { - stopWatchingForChangeEventIE8(); - } -} - - -/** - * SECTION: handle `input` event - */ -var isInputEventSupported = false; -if (ExecutionEnvironment.canUseDOM) { - // IE9 claims to support the input event but fails to trigger it when - // deleting text, so we ignore its input events - isInputEventSupported = isEventSupported('input') && ( - !('documentMode' in document) || document.documentMode > 9 - ); -} - -/** - * (For old IE.) Replacement getter/setter for the `value` property that gets - * set on the active element. - */ -var newValueProp = { - get: function() { - return activeElementValueProp.get.call(this); - }, - set: function(val) { - // Cast to a string so we can do equality checks. - activeElementValue = '' + val; - activeElementValueProp.set.call(this, val); - } -}; - -/** - * (For old IE.) Starts tracking propertychange events on the passed-in element - * and override the value property so that we can distinguish user events from - * value changes in JS. - */ -function startWatchingForValueChange(target, targetID) { - activeElement = target; - activeElementID = targetID; - activeElementValue = target.value; - activeElementValueProp = Object.getOwnPropertyDescriptor( - target.constructor.prototype, - 'value' - ); - - Object.defineProperty(activeElement, 'value', newValueProp); - activeElement.attachEvent('onpropertychange', handlePropertyChange); -} - -/** - * (For old IE.) Removes the event listeners from the currently-tracked element, - * if any exists. - */ -function stopWatchingForValueChange() { - if (!activeElement) { - return; - } - - // delete restores the original property definition - delete activeElement.value; - activeElement.detachEvent('onpropertychange', handlePropertyChange); - - activeElement = null; - activeElementID = null; - activeElementValue = null; - activeElementValueProp = null; -} - -/** - * (For old IE.) Handles a propertychange event, sending a `change` event if - * the value of the active element has changed. - */ -function handlePropertyChange(nativeEvent) { - if (nativeEvent.propertyName !== 'value') { - return; - } - var value = nativeEvent.srcElement.value; - if (value === activeElementValue) { - return; - } - activeElementValue = value; - - manualDispatchChangeEvent(nativeEvent); -} - -/** - * If a `change` event should be fired, returns the target's ID. - */ -function getTargetIDForInputEvent( - topLevelType, - topLevelTarget, - topLevelTargetID) { - if (topLevelType === topLevelTypes.topInput) { - // In modern browsers (i.e., not IE8 or IE9), the input event is exactly - // what we want so fall through here and trigger an abstract event - return topLevelTargetID; - } -} - -// For IE8 and IE9. -function handleEventsForInputEventIE( - topLevelType, - topLevelTarget, - topLevelTargetID) { - if (topLevelType === topLevelTypes.topFocus) { - // In IE8, we can capture almost all .value changes by adding a - // propertychange handler and looking for events with propertyName - // equal to 'value' - // In IE9, propertychange fires for most input events but is buggy and - // doesn't fire when text is deleted, but conveniently, selectionchange - // appears to fire in all of the remaining cases so we catch those and - // forward the event if the value has changed - // In either case, we don't want to call the event handler if the value - // is changed from JS so we redefine a setter for `.value` that updates - // our activeElementValue variable, allowing us to ignore those changes - // - // stopWatching() should be a noop here but we call it just in case we - // missed a blur event somehow. - stopWatchingForValueChange(); - startWatchingForValueChange(topLevelTarget, topLevelTargetID); - } else if (topLevelType === topLevelTypes.topBlur) { - stopWatchingForValueChange(); - } -} - -// For IE8 and IE9. -function getTargetIDForInputEventIE( - topLevelType, - topLevelTarget, - topLevelTargetID) { - if (topLevelType === topLevelTypes.topSelectionChange || - topLevelType === topLevelTypes.topKeyUp || - topLevelType === topLevelTypes.topKeyDown) { - // On the selectionchange event, the target is just document which isn't - // helpful for us so just check activeElement instead. - // - // 99% of the time, keydown and keyup aren't necessary. IE8 fails to fire - // propertychange on the first input event after setting `value` from a - // script and fires only keydown, keypress, keyup. Catching keyup usually - // gets it and catching keydown lets us fire an event for the first - // keystroke if user does a key repeat (it'll be a little delayed: right - // before the second keystroke). Other input methods (e.g., paste) seem to - // fire selectionchange normally. - if (activeElement && activeElement.value !== activeElementValue) { - activeElementValue = activeElement.value; - return activeElementID; - } - } -} - - -/** - * SECTION: handle `click` event - */ -function shouldUseClickEvent(elem) { - // Use the `click` event to detect changes to checkbox and radio inputs. - // This approach works across all browsers, whereas `change` does not fire - // until `blur` in IE8. - return ( - elem.nodeName === 'INPUT' && - (elem.type === 'checkbox' || elem.type === 'radio') - ); -} - -function getTargetIDForClickEvent( - topLevelType, - topLevelTarget, - topLevelTargetID) { - if (topLevelType === topLevelTypes.topClick) { - return topLevelTargetID; - } -} - -/** - * This plugin creates an `onChange` event that normalizes change events - * across form elements. This event fires at a time when it's possible to - * change the element's value without seeing a flicker. - * - * Supported elements are: - * - input (see `isTextInputElement`) - * - textarea - * - select - */ -var ChangeEventPlugin = { - - eventTypes: eventTypes, - - /** - * @param {string} topLevelType Record from `EventConstants`. - * @param {DOMEventTarget} topLevelTarget The listening component root node. - * @param {string} topLevelTargetID ID of `topLevelTarget`. - * @param {object} nativeEvent Native browser event. - * @return {*} An accumulation of synthetic events. - * @see {EventPluginHub.extractEvents} - */ - extractEvents: function( - topLevelType, - topLevelTarget, - topLevelTargetID, - nativeEvent) { - - var getTargetIDFunc, handleEventFunc; - if (shouldUseChangeEvent(topLevelTarget)) { - if (doesChangeEventBubble) { - getTargetIDFunc = getTargetIDForChangeEvent; - } else { - handleEventFunc = handleEventsForChangeEventIE8; - } - } else if (isTextInputElement(topLevelTarget)) { - if (isInputEventSupported) { - getTargetIDFunc = getTargetIDForInputEvent; - } else { - getTargetIDFunc = getTargetIDForInputEventIE; - handleEventFunc = handleEventsForInputEventIE; - } - } else if (shouldUseClickEvent(topLevelTarget)) { - getTargetIDFunc = getTargetIDForClickEvent; - } - - if (getTargetIDFunc) { - var targetID = getTargetIDFunc( - topLevelType, - topLevelTarget, - topLevelTargetID - ); - if (targetID) { - var event = SyntheticEvent.getPooled( - eventTypes.change, - targetID, - nativeEvent - ); - EventPropagators.accumulateTwoPhaseDispatches(event); - return event; - } - } - - if (handleEventFunc) { - handleEventFunc( - topLevelType, - topLevelTarget, - topLevelTargetID - ); - } - } - -}; - -module.exports = ChangeEventPlugin; - -},{"./EventConstants":15,"./EventPluginHub":17,"./EventPropagators":20,"./ExecutionEnvironment":21,"./SyntheticEvent":80,"./isEventSupported":114,"./isTextInputElement":116,"./keyOf":120}],7:[function(require,module,exports){ -/** - * Copyright 2013 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @providesModule CompositionEventPlugin - * @typechecks static-only - */ - -"use strict"; - -var EventConstants = require("./EventConstants"); -var EventPropagators = require("./EventPropagators"); -var ExecutionEnvironment = require("./ExecutionEnvironment"); -var ReactInputSelection = require("./ReactInputSelection"); -var SyntheticCompositionEvent = require("./SyntheticCompositionEvent"); - -var getTextContentAccessor = require("./getTextContentAccessor"); -var keyOf = require("./keyOf"); - -var END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space -var START_KEYCODE = 229; - -var useCompositionEvent = ExecutionEnvironment.canUseDOM && - 'CompositionEvent' in window; -var topLevelTypes = EventConstants.topLevelTypes; -var currentComposition = null; - -// Events and their corresponding property names. -var eventTypes = { - compositionEnd: { - phasedRegistrationNames: { - bubbled: keyOf({onCompositionEnd: null}), - captured: keyOf({onCompositionEndCapture: null}) - } - }, - compositionStart: { - phasedRegistrationNames: { - bubbled: keyOf({onCompositionStart: null}), - captured: keyOf({onCompositionStartCapture: null}) - } - }, - compositionUpdate: { - phasedRegistrationNames: { - bubbled: keyOf({onCompositionUpdate: null}), - captured: keyOf({onCompositionUpdateCapture: null}) - } - } -}; - -/** - * Translate native top level events into event types. - * - * @param {string} topLevelType - * @return {object} - */ -function getCompositionEventType(topLevelType) { - switch (topLevelType) { - case topLevelTypes.topCompositionStart: - return eventTypes.compositionStart; - case topLevelTypes.topCompositionEnd: - return eventTypes.compositionEnd; - case topLevelTypes.topCompositionUpdate: - return eventTypes.compositionUpdate; - } -} - -/** - * Does our fallback best-guess model think this event signifies that - * composition has begun? - * - * @param {string} topLevelType - * @param {object} nativeEvent - * @return {boolean} - */ -function isFallbackStart(topLevelType, nativeEvent) { - return ( - topLevelType === topLevelTypes.topKeyDown && - nativeEvent.keyCode === START_KEYCODE - ); -} - -/** - * Does our fallback mode think that this event is the end of composition? - * - * @param {string} topLevelType - * @param {object} nativeEvent - * @return {boolean} - */ -function isFallbackEnd(topLevelType, nativeEvent) { - switch (topLevelType) { - case topLevelTypes.topKeyUp: - // Command keys insert or clear IME input. - return (END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1); - case topLevelTypes.topKeyDown: - // Expect IME keyCode on each keydown. If we get any other - // code we must have exited earlier. - return (nativeEvent.keyCode !== START_KEYCODE); - case topLevelTypes.topKeyPress: - case topLevelTypes.topMouseDown: - case topLevelTypes.topBlur: - // Events are not possible without cancelling IME. - return true; - default: - return false; - } -} - -/** - * Helper class stores information about selection and document state - * so we can figure out what changed at a later date. - * - * @param {DOMEventTarget} root - */ -function FallbackCompositionState(root) { - this.root = root; - this.startSelection = ReactInputSelection.getSelection(root); - this.startValue = this.getText(); -} - -/** - * Get current text of input. - * - * @return {string} - */ -FallbackCompositionState.prototype.getText = function() { - return this.root.value || this.root[getTextContentAccessor()]; -}; - -/** - * Text that has changed since the start of composition. - * - * @return {string} - */ -FallbackCompositionState.prototype.getData = function() { - var endValue = this.getText(); - var prefixLength = this.startSelection.start; - var suffixLength = this.startValue.length - this.startSelection.end; - - return endValue.substr( - prefixLength, - endValue.length - suffixLength - prefixLength - ); -}; - -/** - * This plugin creates `onCompositionStart`, `onCompositionUpdate` and - * `onCompositionEnd` events on inputs, textareas and contentEditable - * nodes. - */ -var CompositionEventPlugin = { - - eventTypes: eventTypes, - - /** - * @param {string} topLevelType Record from `EventConstants`. - * @param {DOMEventTarget} topLevelTarget The listening component root node. - * @param {string} topLevelTargetID ID of `topLevelTarget`. - * @param {object} nativeEvent Native browser event. - * @return {*} An accumulation of synthetic events. - * @see {EventPluginHub.extractEvents} - */ - extractEvents: function( - topLevelType, - topLevelTarget, - topLevelTargetID, - nativeEvent) { - - var eventType; - var data; - - if (useCompositionEvent) { - eventType = getCompositionEventType(topLevelType); - } else if (!currentComposition) { - if (isFallbackStart(topLevelType, nativeEvent)) { - eventType = eventTypes.start; - currentComposition = new FallbackCompositionState(topLevelTarget); - } - } else if (isFallbackEnd(topLevelType, nativeEvent)) { - eventType = eventTypes.compositionEnd; - data = currentComposition.getData(); - currentComposition = null; - } - - if (eventType) { - var event = SyntheticCompositionEvent.getPooled( - eventType, - topLevelTargetID, - nativeEvent - ); - if (data) { - // Inject data generated from fallback path into the synthetic event. - // This matches the property of native CompositionEventInterface. - event.data = data; - } - EventPropagators.accumulateTwoPhaseDispatches(event); - return event; - } - } -}; - -module.exports = CompositionEventPlugin; - -},{"./EventConstants":15,"./EventPropagators":20,"./ExecutionEnvironment":21,"./ReactInputSelection":51,"./SyntheticCompositionEvent":79,"./getTextContentAccessor":110,"./keyOf":120}],8:[function(require,module,exports){ -/** - * Copyright 2013 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @providesModule DOMChildrenOperations - * @typechecks static-only - */ - -"use strict"; - -var Danger = require("./Danger"); -var ReactMultiChildUpdateTypes = require("./ReactMultiChildUpdateTypes"); - -var getTextContentAccessor = require("./getTextContentAccessor"); - -/** - * The DOM property to use when setting text content. - * - * @type {string} - * @private - */ -var textContentAccessor = getTextContentAccessor() || 'NA'; - -/** - * Inserts `childNode` as a child of `parentNode` at the `index`. - * - * @param {DOMElement} parentNode Parent node in which to insert. - * @param {DOMElement} childNode Child node to insert. - * @param {number} index Index at which to insert the child. - * @internal - */ -function insertChildAt(parentNode, childNode, index) { - var childNodes = parentNode.childNodes; - if (childNodes[index] === childNode) { - return; - } - // If `childNode` is already a child of `parentNode`, remove it so that - // computing `childNodes[index]` takes into account the removal. - if (childNode.parentNode === parentNode) { - parentNode.removeChild(childNode); - } - if (index >= childNodes.length) { - parentNode.appendChild(childNode); - } else { - parentNode.insertBefore(childNode, childNodes[index]); - } -} - -/** - * Operations for updating with DOM children. - */ -var DOMChildrenOperations = { - - dangerouslyReplaceNodeWithMarkup: Danger.dangerouslyReplaceNodeWithMarkup, - - /** - * Updates a component's children by processing a series of updates. The - * update configurations are each expected to have a `parentNode` property. - * - * @param {array} updates List of update configurations. - * @param {array} markupList List of markup strings. - * @internal - */ - processUpdates: function(updates, markupList) { - var update; - // Mapping from parent IDs to initial child orderings. - var initialChildren = null; - // List of children that will be moved or removed. - var updatedChildren = null; - - for (var i = 0; update = updates[i]; i++) { - if (update.type === ReactMultiChildUpdateTypes.MOVE_EXISTING || - update.type === ReactMultiChildUpdateTypes.REMOVE_NODE) { - var updatedIndex = update.fromIndex; - var updatedChild = update.parentNode.childNodes[updatedIndex]; - var parentID = update.parentID; - - initialChildren = initialChildren || {}; - initialChildren[parentID] = initialChildren[parentID] || []; - initialChildren[parentID][updatedIndex] = updatedChild; - - updatedChildren = updatedChildren || []; - updatedChildren.push(updatedChild); - } - } - - var renderedMarkup = Danger.dangerouslyRenderMarkup(markupList); - - // Remove updated children first so that `toIndex` is consistent. - if (updatedChildren) { - for (var j = 0; j < updatedChildren.length; j++) { - updatedChildren[j].parentNode.removeChild(updatedChildren[j]); - } - } - - for (var k = 0; update = updates[k]; k++) { - switch (update.type) { - case ReactMultiChildUpdateTypes.INSERT_MARKUP: - insertChildAt( - update.parentNode, - renderedMarkup[update.markupIndex], - update.toIndex - ); - break; - case ReactMultiChildUpdateTypes.MOVE_EXISTING: - insertChildAt( - update.parentNode, - initialChildren[update.parentID][update.fromIndex], - update.toIndex - ); - break; - case ReactMultiChildUpdateTypes.TEXT_CONTENT: - update.parentNode[textContentAccessor] = update.textContent; - break; - case ReactMultiChildUpdateTypes.REMOVE_NODE: - // Already removed by the for-loop above. - break; - } - } - } - -}; - -module.exports = DOMChildrenOperations; - -},{"./Danger":11,"./ReactMultiChildUpdateTypes":58,"./getTextContentAccessor":110}],9:[function(require,module,exports){ -/** - * Copyright 2013 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @providesModule DOMProperty - * @typechecks static-only - */ - -/*jslint bitwise: true */ - -"use strict"; - -var invariant = require("./invariant"); - -var DOMPropertyInjection = { - /** - * Mapping from normalized, camelcased property names to a configuration that - * specifies how the associated DOM property should be accessed or rendered. - */ - MUST_USE_ATTRIBUTE: 0x1, - MUST_USE_PROPERTY: 0x2, - HAS_SIDE_EFFECTS: 0x4, - HAS_BOOLEAN_VALUE: 0x8, - HAS_POSITIVE_NUMERIC_VALUE: 0x10, - - /** - * Inject some specialized knowledge about the DOM. This takes a config object - * with the following properties: - * - * isCustomAttribute: function that given an attribute name will return true - * if it can be inserted into the DOM verbatim. Useful for data-* or aria-* - * attributes where it's impossible to enumerate all of the possible - * attribute names, - * - * Properties: object mapping DOM property name to one of the - * DOMPropertyInjection constants or null. If your attribute isn't in here, - * it won't get written to the DOM. - * - * DOMAttributeNames: object mapping React attribute name to the DOM - * attribute name. Attribute names not specified use the **lowercase** - * normalized name. - * - * DOMPropertyNames: similar to DOMAttributeNames but for DOM properties. - * Property names not specified use the normalized name. - * - * DOMMutationMethods: Properties that require special mutation methods. If - * `value` is undefined, the mutation method should unset the property. - * - * @param {object} domPropertyConfig the config as described above. - */ - injectDOMPropertyConfig: function(domPropertyConfig) { - var Properties = domPropertyConfig.Properties || {}; - var DOMAttributeNames = domPropertyConfig.DOMAttributeNames || {}; - var DOMPropertyNames = domPropertyConfig.DOMPropertyNames || {}; - var DOMMutationMethods = domPropertyConfig.DOMMutationMethods || {}; - - if (domPropertyConfig.isCustomAttribute) { - DOMProperty._isCustomAttributeFunctions.push( - domPropertyConfig.isCustomAttribute - ); - } - - for (var propName in Properties) { - ("production" !== "development" ? invariant( - !DOMProperty.isStandardName[propName], - 'injectDOMPropertyConfig(...): You\'re trying to inject DOM property ' + - '\'%s\' which has already been injected. You may be accidentally ' + - 'injecting the same DOM property config twice, or you may be ' + - 'injecting two configs that have conflicting property names.', - propName - ) : invariant(!DOMProperty.isStandardName[propName])); - - DOMProperty.isStandardName[propName] = true; - - var lowerCased = propName.toLowerCase(); - DOMProperty.getPossibleStandardName[lowerCased] = propName; - - var attributeName = DOMAttributeNames[propName]; - if (attributeName) { - DOMProperty.getPossibleStandardName[attributeName] = propName; - } - - DOMProperty.getAttributeName[propName] = attributeName || lowerCased; - - DOMProperty.getPropertyName[propName] = - DOMPropertyNames[propName] || propName; - - var mutationMethod = DOMMutationMethods[propName]; - if (mutationMethod) { - DOMProperty.getMutationMethod[propName] = mutationMethod; - } - - var propConfig = Properties[propName]; - DOMProperty.mustUseAttribute[propName] = - propConfig & DOMPropertyInjection.MUST_USE_ATTRIBUTE; - DOMProperty.mustUseProperty[propName] = - propConfig & DOMPropertyInjection.MUST_USE_PROPERTY; - DOMProperty.hasSideEffects[propName] = - propConfig & DOMPropertyInjection.HAS_SIDE_EFFECTS; - DOMProperty.hasBooleanValue[propName] = - propConfig & DOMPropertyInjection.HAS_BOOLEAN_VALUE; - DOMProperty.hasPositiveNumericValue[propName] = - propConfig & DOMPropertyInjection.HAS_POSITIVE_NUMERIC_VALUE; - - ("production" !== "development" ? invariant( - !DOMProperty.mustUseAttribute[propName] || - !DOMProperty.mustUseProperty[propName], - 'DOMProperty: Cannot require using both attribute and property: %s', - propName - ) : invariant(!DOMProperty.mustUseAttribute[propName] || - !DOMProperty.mustUseProperty[propName])); - ("production" !== "development" ? invariant( - DOMProperty.mustUseProperty[propName] || - !DOMProperty.hasSideEffects[propName], - 'DOMProperty: Properties that have side effects must use property: %s', - propName - ) : invariant(DOMProperty.mustUseProperty[propName] || - !DOMProperty.hasSideEffects[propName])); - ("production" !== "development" ? invariant( - !DOMProperty.hasBooleanValue[propName] || - !DOMProperty.hasPositiveNumericValue[propName], - 'DOMProperty: Cannot have both boolean and positive numeric value: %s', - propName - ) : invariant(!DOMProperty.hasBooleanValue[propName] || - !DOMProperty.hasPositiveNumericValue[propName])); - } - } -}; -var defaultValueCache = {}; - -/** - * DOMProperty exports lookup objects that can be used like functions: - * - * > DOMProperty.isValid['id'] - * true - * > DOMProperty.isValid['foobar'] - * undefined - * - * Although this may be confusing, it performs better in general. - * - * @see http://jsperf.com/key-exists - * @see http://jsperf.com/key-missing - */ -var DOMProperty = { - - /** - * Checks whether a property name is a standard property. - * @type {Object} - */ - isStandardName: {}, - - /** - * Mapping from lowercase property names to the properly cased version, used - * to warn in the case of missing properties. - * @type {Object} - */ - getPossibleStandardName: {}, - - /** - * Mapping from normalized names to attribute names that differ. Attribute - * names are used when rendering markup or with `*Attribute()`. - * @type {Object} - */ - getAttributeName: {}, - - /** - * Mapping from normalized names to properties on DOM node instances. - * (This includes properties that mutate due to external factors.) - * @type {Object} - */ - getPropertyName: {}, - - /** - * Mapping from normalized names to mutation methods. This will only exist if - * mutation cannot be set simply by the property or `setAttribute()`. - * @type {Object} - */ - getMutationMethod: {}, - - /** - * Whether the property must be accessed and mutated as an object property. - * @type {Object} - */ - mustUseAttribute: {}, - - /** - * Whether the property must be accessed and mutated using `*Attribute()`. - * (This includes anything that fails ` in `.) - * @type {Object} - */ - mustUseProperty: {}, - - /** - * Whether or not setting a value causes side effects such as triggering - * resources to be loaded or text selection changes. We must ensure that - * the value is only set if it has changed. - * @type {Object} - */ - hasSideEffects: {}, - - /** - * Whether the property should be removed when set to a falsey value. - * @type {Object} - */ - hasBooleanValue: {}, - - /** - * Whether the property must be positive numeric or parse as a positive - * numeric and should be removed when set to a falsey value. - * @type {Object} - */ - hasPositiveNumericValue: {}, - - /** - * All of the isCustomAttribute() functions that have been injected. - */ - _isCustomAttributeFunctions: [], - - /** - * Checks whether a property name is a custom attribute. - * @method - */ - isCustomAttribute: function(attributeName) { - return DOMProperty._isCustomAttributeFunctions.some( - function(isCustomAttributeFn) { - return isCustomAttributeFn.call(null, attributeName); - } - ); - }, - - /** - * Returns the default property value for a DOM property (i.e., not an - * attribute). Most default values are '' or false, but not all. Worse yet, - * some (in particular, `type`) vary depending on the type of element. - * - * TODO: Is it better to grab all the possible properties when creating an - * element to avoid having to create the same element twice? - */ - getDefaultValueForProperty: function(nodeName, prop) { - var nodeDefaults = defaultValueCache[nodeName]; - var testElement; - if (!nodeDefaults) { - defaultValueCache[nodeName] = nodeDefaults = {}; - } - if (!(prop in nodeDefaults)) { - testElement = document.createElement(nodeName); - nodeDefaults[prop] = testElement[prop]; - } - return nodeDefaults[prop]; - }, - - injection: DOMPropertyInjection -}; - -module.exports = DOMProperty; - -},{"./invariant":113}],10:[function(require,module,exports){ -/** - * Copyright 2013 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @providesModule DOMPropertyOperations - * @typechecks static-only - */ - -"use strict"; - -var DOMProperty = require("./DOMProperty"); - -var escapeTextForBrowser = require("./escapeTextForBrowser"); -var memoizeStringOnly = require("./memoizeStringOnly"); - -function shouldIgnoreValue(name, value) { - return value == null || - DOMProperty.hasBooleanValue[name] && !value || - DOMProperty.hasPositiveNumericValue[name] && (isNaN(value) || value < 1); -} - -var processAttributeNameAndPrefix = memoizeStringOnly(function(name) { - return escapeTextForBrowser(name) + '="'; -}); - -if ("production" !== "development") { - var reactProps = { - children: true, - dangerouslySetInnerHTML: true, - key: true, - ref: true - }; - var warnedProperties = {}; - - var warnUnknownProperty = function(name) { - if (reactProps[name] || warnedProperties[name]) { - return; - } - - warnedProperties[name] = true; - var lowerCasedName = name.toLowerCase(); - - // data-* attributes should be lowercase; suggest the lowercase version - var standardName = DOMProperty.isCustomAttribute(lowerCasedName) ? - lowerCasedName : DOMProperty.getPossibleStandardName[lowerCasedName]; - - // For now, only warn when we have a suggested correction. This prevents - // logging too much when using transferPropsTo. - if (standardName != null) { - console.warn( - 'Unknown DOM property ' + name + '. Did you mean ' + standardName + '?' - ); - } - - }; -} - -/** - * Operations for dealing with DOM properties. - */ -var DOMPropertyOperations = { - - /** - * Creates markup for a property. - * - * @param {string} name - * @param {*} value - * @return {?string} Markup string, or null if the property was invalid. - */ - createMarkupForProperty: function(name, value) { - if (DOMProperty.isStandardName[name]) { - if (shouldIgnoreValue(name, value)) { - return ''; - } - var attributeName = DOMProperty.getAttributeName[name]; - return processAttributeNameAndPrefix(attributeName) + - escapeTextForBrowser(value) + '"'; - } else if (DOMProperty.isCustomAttribute(name)) { - if (value == null) { - return ''; - } - return processAttributeNameAndPrefix(name) + - escapeTextForBrowser(value) + '"'; - } else if ("production" !== "development") { - warnUnknownProperty(name); - } - return null; - }, - - /** - * Sets the value for a property on a node. - * - * @param {DOMElement} node - * @param {string} name - * @param {*} value - */ - setValueForProperty: function(node, name, value) { - if (DOMProperty.isStandardName[name]) { - var mutationMethod = DOMProperty.getMutationMethod[name]; - if (mutationMethod) { - mutationMethod(node, value); - } else if (shouldIgnoreValue(name, value)) { - this.deleteValueForProperty(node, name); - } else if (DOMProperty.mustUseAttribute[name]) { - node.setAttribute(DOMProperty.getAttributeName[name], '' + value); - } else { - var propName = DOMProperty.getPropertyName[name]; - if (!DOMProperty.hasSideEffects[name] || node[propName] !== value) { - node[propName] = value; - } - } - } else if (DOMProperty.isCustomAttribute(name)) { - if (value == null) { - node.removeAttribute(DOMProperty.getAttributeName[name]); - } else { - node.setAttribute(name, '' + value); - } - } else if ("production" !== "development") { - warnUnknownProperty(name); - } - }, - - /** - * Deletes the value for a property on a node. - * - * @param {DOMElement} node - * @param {string} name - */ - deleteValueForProperty: function(node, name) { - if (DOMProperty.isStandardName[name]) { - var mutationMethod = DOMProperty.getMutationMethod[name]; - if (mutationMethod) { - mutationMethod(node, undefined); - } else if (DOMProperty.mustUseAttribute[name]) { - node.removeAttribute(DOMProperty.getAttributeName[name]); - } else { - var propName = DOMProperty.getPropertyName[name]; - var defaultValue = DOMProperty.getDefaultValueForProperty( - node.nodeName, - name - ); - if (!DOMProperty.hasSideEffects[name] || - node[propName] !== defaultValue) { - node[propName] = defaultValue; - } - } - } else if (DOMProperty.isCustomAttribute(name)) { - node.removeAttribute(name); - } else if ("production" !== "development") { - warnUnknownProperty(name); - } - } - -}; - -module.exports = DOMPropertyOperations; - -},{"./DOMProperty":9,"./escapeTextForBrowser":99,"./memoizeStringOnly":121}],11:[function(require,module,exports){ -/** - * Copyright 2013 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @providesModule Danger - * @typechecks static-only - */ - -/*jslint evil: true, sub: true */ - -"use strict"; - -var ExecutionEnvironment = require("./ExecutionEnvironment"); - -var createNodesFromMarkup = require("./createNodesFromMarkup"); -var emptyFunction = require("./emptyFunction"); -var getMarkupWrap = require("./getMarkupWrap"); -var invariant = require("./invariant"); -var mutateHTMLNodeWithMarkup = require("./mutateHTMLNodeWithMarkup"); - -var OPEN_TAG_NAME_EXP = /^(<[^ \/>]+)/; -var RESULT_INDEX_ATTR = 'data-danger-index'; - -/** - * Extracts the `nodeName` from a string of markup. - * - * NOTE: Extracting the `nodeName` does not require a regular expression match - * because we make assumptions about React-generated markup (i.e. there are no - * spaces surrounding the opening tag and there is at least one attribute). - * - * @param {string} markup String of markup. - * @return {string} Node name of the supplied markup. - * @see http://jsperf.com/extract-nodename - */ -function getNodeName(markup) { - return markup.substring(1, markup.indexOf(' ')); -} - -var Danger = { - - /** - * Renders markup into an array of nodes. The markup is expected to render - * into a list of root nodes. Also, the length of `resultList` and - * `markupList` should be the same. - * - * @param {array} markupList List of markup strings to render. - * @return {array} List of rendered nodes. - * @internal - */ - dangerouslyRenderMarkup: function(markupList) { - ("production" !== "development" ? invariant( - ExecutionEnvironment.canUseDOM, - 'dangerouslyRenderMarkup(...): Cannot render markup in a Worker ' + - 'thread. This is likely a bug in the framework. Please report ' + - 'immediately.' - ) : invariant(ExecutionEnvironment.canUseDOM)); - var nodeName; - var markupByNodeName = {}; - // Group markup by `nodeName` if a wrap is necessary, else by '*'. - for (var i = 0; i < markupList.length; i++) { - ("production" !== "development" ? invariant( - markupList[i], - 'dangerouslyRenderMarkup(...): Missing markup.' - ) : invariant(markupList[i])); - nodeName = getNodeName(markupList[i]); - nodeName = getMarkupWrap(nodeName) ? nodeName : '*'; - markupByNodeName[nodeName] = markupByNodeName[nodeName] || []; - markupByNodeName[nodeName][i] = markupList[i]; - } - var resultList = []; - var resultListAssignmentCount = 0; - for (nodeName in markupByNodeName) { - if (!markupByNodeName.hasOwnProperty(nodeName)) { - continue; - } - var markupListByNodeName = markupByNodeName[nodeName]; - - // This for-in loop skips the holes of the sparse array. The order of - // iteration should follow the order of assignment, which happens to match - // numerical index order, but we don't rely on that. - for (var resultIndex in markupListByNodeName) { - if (markupListByNodeName.hasOwnProperty(resultIndex)) { - var markup = markupListByNodeName[resultIndex]; - - // Push the requested markup with an additional RESULT_INDEX_ATTR - // attribute. If the markup does not start with a < character, it - // will be discarded below (with an appropriate console.error). - markupListByNodeName[resultIndex] = markup.replace( - OPEN_TAG_NAME_EXP, - // This index will be parsed back out below. - '$1 ' + RESULT_INDEX_ATTR + '="' + resultIndex + '" ' - ); - } - } - - // Render each group of markup with similar wrapping `nodeName`. - var renderNodes = createNodesFromMarkup( - markupListByNodeName.join(''), - emptyFunction // Do nothing special with