├── .editorconfig
├── .eslintrc
├── .gitignore
├── LICENSE.md
├── README.md
├── buildConfig.js
├── esdoc.json
├── gulp
├── assets.js
├── build.js
├── custom-task.js
├── debug.js
├── index.js
└── utils
│ └── define-plugin.js
├── gulpfile.js
├── index.html
├── package.json
├── src
├── app.jsx
├── app
│ └── index.js
├── components
│ ├── chrome
│ │ ├── index.js
│ │ └── template.jsx
│ ├── generated
│ │ ├── index.js
│ │ ├── store.js
│ │ ├── style.less
│ │ └── template.jsx
│ └── navigation
│ │ ├── index.js
│ │ └── template.jsx
├── index.js
├── pages
│ ├── index
│ │ ├── index.js
│ │ ├── page.js
│ │ └── template.jsx
│ ├── notfound
│ │ ├── index.js
│ │ ├── page.js
│ │ └── template.jsx
│ ├── other
│ │ ├── index.js
│ │ ├── page.js
│ │ └── template.jsx
│ └── test
│ │ ├── index.js
│ │ ├── page.js
│ │ └── template.jsx
└── routes.js
├── style
└── main.less
├── test
├── app.jsx
├── component-generated.jsx
├── environment.js
├── index.js
└── page-test.jsx
├── webpack.config.js
└── webpack.config.prod.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig: http://EditorConfig.org
2 | # all files defaults
3 | [**]
4 | # Unix-style newlines with a newline ending
5 | end_of_line = lf
6 | insert_final_newline = true
7 | # Set default charset
8 | charset = utf-8
9 | # 4 space indentation
10 | indent_style = space
11 | indent_size = 4
12 | # trim whitespaces
13 | trim_trailing_whitespace = true
14 | # always insert final newline
15 | insert_final_newline = true
16 |
17 | # 2 spaces indent for config files
18 | [{package.json}]
19 | indent_style = space
20 | indent_size = 2
21 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | // I want to use babel-eslint for parsing!
3 | "parser": "babel-eslint",
4 | "env": {
5 | // I write for browser
6 | "browser": true,
7 | // in CommonJS
8 | "node": true,
9 | // use ES6
10 | "es6": true
11 | },
12 | "ecmaProperties": {
13 | // enable JSX support
14 | "jsx": true
15 | },
16 | "plugins": [
17 | // enable react plugin
18 | "react"
19 | ],
20 | "globals": {
21 | "__WEBPACK__": true
22 | },
23 | // To give you an idea how to override rule options
24 | "rules": {
25 | // Possible Errors
26 | "comma-dangle": 0,
27 | "no-console": 2,
28 | "no-debugger": 2,
29 | "no-dupe-keys": 2,
30 | "no-dupe-args": 2,
31 | "no-empty": 2,
32 | "no-extra-boolean-cast": 2,
33 | "no-extra-semi": 2,
34 | "no-invalid-regexp": 2,
35 | "no-irregular-whitespace": 2,
36 | "quote-props": [2, "consistent-as-needed", {"keywords": true}],
37 | "no-sparse-arrays": 2,
38 | "no-unreachable": 2,
39 | "use-isnan": 2,
40 | "valid-jsdoc": 2,
41 | "valid-typeof": 2,
42 | // Best Practices
43 | "consistent-return": 1,
44 | "curly": 2,
45 | "default-case": 2,
46 | "dot-notation": 2,
47 | "eqeqeq": 2,
48 | "no-alert": 2,
49 | "no-caller": 2,
50 | "no-else-return": 2,
51 | "no-eq-null": 2,
52 | "no-eval": 2,
53 | "no-extend-native": 2,
54 | "no-floating-decimal": 2,
55 | "no-implied-eval": 2,
56 | "no-iterator": 2,
57 | "no-labels": 2,
58 | "no-loop-func": 1,
59 | "no-lone-blocks": 2,
60 | "no-multi-spaces": 2,
61 | "no-native-reassign": 2,
62 | "no-new": 2,
63 | "no-new-func": 2,
64 | "no-new-wrappers": 2,
65 | "no-proto": 2,
66 | "no-redeclare": 2,
67 | "no-return-assign": 2,
68 | "no-script-url": 2,
69 | "no-self-compare": 2,
70 | "no-sequences": 2,
71 | "no-throw-literal": 2,
72 | "no-unused-expressions": 2,
73 | "no-void": 2,
74 | "radix": 2,
75 | "yoda": 0,
76 | // Strict Mode
77 | "strict": 0,
78 | // Variables
79 | "no-catch-shadow": 2,
80 | "no-delete-var": 2,
81 | "no-shadow": 2,
82 | "no-shadow-restricted-names": 2,
83 | "no-undef": 2,
84 | "no-unused-vars": [2, {"vars": "all", "args": "after-used"}],
85 | "no-use-before-define": 2,
86 | // Node
87 | "handle-callback-err": 2,
88 | "no-new-require": 2,
89 | "no-path-concat": 2,
90 | // Stylistic Issues
91 | "indent": 2, // 4 spaces
92 | "camelcase": 2,
93 | "comma-spacing": [2, {"before": false, "after": true}],
94 | "comma-style": [2, "last"],
95 | "eol-last": 2,
96 | "func-style": [2, "expression"],
97 | "max-nested-callbacks": [2, 3],
98 | "no-array-constructor": 2,
99 | "no-mixed-spaces-and-tabs": 2,
100 | "no-multiple-empty-lines": [1, {"max": 2}],
101 | "no-nested-ternary": 2,
102 | "no-new-object": 2,
103 | "semi-spacing": [2, {"before": false, "after": true}],
104 | "no-spaced-func": 2,
105 | "no-trailing-spaces": 2,
106 | "no-underscore-dangle": 2,
107 | "no-extra-parens": [2, "functions"],
108 | "quote-props": [1, "as-needed"],
109 | "quotes": [1, "single"],
110 | "semi": [2, "always"],
111 | "semi-spacing": [2, {"before": false, "after": true}],
112 | "space-before-function-paren": [1, {"anonymous": "never", "named": "never"}],
113 | "space-after-keywords": [1, "always"],
114 | "space-before-blocks": [1, "always"],
115 | "object-curly-spacing": [1, "never"],
116 | "array-bracket-spacing": [1, "never"],
117 | "computed-property-spacing": [1, "never"],
118 | "space-in-parens": [1, "never"],
119 | "key-spacing": [1, {"beforeColon": false, "afterColon": true}],
120 | "object-curly-spacing": [1, "never"],
121 | "space-infix-ops": 2,
122 | // complexity rules
123 | "max-depth": [2, 3],
124 | "max-statements": [1, 20],
125 | "complexity": [1, 3],
126 | "max-len": [2, 120],
127 | "max-params": [2, 2],
128 | // jsx rules
129 | "react/jsx-quotes": 1,
130 | "react/jsx-no-undef": 1,
131 | "react/jsx-uses-react": 1,
132 | "react/jsx-uses-vars": 1,
133 | "react/no-did-mount-set-state": 1,
134 | "react/no-did-update-set-state": 1,
135 | "react/no-multi-comp": 1,
136 | "react/react-in-jsx-scope": 1,
137 | "react/self-closing-comp": 1,
138 | "react/wrap-multilines": 1,
139 | // ES6
140 | "prefer-const": 2,
141 | "object-shorthand": [2, "always"],
142 | "no-var": 2
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # ignore node deps
2 | node_modules/
3 |
4 | # ignore compiled
5 | dist/
6 |
7 | # ignore coverage report
8 | coverage/
9 |
10 | # ignore docs
11 | esdoc/
12 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Your license text here
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Awesome exampleApp application
2 |
3 | No description yet
4 |
5 | Made with [Turris.js](https://github.com/turrisjs)
6 |
--------------------------------------------------------------------------------
/buildConfig.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | webpackConfig: {
3 | debug: require('./webpack.config.js'),
4 | production: require('./webpack.config.prod.js'),
5 | },
6 | devServer: {
7 | // settings for webpack-dev-server
8 | proxy: {
9 | // put your custom proxy routes here, e.g.:
10 | // '/api/': 'http://localhost:8081'
11 | },
12 | headers: {
13 | // put your custom headers here, e.g.:
14 | // 'X-TEST': 1,
15 | },
16 | },
17 | };
18 |
--------------------------------------------------------------------------------
/esdoc.json:
--------------------------------------------------------------------------------
1 | {
2 | "source": "./src",
3 | "destination": "./esdoc",
4 | "coverage": true
5 | }
6 |
--------------------------------------------------------------------------------
/gulp/assets.js:
--------------------------------------------------------------------------------
1 | export default (gulp) => {
2 | gulp.task('assets', function() {
3 | return gulp.src('./index.html').pipe(gulp.dest('./dist'));
4 | });
5 | };
6 |
--------------------------------------------------------------------------------
/gulp/build.js:
--------------------------------------------------------------------------------
1 | import gutil from 'gulp-util';
2 | import webpack from 'webpack';
3 | import definePlugin from './utils/define-plugin.js';
4 |
5 | // create optimizations array
6 | const optimizations = [
7 | definePlugin,
8 | new webpack.optimize.DedupePlugin(),
9 | new webpack.optimize.UglifyJsPlugin({
10 | output: {
11 | comments: false,
12 | },
13 | compress: {
14 | warnings: false,
15 | },
16 | }),
17 | ];
18 |
19 | // get build config
20 | const buildConfig = require('../buildConfig');
21 | // get webpack config
22 | const wpConfig = buildConfig.webpackConfig.production;
23 |
24 | // export initilizer
25 | export default (gulp) => {
26 | gulp.task('build', function(callback) {
27 | if (wpConfig.plugins) {
28 | wpConfig.plugins = wpConfig.plugins.concat(optimizations);
29 | } else {
30 | wpConfig.plugins = optimizations;
31 | }
32 | // run webpack
33 | webpack(wpConfig, function(err, stats) {
34 | if (err) {
35 | throw new gutil.PluginError('webpack', err);
36 | }
37 | // only log when errors
38 | gutil.log('[webpack]: ', stats.toString({
39 | chunks: false,
40 | modules: false,
41 | colors: true,
42 | }));
43 | callback();
44 | });
45 | });
46 | };
47 |
--------------------------------------------------------------------------------
/gulp/custom-task.js:
--------------------------------------------------------------------------------
1 | module.exports = function(gulp) {
2 | gulp.task('custom-task', function() {
3 | console.log('custom task done!');
4 | });
5 | };
6 |
--------------------------------------------------------------------------------
/gulp/debug.js:
--------------------------------------------------------------------------------
1 | /* eslint no-console: 0 */
2 | import webpack from 'webpack';
3 | import WebpackDevServer from 'webpack-dev-server';
4 | import definePlugin from './utils/define-plugin.js';
5 |
6 | // create optimizations array
7 | const optimizations = [definePlugin];
8 |
9 | // get build config
10 | const buildConfig = require('../buildConfig');
11 | // get webpack config
12 | const wpConfig = buildConfig.webpackConfig.debug;
13 |
14 | // export initilizer
15 | export default (gulp) => {
16 | gulp.task('debug', function() {
17 | // append our define plugin
18 | wpConfig.plugins = wpConfig.plugins ? wpConfig.plugins.concat(optimizations) : optimizations;
19 | // get server config
20 | let proxy = {};
21 | if (buildConfig.devServer && buildConfig.devServer.proxy) {
22 | proxy = buildConfig.devServer.proxy;
23 | }
24 | let headers = {};
25 | if (buildConfig.devServer && buildConfig.devServer.headers) {
26 | headers = buildConfig.devServer.headers;
27 | }
28 | // run webpack
29 | const compiler = webpack(wpConfig);
30 | const server = new WebpackDevServer(compiler, {
31 | // webpack-dev-server options
32 | contentBase: wpConfig.context,
33 |
34 | hot: true,
35 | // Enable special support for Hot Module Replacement
36 | // Page is no longer updated, but a "webpackHotUpdate" message is send to the content
37 | // Use "webpack/hot/dev-server" as additional module in your entry point
38 | // Note: this does _not_ add the `HotModuleReplacementPlugin` like the CLI option does.
39 |
40 | // webpack-dev-middleware options
41 | quiet: false,
42 | noInfo: false,
43 | watchOptions: {
44 | aggregateTimeout: 300,
45 | poll: true
46 | },
47 | headers,
48 | stats: {
49 | chunks: false,
50 | colors: true,
51 | },
52 | // Set this as true if you want to access dev server from arbitrary url.
53 | // This is handy if you are using a html5 router.
54 | historyApiFallback: true,
55 | // Set this if you want webpack-dev-server to delegate a single path to an arbitrary server.
56 | // Use "*" to proxy all paths to the specified server.
57 | // This is useful if you want to get rid of 'http://localhost:8080/' in script[src],
58 | // and has many other use cases (see https://github.com/webpack/webpack-dev-server/pull/127 ).
59 | proxy,
60 | });
61 | server.listen(8080, 'localhost', function() {
62 | console.log('Webpack-Dev-Server: started on port 8080');
63 | });
64 | });
65 | };
66 |
--------------------------------------------------------------------------------
/gulp/index.js:
--------------------------------------------------------------------------------
1 | import fs from 'fs';
2 | import gulp from 'gulp';
3 |
4 | // blacklist self and utils folder
5 | const blacklist = ['index.js', 'utils'];
6 | // get local files
7 | const files = fs.readdirSync('./gulp').filter(f => !blacklist.includes(f));
8 |
9 | // load custom tasks
10 | files.forEach(function(file) {
11 | require('./' + file)(gulp);
12 | });
13 |
14 | gulp.task('default', ['debug']);
15 | gulp.task('deploy', ['build', 'assets']);
16 |
--------------------------------------------------------------------------------
/gulp/utils/define-plugin.js:
--------------------------------------------------------------------------------
1 | import webpack from 'webpack';
2 |
3 | // definePlugin takes raw strings and inserts them, so you can put strings of JS if you want.
4 | const definePlugin = new webpack.DefinePlugin({
5 | __WEBPACK__: true, // say we're the webpack
6 | __DEV__: process.env.BUILD_DEV, // dev environment indication
7 | });
8 |
9 | export default definePlugin;
10 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | // enable babel
2 | require('babel/register');
3 | // require gulp entry
4 | require('./gulp');
5 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | exampleApp app
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "exampleApp",
3 | "version": "1.0.0",
4 | "description": "No description yet",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "tape ./test | faucet",
8 | "cover": "istanbul cover tape ./test",
9 | "docs": "esdoc -c esdoc.json",
10 | "start": "gulp",
11 | "build": "gulp build",
12 | "deploy": "gulp deploy"
13 | },
14 | "author": "",
15 | "license": "MIT",
16 | "dependencies": {
17 | "bootstrap": "^3.3.4",
18 | "postal": "^1.0.7",
19 | "react": "^0.13.2",
20 | "react-router": "^0.13.3"
21 | },
22 | "devDependencies": {
23 | "babel": "^5.8.19",
24 | "babel-core": "^5.8.19",
25 | "babel-eslint": "^4.0.5",
26 | "babel-loader": "^5.3.2",
27 | "css-loader": "^0.17.0",
28 | "eslint": "^1.1.0",
29 | "eslint-loader": "^1.0.0",
30 | "eslint-plugin-react": "^3.1.0",
31 | "extract-text-webpack-plugin": "^0.8.2",
32 | "faucet": "0.0.1",
33 | "file-loader": "^0.8.4",
34 | "gulp": "^3.9.0",
35 | "gulp-util": "^3.0.6",
36 | "istanbul": "^0.3.17",
37 | "jsdom": "^6.3.0",
38 | "less-loader": "^2.2.0",
39 | "localStorage": "^1.0.3",
40 | "react-hot-loader": "^1.3.0",
41 | "style-loader": "^0.12.3",
42 | "tape": "^4.0.1",
43 | "url-loader": "^0.5.6",
44 | "webpack": "^1.10.5",
45 | "webpack-dev-server": "^1.10.1"
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/app.jsx:
--------------------------------------------------------------------------------
1 | // react
2 | import React from 'react';
3 | import ReactRouter from 'react-router';
4 | // app core
5 | import App from './app/index.js';
6 | // user routes
7 | import routes from './routes.js';
8 |
9 | const appInstance = (
10 |
11 | {routes}
12 |
13 | );
14 |
15 | const Bootstrapper = {
16 | start() {
17 | ReactRouter.run(appInstance, ReactRouter.HistoryLocation, function(Handler) {
18 | React.render(, document.getElementById('mainContainer'));
19 | });
20 | },
21 | };
22 |
23 | export default Bootstrapper;
24 |
--------------------------------------------------------------------------------
/src/app/index.js:
--------------------------------------------------------------------------------
1 | // react
2 | import React from 'react';
3 | import {RouteHandler} from 'react-router';
4 |
5 | // main class
6 | const App = React.createClass({
7 | render() {
8 | return ;
9 | },
10 | });
11 |
12 | export default App;
13 |
--------------------------------------------------------------------------------
/src/components/chrome/index.js:
--------------------------------------------------------------------------------
1 | // react
2 | import React from 'react';
3 | import Template from './template.jsx';
4 |
5 | const Chrome = React.createClass({
6 | render: Template,
7 | });
8 |
9 | export default Chrome;
10 |
--------------------------------------------------------------------------------
/src/components/chrome/template.jsx:
--------------------------------------------------------------------------------
1 | // react
2 | import React from 'react';
3 | import Navigation from '../navigation';
4 |
5 | const render = function() {
6 | return (
7 |
8 |
9 |
10 |
11 |
12 | {this.props.children}
13 |
14 |
15 |
16 | );
17 | };
18 |
19 | export default render;
20 |
--------------------------------------------------------------------------------
/src/components/generated/index.js:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | */
4 | import React from 'react';
5 | import Template from './template.jsx';
6 | import generatedChannel from './store.js';
7 |
8 | // only load style when using webpack
9 | if (__WEBPACK__) {
10 | require('./style.less');
11 | }
12 |
13 | const GeneratedComponent = React.createClass({
14 | getInitialState() {
15 | generatedChannel.subscribe('response', this.onResponse);
16 | return {
17 | response: 'Click the button.',
18 | };
19 | },
20 | onResponse({data}) {
21 | this.setState({response: data});
22 | },
23 | handleClick() {
24 | generatedChannel.publish('request', {request: 'test'});
25 | },
26 | render: Template,
27 | });
28 |
29 | export default GeneratedComponent;
30 |
--------------------------------------------------------------------------------
/src/components/generated/store.js:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | */
4 | import postal from 'postal';
5 |
6 | const generatedChannel = postal.channel('generated');
7 |
8 | generatedChannel.subscribe('request', ({request}) => {
9 | if (request === 'test') {
10 | generatedChannel.publish('response', {data: 'ok!'});
11 | }
12 | });
13 |
14 | export default generatedChannel;
15 |
--------------------------------------------------------------------------------
/src/components/generated/style.less:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | */
4 | .generated-component {
5 | // put you styles here
6 | h3 {
7 | color: red;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/components/generated/template.jsx:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | */
4 | import React from 'react';
5 |
6 | const render = function() {
7 | return (
8 |
9 |
I am new generated component.
10 | Here's response from store: {this.state.response}
11 |
12 |
13 | );
14 | };
15 |
16 | export default render;
17 |
--------------------------------------------------------------------------------
/src/components/navigation/index.js:
--------------------------------------------------------------------------------
1 | // react
2 | import React from 'react';
3 | import Template from './template.jsx';
4 |
5 | const Navbar = React.createClass({
6 | render: Template,
7 | });
8 |
9 | export default Navbar;
10 |
--------------------------------------------------------------------------------
/src/components/navigation/template.jsx:
--------------------------------------------------------------------------------
1 | // react
2 | import React from 'react';
3 | import ReactRouter from 'react-router';
4 |
5 | const render = function() {
6 | return (
7 |
8 |
9 |
10 |
16 | exampleApp
17 |
18 |
19 |
20 |
21 | - Home
22 | - Other
23 | - Test
24 |
25 |
26 |
27 |
28 | );
29 | };
30 |
31 | export default render;
32 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | /* istanbul ignore if */
2 | if (__WEBPACK__) {
3 | require('bootstrap/dist/css/bootstrap.css');
4 | require('../style/main.less');
5 | }
6 | import App from './app.jsx';
7 |
8 | App.start();
9 |
--------------------------------------------------------------------------------
/src/pages/index/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {DefaultRoute} from 'react-router';
3 | import IndexPage from './page';
4 |
5 | const IndexRoute = React.createElement(DefaultRoute, {name: 'home', key: 'route_default', handler: IndexPage});
6 |
7 | export default IndexRoute;
8 |
--------------------------------------------------------------------------------
/src/pages/index/page.js:
--------------------------------------------------------------------------------
1 | // react
2 | import React from 'react';
3 | import Template from './template.jsx';
4 |
5 | const IndexPage = React.createClass({
6 | getInitialState() {
7 | // init state
8 | return {
9 | // your stuff here
10 | };
11 | },
12 | render: Template,
13 | });
14 |
15 | export default IndexPage;
16 |
--------------------------------------------------------------------------------
/src/pages/index/template.jsx:
--------------------------------------------------------------------------------
1 | // react
2 | import React from 'react';
3 | import Chrome from '../../components/chrome/index.js';
4 | import Generated from '../../components/generated/index.js';
5 |
6 | const render = function() {
7 | return (
8 |
9 | I am index page
10 |
11 |
12 | );
13 | };
14 |
15 | export default render;
16 |
--------------------------------------------------------------------------------
/src/pages/notfound/index.js:
--------------------------------------------------------------------------------
1 | // imports
2 | import React from 'react';
3 | import {NotFoundRoute} from 'react-router';
4 | import NotFoundPage from './page';
5 |
6 | const route = React.createElement(NotFoundRoute, {name: 'notfound', key: 'route_notfound', handler: NotFoundPage});
7 |
8 | export default route;
9 |
--------------------------------------------------------------------------------
/src/pages/notfound/page.js:
--------------------------------------------------------------------------------
1 | // imports
2 | import React from 'react';
3 | import Template from './template.jsx';
4 |
5 | const NotFoundPage = React.createClass({
6 | render: Template,
7 | });
8 |
9 | export default NotFoundPage;
10 |
--------------------------------------------------------------------------------
/src/pages/notfound/template.jsx:
--------------------------------------------------------------------------------
1 | // imports
2 | import React from 'react';
3 | import Chrome from '../../components/chrome/index.js';
4 |
5 | const render = function() {
6 | return (
7 |
8 | 404 - page not found!
9 |
10 | );
11 | };
12 |
13 | export default render;
14 |
--------------------------------------------------------------------------------
/src/pages/other/index.js:
--------------------------------------------------------------------------------
1 | // react
2 | import React from 'react';
3 | import {Route} from 'react-router';
4 | import OtherPage from './page';
5 |
6 | const route = React.createElement(Route, {name: 'other', key: 'route_other', handler: OtherPage});
7 |
8 | export default route;
9 |
--------------------------------------------------------------------------------
/src/pages/other/page.js:
--------------------------------------------------------------------------------
1 | // react
2 | import React from 'react';
3 | import Template from './template.jsx';
4 |
5 | const OtherPage = React.createClass({
6 | render: Template,
7 | });
8 |
9 | export default OtherPage;
10 |
--------------------------------------------------------------------------------
/src/pages/other/template.jsx:
--------------------------------------------------------------------------------
1 | // react
2 | import React from 'react';
3 | import Chrome from '../../components/chrome/index.js';
4 |
5 | const render = function() {
6 | return (
7 |
8 | I am other page
9 |
10 | );
11 | };
12 |
13 | export default render;
14 |
--------------------------------------------------------------------------------
/src/pages/test/index.js:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | */
4 | import React from 'react';
5 | import {Route} from 'react-router';
6 | import TestPage from './page.js';
7 |
8 | const route = React.createElement(Route, {name: 'test', key: 'route_test', handler: TestPage});
9 |
10 | export default route;
11 |
--------------------------------------------------------------------------------
/src/pages/test/page.js:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | */
4 | import React from 'react';
5 | import Template from './template.jsx';
6 |
7 | const TestPage = React.createClass({
8 | render: Template,
9 | });
10 |
11 | export default TestPage;
12 |
--------------------------------------------------------------------------------
/src/pages/test/template.jsx:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | */
4 | import Chrome from '../../components/chrome';
5 | import React from 'react';
6 |
7 | const render = function() {
8 | return (
9 | I am new test page
10 | );
11 | };
12 |
13 | export default render;
14 |
--------------------------------------------------------------------------------
/src/routes.js:
--------------------------------------------------------------------------------
1 | // import all routes
2 | import Test from './pages/test/index.js';
3 | import Index from './pages/index/index.js';
4 | import Other from './pages/other/index.js';
5 | import NotFound from './pages/notfound/index.js';
6 |
7 | // create route array
8 | const routes = [
9 | Test,
10 | Index,
11 | Other,
12 | NotFound,
13 | ];
14 |
15 | export default routes;
16 |
--------------------------------------------------------------------------------
/style/main.less:
--------------------------------------------------------------------------------
1 | body {
2 | padding-top: 50px;
3 | }
4 |
--------------------------------------------------------------------------------
/test/app.jsx:
--------------------------------------------------------------------------------
1 | // import helpers
2 | import test from 'tape';
3 |
4 | // import app
5 | import App from '../src/app.jsx';
6 |
7 | test('App suite', function(it) {
8 | it.test('# should render', function(t) {
9 | // render
10 | App.start();
11 | // verify it exists
12 | t.equal(1, document.getElementById('mainContainer').children.length);
13 | t.end();
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/test/component-generated.jsx:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | */
4 | /* global describe, it */
5 | // import helpers
6 | import test from 'tape';
7 | import React from 'React/addons';
8 | const {TestUtils} = React.addons;
9 |
10 | // import page
11 | import Component from '../src/components/generated/index.js';
12 |
13 | test('Generated component suite', function(it) {
14 | it.test('# should render', function(t) {
15 | // render
16 | const comp = TestUtils.renderIntoDocument();
17 |
18 | // check if link and name are correct
19 | const divs = TestUtils.scryRenderedDOMComponentsWithTag(comp, 'div');
20 | t.equal(1, divs.length);
21 | t.end();
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/test/environment.js:
--------------------------------------------------------------------------------
1 | import localStorage from 'localStorage';
2 | import {jsdom} from 'jsdom';
3 |
4 | // say we're not in webpack environment
5 | // this is required to skip including styles
6 | global.__WEBPACK__ = false; // eslint-disable-line no-underscore-dangle
7 |
8 | // init jsdom
9 | global.document = jsdom('');
10 | global.window = global.document.defaultView;
11 | global.navigator = global.window.navigator;
12 |
13 | // mock location
14 | global.window.location.href = 'http://localhost/';
15 |
16 | // local storage polyfill
17 | global.window.localStorage = localStorage;
18 | global.localStorage = localStorage;
19 |
--------------------------------------------------------------------------------
/test/index.js:
--------------------------------------------------------------------------------
1 | require('babel/register');
2 | require('./environment');
3 | require('./app.jsx');
4 | require('./page-test.jsx');
5 | require('./component-generated.jsx');
6 |
--------------------------------------------------------------------------------
/test/page-test.jsx:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | */
4 | /* global describe, it */
5 | // import helpers
6 | import test from 'tape';
7 | import React from 'React/addons';
8 | const {TestUtils} = React.addons;
9 |
10 | // import page
11 | import Page from '../src/pages/test/page.js';
12 |
13 | test('Test page suite', function(it) {
14 | it.test('# should render', function(t) {
15 | // render
16 | const comp = TestUtils.renderIntoDocument();
17 |
18 | // check if link and name are correct
19 | const divs = TestUtils.scryRenderedDOMComponentsWithTag(comp, 'h1');
20 | t.equal(1, divs.length);
21 | t.end();
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var webpack = require('webpack');
3 |
4 | module.exports = {
5 | devtool: 'inline-source-map',
6 | debug: true,
7 | context: path.resolve(__dirname),
8 | entry: [
9 | 'webpack-dev-server/client?http://0.0.0.0:8080', // WebpackDevServer host and port
10 | 'webpack/hot/only-dev-server', // "only" prevents reload on syntax errors
11 | './src/index.js',
12 | ],
13 | output: {
14 | path: path.resolve(__dirname, 'dist'),
15 | publicPath: '/',
16 | filename: 'app.min.js',
17 | },
18 | resolve: {
19 | root: path.resolve(__dirname),
20 | extensions: ['', '.js', '.jsx'],
21 | modulesDirectories: ['node_modules'],
22 | },
23 | node: {
24 | fs: 'empty',
25 | },
26 | eslint: {
27 | configFile: path.join(__dirname, '.eslintrc'),
28 | },
29 | module: {
30 | preLoaders: [
31 | {
32 | test: /\.jsx?$/,
33 | exclude: /node_modules/,
34 | loader: 'eslint'
35 | },
36 | ],
37 | loaders: [
38 | {
39 | test: /\.css$/,
40 | loaders: ['style', 'css'],
41 | },
42 | {
43 | test: /\.json$/,
44 | loader: 'json',
45 | },
46 | {
47 | test: /\.less$/,
48 | loaders: ['style', 'css', 'less'],
49 | },
50 | {
51 | test: /\.scss$/,
52 | loaders: ['style', 'css', 'sass'],
53 | },
54 | {
55 | test: /\.styl$/,
56 | loaders: ['style', 'css', 'stylus'],
57 | },
58 | {
59 | test: /\.jsx?$/,
60 | exclude: /node_modules/,
61 | loaders: ['react-hot', 'babel'],
62 | },
63 | {
64 | test: /\.woff\d?(\?.+)?$/,
65 | loader: 'url?limit=10000&minetype=application/font-woff',
66 | },
67 | {
68 | test: /\.ttf(\?.+)?$/,
69 | loader: 'url?limit=10000&minetype=application/octet-stream',
70 | },
71 | {
72 | test: /\.eot(\?.+)?$/,
73 | loader: 'url?limit=10000',
74 | },
75 | {
76 | test: /\.svg(\?.+)?$/,
77 | loader: 'url?limit=10000&minetype=image/svg+xml',
78 | },
79 | {
80 | test: /\.png$/,
81 | loader: 'url?limit=10000&mimetype=image/png',
82 | },
83 | {
84 | test: /\.gif$/,
85 | loader: 'url?limit=10000&mimetype=image/gif'
86 | }
87 | ],
88 | },
89 | plugins: [
90 | new webpack.HotModuleReplacementPlugin(),
91 | ],
92 | };
93 |
--------------------------------------------------------------------------------
/webpack.config.prod.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var ExtractTextPlugin = require('extract-text-webpack-plugin');
3 |
4 | module.exports = {
5 | context: path.resolve(__dirname),
6 | entry: './src/index.js',
7 | output: {
8 | path: path.join(__dirname, 'dist'),
9 | filename: 'app.min.js',
10 | },
11 | resolve: {
12 | root: path.resolve(__dirname),
13 | packageMains: ['style', 'main'],
14 | extensions: ['', '.js', '.jsx'],
15 | modulesDirectories: ['node_modules'],
16 | },
17 | node: {
18 | fs: 'empty',
19 | },
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loader: ExtractTextPlugin.extract('style', 'css'),
25 | },
26 | {
27 | test: /\.json$/,
28 | loader: 'json',
29 | },
30 | {
31 | test: /\.less$/,
32 | loader: ExtractTextPlugin.extract('style', 'css!less'),
33 | },
34 | {
35 | test: /\.scss$/,
36 | loader: ExtractTextPlugin.extract('style', 'css!sass'),
37 | },
38 | {
39 | test: /\.styl$/,
40 | loader: ExtractTextPlugin.extract('style', 'css!stylus'),
41 | },
42 | {
43 | test: /\.jsx?$/,
44 | exclude: /node_modules/,
45 | loader: 'babel',
46 | },
47 | {
48 | test: /\.woff\d?(\?.+)?$/,
49 | loader: 'url?limit=1000&minetype=application/font-woff',
50 | },
51 | {
52 | test: /\.ttf(\?.+)?$/,
53 | loader: 'url?limit=1000&minetype=application/octet-stream',
54 | },
55 | {
56 | test: /\.eot(\?.+)?$/,
57 | loader: 'url?limit=1000',
58 | },
59 | {
60 | test: /\.svg(\?.+)?$/,
61 | loader: 'url?limit=1000&minetype=image/svg+xml',
62 | },
63 | {
64 | test: /\.png$/,
65 | loader: 'url?limit=1000&mimetype=image/png',
66 | },
67 | {
68 | test: /\.gif$/,
69 | loader: 'url?limit=1000&mimetype=image/gif'
70 | }
71 | ],
72 | },
73 | plugins: [
74 | new ExtractTextPlugin('style.css', {allChunks: true}),
75 | ],
76 | };
77 |
--------------------------------------------------------------------------------