mirror of
https://github.com/react-webpack-generators/generator-react-webpack.git
synced 2025-12-08 18:01:59 +00:00
Basic project generator setup
TODO: - App tests - Generator tests - Component generator Signed-off-by: Simon Bailey <simon@newtriks.com>
This commit is contained in:
commit
b1562cd74c
13
.editorconfig
Normal file
13
.editorconfig
Normal file
@ -0,0 +1,13 @@
|
||||
# http://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
||||
* text=auto
|
||||
31
.gitignore
vendored
Normal file
31
.gitignore
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
### 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/
|
||||
temp/
|
||||
21
.jshintrc
Normal file
21
.jshintrc
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"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
|
||||
}
|
||||
8
.travis.yml
Normal file
8
.travis.yml
Normal file
@ -0,0 +1,8 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- '0.8'
|
||||
- '0.10'
|
||||
before_install:
|
||||
- currentfolder=${PWD##*/}
|
||||
- if [ "$currentfolder" != 'generator-react-webpack' ]; then cd .. && eval "mv $currentfolder generator-react-webpack" && cd generator-react-webpack; fi
|
||||
|
||||
20
LICENSE
Normal file
20
LICENSE
Normal file
@ -0,0 +1,20 @@
|
||||
Copyright 2014 Simon Bailey
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
47
README.md
Normal file
47
README.md
Normal file
@ -0,0 +1,47 @@
|
||||
# generator-react-webpack [](https://travis-ci.org/newtriks/generator-react-webpack)
|
||||
|
||||
A generator for [Yeoman](http://yeoman.io).
|
||||
|
||||
|
||||
## Getting Started
|
||||
|
||||
### What is Yeoman?
|
||||
|
||||
Trick question. It's not a thing. It's this guy:
|
||||
|
||||

|
||||
|
||||
Basically, he wears a top hat, lives in your computer, and waits for you to tell him what kind of application you wish to create.
|
||||
|
||||
Not every new computer comes with a Yeoman pre-installed. He lives in the [npm](https://npmjs.org) package repository. You only have to ask for him once, then he packs up and moves into your hard drive. *Make sure you clean up, he likes new and shiny things.*
|
||||
|
||||
```
|
||||
$ npm install -g yo
|
||||
```
|
||||
|
||||
### Yeoman Generators
|
||||
|
||||
Yeoman travels light. He didn't pack any generators when he moved in. You can think of a generator like a plug-in. You get to choose what type of application you wish to create, such as a Backbone application or even a Chrome extension.
|
||||
|
||||
To install generator-react-webpack from npm, run:
|
||||
|
||||
```
|
||||
$ npm install -g generator-react-webpack
|
||||
```
|
||||
|
||||
Finally, initiate the generator:
|
||||
|
||||
```
|
||||
$ yo react-webpack
|
||||
```
|
||||
|
||||
### Getting To Know Yeoman
|
||||
|
||||
Yeoman has a heart of gold. He's a person with feelings and opinions, but he's very easy to work with. If you think he's too opinionated, he can be easily convinced.
|
||||
|
||||
If you'd like to get to know Yeoman better and meet some of his friends, [Grunt](http://gruntjs.com) and [Bower](http://bower.io), check out the complete [Getting Started Guide](https://github.com/yeoman/yeoman/wiki/Getting-Started).
|
||||
|
||||
|
||||
## License
|
||||
|
||||
[MIT License](http://en.wikipedia.org/wiki/MIT_License)
|
||||
74
app/index.js
Normal file
74
app/index.js
Normal file
@ -0,0 +1,74 @@
|
||||
'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.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);
|
||||
|
||||
args = ['main'];
|
||||
|
||||
if (typeof this.env.options.appPath === 'undefined') {
|
||||
this.env.options.appPath = this.env.options.appPath || 'src';
|
||||
}
|
||||
|
||||
this.appPath = this.env.options.appPath;
|
||||
|
||||
this.hookFor('react-webpack:common', {
|
||||
args: args
|
||||
});
|
||||
|
||||
this.hookFor('react-webpack:main', {
|
||||
args: args
|
||||
});
|
||||
|
||||
this.on('end', function () {
|
||||
this.installDependencies({ skipInstall: options['skip-install'] });
|
||||
});
|
||||
|
||||
this.pkg = JSON.parse(this.readFileAsString(path.join(__dirname, '../package.json')));
|
||||
};
|
||||
|
||||
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.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.template('../../templates/common/_package.json', 'package.json');
|
||||
this.copy('../../templates/common/Gruntfile.js', 'Gruntfile.js');
|
||||
};
|
||||
|
||||
ReactWebpackGenerator.prototype.styleFiles = function styleFiles() {
|
||||
var mainFile = 'main.css';
|
||||
var resetFile = 'reset.css';
|
||||
this.copy('styles/' + mainFile, 'src/styles/' + mainFile);
|
||||
this.copy('styles/' + resetFile, 'src/styles/' + resetFile);
|
||||
};
|
||||
|
||||
ReactWebpackGenerator.prototype.imageFiles = function () {
|
||||
this.sourceRoot(path.join(__dirname, 'templates'));
|
||||
this.directory('images', 'src/images', true);
|
||||
};
|
||||
BIN
app/templates/images/yeoman.png
Normal file
BIN
app/templates/images/yeoman.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
41
app/templates/styles/main.css
Normal file
41
app/templates/styles/main.css
Normal file
@ -0,0 +1,41 @@
|
||||
/* 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;
|
||||
}
|
||||
48
app/templates/styles/reset.css
Normal file
48
app/templates/styles/reset.css
Normal file
@ -0,0 +1,48 @@
|
||||
/* http://meyerweb.com/eric/tools/css/reset/
|
||||
v2.0 | 20110126
|
||||
License: none (public domain)
|
||||
*/
|
||||
|
||||
html, body, div, span, applet, object, iframe,
|
||||
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||
a, abbr, acronym, address, big, cite, code,
|
||||
del, dfn, em, img, ins, kbd, q, s, samp,
|
||||
small, strike, strong, sub, sup, tt, var,
|
||||
b, u, i, center,
|
||||
dl, dt, dd, ol, ul, li,
|
||||
fieldset, form, label, legend,
|
||||
table, caption, tbody, tfoot, thead, tr, th, td,
|
||||
article, aside, canvas, details, embed,
|
||||
figure, figcaption, footer, header, hgroup,
|
||||
menu, nav, output, ruby, section, summary,
|
||||
time, mark, audio, video {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
font-size: 100%;
|
||||
font: inherit;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
/* HTML5 display-role reset for older browsers */
|
||||
article, aside, details, figcaption, figure,
|
||||
footer, header, hgroup, menu, nav, section {
|
||||
display: block;
|
||||
}
|
||||
body {
|
||||
line-height: 1;
|
||||
}
|
||||
ol, ul {
|
||||
list-style: none;
|
||||
}
|
||||
blockquote, q {
|
||||
quotes: none;
|
||||
}
|
||||
blockquote:before, blockquote:after,
|
||||
q:before, q:after {
|
||||
content: '';
|
||||
content: none;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
17
common/index.js
Normal file
17
common/index.js
Normal file
@ -0,0 +1,17 @@
|
||||
'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);
|
||||
};
|
||||
13
main/index.js
Normal file
13
main/index.js
Normal file
@ -0,0 +1,13 @@
|
||||
'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() {
|
||||
this.appTemplate('app', 'scripts/components/'+this.scriptAppName);
|
||||
};
|
||||
41
package.json
Normal file
41
package.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"name": "generator-react-webpack",
|
||||
"version": "0.0.0",
|
||||
"description": "A generator for Yeoman",
|
||||
"keywords": [
|
||||
"yeoman-generator"
|
||||
],
|
||||
"homepage": "https://github.com/newtriks/generator-react-webpack",
|
||||
"bugs": "https://github.com/newtriks/generator-react-webpack/issues",
|
||||
"author": {
|
||||
"name": "Simon Bailey",
|
||||
"email": "simon@newtriks.com",
|
||||
"url": "https://github.com/newtriks"
|
||||
},
|
||||
"main": "app/index.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/newtriks/generator-react-webpack.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "mocha"
|
||||
},
|
||||
"dependencies": {
|
||||
"yeoman-generator": "~0.14.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mocha": "~1.14.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"yo": ">=1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8.0",
|
||||
"npm": ">=1.2.10"
|
||||
},
|
||||
"licenses": [
|
||||
{
|
||||
"type": "MIT"
|
||||
}
|
||||
]
|
||||
}
|
||||
61
script-base.js
Normal file
61
script-base.js
Normal file
@ -0,0 +1,61 @@
|
||||
'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.appname = path.basename(process.cwd());
|
||||
|
||||
this.appname = this._.slugify(this._.humanize(this.appname));
|
||||
this.scriptAppName = this._.capitalize(this.appname) + generalUtils.appName(this);
|
||||
|
||||
if (typeof this.env.options.appPath === 'undefined') {
|
||||
this.env.options.appPath = this.env.options.appPath || 'src';
|
||||
}
|
||||
|
||||
if (typeof this.env.options.testPath === 'undefined') {
|
||||
this.env.options.testPath = this.env.options.testPath || 'test/spec';
|
||||
}
|
||||
|
||||
var sourceRoot = '/templates/javascript';
|
||||
this.scriptSuffix = '.js';
|
||||
|
||||
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, [
|
||||
src + this.scriptSuffix,
|
||||
path.join(this.env.options.appPath, dest) + this.scriptSuffix
|
||||
]);
|
||||
};
|
||||
|
||||
Generator.prototype.testTemplate = function (src, dest) {
|
||||
yeoman.generators.Base.prototype.template.apply(this, [
|
||||
src + this.scriptSuffix,
|
||||
path.join(this.env.options.testPath, dest) + this.scriptSuffix
|
||||
]);
|
||||
};
|
||||
|
||||
Generator.prototype.htmlTemplate = function (src, dest) {
|
||||
yeoman.generators.Base.prototype.template.apply(this, [
|
||||
src,
|
||||
path.join(this.env.options.appPath, dest.toLowerCase())
|
||||
]);
|
||||
};
|
||||
|
||||
Generator.prototype.generateSourceAndTest = function (appTemplate, testTemplate, targetDirectory, skipAdd) {
|
||||
this.appTemplate(appTemplate, path.join('scripts', targetDirectory, this.name));
|
||||
this.testTemplate(testTemplate, path.join(targetDirectory, this.name));
|
||||
if (!skipAdd) {
|
||||
this.addScriptToIndex(path.join(targetDirectory, this.name));
|
||||
}
|
||||
};
|
||||
137
templates/common/Gruntfile.js
Normal file
137
templates/common/Gruntfile.js
Normal file
@ -0,0 +1,137 @@
|
||||
'use strict';
|
||||
var LIVERELOAD_PORT = 35729;
|
||||
var lrSnippet = require('connect-livereload')({
|
||||
port: LIVERELOAD_PORT
|
||||
});
|
||||
var mountFolder = function (connect, dir) {
|
||||
return connect.static(require('path').resolve(dir));
|
||||
};
|
||||
|
||||
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');
|
||||
var jshintConfig = grunt.file.readJSON('.jshintrc');
|
||||
|
||||
var loaders = [{
|
||||
test: /\.css$/,
|
||||
loader: 'style!css'
|
||||
}, {
|
||||
test: /\.gif/,
|
||||
loader: 'url-loader?limit=10000&minetype=image/gif'
|
||||
}, {
|
||||
test: /\.jpg/,
|
||||
loader: 'url-loader?limit=10000&minetype=image/jpg'
|
||||
}, {
|
||||
test: /\.png/,
|
||||
loader: 'url-loader?limit=10000&minetype=image/png'
|
||||
}, {
|
||||
test: /\.js$/,
|
||||
loader: 'jsx-loader'
|
||||
}];
|
||||
|
||||
grunt.initConfig({
|
||||
pkg: pkgConfig,
|
||||
webpack: {
|
||||
development: {
|
||||
entry: './<%= pkg.src %>/scripts/components/<%= pkg.mainInput %>.js',
|
||||
output: {
|
||||
path: '<%= pkg.src %>/scripts/',
|
||||
filename: '<%= pkg.mainOutput %>.js'
|
||||
},
|
||||
debug: true,
|
||||
cache: true,
|
||||
stats: {
|
||||
colors: true,
|
||||
reasons: true
|
||||
},
|
||||
jshint: grunt.util._.merge(jshintConfig, {
|
||||
emitErrors: false,
|
||||
failOnHint: false
|
||||
}),
|
||||
module: {
|
||||
preLoaders: [{
|
||||
test: '\\.js$',
|
||||
exclude: 'node_modules',
|
||||
loader: 'jshint'
|
||||
}],
|
||||
loaders: loaders
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
webpack: {
|
||||
files: ['<%= pkg.src %>/scripts/{,*/}*.js',
|
||||
'<%= pkg.src %>/styles/{,*/}*.css',
|
||||
'!<%= pkg.src %>/scripts/<%= pkg.mainOutput %>.js'
|
||||
],
|
||||
tasks: ['webpack:development']
|
||||
},
|
||||
livereload: {
|
||||
options: {
|
||||
livereload: LIVERELOAD_PORT
|
||||
},
|
||||
files: [
|
||||
'<%= pkg.src %>/{,*/}*.html',
|
||||
'<%= pkg.src %>/scripts/<%= pkg.mainOutput %>.js'
|
||||
]
|
||||
}
|
||||
},
|
||||
connect: {
|
||||
options: {
|
||||
port: 8000,
|
||||
// Change this to '0.0.0.0' to access the server from outside.
|
||||
hostname: 'localhost'
|
||||
},
|
||||
livereload: {
|
||||
options: {
|
||||
middleware: function (connect) {
|
||||
return [
|
||||
lrSnippet,
|
||||
mountFolder(connect, pkgConfig.src)
|
||||
];
|
||||
}
|
||||
}
|
||||
},
|
||||
dist: {
|
||||
options: {
|
||||
middleware: function (connect) {
|
||||
return [
|
||||
mountFolder(connect, pkgConfig.dist)
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
open: {
|
||||
server: {
|
||||
url: 'http://localhost:<%= connect.options.port %>'
|
||||
}
|
||||
},
|
||||
karma: {
|
||||
unit: {
|
||||
configFile: 'karma.conf.js'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
grunt.registerTask('server', function (target) {
|
||||
if (target === 'dist') {
|
||||
return grunt.task.run(['build', 'open', 'connect:dist:keepalive']);
|
||||
}
|
||||
|
||||
grunt.task.run([
|
||||
'connect:livereload',
|
||||
'webpack:development',
|
||||
'open',
|
||||
'watch'
|
||||
]);
|
||||
});
|
||||
|
||||
grunt.registerTask('test', ['karma']);
|
||||
|
||||
grunt.registerTask('build', []);
|
||||
|
||||
grunt.registerTask('default', []);
|
||||
};
|
||||
36
templates/common/_package.json
Normal file
36
templates/common/_package.json
Normal file
@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "<%= _.slugify(appname) %>",
|
||||
"version": "0.0.0",
|
||||
"src": "src",
|
||||
"test": "test",
|
||||
"dist": "dist",
|
||||
"mainInput": "<%= scriptAppName %>",
|
||||
"mainOutput": "main",
|
||||
"dependencies": {
|
||||
"react": "~0.8.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"grunt": "~0.4.2",
|
||||
"load-grunt-tasks": "~0.2.1",
|
||||
"grunt-contrib-watch": "~0.5.3",
|
||||
"grunt-contrib-connect": "~0.6.0",
|
||||
"connect-livereload": "~0.3.1",
|
||||
"webpack": "~1.0.0-beta4",
|
||||
"jsx-loader": "petehunt/jsx-loader",
|
||||
"grunt-webpack": "~1.0.0",
|
||||
"style-loader": "~0.6.0",
|
||||
"url-loader": "~0.5.2",
|
||||
"css-loader": "~0.6.6",
|
||||
"karma-script-launcher": "~0.1.0",
|
||||
"karma-chrome-launcher": "~0.1.2",
|
||||
"karma-firefox-launcher": "~0.1.3",
|
||||
"karma-jasmine": "~0.1.5",
|
||||
"karma-phantomjs-launcher": "~0.1.1",
|
||||
"karma": "~0.10.9",
|
||||
"grunt-karma": "~0.6.2",
|
||||
"karma-webpack-plugin": "~1.0.0",
|
||||
"webpack-dev-server": "~1.0.2",
|
||||
"grunt-open": "~0.2.2",
|
||||
"jshint-loader": "~0.6.0"
|
||||
}
|
||||
}
|
||||
32
templates/common/gitignore
Normal file
32
templates/common/gitignore
Normal file
@ -0,0 +1,32 @@
|
||||
### 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
|
||||
/src/scripts/main.js
|
||||
19
templates/common/index.html
Normal file
19
templates/common/index.html
Normal file
@ -0,0 +1,19 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<title></title>
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
</head>
|
||||
<body>
|
||||
<!--[if lt IE 8]>
|
||||
<p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
|
||||
<![endif]-->
|
||||
<div id="content">
|
||||
<h1>If you can see this, something is broken (or JS is not enabled).</h1>
|
||||
</div>
|
||||
<script type="text/javascript" src="scripts/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
13
templates/common/root/.editorconfig
Normal file
13
templates/common/root/.editorconfig
Normal file
@ -0,0 +1,13 @@
|
||||
# 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
|
||||
27
templates/common/root/.jshintrc
Normal file
27
templates/common/root/.jshintrc
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"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": "single",
|
||||
"regexp": true,
|
||||
"undef": true,
|
||||
"unused": false,
|
||||
"strict": true,
|
||||
"trailing": true,
|
||||
"smarttabs": true,
|
||||
"white": true,
|
||||
"newcap": false,
|
||||
"globals": {
|
||||
"React": true
|
||||
}
|
||||
}
|
||||
|
||||
BIN
templates/common/root/src/favicon.ico
Normal file
BIN
templates/common/root/src/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
40
templates/common/root/test/.jshintrc
Normal file
40
templates/common/root/test/.jshintrc
Normal file
@ -0,0 +1,40 @@
|
||||
{
|
||||
"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": "single",
|
||||
"regexp": true,
|
||||
"undef": true,
|
||||
"unused": false,
|
||||
"strict": true,
|
||||
"trailing": true,
|
||||
"smarttabs": true,
|
||||
"white": true,
|
||||
"newcap": false,
|
||||
"globals": {
|
||||
"after": false,
|
||||
"afterEach": false,
|
||||
"react": false,
|
||||
"before": false,
|
||||
"beforeEach": false,
|
||||
"browser": false,
|
||||
"describe": false,
|
||||
"expect": false,
|
||||
"inject": false,
|
||||
"it": false,
|
||||
"spyOn": false,
|
||||
"jasmine": false,
|
||||
"spyOnConstructor": false,
|
||||
"React": true
|
||||
}
|
||||
}
|
||||
|
||||
34
templates/common/root/test/helpers/phantomjs-shims.js
Normal file
34
templates/common/root/test/helpers/phantomjs-shims.js
Normal file
@ -0,0 +1,34 @@
|
||||
(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;
|
||||
};
|
||||
}
|
||||
})();
|
||||
16336
templates/common/root/test/helpers/react/addons.js
Executable file
16336
templates/common/root/test/helpers/react/addons.js
Executable file
File diff suppressed because it is too large
Load Diff
32
templates/javascript/App.js
Normal file
32
templates/javascript/App.js
Normal file
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* @jsx React.DOM
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var React = require('react/addons');
|
||||
var ReactTransitionGroup = React.addons.TransitionGroup;
|
||||
|
||||
// CSS
|
||||
require('../../styles/reset.css');
|
||||
require('../../styles/main.css');
|
||||
|
||||
var imageURL = '../../images/yeoman.png';
|
||||
|
||||
var <%= scriptAppName %> = React.createClass({
|
||||
/*jshint ignore:start */
|
||||
render: function() {
|
||||
return (
|
||||
<div className='main'>
|
||||
<ReactTransitionGroup transitionName="fade">
|
||||
<img src={imageURL} />
|
||||
</ReactTransitionGroup>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
/*jshint ignore:end */
|
||||
});
|
||||
|
||||
React.renderComponent(<<%= scriptAppName %> />, document.getElementById('content')); // jshint ignore:line
|
||||
|
||||
module.exports = <%= scriptAppName %>;
|
||||
38
test/test-creation.js
Normal file
38
test/test-creation.js
Normal file
@ -0,0 +1,38 @@
|
||||
/*global describe, beforeEach, it*/
|
||||
'use strict';
|
||||
|
||||
var path = require('path');
|
||||
var helpers = require('yeoman-generator').test;
|
||||
|
||||
|
||||
describe('react-webpack generator', function () {
|
||||
beforeEach(function (done) {
|
||||
helpers.testDirectory(path.join(__dirname, 'temp'), function (err) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
this.app = helpers.createGenerator('react-webpack:app', [
|
||||
'../../app'
|
||||
]);
|
||||
done();
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
it('creates expected files', function (done) {
|
||||
var expected = [
|
||||
// add files you expect to exist here.
|
||||
'.jshintrc',
|
||||
'.editorconfig'
|
||||
];
|
||||
|
||||
helpers.mockPrompt(this.app, {
|
||||
'someOption': true
|
||||
});
|
||||
this.app.options['skip-install'] = true;
|
||||
this.app.run({}, function () {
|
||||
helpers.assertFiles(expected);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
11
test/test-load.js
Normal file
11
test/test-load.js
Normal file
@ -0,0 +1,11 @@
|
||||
/*global describe, beforeEach, it*/
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
|
||||
describe('react-webpack generator', function () {
|
||||
it('can be imported without blowing up', function () {
|
||||
var app = require('../app');
|
||||
assert(app !== undefined);
|
||||
});
|
||||
});
|
||||
80
util.js
Normal file
80
util.js
Normal file
@ -0,0 +1,80 @@
|
||||
'use strict';
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
|
||||
|
||||
module.exports = {
|
||||
rewrite: rewrite,
|
||||
rewriteFile: rewriteFile,
|
||||
appName: appName,
|
||||
capitalize: capitalize
|
||||
};
|
||||
|
||||
function rewriteFile (args) {
|
||||
args.path = args.path || process.cwd();
|
||||
var fullPath = path.join(args.path, args.file);
|
||||
|
||||
args.haystack = fs.readFileSync(fullPath, 'utf8');
|
||||
var body = rewrite(args);
|
||||
|
||||
fs.writeFileSync(fullPath, body);
|
||||
}
|
||||
|
||||
function escapeRegExp (str) {
|
||||
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
|
||||
}
|
||||
|
||||
function rewrite (args) {
|
||||
// check if splicable is already in the body text
|
||||
var re = new RegExp(args.splicable.map(function (line) {
|
||||
return '\s*' + escapeRegExp(line);
|
||||
}).join('\n'));
|
||||
|
||||
if (re.test(args.haystack)) {
|
||||
return args.haystack;
|
||||
}
|
||||
|
||||
var lines = args.haystack.split('\n');
|
||||
|
||||
var otherwiseLineIndex = 0;
|
||||
lines.forEach(function (line, i) {
|
||||
if (line.indexOf(args.needle) !== -1) {
|
||||
otherwiseLineIndex = i;
|
||||
}
|
||||
});
|
||||
|
||||
var spaces = 0;
|
||||
while (lines[otherwiseLineIndex].charAt(spaces) === ' ') {
|
||||
spaces += 1;
|
||||
}
|
||||
|
||||
var spaceStr = '';
|
||||
while ((spaces -= 1) >= 0) {
|
||||
spaceStr += ' ';
|
||||
}
|
||||
|
||||
lines.splice(otherwiseLineIndex, 0, args.splicable.map(function (line) {
|
||||
return spaceStr + line;
|
||||
}).join('\n'));
|
||||
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
function capitalize(string) {
|
||||
return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
|
||||
}
|
||||
|
||||
function appName(self) {
|
||||
var counter = 0, suffix = self.options['app-suffix'];
|
||||
// Have to check this because of generator bug #386
|
||||
process.argv.forEach(function (val) {
|
||||
if (val.indexOf('--app-suffix') > -1) {
|
||||
counter++;
|
||||
}
|
||||
});
|
||||
if (counter === 0 || (typeof suffix === 'boolean' && suffix)) {
|
||||
suffix = 'App';
|
||||
}
|
||||
return suffix ? self._.classify(suffix) : '';
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user