├── .editorconfig ├── .gitignore ├── .travis.yml ├── GUIDE.md ├── LICENSE ├── README.md ├── envwarning.png ├── examples ├── README.md ├── complex │ ├── config │ │ └── default.json │ ├── files │ │ ├── favicon.png │ │ └── test │ │ │ └── index.html │ ├── package.json │ ├── roc.config.js │ └── src │ │ ├── components │ │ ├── about │ │ │ └── index.js │ │ ├── app │ │ │ └── index.js │ │ ├── async │ │ │ └── index.js │ │ ├── bacon │ │ │ └── index.js │ │ ├── clicker │ │ │ ├── index.js │ │ │ └── style.css │ │ ├── errors │ │ │ ├── index.js │ │ │ ├── item.js │ │ │ └── style.css │ │ ├── long │ │ │ └── index.js │ │ ├── main │ │ │ ├── actions.js │ │ │ ├── index.js │ │ │ ├── logo.png │ │ │ ├── style.css │ │ │ └── util.js │ │ ├── repo │ │ │ ├── button.js │ │ │ ├── data.js │ │ │ ├── error.js │ │ │ ├── index.js │ │ │ ├── loader.js │ │ │ └── style.css │ │ ├── shared.css │ │ └── simple │ │ │ └── index.js │ │ ├── enhancers.js │ │ ├── koa-middlewares.js │ │ ├── middlewares.js │ │ ├── reducers.js │ │ ├── reducers │ │ ├── clicker.js │ │ ├── repofetch.js │ │ └── repouser.js │ │ ├── routes.js │ │ ├── sagas.js │ │ └── template-values.js ├── extensible-templates │ ├── main.js │ ├── package.json │ ├── public │ │ └── static.css │ ├── roc.config.js │ ├── roc.png │ ├── routes.js │ ├── style.css │ └── views │ │ ├── A │ │ └── a.njk │ │ ├── B │ │ └── b.njk │ │ ├── C │ │ └── c.njk │ │ └── entry.njk ├── realtime-redux │ ├── components │ │ ├── stock-event-list │ │ │ ├── index.js │ │ │ └── style.css │ │ ├── stock-event │ │ │ ├── index.js │ │ │ └── style.scss │ │ ├── stock-graph-list │ │ │ ├── index.js │ │ │ └── style.css │ │ ├── stock-graph │ │ │ ├── index.js │ │ │ └── style.css │ │ └── stock │ │ │ ├── index.js │ │ │ └── style.css │ ├── config │ │ ├── custom-environment-variables.json │ │ └── default.json │ ├── main.js │ ├── package.json │ ├── reducers.js │ ├── roc.config.js │ ├── routes.js │ ├── stock.js │ ├── style.scss │ └── util │ │ ├── rest.js │ │ └── sse.js ├── simple-redux │ ├── clicker.js │ ├── main.js │ ├── package.json │ ├── reducers.js │ ├── routes.js │ └── style.scss └── simple │ ├── main.js │ ├── package.json │ ├── roc.png │ ├── routes.js │ └── style.css ├── extensions ├── roc-package-web-app-react-dev │ ├── .eslintignore │ ├── .eslintrc │ ├── LICENSE │ ├── README.md │ ├── docs │ │ ├── Actions.md │ │ ├── Commands.md │ │ ├── Configuration.md │ │ ├── Dependencies.md │ │ ├── Extensions.md │ │ ├── Hooks.md │ │ └── Settings.md │ ├── package.json │ └── src │ │ ├── config │ │ ├── roc.config.js │ │ └── roc.config.meta.js │ │ ├── index.js │ │ ├── roc │ │ ├── index.js │ │ └── util.js │ │ └── webpack │ │ └── index.js └── roc-package-web-app-react │ ├── .babelrc │ ├── .eslintignore │ ├── .eslintrc │ ├── LICENSE │ ├── README.md │ ├── app │ ├── client │ │ ├── create-client.js │ │ ├── dev-tools.js │ │ ├── index.js │ │ └── render-to-dom.js │ ├── default │ │ ├── client.js │ │ ├── get-routes-and-store.js │ │ └── server.js │ ├── server │ │ ├── index.js │ │ └── useReact.js │ └── shared │ │ ├── application.js │ │ ├── create-routes.js │ │ ├── flux │ │ ├── create-store.js │ │ ├── middlewares │ │ │ └── index.js │ │ └── reducers │ │ │ ├── errors.js │ │ │ └── index.js │ │ ├── header.js │ │ ├── index.js │ │ └── universal-config.js │ ├── docs │ ├── Actions.md │ ├── Commands.md │ ├── Configuration.md │ ├── Dependencies.md │ ├── Extensions.md │ ├── Hooks.md │ └── Settings.md │ ├── package.json │ ├── src │ ├── app │ │ └── server │ │ │ ├── helpers │ │ │ ├── myPath.js │ │ │ └── readStats.js │ │ │ ├── reactRenderer.js │ │ │ ├── reactRouter.js │ │ │ ├── setupForRender.js │ │ │ └── useReact.js │ ├── config │ │ ├── roc.config.js │ │ └── roc.config.meta.js │ ├── index.js │ └── roc │ │ ├── index.js │ │ └── util.js │ ├── styles │ └── base.css │ └── views │ ├── main.html │ └── roc-package-web-app-react │ └── main.njk ├── package.json ├── rocdev.png └── roctest.png /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent coding styles between different editors and IDEs. 2 | # Requires EditorConfig JetBrains Plugin - http://github.com/editorconfig/editorconfig-jetbrains 3 | 4 | # Set this file as the topmost .editorconfig 5 | # (multiple files can be used, and are applied starting from current document location) 6 | root = true 7 | 8 | [{package.json,.travis.yml}] 9 | indent_style = space 10 | indent_size = 2 11 | 12 | # Use bracketed regexp to target specific file types or file locations 13 | [*.{js,json}] 14 | 15 | # Use hard or soft tabs ["tab", "space"] 16 | indent_style = space 17 | 18 | # Size of a single indent [an integer, "tab"] 19 | indent_size = tab 20 | 21 | # Number of columns representing a tab character [an integer] 22 | tab_width = 4 23 | 24 | # Line breaks representation ["lf", "cr", "crlf"] 25 | end_of_line = lf 26 | 27 | # ["latin1", "utf-8", "utf-16be", "utf-16le"] 28 | charset = utf-8 29 | 30 | # Remove any whitespace characters preceding newline characters ["true", "false"] 31 | trim_trailing_whitespace = true 32 | 33 | # Ensure file ends with a newline when saving ["true", "false"] 34 | insert_final_newline = true 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | .DS_Store 4 | lib 5 | esdocs 6 | coverage 7 | build 8 | package-lock.json 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | cache: 3 | directories: 4 | - node_modules 5 | node_js: 6 | - 4.2 7 | before_install: 8 | - npm install -g npm@3 9 | before_script: 10 | - npm run link 11 | after_success: 12 | - npm start build && npm start docs 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Verdens Gang AS 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [This extension have been moved into the Roc extension monorepo here.](https://github.com/rocjs/extensions) 2 | 3 | This change has been made to make it easier to work with the extensions overall and release new versions quickly. Please use this repo for reporting issues and open pull requests. 4 | 5 | [The code for `roc-package-web-app-react` can be found here.](https://github.com/rocjs/extensions/tree/master/packages/roc-package-web-app-react) 6 | [The code for `roc-package-web-app-react-dev` can be found here.](https://github.com/rocjs/extensions/tree/master/packages/roc-package-web-app-react-dev) 7 | 8 | ---- 9 | 10 | # roc-package-web-app-react [![Build Status](https://travis-ci.org/rocjs/roc-package-web-app-react.svg?branch=master)](https://travis-ci.org/rocjs/roc-package-web-app-react) 11 | 12 | __Package for building React applications with Roc__ 13 | - [roc-package-web-app-react](/extensions/roc-package-web-app-react) 14 | - [roc-package-web-app-react-dev](/extensions/roc-package-web-app-react-dev) 15 | 16 | ## User guide 17 | Read the comprehensive user-guide on how to best utilize the tools and libraries provided by this Roc extension [here](GUIDE.md). 18 | 19 | --- 20 | To be used together with [Roc](https://github.com/rocjs/roc). 21 | ” 22 | -------------------------------------------------------------------------------- /envwarning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rocjs/roc-package-web-app-react/26cd2b51acbfcaf3a61267ded00afb3a19907198/envwarning.png -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | Not all examples are fully updated to use the latest code, please be aware. 2 | -------------------------------------------------------------------------------- /examples/complex/config/default.json: -------------------------------------------------------------------------------- 1 | { 2 | "DANGEROUSLY_EXPOSE_TO_CLIENT": { 3 | "foo": "bar" 4 | }, 5 | "auth": { 6 | "publicKey": "1", 7 | "privateKey": "foobar" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/complex/files/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rocjs/roc-package-web-app-react/26cd2b51acbfcaf3a61267ded00afb3a19907198/examples/complex/files/favicon.png -------------------------------------------------------------------------------- /examples/complex/files/test/index.html: -------------------------------------------------------------------------------- 1 | Hello 2 | -------------------------------------------------------------------------------- /examples/complex/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "roc-web-react-complex-example", 3 | "version": "1.0.0", 4 | "description": "Roc Web React complex example", 5 | "author": "VG", 6 | "license": "MIT", 7 | "dependencies": { 8 | "koa-session": "3.4.0", 9 | "react-toggle": "~2.1.1", 10 | "redux-api-middleware": "~1.0.2", 11 | "redux-fetcher": "~2.0.0", 12 | "roc-package-web-app-react": "*" 13 | }, 14 | "devDependencies": { 15 | "roc-package-web-app-react-dev": "*", 16 | "roc-plugin-style-sass": "^1.0.0-beta.2" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/complex/roc.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | settings: { 3 | runtime: { 4 | applicationName: 'My Roc Application', 5 | serve: ['files', 'build/client'], 6 | fetch: { 7 | server: [['fetch', 'defer']] 8 | } 9 | }, 10 | build: { 11 | koaMiddlewares: 'src/koa-middlewares.js', 12 | redux: { 13 | middlewares: 'src/middlewares.js', 14 | enhancers: 'src/enhancers.js', 15 | sagas: 'src/sagas.js', 16 | }, 17 | reducers: 'src/reducers.js', 18 | routes: 'src/routes.js', 19 | templateValues: 'src/template-values.js' 20 | } 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /examples/complex/src/components/about/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { provideHooks } from 'redial'; 3 | 4 | @provideHooks({ 5 | fetch: (locals) => new Promise((resolve) => { 6 | if (locals.force || !locals.getProps()) { 7 | setTimeout(() => { 8 | locals.setProps({color: 'blue'}); 9 | resolve(); 10 | }, 2500); 11 | } else { 12 | resolve(); 13 | } 14 | }), 15 | defer: (locals) => { 16 | locals.setProps({color: 'red'}); 17 | locals.dispatch({ type: 'CLICKED_ASYNC' }); 18 | }, 19 | }) 20 | export default class About extends Component { 21 | render() { 22 | // "Remove" props that are different on the server and the client - only structure from JSON.stringify 23 | const { location, routes, route, ...props } = this.props; 24 | 25 | return ( 26 |
27 |

About us

28 | 29 |
{ JSON.stringify(props, null, 2) }
30 |
{ JSON.stringify(location, null, 2)}
31 |
32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /examples/complex/src/components/app/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import Link from 'react-router/lib/Link'; 3 | import IndexLink from 'react-router/lib/IndexLink'; 4 | 5 | export default class App extends Component { 6 | static propTypes = { 7 | children: React.PropTypes.object 8 | }; 9 | 10 | render() { 11 | const style = { 12 | opacity: this.props.loading ? 0.5 : 1, 13 | transition: this.props.loading ? 'opacity 250ms ease 300ms' : '' 14 | } 15 | return ( 16 |
17 | 26 | { this.props.children } 27 |
28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /examples/complex/src/components/async/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | export default class Async extends Component { 4 | render() { 5 | return ( 6 |
7 | Such asynchronously rendered! 8 |
9 | ); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/complex/src/components/bacon/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | export default class Bacon extends Component { 4 | render() { 5 | /* eslint-disable max-len */ 6 | return ( 7 |
8 |

Bacon ipsum dolor

9 |

10 | Bacon ipsum dolor amet hamburger swine filet mignon biltong shank, turkey alcatra brisket flank ribeye 11 | landjaeger beef ribs. Ham flank pancetta biltong pork belly shankle brisket doner beef. Pig sirloin turkey 12 | corned beef, alcatra biltong boudin pastrami. Tail pig pork filet mignon kevin chuck. Prosciutto ball tip 13 | flank jerky ham, porchetta fatback kevin swine alcatra spare ribs pancetta. Pork belly tenderloin meatball 14 | venison filet mignon andouille doner pork loin turducken strip steak. Shank andouille pig shankle. 15 | 16 | Drumstick shankle tri-tip pork chop salami bacon jowl. Shankle bacon tongue venison, brisket strip steak 17 | cupim meatball. Flank turducken tenderloin rump pork belly ribeye. Drumstick tenderloin turkey, short loin 18 | andouille meatloaf meatball brisket bresaola rump jowl. Drumstick tongue ball tip t-bone leberkas rump. 19 | 20 | Porchetta pastrami cow, short loin rump landjaeger brisket tongue beef bresaola pork chop drumstick. Swine 21 | t-bone tongue pork belly ham turducken alcatra rump pork loin flank ribeye meatloaf capicola short ribs. 22 | Flank ribeye shank, turkey pork chop tail tongue hamburger swine. Ham hock jowl meatloaf ham cow, rump 23 | drumstick shankle flank hamburger fatback prosciutto biltong. 24 | 25 | Landjaeger bacon kevin sausage, tail bresaola shank alcatra pastrami jerky. Kielbasa salami landjaeger 26 | ground round. Chicken ham brisket, boudin andouille corned beef jerky tri-tip short ribs kielbasa 27 | landjaeger beef biltong jowl bacon. Pork shank leberkas, picanha beef ribs spare ribs cow beef drumstick 28 | ball tip shankle short loin ground round pig. Picanha ground round venison pancetta drumstick ham biltong 29 | bresaola salami sausage beef ribs boudin pork chop jerky. Brisket jowl chicken, kevin tongue beef 30 | prosciutto meatloaf. 31 | 32 | Frankfurter meatball sausage turkey rump ham hock tongue doner leberkas drumstick jowl ground round filet 33 | mignon. Tenderloin sirloin salami, shoulder ham landjaeger corned beef pastrami cow porchetta capicola 34 | boudin tongue rump. Pork loin sirloin rump landjaeger drumstick pastrami frankfurter andouille doner 35 | salami flank shoulder. Fatback bacon turducken frankfurter. Pancetta ground round flank pork, sausage pork 36 | chop doner bacon ribeye shank tail filet mignon jowl swine short ribs. Jerky shank prosciutto ham hock 37 | kevin picanha meatball short loin pork loin shankle ground round brisket pork belly. 38 | 39 | Chuck pig tri-tip, doner meatloaf rump ball tip tenderloin venison leberkas. Pork loin biltong t-bone 40 | turducken. Jerky pork loin pork short ribs pastrami biltong, turkey meatball kevin sausage. Alcatra strip 41 | steak corned beef, beef ribs andouille tenderloin biltong ribeye chuck. Doner chuck biltong venison pork 42 | belly tail fatback cow t-bone short ribs ham hock jowl hamburger frankfurter meatball. 43 | 44 | Sausage beef ribs tail shoulder pork belly shank prosciutto pork tri-tip sirloin t-bone. Ground round spare 45 | ribs turducken tongue. Shank tenderloin meatloaf, beef tongue beef ribs pastrami. Porchetta short ribs 46 | sirloin, bacon drumstick prosciutto doner kevin pancetta tri-tip fatback. 47 | 48 | Meatloaf salami biltong shank, venison cow drumstick picanha capicola doner short loin. Doner filet mignon 49 | biltong meatloaf. Filet mignon ribeye tail porchetta strip steak shoulder chicken short ribs. Strip steak 50 | tenderloin pig filet mignon spare ribs, capicola pork loin prosciutto ground round leberkas tail chuck 51 | porchetta biltong. Corned beef brisket frankfurter tongue capicola venison. Tail jowl ham venison. 52 | 53 | Venison spare ribs shank beef ribs sausage pork chop capicola jerky. Sirloin spare ribs ribeye strip steak 54 | cow beef fatback brisket pork ball tip doner hamburger. Pork loin fatback swine kielbasa doner alcatra 55 | salami porchetta drumstick tongue ground round. Strip steak sausage sirloin rump shoulder t-bone. Meatloaf 56 | corned beef sausage, chuck ground round short ribs porchetta tri-tip. Hamburger kielbasa cow, picanha 57 | boudin capicola rump pastrami ball tip pork chop swine. 58 | 59 | Chuck landjaeger pork, pork loin shankle tri-tip pastrami flank kielbasa picanha drumstick cupim chicken 60 | beef. Pork loin frankfurter short loin, pancetta cupim ribeye jerky turkey beef ribs tri-tip meatball 61 | swine tail flank. Pastrami salami turkey, turducken ball tip venison meatloaf sirloin pork chop drumstick 62 | short loin. Andouille sirloin pig, tongue pork chop pastrami meatball filet mignon beef ribs chuck fatback. 63 |

64 |
65 | ); 66 | /* eslint-enable max-len */ 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /examples/complex/src/components/clicker/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import styles from './style.css'; 3 | import sharedStyles from './../shared.css'; 4 | 5 | export default class Clicker extends Component { 6 | static propTypes = { 7 | clicker: React.PropTypes.number.isRequired, 8 | click: React.PropTypes.func.isRequired 9 | }; 10 | 11 | render() { 12 | return ( 13 |
14 |

Clicker

15 |
16 | { this.props.clicker } 17 | 18 |
19 |
20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/complex/src/components/clicker/style.css: -------------------------------------------------------------------------------- 1 | .clicker { 2 | height: 230px; 3 | } 4 | -------------------------------------------------------------------------------- /examples/complex/src/components/errors/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import ErrorItem from './item'; 4 | 5 | export default class Errors extends Component { 6 | static defaultProps = { 7 | errors: [] 8 | }; 9 | 10 | static propTypes = { 11 | errors: React.PropTypes.array, 12 | resetErrors: React.PropTypes.func 13 | }; 14 | 15 | render() { 16 | const errorList = this.props.errors.map((error, i) => ( 17 | 18 | )); 19 | 20 | if (errorList.length > 0) { 21 | return ( 22 |
23 | { errorList } 24 | 25 |
26 | ); 27 | } 28 | 29 | return false; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /examples/complex/src/components/errors/item.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import styles from './style.css'; 4 | 5 | export default class ErrorItem extends Component { 6 | static defaultProps = { 7 | key: 0, 8 | error: '' 9 | }; 10 | 11 | static propTypes = { 12 | key: React.PropTypes.number.isRequired, 13 | error: React.PropTypes.string.isRequired 14 | }; 15 | 16 | render() { 17 | return ( 18 |
19 |

Error

20 |

{ this.props.error }

21 |
22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/complex/src/components/errors/style.css: -------------------------------------------------------------------------------- 1 | .error { 2 | background: #ff0000; 3 | color: #fff; 4 | padding: 5px; 5 | margin: 0 0 10px 0; 6 | border-radius: 8px; 7 | } 8 | -------------------------------------------------------------------------------- /examples/complex/src/components/long/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import Bacon from '../bacon'; 4 | 5 | export default class Long extends Component { 6 | render() { 7 | return ( 8 |
9 | 10 | 11 | 12 |
13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/complex/src/components/main/actions.js: -------------------------------------------------------------------------------- 1 | export function resetErrors() { 2 | return { 3 | type: 'RESET_ERROR_MESSAGES' 4 | }; 5 | } 6 | -------------------------------------------------------------------------------- /examples/complex/src/components/main/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { bindActionCreators } from 'redux'; 3 | import { connect } from 'react-redux'; 4 | import { provideHooks } from 'redial'; 5 | 6 | // components 7 | import Repo from '../repo'; 8 | import Clicker from '../clicker'; 9 | import Bacon from '../bacon'; 10 | import Errors from '../errors'; 11 | 12 | import { createFetchAction } from 'redux-fetcher' 13 | import { updateUser } from '../../reducers/repouser'; 14 | 15 | // roc error action 16 | import { resetErrors } from './actions'; 17 | 18 | // clicker reducer 19 | import { click } from '../../reducers/clicker'; 20 | 21 | // util 22 | import { prefetchRepos, mergeReposProps } from './util'; 23 | 24 | import styles from './style.css'; 25 | import logo from './logo.png'; 26 | 27 | // this maps values from redux store to props of this component 28 | function mapStateToProps(state) { 29 | return { 30 | clicker: state.clicker, 31 | repoUser: state.repoUser, 32 | repositories: state.repositories, 33 | errors: state.errors 34 | }; 35 | } 36 | 37 | // this maps action creators to dispatch, available as props on component 38 | function mapDispatchToProps(dispatch) { 39 | return bindActionCreators({ click, resetErrors, createFetchAction, updateUser }, dispatch); 40 | } 41 | 42 | // fetch triggers on both server and client 43 | @provideHooks({ 44 | fetch: prefetchRepos 45 | }) 46 | // mergeReposProps enriches dispatch props with reposForceFetch 47 | @connect(mapStateToProps, mapDispatchToProps, mergeReposProps) 48 | export default class Main extends React.Component { 49 | static propTypes = { 50 | // bound actions 51 | click: React.PropTypes.func.isRequired, 52 | resetErrors: React.PropTypes.func.isRequired, 53 | createFetchAction: React.PropTypes.func.isRequired, 54 | reposForceFetch: React.PropTypes.func.isRequired, 55 | updateUser: React.PropTypes.func.isRequired, 56 | repoUser: React.PropTypes.string, 57 | // connected values from store 58 | clicker: React.PropTypes.number, 59 | repositories: React.PropTypes.object, 60 | errors: React.PropTypes.array 61 | }; 62 | 63 | render() { 64 | return ( 65 |
66 | 67 | 68 | 69 | 70 | 71 | 77 | 78 |
79 | ); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /examples/complex/src/components/main/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rocjs/roc-package-web-app-react/26cd2b51acbfcaf3a61267ded00afb3a19907198/examples/complex/src/components/main/logo.png -------------------------------------------------------------------------------- /examples/complex/src/components/main/style.css: -------------------------------------------------------------------------------- 1 | .main { 2 | background: #fff; 3 | width: 700px; 4 | margin: auto; 5 | padding: 20px; 6 | } 7 | 8 | .logo { 9 | float: left; 10 | padding: 30px; 11 | margin: 0 20px 20px 0; 12 | border-radius: 8px; 13 | width: 200px; 14 | background: #2a7e8e; 15 | } 16 | -------------------------------------------------------------------------------- /examples/complex/src/components/main/util.js: -------------------------------------------------------------------------------- 1 | import { createFetchAction } from 'redux-fetcher'; 2 | import { FETCH_REPOS } from '../../reducers/repofetch'; 3 | 4 | const userUrl = (user) => `https://api.github.com/users/${user}/repos`; 5 | 6 | // compatible with redial '@provideHooks'-fetch 7 | export function prefetchRepos({ dispatch, getState }) { 8 | // read the repository source URL from state 9 | const user = getState().repoUser; 10 | 11 | // createFetchAction creates a redux action for us that will trigger 12 | // respective types WEATHER_FETCH_SUCCESS, WEATHER_FETCH_PENDING or WEATHER_FETCH_FAILURE. 13 | const reposAction = createFetchAction(FETCH_REPOS, userUrl(user)); 14 | 15 | // dispatch the action 16 | return dispatch(reposAction); 17 | } 18 | 19 | // compatible with react-redux third param 'mergeProps' 20 | export function mergeReposProps(stateProps, dispatchProps, ownProps) { 21 | // enrich dispatch props with a repos forced fetch, typically used for buttons 22 | const newDispatchProps = { 23 | ...dispatchProps, 24 | reposForceFetch: () => dispatchProps.createFetchAction( 25 | FETCH_REPOS, 26 | userUrl(stateProps.repoUser), 27 | { force: true, method: 'GET' } 28 | ) 29 | }; 30 | 31 | return Object.assign({}, ownProps, stateProps, newDispatchProps); 32 | } 33 | -------------------------------------------------------------------------------- /examples/complex/src/components/repo/button.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import sharedStyles from '../shared.css'; 3 | 4 | export default class RepoUpdateButton extends Component { 5 | static propTypes = { 6 | text: React.PropTypes.string, 7 | onClick: React.PropTypes.func 8 | }; 9 | 10 | render() { 11 | return ( 12 | 17 | ); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/complex/src/components/repo/data.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import styles from './style.css'; 4 | 5 | export default class RepoData extends Component { 6 | static propTypes = { 7 | city: React.PropTypes.object, 8 | list: React.PropTypes.array 9 | }; 10 | 11 | render() { 12 | const repos = []; 13 | 14 | Object.keys(this.props).forEach((repo, i) => { 15 | const repoData = this.props[repo]; 16 | 17 | repos.push( 18 |
19 | 30 |
31 | ); 32 | }); 33 | 34 | return ( 35 |
36 |

Fetched repo data

37 |
38 | { repos } 39 |
40 |
41 | ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /examples/complex/src/components/repo/error.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | export default class RepoError extends Component { 4 | static propTypes = { 5 | error: React.PropTypes.string 6 | }; 7 | 8 | render() { 9 | return ( 10 |
11 |

Error loading repos data.

12 | { this.props.error } 13 |
14 | ); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/complex/src/components/repo/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import styles from './style.css'; 4 | 5 | import RepoLoader from './loader'; 6 | import RepoError from './error'; 7 | import RepoData from './data'; 8 | import RepoUpdateButton from './button'; 9 | 10 | export default class Repo extends Component { 11 | static propTypes = { 12 | payload: React.PropTypes.oneOfType([React.PropTypes.object, React.PropTypes.array]), 13 | loading: React.PropTypes.bool, 14 | endpoint: React.PropTypes.string, 15 | reposForceFetch: React.PropTypes.func, 16 | updateUser: React.PropTypes.func, 17 | repoUser: React.PropTypes.string, 18 | error: React.PropTypes.bool 19 | }; 20 | 21 | render() { 22 | let buttonText, data; 23 | 24 | if (this.props.error) { 25 | buttonText = 'Oops! Try again.'; 26 | data = 27 | } else if (this.props.loading) { 28 | buttonText = 'Try again.'; 29 | data = 30 | } else if (!this.props.payload && !this.props.loading) { 31 | buttonText = 'No data provided. Try again.'; 32 | } else { 33 | buttonText = 'Reload repos data.'; 34 | data = 35 | } 36 | 37 | return ( 38 |
39 | 40 | 41 | { 46 | this.props.updateUser(e.target.value) 47 | } 48 | } 49 | /> 50 | 51 | 55 | { data } 56 |
57 | ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /examples/complex/src/components/repo/loader.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | export default class Repo extends Component { 4 | static propTypes = { 5 | endpoint: React.PropTypes.string 6 | }; 7 | 8 | render() { 9 | const source = this.props.endpoint ? ` from ${this.props.endpoint}` : ''; 10 | 11 | return ( 12 |
13 | { `Loading repos data${source}...` } 14 |
15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/complex/src/components/repo/style.css: -------------------------------------------------------------------------------- 1 | .repos { 2 | margin: 20px 0 20px 0; 3 | 4 | input { 5 | padding: 4px; 6 | width: 50%; 7 | } 8 | } 9 | 10 | .data { 11 | font-size: 12px; 12 | } 13 | 14 | .list { 15 | list-style-type: none; 16 | margin-bottom: 20px; 17 | } 18 | 19 | 20 | -------------------------------------------------------------------------------- /examples/complex/src/components/shared.css: -------------------------------------------------------------------------------- 1 | .button { 2 | margin: 0 0 0 1%; 3 | border: 0; 4 | border-radius: 8px; 5 | width: 20%; 6 | background: #2a7e8e; 7 | color: #fff; 8 | padding: 4px; 9 | } 10 | -------------------------------------------------------------------------------- /examples/complex/src/components/simple/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import Toggle from 'react-toggle'; 4 | 5 | import 'react-toggle/style.css?modules=false'; 6 | 7 | export default class Simple extends Component { 8 | 9 | constructor() { 10 | super(); 11 | this.state = { enabled: false }; 12 | } 13 | 14 | render() { 15 | return ( 16 |
17 | { this.state.enabled ?

Something 🎉

:

Nothing ☹️

} 18 | 24 |
25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/complex/src/enhancers.js: -------------------------------------------------------------------------------- 1 | /* global __NODE__ __DEV__ */ 2 | 3 | export default function getEnhancers() { 4 | if (__NODE__) { 5 | // Add server enhancers here 6 | } else { 7 | // Add client enhancers here 8 | } 9 | 10 | if (__DEV__) { 11 | // Add dev enhancers here 12 | } 13 | 14 | return []; 15 | } 16 | -------------------------------------------------------------------------------- /examples/complex/src/koa-middlewares.js: -------------------------------------------------------------------------------- 1 | // Used as a silly example how a Koa middlware can acces the Redux store. 2 | // If we have a querystring then counter will on the server be incremented. 3 | 4 | // Important that the middlewares yield next for everyting to work correct 5 | 6 | const session = require('koa-session'); 7 | 8 | export default function middlewares(_, { server }) { 9 | server.keys = ['secret']; 10 | return [session(server), function* (next) { 11 | if (this.path == '/session/') { 12 | var n = this.session.views || 0; 13 | this.session.views = ++n; 14 | this.body = n + ' views'; 15 | } else { 16 | yield next; 17 | } 18 | 19 | }, function* (next) { 20 | if (this.querystring.length > 0) { 21 | this.state.reduxStore.dispatch({ 22 | type: 'CLICKED' 23 | }); 24 | } 25 | yield next; 26 | }, function* (next) { 27 | if (this.querystring.length > 0) { 28 | this.state.reduxStore.dispatch({ 29 | type: 'CLICKED' 30 | }); 31 | } 32 | yield next; 33 | }]; 34 | } 35 | -------------------------------------------------------------------------------- /examples/complex/src/middlewares.js: -------------------------------------------------------------------------------- 1 | /* global __NODE__ __DEV__ */ 2 | 3 | import { apiMiddleware } from 'redux-api-middleware'; 4 | 5 | export default function getMiddlewares() { 6 | if (__NODE__) { 7 | // Add server middlewares here 8 | } else { 9 | // Add client middlewares here 10 | } 11 | 12 | if (__DEV__) { 13 | // Add dev middlewares here 14 | } 15 | 16 | return [apiMiddleware]; 17 | } 18 | -------------------------------------------------------------------------------- /examples/complex/src/reducers.js: -------------------------------------------------------------------------------- 1 | export clicker from './reducers/clicker'; 2 | export repoUser from './reducers/repouser'; 3 | export repositories from './reducers/repofetch'; 4 | -------------------------------------------------------------------------------- /examples/complex/src/reducers/clicker.js: -------------------------------------------------------------------------------- 1 | const CLICKED = 'CLICKED'; 2 | 3 | export default function clicker(state = 0, action = {}) { 4 | if (action.type === CLICKED) { 5 | return state + 1; 6 | } 7 | 8 | return state; 9 | } 10 | 11 | export function click() { 12 | return { type: CLICKED }; 13 | } 14 | -------------------------------------------------------------------------------- /examples/complex/src/reducers/repofetch.js: -------------------------------------------------------------------------------- 1 | import { createFetchReducer } from 'redux-fetcher'; 2 | 3 | export const FETCH_REPOS = 'repositories'; 4 | export default createFetchReducer(FETCH_REPOS); 5 | -------------------------------------------------------------------------------- /examples/complex/src/reducers/repouser.js: -------------------------------------------------------------------------------- 1 | const UPDATE_REPO_USER = 'UPDATE_REPO_USER'; 2 | 3 | export default function reducer(state = 'rocjs', action = {}) { 4 | if (action.type === UPDATE_REPO_USER) { 5 | return action.user; 6 | } 7 | return state; 8 | } 9 | 10 | export function updateUser(user) { 11 | return { 12 | type: UPDATE_REPO_USER, 13 | user 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /examples/complex/src/routes.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Route from 'react-router/lib/Route'; 3 | import IndexRoute from 'react-router/lib/IndexRoute'; 4 | 5 | import App from './components/app'; 6 | import Main from './components/main'; 7 | import About from './components/about'; 8 | import Long from './components/long'; 9 | import Simple from './components/simple'; 10 | 11 | export default () => ( 12 | 13 | 14 | 15 | 16 | 17 | { 20 | require.ensure([], (require) => { 21 | const Async = require('./components/async').default; 22 | callback( 23 | null, 24 | Async 25 | ); 26 | }); 27 | }} 28 | data={4} 29 | /> 30 | 31 | ); 32 | 33 | export const middlewareConfig = { 34 | 'react-router-scroll-async': { 35 | /* 36 | This function will allow us to do two things. 37 | 38 | 1. Prevent the scroll behaviour on routes that has defined 39 | ignoreScrollBehavior on them to true or if a link has set 40 | the state with ignoreScrollBehavior to true. 41 | 42 | 2. Make sure we go to the top of the page if scrollToTop 43 | has been defined on the route or on the state of the link 44 | transition. 45 | 46 | Route: 47 | 48 | 49 | Link: 50 | Foo 51 | */ 52 | shouldUpdateScroll: (prevRouterProps, { routes, location }) => { 53 | if ( 54 | routes.some(route => route.ignoreScrollBehavior) || 55 | location.state && location.state.ignoreScrollBehavior 56 | ) { 57 | return false; 58 | } 59 | 60 | if ( 61 | routes.some(route => route.scrollToTop) || 62 | location.state && location.state.scrollToTop 63 | ) { 64 | return [0, 0]; 65 | } 66 | 67 | return true; 68 | }, 69 | }, 70 | }; 71 | -------------------------------------------------------------------------------- /examples/complex/src/sagas.js: -------------------------------------------------------------------------------- 1 | import { takeEvery } from 'redux-saga' 2 | import { put, call } from 'redux-saga/effects' 3 | import { delay } from 'redux-saga' 4 | 5 | export function* incrementAsync() { 6 | yield call(delay, 1000) 7 | yield put({type: 'CLICKED'}) 8 | } 9 | 10 | export default function* rootSaga() { 11 | yield* takeEvery('CLICKED_ASYNC', incrementAsync) 12 | } 13 | -------------------------------------------------------------------------------- /examples/complex/src/template-values.js: -------------------------------------------------------------------------------- 1 | export default function getTemplateValues(/* { koaState, settings, reduxState } */) { 2 | return { 3 | bodyClass: 'main' 4 | }; 5 | } 6 | -------------------------------------------------------------------------------- /examples/extensible-templates/main.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import styles from './style.css'; 4 | 5 | export default class Main extends React.Component { 6 | render() { 7 | //const image = require('./roc.png'); 8 | 9 | return ( 10 |
11 |

Bacon ipsum dolor?

12 |

13 | Bacon ipsum dolor amet hamburger swine filet mignon biltong shank, turkey alcatra brisket flank ribeye 14 | landjaeger beef ribs. Ham flank pancetta biltong pork belly shankle brisket doner beef. Pig sirloin turkey 15 | corned beef, alcatra biltong boudin pastrami. Tail pig pork filet mignon kevin chuck. Prosciutto ball tip 16 | flank jerky ham, porchetta fatback kevin swine alcatra spare ribs pancetta. Pork belly tenderloin meatball 17 | venison filet mignon andouille doner pork loin turducken strip steak. Shank andouille pig shankle. 18 | 19 | Drumstick shankle tri-tip pork chop salami bacon jowl. Shankle bacon tongue venison, brisket strip steak 20 | cupim meatball. Flank turducken tenderloin rump pork belly ribeye. Drumstick tenderloin turkey, short loin 21 | andouille meatloaf meatball brisket bresaola rump jowl. Drumstick tongue ball tip t-bone leberkas rump. 22 | 23 | Porchetta pastrami cow, short loin rump landjaeger brisket tongue beef bresaola pork chop drumstick. Swine 24 | t-bone tongue pork belly ham turducken alcatra rump pork loin flank ribeye meatloaf capicola short ribs. 25 | Flank ribeye shank, turkey pork chop tail tongue hamburger swine. Ham hock jowl meatloaf ham cow, rump 26 | drumstick shankle flank hamburger fatback prosciutto biltong. 27 | 28 | Landjaeger bacon kevin sausage, tail bresaola shank alcatra pastrami jerky. Kielbasa salami landjaeger 29 | ground round. Chicken ham brisket, boudin andouille corned beef jerky tri-tip short ribs kielbasa 30 | landjaeger beef biltong jowl bacon. Pork shank leberkas, picanha beef ribs spare ribs cow beef drumstick 31 | ball tip shankle short loin ground round pig. Picanha ground round venison pancetta drumstick ham biltong 32 | bresaola salami sausage beef ribs boudin pork chop jerky. Brisket jowl chicken, kevin tongue beef 33 | prosciutto meatloaf. 34 | 35 | Frankfurter meatball sausage turkey rump ham hock tongue doner leberkas drumstick jowl ground round filet 36 | mignon. Tenderloin sirloin salami, shoulder ham landjaeger corned beef pastrami cow porchetta capicola 37 | boudin tongue rump. Pork loin sirloin rump landjaeger drumstick pastrami frankfurter andouille doner 38 | salami flank shoulder. Fatback bacon turducken frankfurter. Pancetta ground round flank pork, sausage pork 39 | chop doner bacon ribeye shank tail filet mignon jowl swine short ribs. Jerky shank prosciutto ham hock 40 | kevin picanha meatball short loin pork loin shankle ground round brisket pork belly. 41 | 42 | Chuck pig tri-tip, doner meatloaf rump ball tip tenderloin venison leberkas. Pork loin biltong t-bone 43 | turducken. Jerky pork loin pork short ribs pastrami biltong, turkey meatball kevin sausage. Alcatra strip 44 | steak corned beef, beef ribs andouille tenderloin biltong ribeye chuck. Doner chuck biltong venison pork 45 | belly tail fatback cow t-bone short ribs ham hock jowl hamburger frankfurter meatball. 46 | 47 | Sausage beef ribs tail shoulder pork belly shank prosciutto pork tri-tip sirloin t-bone. Ground round spare 48 | ribs turducken tongue. Shank tenderloin meatloaf, beef tongue beef ribs pastrami. Porchetta short ribs 49 | sirloin, bacon drumstick prosciutto doner kevin pancetta tri-tip fatback. 50 | 51 | Meatloaf salami biltong shank, venison cow drumstick picanha capicola doner short loin. Doner filet mignon 52 | biltong meatloaf. Filet mignon ribeye tail porchetta strip steak shoulder chicken short ribs. Strip steak 53 | tenderloin pig filet mignon spare ribs, capicola pork loin prosciutto ground round leberkas tail chuck 54 | porchetta biltong. Corned beef brisket frankfurter tongue capicola venison. Tail jowl ham venison. 55 | 56 | Venison spare ribs shank beef ribs sausage pork chop capicola jerky. Sirloin spare ribs ribeye strip steak 57 | cow beef fatback brisket pork ball tip doner hamburger. Pork loin fatback swine kielbasa doner alcatra 58 | salami porchetta drumstick tongue ground round. Strip steak sausage sirloin rump shoulder t-bone. Meatloaf 59 | corned beef sausage, chuck ground round short ribs porchetta tri-tip. Hamburger kielbasa cow, picanha 60 | boudin capicola rump pastrami ball tip pork chop swine. 61 | 62 | Chuck landjaeger pork, pork loin shankle tri-tip pastrami flank kielbasa picanha drumstick cupim chicken 63 | beef. Pork loin frankfurter short loin, pancetta cupim ribeye jerky turkey beef ribs tri-tip meatball 64 | swine tail flank. Pastrami salami turkey, turducken ball tip venison meatloaf sirloin pork chop drumstick 65 | short loin. Andouille sirloin pig, tongue pork chop pastrami meatball filet mignon beef ribs chuck fatback. 66 |

67 |
68 | ); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /examples/extensible-templates/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "roc-web-react-extensible-templates-example", 3 | "version": "1.0.0", 4 | "description": "Roc Web React simple example", 5 | "author": "Patrik Åkerstrand ", 6 | "license": "MIT", 7 | "scripts": { 8 | "dev": "roc dev" 9 | }, 10 | "dependencies": { 11 | "roc-package-web-app-react": "*" 12 | }, 13 | "devDependencies": { 14 | "roc-package-web-app-react-dev": "*" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/extensible-templates/public/static.css: -------------------------------------------------------------------------------- 1 | header { 2 | display: flex; 3 | flex-wrap: wrap; 4 | align-items: center; 5 | height: 50px; 6 | background: darkblue; 7 | color: #fefefe; 8 | } 9 | 10 | header > .main, header > .item { 11 | flex: 1 1 auto; 12 | display: inline-flex; 13 | justify-content: center; 14 | align-items: center; 15 | } 16 | 17 | header > .main { 18 | flex: 0 0 100%; 19 | } 20 | 21 | footer { 22 | display: flex; 23 | flex-direction: column; 24 | justify-content: center; 25 | align-items: center; 26 | background: darkblue; 27 | color: #fefefe; 28 | height: 100px; 29 | } 30 | -------------------------------------------------------------------------------- /examples/extensible-templates/roc.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | settings: { 5 | runtime: { 6 | applicationName: 'Extensible templates', 7 | serve: ['public'], 8 | template: { 9 | path: './views', 10 | name: 'entry.njk', 11 | }, 12 | }, 13 | build: { 14 | routes: './routes', 15 | }, 16 | }, 17 | project: { 18 | actions: [ 19 | { 20 | hook: 'extend-template', 21 | action: () => () => () => ({ 22 | path: path.resolve('./views'), 23 | namespace: 'testA', 24 | template: 'A/a.njk', 25 | }), 26 | }, 27 | { 28 | hook: 'extend-template', 29 | action: () => () => () => ({ 30 | namespace: 'testB', 31 | template: 'B/b.njk', 32 | }), 33 | }, 34 | { 35 | hook: 'extend-template', 36 | action: () => () => () => ({ 37 | namespace: 'testC', 38 | template: 'C/c.njk', 39 | }), 40 | }, 41 | { 42 | hook: 'get-template-values', 43 | action: () => () => (previousValue) => Object.assign(previousValue, { 44 | project: Object.assign({}, previousValue.project, { 45 | a: 'Custom data A', 46 | b: 'B has additional custom data', 47 | }), 48 | }), 49 | }, 50 | { 51 | hook: 'get-template-values', 52 | action: () => () => (previousValue) => Object.assign(previousValue, { 53 | project: Object.assign({}, previousValue.project, { 54 | c: 'Merged with previous value', 55 | }), 56 | }), 57 | }, 58 | ], 59 | }, 60 | }; 61 | -------------------------------------------------------------------------------- /examples/extensible-templates/roc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rocjs/roc-package-web-app-react/26cd2b51acbfcaf3a61267ded00afb3a19907198/examples/extensible-templates/roc.png -------------------------------------------------------------------------------- /examples/extensible-templates/routes.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Route, IndexRoute } from 'react-router'; 3 | 4 | import Main from './main'; 5 | 6 | export default () => ( 7 | 8 | ); 9 | -------------------------------------------------------------------------------- /examples/extensible-templates/style.css: -------------------------------------------------------------------------------- 1 | .main { 2 | background: #fff; 3 | width: 700px; 4 | margin: auto; 5 | padding: 20px; 6 | } 7 | -------------------------------------------------------------------------------- /examples/extensible-templates/views/A/a.njk: -------------------------------------------------------------------------------- 1 | {%- extends inheritance.testA -%} 2 | 3 | {%- block bodyPreApplication -%} 4 | {{ super() }} 5 |
{{ custom.project.a }}
6 | {%- endblock -%} 7 | -------------------------------------------------------------------------------- /examples/extensible-templates/views/B/b.njk: -------------------------------------------------------------------------------- 1 | {%- extends inheritance.testB -%} 2 | 3 | {%- block bodyPreApplication -%} 4 | {{ super() }} 5 |
{{ custom.project.b }}
6 | {%- endblock -%} 7 | {% block bodyPostApplication %} 8 | {{ super() }} 9 |

10 | It's not part of the React application, but defined in the template 11 |

12 | {% endblock %} 13 | -------------------------------------------------------------------------------- /examples/extensible-templates/views/C/c.njk: -------------------------------------------------------------------------------- 1 | {%- extends inheritance.testC -%} 2 | 3 | {%- block bodyPreApplication -%} 4 | {{ super() }} 5 |
{{ custom.project.c }}
6 | {%- endblock -%} 7 | -------------------------------------------------------------------------------- /examples/extensible-templates/views/entry.njk: -------------------------------------------------------------------------------- 1 | {%- extends parentTemplate -%} 2 | 3 | {% block head %} 4 | 5 | {% endblock %} 6 | 7 | {%- block bodyPreApplication -%} 8 |
9 |
10 | This is a very nice static header. 11 |
12 | {{ super() }} 13 |
14 | {%- endblock -%} 15 | 16 | {% block bodyPostApplication %} 17 |
18 |

19 | This is a very nice static footer. 20 |

21 | {{ super() }} 22 |
23 | {% endblock %} 24 | 25 | {% block bodyScripts %} 26 | {{ super() }} 27 | 28 | {% endblock %} 29 | -------------------------------------------------------------------------------- /examples/realtime-redux/components/stock-event-list/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import styles from './style.css'; 4 | import StockEventView from '../stock-event'; 5 | 6 | export default class StockEventListView extends React.Component { 7 | static propTypes = { 8 | numToDisplay: React.PropTypes.number, 9 | events: React.PropTypes.array.isRequired 10 | }; 11 | 12 | static defaultProps = { 13 | numToDisplay: 7, 14 | events: [] 15 | }; 16 | 17 | render() { 18 | const events = this.props.events.map((event) => { 19 | return ( 20 | 26 | ); 27 | }); 28 | 29 | return ( 30 |
31 | { events } 32 |
33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /examples/realtime-redux/components/stock-event-list/style.css: -------------------------------------------------------------------------------- 1 | .list { 2 | width: 250px; 3 | float: right; 4 | } 5 | -------------------------------------------------------------------------------- /examples/realtime-redux/components/stock-event/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import styles from './style.scss'; 4 | 5 | export default class StockEventView extends React.Component { 6 | static propTypes = { 7 | name: React.PropTypes.string.isRequired, 8 | current: React.PropTypes.number.isRequired, 9 | diff: React.PropTypes.number.isRequired 10 | }; 11 | 12 | static defaultProps = { 13 | name: '', 14 | current: 0, 15 | diff: 0 16 | }; 17 | 18 | render() { 19 | const diffClass = this.props.diff < 0 ? styles.down : styles.up; 20 | 21 | return ( 22 |
23 |
24 | { this.props.name } 25 |
26 |
27 | { this.props.current } 28 |
29 |
30 | { this.props.diff } 31 |
32 |
33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /examples/realtime-redux/components/stock-event/style.scss: -------------------------------------------------------------------------------- 1 | .event { 2 | text-align: center; 3 | font-size: 12px; 4 | border: 1px solid; 5 | border-radius: 4px; 6 | padding: 10px; 7 | margin: 0 0 4px 0; 8 | background: rgba(151,187,205, 0.7); 9 | animation: fadein 0.5s; 10 | height: 65px; 11 | @keyframes fadein { 12 | from { font-size: 0; padding: 0; height: 5px; } 13 | } 14 | } 15 | 16 | .name { 17 | font-weight: bold; 18 | } 19 | 20 | .up { 21 | color: green; 22 | } 23 | 24 | .down { 25 | color: red; 26 | } 27 | -------------------------------------------------------------------------------- /examples/realtime-redux/components/stock-graph-list/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import styles from './style.css'; 4 | import StockGraphView from '../stock-graph'; 5 | 6 | export default class StockGraphList extends React.Component { 7 | static propTypes = { 8 | graphs: React.PropTypes.object.isRequired 9 | }; 10 | 11 | static defaultProps = { 12 | graphs: {} 13 | }; 14 | 15 | render() { 16 | const graphs = Object.keys(this.props.graphs).map((e) => { 17 | const graph = this.props.graphs[e]; 18 | return ; 19 | }); 20 | 21 | return ( 22 |
23 |

SSE Graphed Events

24 | { graphs } 25 |
26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /examples/realtime-redux/components/stock-graph-list/style.css: -------------------------------------------------------------------------------- 1 | .graphs { 2 | width: 500px; 3 | float: left; 4 | } 5 | -------------------------------------------------------------------------------- /examples/realtime-redux/components/stock-graph/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Line as LineChart } from 'react-chartjs'; 3 | 4 | import styles from './style.css'; 5 | 6 | export default class StockGraphView extends React.Component { 7 | static propTypes = { 8 | points: React.PropTypes.number.isRequired, 9 | data: React.PropTypes.object.isRequired 10 | }; 11 | 12 | static defaultProps = { 13 | points: 15, 14 | data: { 15 | LONG_NAME: 'Loading...', 16 | TICKER: 'Loading...', 17 | LAST: '-', 18 | CHANGE: '-', 19 | times: [], 20 | index: [] 21 | } 22 | }; 23 | 24 | render() { 25 | const header = `${this.props.data.LONG_NAME} (${this.props.data.TICKER})`; 26 | const chart = livePresentationView(this.props); 27 | 28 | return ( 29 |
30 |

{ header }

31 | Nå: {this.props.data.LAST}
32 | Endring: {this.props.data.CHANGE}
33 | { chart } 34 |
35 | ); 36 | } 37 | } 38 | 39 | const calculateChartData = (props) => { 40 | return { 41 | labels: props.data.times, 42 | datasets: [ 43 | { 44 | label: 'Main Index', 45 | fillColor: 'rgba(151,187,205,0.2)', 46 | strokeColor: 'rgba(151,187,205,1)', 47 | pointColor: 'rgba(151,187,205,1)', 48 | pointStrokeColor: '#fff', 49 | pointHighlightFill: '#fff', 50 | pointHighlightStroke: 'rgba(151,187,205,1)', 51 | data: props.data.index 52 | } 53 | ] 54 | }; 55 | }; 56 | 57 | const plotDataCollectComplete = (props) => props.data.index.length >= props.points; 58 | const plotDataCollectProgress = (props) => Math.floor(props.data.index.length / props.points * 100) + '%'; 59 | 60 | const graphView = (props) => React.createElement(LineChart, { data: calculateChartData(props), width: 500 }); 61 | const progressView = (props) => React.createElement('h3', null, 'Collecting Data: ' + plotDataCollectProgress(props)); 62 | const livePresentationView = (props) => plotDataCollectComplete(props) ? graphView(props) : progressView(props); 63 | -------------------------------------------------------------------------------- /examples/realtime-redux/components/stock-graph/style.css: -------------------------------------------------------------------------------- 1 | .graph { 2 | margin: 0 0 40px 0; 3 | } 4 | -------------------------------------------------------------------------------- /examples/realtime-redux/components/stock/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import StockEventListView from '../stock-event-list'; 4 | import StockGraphListView from '../stock-graph-list'; 5 | import styles from './style.css'; 6 | 7 | export default class StockView extends React.Component { 8 | static propTypes = { 9 | data: React.PropTypes.object.isRequired 10 | }; 11 | 12 | static defaultProps = { 13 | data: { 14 | graphs: {}, 15 | events: [] 16 | } 17 | }; 18 | 19 | render() { 20 | return ( 21 |
22 | 23 | 24 |
25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/realtime-redux/components/stock/style.css: -------------------------------------------------------------------------------- 1 | .stock { 2 | position: relative; 3 | background: #fff; 4 | border: 1px solid; 5 | font-size: 14px; 6 | font-family: "Helvetica"; 7 | padding: 10px; 8 | height: 650px; 9 | } 10 | -------------------------------------------------------------------------------- /examples/realtime-redux/config/custom-environment-variables.json: -------------------------------------------------------------------------------- 1 | { 2 | "stock": { 3 | "sseSource": "STOCK_SSE_SOURCE", 4 | "restSource": "STOCK_REST_SOURCE", 5 | "collect": "STOCK_COLLECT" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /examples/realtime-redux/config/default.json: -------------------------------------------------------------------------------- 1 | { 2 | "stock": { 3 | "sseSource": "http://sse.e24.no/market", 4 | "restSource": "http://bors.e24.no/e24/servlets/newt/json/instrument?ticker=", 5 | "collect": [ 6 | "OSEBX.OSE", 7 | "C:PBROUSDBR\\SP.IDCENE" 8 | ] 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/realtime-redux/main.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { bindActionCreators } from 'redux'; 3 | import { connect } from 'react-redux'; 4 | import { provideHooks } from 'redial'; 5 | 6 | import { appConfig } from 'roc-package-web-app-react/app/shared'; 7 | 8 | import { stockLoad, stockError } from './stock'; 9 | import * as rest from './util/rest'; 10 | import * as sse from './util/sse'; 11 | import StockView from './components/stock'; 12 | import styles from './style.scss'; 13 | 14 | function mapStateToProps(state) { 15 | return { 16 | data: state.stock.data, 17 | errors: state.stock.errors 18 | }; 19 | } 20 | 21 | function mapDispatchToProps(dispatch) { 22 | return bindActionCreators({ stockLoad, stockError }, dispatch); 23 | } 24 | 25 | @provideHooks({ fetch: ({ dispatch }) => { 26 | const dataForServer = rest.fetchServerData(); 27 | 28 | if (dataForServer) { 29 | return dataForServer 30 | .then(rest.getTickerData) 31 | .then(rest.createEventsFromTickerData) 32 | .then(rest.handleEvents(dispatch, stockLoad, stockError)) 33 | .catch(rest.handleFetchDataError(dispatch, stockError)); 34 | } 35 | } }) 36 | @connect(mapStateToProps, mapDispatchToProps) 37 | export default class Stock extends React.Component { 38 | static propTypes = { 39 | data: React.PropTypes.object.isRequired, 40 | errors: React.PropTypes.array, 41 | stockLoad: React.PropTypes.func.isRequired, 42 | stockError: React.PropTypes.func.isRequired 43 | }; 44 | 45 | static defaultProps = { 46 | data: {}, 47 | errors: [] 48 | }; 49 | 50 | // provides realtime datastream clientside 51 | componentDidMount() { 52 | this.sseSub = sse.subscribe(appConfig.sseSource, (stockEvent) => { 53 | const data = JSON.parse(stockEvent.data); 54 | this.props.stockLoad([data]); 55 | }); 56 | } 57 | 58 | componentWillUnmount() { 59 | if (this.sseSub) { 60 | this.sseSub.close(); 61 | } 62 | } 63 | 64 | render() { 65 | const errors = this.props.errors.map((error, key) => { 66 | return ( 67 |

{error}

68 | ); 69 | }); 70 | 71 | return ( 72 |
73 |
74 | { errors.length > 0 ? errors : } 75 |
76 |
77 | ); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /examples/realtime-redux/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "roc-package-web-app-react-realtime-example", 3 | "version": "1.0.0", 4 | "description": "Roc Web React realtime example", 5 | "author": "VG", 6 | "license": "MIT", 7 | "dependencies": { 8 | "roc-package-web-app-react": "*", 9 | "chart.js": "^1.0.2", 10 | "isomorphic-fetch": "^2.2.0", 11 | "react-chartjs": "^0.6.0" 12 | }, 13 | "devDependencies": { 14 | "roc-package-web-app-react-dev": "*", 15 | "roc-plugin-style-sass": "^1.0.0-beta.2" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/realtime-redux/reducers.js: -------------------------------------------------------------------------------- 1 | export stock from './stock'; 2 | -------------------------------------------------------------------------------- /examples/realtime-redux/roc.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | settings: { 3 | runtime: { 4 | applicationName: 'Stock live demo', 5 | configWhitelistProperty: 'stock' 6 | }, 7 | build: { 8 | routes: 'routes.js', 9 | reducers: 'reducers.js', 10 | }, 11 | }, 12 | }; 13 | -------------------------------------------------------------------------------- /examples/realtime-redux/routes.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Route, IndexRoute } from 'react-router'; 3 | 4 | import Main from './main'; 5 | 6 | export default () => ( 7 | 8 | ); 9 | -------------------------------------------------------------------------------- /examples/realtime-redux/stock.js: -------------------------------------------------------------------------------- 1 | import { appConfig } from 'roc-package-web-app-react/app/shared'; 2 | 3 | const STOCK_LOAD = 'STOCK_LOAD'; 4 | const STOCK_REMOVE = 'STOCK_REMOVE'; 5 | const STOCK_LOAD_ERROR = 'STOCK_LOAD_ERROR'; 6 | 7 | function createGraph(name, event, point) { 8 | const index = [point]; 9 | const times = []; 10 | 11 | for (let i = 1; i <= 15; i++) { 12 | times.push(i); 13 | } 14 | 15 | return { ...event, index, times }; 16 | } 17 | 18 | function updateGraph(event, graph, point) { 19 | const index = [...graph.index]; 20 | const times = [...graph.times]; 21 | 22 | index.push(point); 23 | 24 | return { ...event, index: index.slice(-15), times }; 25 | } 26 | 27 | export default function reducer( 28 | state = { data: { graphs: {}, events: []}, errors: [] }, 29 | action = { data: [], errors: [] } 30 | ) { 31 | if (action.type === STOCK_LOAD) { 32 | // get copy of action data 33 | const newEvents = [ ...action.data ]; 34 | 35 | // get copy of existing events 36 | const events = [...state.data.events]; 37 | 38 | // get copy of current graph data 39 | const graphs = {...state.data.graphs }; 40 | 41 | // the tickers we want to generate graph data for from configuration 42 | const tickersToGraph = appConfig.collect; 43 | 44 | for (const event of newEvents) { 45 | // build event key, used by react motion 46 | event.key = event.TICKER + event.LAST + event.TIME; 47 | 48 | // ignore identical events 49 | if (state.data.events.find(e => e.key === event.key)) { 50 | continue; 51 | } 52 | 53 | // add to events 54 | events.unshift(event); 55 | 56 | // graph ticker if configured 57 | if (tickersToGraph.indexOf(event.TICKER) > -1) { 58 | const graph = graphs[event.TICKER]; 59 | const graphPoint = parseFloat(event.LAST.toFixed(2)); 60 | 61 | if (graph) { 62 | graphs[event.TICKER] = updateGraph(event, graph, graphPoint); 63 | } else { 64 | graphs[event.TICKER] = createGraph(event.TICKER, event, graphPoint); 65 | } 66 | } 67 | } 68 | 69 | return { 70 | ...state, 71 | errors: [], 72 | data: { 73 | graphs, 74 | events: events.slice(0,9) 75 | } 76 | }; 77 | } else if (action.type === STOCK_LOAD_ERROR) { 78 | const errors = [ ...action.errors ]; 79 | const errorTexts = []; 80 | 81 | for (const error of errors) { 82 | if (error.message) { 83 | errorTexts.push(error.message); 84 | } else { 85 | errorTexts.push(error); 86 | } 87 | } 88 | 89 | return { 90 | ...state, 91 | data: {}, 92 | errors: errorTexts 93 | }; 94 | } 95 | 96 | return state; 97 | } 98 | 99 | export function stockLoad(data) { 100 | return { type: STOCK_LOAD, data }; 101 | } 102 | 103 | export function stockError(errors) { 104 | return { type: STOCK_LOAD_ERROR, errors }; 105 | } 106 | -------------------------------------------------------------------------------- /examples/realtime-redux/style.scss: -------------------------------------------------------------------------------- 1 | .stock { 2 | background: #fff; 3 | width: 800px; 4 | margin: auto; 5 | } 6 | -------------------------------------------------------------------------------- /examples/realtime-redux/util/rest.js: -------------------------------------------------------------------------------- 1 | /* globals __NODE__ */ 2 | import { appConfig } from 'roc-package-web-app-react/app/shared'; 3 | 4 | /** 5 | * Promises to return data from configured rest endpoint 6 | * 7 | * @return {Promise} data 8 | */ 9 | export function fetchServerData() { 10 | if (__NODE__) { 11 | let fetchTickers = []; 12 | const fetch = require('isomorphic-fetch'); 13 | for (const ticker of appConfig.collect) { 14 | const tickerUrl = appConfig.restSource + encodeURIComponent(ticker); 15 | fetchTickers.push(fetch(tickerUrl)); 16 | } 17 | 18 | return Promise.all(fetchTickers); 19 | } 20 | } 21 | 22 | /** 23 | * Promises to extract all tickers from raw responses 24 | * 25 | * @return {Promise} tickers 26 | */ 27 | export function getTickerData(responses) { 28 | const tickers = []; 29 | 30 | for (const response of responses) { 31 | if (response.status < 400) { 32 | tickers.push(response.json()); 33 | } 34 | } 35 | 36 | return Promise.all(tickers); 37 | } 38 | 39 | /** Promises to create event objects from ticker data 40 | * @param {array} tickersData 41 | * 42 | * @return {Promise} ticker data 43 | */ 44 | export function createEventsFromTickerData(tickersData) { 45 | return new Promise((resolve) => { 46 | const events = []; 47 | 48 | for (const tickerJson of tickersData) { 49 | const eventJson = tickerJson[0]; 50 | 51 | events.push({ 52 | TICKER: eventJson.it, 53 | TIME: eventJson.tu, 54 | LAST: eventJson.la, 55 | CHANGE: eventJson.ch, 56 | LONG_NAME: eventJson.ln 57 | }); 58 | } 59 | resolve(events); 60 | }); 61 | } 62 | 63 | /** Event handling function using given dispatcher and handlers 64 | * 65 | * @param {function} dispatch 66 | * @param {function} onSuccess 67 | * @param {function} onError 68 | * 69 | * @return {function} eventHandler 70 | */ 71 | export function handleEvents(dispatch, onSuccess, onError) { 72 | return (events) => { 73 | return new Promise((resolve, reject) => { 74 | if (events.length > 0) { 75 | dispatch(onSuccess(events)); 76 | return resolve(events.length); 77 | } 78 | 79 | dispatch(onError(new Error('No events found'))); 80 | return reject(0); 81 | }); 82 | }; 83 | } 84 | 85 | /** Error handling function using given dispatcher and error handler 86 | * 87 | * @param {function} dispatch 88 | * @param {function} onError 89 | * 90 | * @return {function} errorHandler 91 | */ 92 | export function handleFetchDataError(dispatch, onError) { 93 | return (error) => { 94 | const errorAction = onError([error]); 95 | return dispatch(errorAction); 96 | }; 97 | } 98 | -------------------------------------------------------------------------------- /examples/realtime-redux/util/sse.js: -------------------------------------------------------------------------------- 1 | export function subscribe(url, onMessage, onOpen, onError) { 2 | if (!!window.EventSource) { 3 | const source = new window.EventSource(url); 4 | if (onMessage) { 5 | source.addEventListener('message', onMessage); 6 | } 7 | if (onOpen) { 8 | source.addEventListener('open', onOpen); 9 | } 10 | if (onError) { 11 | source.addEventListener('error', onError); 12 | } 13 | 14 | return source; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/simple-redux/clicker.js: -------------------------------------------------------------------------------- 1 | const CLICKED = 'CLICKED'; 2 | 3 | export default function clicker(state = 0, action = {}) { 4 | if (action.type === CLICKED) { 5 | return state + 1; 6 | } 7 | 8 | return state; 9 | } 10 | 11 | export function click() { 12 | return { type: CLICKED }; 13 | } 14 | -------------------------------------------------------------------------------- /examples/simple-redux/main.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { bindActionCreators } from 'redux'; 3 | import { connect } from 'react-redux'; 4 | 5 | import { click } from './clicker'; 6 | 7 | import styles from './style.scss'; 8 | 9 | function mapStateToProps(state) { 10 | return { 11 | clicker: state.clicker 12 | }; 13 | } 14 | 15 | function mapDispatchToProps(dispatch) { 16 | return bindActionCreators({ click }, dispatch); 17 | } 18 | 19 | @connect(mapStateToProps, mapDispatchToProps) 20 | export default class Main extends React.Component { 21 | static propTypes = { 22 | clicker: React.PropTypes.number.isRequired, 23 | click: React.PropTypes.func.isRequired 24 | }; 25 | 26 | render() { 27 | return ( 28 |
29 |

Bacon ipsum dolor

30 |
31 | { this.props.clicker } 32 |
33 |

34 | Bacon ipsum dolor amet hamburger swine filet mignon biltong shank, turkey alcatra brisket flank ribeye 35 | landjaeger beef ribs. Ham flank pancetta biltong pork belly shankle brisket doner beef. Pig sirloin turkey 36 | corned beef, alcatra biltong boudin pastrami. Tail pig pork filet mignon kevin chuck. Prosciutto ball tip 37 | flank jerky ham, porchetta fatback kevin swine alcatra spare ribs pancetta. Pork belly tenderloin meatball 38 | venison filet mignon andouille doner pork loin turducken strip steak. Shank andouille pig shankle. 39 | 40 | Drumstick shankle tri-tip pork chop salami bacon jowl. Shankle bacon tongue venison, brisket strip steak 41 | cupim meatball. Flank turducken tenderloin rump pork belly ribeye. Drumstick tenderloin turkey, short loin 42 | andouille meatloaf meatball brisket bresaola rump jowl. Drumstick tongue ball tip t-bone leberkas rump. 43 | 44 | Porchetta pastrami cow, short loin rump landjaeger brisket tongue beef bresaola pork chop drumstick. Swine 45 | t-bone tongue pork belly ham turducken alcatra rump pork loin flank ribeye meatloaf capicola short ribs. 46 | Flank ribeye shank, turkey pork chop tail tongue hamburger swine. Ham hock jowl meatloaf ham cow, rump 47 | drumstick shankle flank hamburger fatback prosciutto biltong. 48 | 49 | Landjaeger bacon kevin sausage, tail bresaola shank alcatra pastrami jerky. Kielbasa salami landjaeger 50 | ground round. Chicken ham brisket, boudin andouille corned beef jerky tri-tip short ribs kielbasa 51 | landjaeger beef biltong jowl bacon. Pork shank leberkas, picanha beef ribs spare ribs cow beef drumstick 52 | ball tip shankle short loin ground round pig. Picanha ground round venison pancetta drumstick ham biltong 53 | bresaola salami sausage beef ribs boudin pork chop jerky. Brisket jowl chicken, kevin tongue beef 54 | prosciutto meatloaf. 55 | 56 | Frankfurter meatball sausage turkey rump ham hock tongue doner leberkas drumstick jowl ground round filet 57 | mignon. Tenderloin sirloin salami, shoulder ham landjaeger corned beef pastrami cow porchetta capicola 58 | boudin tongue rump. Pork loin sirloin rump landjaeger drumstick pastrami frankfurter andouille doner 59 | salami flank shoulder. Fatback bacon turducken frankfurter. Pancetta ground round flank pork, sausage pork 60 | chop doner bacon ribeye shank tail filet mignon jowl swine short ribs. Jerky shank prosciutto ham hock 61 | kevin picanha meatball short loin pork loin shankle ground round brisket pork belly. 62 | 63 | Chuck pig tri-tip, doner meatloaf rump ball tip tenderloin venison leberkas. Pork loin biltong t-bone 64 | turducken. Jerky pork loin pork short ribs pastrami biltong, turkey meatball kevin sausage. Alcatra strip 65 | steak corned beef, beef ribs andouille tenderloin biltong ribeye chuck. Doner chuck biltong venison pork 66 | belly tail fatback cow t-bone short ribs ham hock jowl hamburger frankfurter meatball. 67 | 68 | Sausage beef ribs tail shoulder pork belly shank prosciutto pork tri-tip sirloin t-bone. Ground round spare 69 | ribs turducken tongue. Shank tenderloin meatloaf, beef tongue beef ribs pastrami. Porchetta short ribs 70 | sirloin, bacon drumstick prosciutto doner kevin pancetta tri-tip fatback. 71 | 72 | Meatloaf salami biltong shank, venison cow drumstick picanha capicola doner short loin. Doner filet mignon 73 | biltong meatloaf. Filet mignon ribeye tail porchetta strip steak shoulder chicken short ribs. Strip steak 74 | tenderloin pig filet mignon spare ribs, capicola pork loin prosciutto ground round leberkas tail chuck 75 | porchetta biltong. Corned beef brisket frankfurter tongue capicola venison. Tail jowl ham venison. 76 | 77 | Venison spare ribs shank beef ribs sausage pork chop capicola jerky. Sirloin spare ribs ribeye strip steak 78 | cow beef fatback brisket pork ball tip doner hamburger. Pork loin fatback swine kielbasa doner alcatra 79 | salami porchetta drumstick tongue ground round. Strip steak sausage sirloin rump shoulder t-bone. Meatloaf 80 | corned beef sausage, chuck ground round short ribs porchetta tri-tip. Hamburger kielbasa cow, picanha 81 | boudin capicola rump pastrami ball tip pork chop swine. 82 | 83 | Chuck landjaeger pork, pork loin shankle tri-tip pastrami flank kielbasa picanha drumstick cupim chicken 84 | beef. Pork loin frankfurter short loin, pancetta cupim ribeye jerky turkey beef ribs tri-tip meatball 85 | swine tail flank. Pastrami salami turkey, turducken ball tip venison meatloaf sirloin pork chop drumstick 86 | short loin. Andouille sirloin pig, tongue pork chop pastrami meatball filet mignon beef ribs chuck fatback. 87 |

88 |
89 | ); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /examples/simple-redux/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "roc-web-react-simple-redux-example", 3 | "version": "1.0.0", 4 | "description": "Roc Web React simple redux example", 5 | "author": "VG", 6 | "license": "MIT", 7 | "dependencies": { 8 | "roc-package-web-app-react": "*" 9 | }, 10 | "devDependencies": { 11 | "roc-package-web-app-react-dev": "*", 12 | "roc-plugin-style-sass": "^1.0.0-beta.2" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /examples/simple-redux/reducers.js: -------------------------------------------------------------------------------- 1 | export clicker from './clicker'; 2 | -------------------------------------------------------------------------------- /examples/simple-redux/routes.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Route, IndexRoute } from 'react-router'; 3 | 4 | import Main from './main'; 5 | 6 | export default () => ( 7 | 8 | ); 9 | -------------------------------------------------------------------------------- /examples/simple-redux/style.scss: -------------------------------------------------------------------------------- 1 | .main { 2 | background: #fff; 3 | width: 700px; 4 | margin: auto; 5 | padding: 20px; 6 | } 7 | -------------------------------------------------------------------------------- /examples/simple/main.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import styles from './style.css'; 4 | 5 | export default class Main extends React.Component { 6 | render() { 7 | //const image = require('./roc.png'); 8 | 9 | return ( 10 |
11 |

Bacon ipsum dolor?

12 |

13 | Bacon ipsum dolor amet hamburger swine filet mignon biltong shank, turkey alcatra brisket flank ribeye 14 | landjaeger beef ribs. Ham flank pancetta biltong pork belly shankle brisket doner beef. Pig sirloin turkey 15 | corned beef, alcatra biltong boudin pastrami. Tail pig pork filet mignon kevin chuck. Prosciutto ball tip 16 | flank jerky ham, porchetta fatback kevin swine alcatra spare ribs pancetta. Pork belly tenderloin meatball 17 | venison filet mignon andouille doner pork loin turducken strip steak. Shank andouille pig shankle. 18 | 19 | Drumstick shankle tri-tip pork chop salami bacon jowl. Shankle bacon tongue venison, brisket strip steak 20 | cupim meatball. Flank turducken tenderloin rump pork belly ribeye. Drumstick tenderloin turkey, short loin 21 | andouille meatloaf meatball brisket bresaola rump jowl. Drumstick tongue ball tip t-bone leberkas rump. 22 | 23 | Porchetta pastrami cow, short loin rump landjaeger brisket tongue beef bresaola pork chop drumstick. Swine 24 | t-bone tongue pork belly ham turducken alcatra rump pork loin flank ribeye meatloaf capicola short ribs. 25 | Flank ribeye shank, turkey pork chop tail tongue hamburger swine. Ham hock jowl meatloaf ham cow, rump 26 | drumstick shankle flank hamburger fatback prosciutto biltong. 27 | 28 | Landjaeger bacon kevin sausage, tail bresaola shank alcatra pastrami jerky. Kielbasa salami landjaeger 29 | ground round. Chicken ham brisket, boudin andouille corned beef jerky tri-tip short ribs kielbasa 30 | landjaeger beef biltong jowl bacon. Pork shank leberkas, picanha beef ribs spare ribs cow beef drumstick 31 | ball tip shankle short loin ground round pig. Picanha ground round venison pancetta drumstick ham biltong 32 | bresaola salami sausage beef ribs boudin pork chop jerky. Brisket jowl chicken, kevin tongue beef 33 | prosciutto meatloaf. 34 | 35 | Frankfurter meatball sausage turkey rump ham hock tongue doner leberkas drumstick jowl ground round filet 36 | mignon. Tenderloin sirloin salami, shoulder ham landjaeger corned beef pastrami cow porchetta capicola 37 | boudin tongue rump. Pork loin sirloin rump landjaeger drumstick pastrami frankfurter andouille doner 38 | salami flank shoulder. Fatback bacon turducken frankfurter. Pancetta ground round flank pork, sausage pork 39 | chop doner bacon ribeye shank tail filet mignon jowl swine short ribs. Jerky shank prosciutto ham hock 40 | kevin picanha meatball short loin pork loin shankle ground round brisket pork belly. 41 | 42 | Chuck pig tri-tip, doner meatloaf rump ball tip tenderloin venison leberkas. Pork loin biltong t-bone 43 | turducken. Jerky pork loin pork short ribs pastrami biltong, turkey meatball kevin sausage. Alcatra strip 44 | steak corned beef, beef ribs andouille tenderloin biltong ribeye chuck. Doner chuck biltong venison pork 45 | belly tail fatback cow t-bone short ribs ham hock jowl hamburger frankfurter meatball. 46 | 47 | Sausage beef ribs tail shoulder pork belly shank prosciutto pork tri-tip sirloin t-bone. Ground round spare 48 | ribs turducken tongue. Shank tenderloin meatloaf, beef tongue beef ribs pastrami. Porchetta short ribs 49 | sirloin, bacon drumstick prosciutto doner kevin pancetta tri-tip fatback. 50 | 51 | Meatloaf salami biltong shank, venison cow drumstick picanha capicola doner short loin. Doner filet mignon 52 | biltong meatloaf. Filet mignon ribeye tail porchetta strip steak shoulder chicken short ribs. Strip steak 53 | tenderloin pig filet mignon spare ribs, capicola pork loin prosciutto ground round leberkas tail chuck 54 | porchetta biltong. Corned beef brisket frankfurter tongue capicola venison. Tail jowl ham venison. 55 | 56 | Venison spare ribs shank beef ribs sausage pork chop capicola jerky. Sirloin spare ribs ribeye strip steak 57 | cow beef fatback brisket pork ball tip doner hamburger. Pork loin fatback swine kielbasa doner alcatra 58 | salami porchetta drumstick tongue ground round. Strip steak sausage sirloin rump shoulder t-bone. Meatloaf 59 | corned beef sausage, chuck ground round short ribs porchetta tri-tip. Hamburger kielbasa cow, picanha 60 | boudin capicola rump pastrami ball tip pork chop swine. 61 | 62 | Chuck landjaeger pork, pork loin shankle tri-tip pastrami flank kielbasa picanha drumstick cupim chicken 63 | beef. Pork loin frankfurter short loin, pancetta cupim ribeye jerky turkey beef ribs tri-tip meatball 64 | swine tail flank. Pastrami salami turkey, turducken ball tip venison meatloaf sirloin pork chop drumstick 65 | short loin. Andouille sirloin pig, tongue pork chop pastrami meatball filet mignon beef ribs chuck fatback. 66 |

67 |
68 | ); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /examples/simple/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "roc-web-react-simple-example", 3 | "version": "1.0.0", 4 | "description": "Roc Web React simple example", 5 | "author": "VG", 6 | "license": "MIT", 7 | "scripts": { 8 | "dev": "roc dev --runtime-applicationName 'Simple Example'" 9 | }, 10 | "dependencies": { 11 | "roc-package-web-app-react": "*" 12 | }, 13 | "devDependencies": { 14 | "roc-package-web-app-react-dev": "*" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/simple/roc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rocjs/roc-package-web-app-react/26cd2b51acbfcaf3a61267ded00afb3a19907198/examples/simple/roc.png -------------------------------------------------------------------------------- /examples/simple/routes.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Route, IndexRoute } from 'react-router'; 3 | 4 | import Main from './main'; 5 | 6 | export default () => ( 7 | 8 | ); 9 | -------------------------------------------------------------------------------- /examples/simple/style.css: -------------------------------------------------------------------------------- 1 | .main { 2 | background: #fff; 3 | width: 700px; 4 | margin: auto; 5 | padding: 20px; 6 | } 7 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react-dev/.eslintignore: -------------------------------------------------------------------------------- 1 | lib 2 | esdocs 3 | docs 4 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react-dev/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "airbnb-base", 3 | 4 | "parser": "babel-eslint", 5 | 6 | "plugins": ["eslint-plugin-babel"], 7 | 8 | "rules": { 9 | "indent": [2, 4, { "SwitchCase": 1 }], 10 | "max-len": [2, 120, 4], 11 | "no-warning-comments": 1, 12 | 13 | "generator-star-spacing": 0, 14 | "babel/generator-star-spacing": [2, { "before": false, "after": true }], 15 | 16 | "import/order": [2, { "groups": ["builtin", "external", "internal", "parent", "sibling", "index"], "newlines-between": "always"}], 17 | "import/newline-after-import": [2], 18 | "import/no-extraneous-dependencies": [1], 19 | "import/no-unresolved": [1] 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react-dev/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Verdens Gang AS 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react-dev/README.md: -------------------------------------------------------------------------------- 1 | # roc-package-web-app-react-dev 2 | 3 | Package for building React applications with Roc (Development) 4 | 5 | ## Documentation 6 | - [Actions](docs/Actions.md) 7 | - [Commands](docs/Commands.md) 8 | - [Configuration](docs/Configuration.md) 9 | - [Dependencies](docs/Dependencies.md) 10 | - [Hooks](docs/Hooks.md) 11 | - [Settings](docs/Settings.md) 12 | - [Extensions](docs/Extensions.md) 13 | 14 | --- 15 | _Generated by [Roc](https://github.com/rocjs/roc)_ 16 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react-dev/docs/Actions.md: -------------------------------------------------------------------------------- 1 | # Actions for `roc-package-web-app-react-dev` 2 | 3 | ## Actions 4 | * [roc-abstract-package-base-dev](#roc-abstract-package-base-dev) 5 | * [after-clean](#after-clean) 6 | * [before-clean](#before-clean) 7 | * [roc-plugin-babel](#roc-plugin-babel) 8 | * [babel-config](#babel-config) 9 | * [roc-package-webpack-dev](#roc-package-webpack-dev) 10 | * [babel-config](#babel-config-1) 11 | * [build-webpack](#build-webpack) 12 | * [run-build-command](#run-build-command) 13 | * [run-dev-command](#run-dev-command) 14 | * [roc-package-webpack-node-dev](#roc-package-webpack-node-dev) 15 | * [build-webpack](#build-webpack-1) 16 | * [create-watchers](#create-watchers) 17 | * [get-webpack-targets](#get-webpack-targets) 18 | * [roc-package-webpack-web-dev](#roc-package-webpack-web-dev) 19 | * [build-webpack](#build-webpack-2) 20 | * [create-watchers](#create-watchers-1) 21 | * [get-webpack-targets](#get-webpack-targets-1) 22 | * [roc-plugin-browsersync](#roc-plugin-browsersync) 23 | * [server-started](#server-started) 24 | * [roc-plugin-style-css](#roc-plugin-style-css) 25 | * [build-webpack](#build-webpack-3) 26 | * [roc-plugin-assets-images](#roc-plugin-assets-images) 27 | * [build-webpack](#build-webpack-4) 28 | * [roc-package-web-app-dev](#roc-package-web-app-dev) 29 | * [build-webpack](#build-webpack-5) 30 | * [dev-process-created](#dev-process-created) 31 | * [roc-plugin-react-dev](#roc-plugin-react-dev) 32 | * [babel-config](#babel-config-2) 33 | * [roc-package-web-app-react-dev](#roc-package-web-app-react-dev) 34 | * [build-webpack](#build-webpack-6) 35 | * [update-settings](#update-settings) 36 | 37 | ## roc-abstract-package-base-dev 38 | 39 | ### after-clean 40 | 41 | Runs after clean command is executed. Logs that the action has been completed successfully. 42 | 43 | __Connects to extension:__ `roc-abstract-package-base-dev` 44 | __Connects to hook:__ `after-clean` 45 | __Have post:__ No 46 | 47 | ### before-clean 48 | 49 | Runs before clean command is executed. Returns an array of paths that should be removed. 50 | 51 | __Connects to extension:__ `roc-abstract-package-base-dev` 52 | __Connects to hook:__ `before-clean` 53 | __Have post:__ No 54 | 55 | ## roc-plugin-babel 56 | 57 | ### babel-config 58 | 59 | Base Babel configuration 60 | 61 | __Connects to extension:__ Not specified 62 | __Connects to hook:__ `babel-config` 63 | __Have post:__ Yes 64 | 65 | ## roc-package-webpack-dev 66 | 67 | ### babel-config 68 | 69 | __Connects to extension:__ Not specified 70 | __Connects to hook:__ `babel-config` 71 | __Have post:__ No 72 | 73 | ### build-webpack 74 | 75 | Adds base Webpack configuration and read webpack from the configuration. 76 | 77 | __Connects to extension:__ Not specified 78 | __Connects to hook:__ `build-webpack` 79 | __Have post:__ Yes 80 | 81 | ### run-build-command 82 | 83 | Build with Webpack. 84 | 85 | __Connects to extension:__ Not specified 86 | __Connects to hook:__ `run-build-command` 87 | __Have post:__ No 88 | 89 | ### run-dev-command 90 | 91 | Run in development mode using Webpack. 92 | 93 | __Connects to extension:__ Not specified 94 | __Connects to hook:__ `run-dev-command` 95 | __Have post:__ No 96 | 97 | ## roc-package-webpack-node-dev 98 | 99 | ### build-webpack 100 | 101 | Adds configuration needed for building for Node. 102 | 103 | __Connects to extension:__ Not specified 104 | __Connects to hook:__ `build-webpack` 105 | __Have post:__ No 106 | 107 | ### create-watchers 108 | 109 | Adds a watcher for automatic reload on change. 110 | 111 | __Connects to extension:__ `roc-package-webpack-dev` 112 | __Connects to hook:__ `create-watchers` 113 | __Have post:__ No 114 | 115 | ### get-webpack-targets 116 | 117 | Adds __node__ as a valid Webpack target. 118 | 119 | __Connects to extension:__ `roc-package-webpack-dev` 120 | __Connects to hook:__ `get-webpack-targets` 121 | __Have post:__ No 122 | 123 | ## roc-package-webpack-web-dev 124 | 125 | ### build-webpack 126 | 127 | Adds configuration need for web builds for Webpack. 128 | 129 | __Connects to extension:__ Not specified 130 | __Connects to hook:__ `build-webpack` 131 | __Have post:__ No 132 | 133 | ### create-watchers 134 | 135 | Adds a web watcher using Webpack Dev Server. 136 | 137 | __Connects to extension:__ `roc-package-webpack-dev` 138 | __Connects to hook:__ `create-watchers` 139 | __Have post:__ No 140 | 141 | ### get-webpack-targets 142 | 143 | Adds __web__ as a valid Webpack target. 144 | 145 | __Connects to extension:__ `roc-package-webpack-dev` 146 | __Connects to hook:__ `get-webpack-targets` 147 | __Have post:__ No 148 | 149 | ## roc-plugin-browsersync 150 | 151 | ### server-started 152 | 153 | Adds a Browsersync instance. 154 | 155 | __Connects to extension:__ Not specified 156 | __Connects to hook:__ `server-started` 157 | __Have post:__ No 158 | 159 | ## roc-plugin-style-css 160 | 161 | ### build-webpack 162 | 163 | Adds CSS support. 164 | 165 | __Connects to extension:__ Not specified 166 | __Connects to hook:__ `build-webpack` 167 | __Have post:__ No 168 | 169 | ## roc-plugin-assets-images 170 | 171 | ### build-webpack 172 | 173 | Adds image support. Also makes `url-loader` and `file-loader` available in the module scope. 174 | 175 | __Connects to extension:__ Not specified 176 | __Connects to hook:__ `build-webpack` 177 | __Have post:__ No 178 | 179 | ## roc-package-web-app-dev 180 | 181 | ### build-webpack 182 | 183 | Adds needed configuration to being able to build web applications. 184 | 185 | __Connects to extension:__ Not specified 186 | __Connects to hook:__ `build-webpack` 187 | __Have post:__ No 188 | 189 | ### dev-process-created 190 | 191 | __Connects to extension:__ Not specified 192 | __Connects to hook:__ `dev-process-created` 193 | __Have post:__ No 194 | 195 | ## roc-plugin-react-dev 196 | 197 | ### babel-config 198 | 199 | Adds the needed Babel configuration to be able to build and develop React code. 200 | 201 | __Connects to extension:__ Not specified 202 | __Connects to hook:__ `babel-config` 203 | __Have post:__ No 204 | 205 | ## roc-package-web-app-react-dev 206 | 207 | ### build-webpack 208 | 209 | __Connects to extension:__ Not specified 210 | __Connects to hook:__ `build-webpack` 211 | __Have post:__ No 212 | 213 | ### update-settings 214 | 215 | __Connects to extension:__ `roc` 216 | __Connects to hook:__ `update-settings` 217 | __Have post:__ No 218 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react-dev/docs/Commands.md: -------------------------------------------------------------------------------- 1 | # Commands for `roc-package-web-app-react-dev` 2 | 3 | ## General Information 4 | All commands can be called with some additional options illustrated in the table below. 5 | 6 | ### General options 7 | 8 | | Name | Description | Required | 9 | | --------------------- | ---------------------------------------------- | -------- | 10 | | -b, --better-feedback | Enables source-map-support and loud-rejection. | No | 11 | | -c, --config | Path to configuration file. | No | 12 | | -d, --directory | Path to working directory. | No | 13 | | -h, --help | Output usage information. | No | 14 | | -V, --verbose | Enable verbose mode. | No | 15 | | -v, --version | Output version number. | No | 16 | 17 | ## Commands 18 | * [development](#development) 19 | * [build](#build) 20 | * [clean](#clean) 21 | * [dev](#dev) 22 | * [meta](#meta) 23 | * [docs](#docs) 24 | * [list-settings](#list-settings) 25 | 26 | ## development 27 | __Project development__ 28 | 29 | ``` 30 | roc development 31 | ``` 32 | Commands for development purposes. 33 | 34 | 35 | ### build 36 | __Build the current project.__ 37 | 38 | ``` 39 | roc development build [targets] 40 | ``` 41 | 42 | #### Arguments 43 | 44 | | Name | Description | Default | Type | Required | Can be empty | 45 | | ------- | -------------------------------------------------------------------------------- | ------- | --------------- | -------- | ------------ | 46 | | targets | The targets the project should be built for, overrides the settings if provided. | | `Array(String)` | No | Yes | 47 | 48 | #### Settings options 49 | * [build](docs/Settings.md#build) 50 | 51 | #### Defined by extensions 52 | roc-abstract-package-base-dev, roc-package-webpack-dev 53 | 54 | ### clean 55 | __Cleans the current project.__ 56 | 57 | ``` 58 | roc development clean 59 | ``` 60 | 61 | #### Settings options 62 | * [build](docs/Settings.md#build) 63 | 64 | #### Defined by extensions 65 | roc-abstract-package-base-dev 66 | 67 | ### dev 68 | __Starts the current project in development mode.__ 69 | 70 | ``` 71 | roc development dev [targets] 72 | ``` 73 | 74 | #### Arguments 75 | 76 | | Name | Description | Default | Type | Required | Can be empty | 77 | | ------- | -------------------------------------------------------------------------------- | ------- | --------------- | -------- | ------------ | 78 | | targets | The targets the project should be built for, overrides the settings if provided. | | `Array(String)` | No | Yes | 79 | 80 | #### Settings options 81 | _All groups are available._ 82 | * [build](docs/Settings.md#build) 83 | * [dev](docs/Settings.md#dev) 84 | 85 | #### Defined by extensions 86 | roc-abstract-package-base-dev, roc-package-webpack-dev 87 | 88 | ## meta 89 | __Meta commands__ 90 | 91 | ``` 92 | roc meta 93 | ``` 94 | Meta commands that can be used to generate meta data about the current project. 95 | 96 | 97 | ### docs 98 | __Generates documentation for the current project.__ 99 | 100 | ``` 101 | roc meta docs 102 | ``` 103 | 104 | #### Command options 105 | 106 | | Name | Description | Default | Type | Required | Can be empty | 107 | | ---------- | ------------------------------------------------------------- | -------------- | ----------------------------------------------------------------- | -------- | ------------ | 108 | | --html | If HTML should be generated. (Not supported yet) | `false` | `Boolean` | No | | 109 | | --markdown | If markdown should be generated. | `true` | `Boolean` | No | | 110 | | --mode | The platform that is to be used, for link generation. | `"github.com"` | `/github\.com|nodejs\.org|bitbucket\.org|ghost\.org|gitlab\.com/` | No | | 111 | | --output | A directory to place the generated documentation inside of. | `"docs"` | `String` | No | No | 112 | | --project | If the projects configuration and actions should be included. | `false` | `Boolean` | No | | 113 | 114 | #### Defined by extensions 115 | roc 116 | 117 | ### list-settings 118 | __Prints all the available settings that can be changed.__ 119 | 120 | ``` 121 | roc meta list-settings 122 | ``` 123 | 124 | #### Defined by extensions 125 | roc 126 | 127 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react-dev/docs/Configuration.md: -------------------------------------------------------------------------------- 1 | # Config for `roc-package-web-app-react-dev` 2 | 3 | Configuration that can be defined in `roc.config.js`, other than settings and project. 4 | 5 | ## `babel` 6 | Babel configuration that can be either a plain object or a function that gets target as argument 7 | 8 | __Extensions__: roc-plugin-babel 9 | 10 | ## `webpack` 11 | Can be either a function or a plain object. If it is a function the argument will be `target`. 12 | 13 | __Extensions__: roc-package-webpack-dev 14 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react-dev/docs/Dependencies.md: -------------------------------------------------------------------------------- 1 | # Dependencies for `roc-package-web-app-react-dev` 2 | 3 | The dependencies that are available in the project. 4 | 5 | ## Exported 6 | ### [react-a11y](https://www.npmjs.com/package/react-a11y) 7 | __Version__: ~0.3.3 8 | __Extension__: roc-package-web-app-react-dev 9 | __Custom resolve function__: No 10 | 11 | ### [redux-devtools](https://www.npmjs.com/package/redux-devtools) 12 | __Version__: ~3.4.0 13 | __Extension__: roc-package-web-app-react-dev 14 | __Custom resolve function__: No 15 | 16 | ### [redux-devtools-dock-monitor](https://www.npmjs.com/package/redux-devtools-dock-monitor) 17 | __Version__: ~1.1.2 18 | __Extension__: roc-package-web-app-react-dev 19 | __Custom resolve function__: No 20 | 21 | ### [redux-devtools-log-monitor](https://www.npmjs.com/package/redux-devtools-log-monitor) 22 | __Version__: ~1.3.0 23 | __Extension__: roc-package-web-app-react-dev 24 | __Custom resolve function__: No 25 | 26 | ### [redux-logger](https://www.npmjs.com/package/redux-logger) 27 | __Version__: ~2.6.1 28 | __Extension__: roc-package-web-app-react-dev 29 | __Custom resolve function__: No 30 | 31 | ### [webpack](https://www.npmjs.com/package/webpack) 32 | __Version__: ~1.12.2 33 | __Extension__: roc-package-webpack-dev 34 | __Custom resolve function__: No 35 | 36 | ### [yellowbox-react](https://www.npmjs.com/package/yellowbox-react) 37 | __Version__: ~0.10.0 38 | __Extension__: roc-package-web-app-react-dev 39 | __Custom resolve function__: No 40 | 41 | ## Requires 42 | Nothing is required. 43 | 44 | ## Uses 45 | Nothing is listed as used. 46 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react-dev/docs/Extensions.md: -------------------------------------------------------------------------------- 1 | # Extensions for `roc-package-web-app-react-dev` 2 | 3 | The extensions that are used in the project, indirect and direct, in the order that they were added. 4 | 5 | ## Packages 6 | ### roc-abstract-package-base-dev — [v1.0.0-beta.2](https://www.npmjs.com/package/roc-abstract-package-base-dev) 7 | Package forming an abstract foundation of the Roc ecosystem. 8 | 9 | The package serves as a base from which other `dev` packages within the ecosystem are to be constructed. 10 | It is therefore _never to be included_ as a direct dependency in app or component projects. 11 | 12 | ### roc-package-webpack-dev — [v1.0.0-beta.8](https://www.npmjs.com/package/roc-package-webpack-dev) 13 | Package providing module support. 14 | 15 | ### roc-package-webpack-node-dev — [v1.0.0-beta.3](https://www.npmjs.com/package/roc-package-webpack-node-dev) 16 | Package providing Node support through Webpack for Roc (Development) 17 | 18 | ### roc-package-webpack-web-dev — [v1.0.0-beta.3](https://www.npmjs.com/package/roc-package-webpack-web-dev) 19 | Package providing browser support through Webpack for Roc (Development) 20 | 21 | ### roc-package-web-app-dev — [v1.0.0-beta.7](https://www.npmjs.com/package/roc-package-web-app-dev) 22 | Package for building web applications using Roc (Development) 23 | 24 | ## Plugins 25 | ### roc-plugin-babel — [v1.0.0-beta.4](https://www.npmjs.com/package/roc-plugin-babel) 26 | Roc plugin that adds basic Babel management 27 | 28 | ### roc-plugin-browsersync — [v1.0.0-beta.2](https://www.npmjs.com/package/roc-plugin-browsersync) 29 | Plugin providing Browsersync for Roc 30 | 31 | ### roc-plugin-style-css — [v1.0.0-beta.8](https://www.npmjs.com/package/roc-plugin-style-css) 32 | Plugin providing CSS support for Webpack in Roc 33 | 34 | ### roc-plugin-assets-images — [v1.0.0-beta.2](https://www.npmjs.com/package/roc-plugin-assets-images) 35 | Adds image loading support to Roc 36 | 37 | ### roc-plugin-react-dev — [v1.0.0-beta.4](https://www.npmjs.com/package/roc-plugin-react-dev) 38 | Adds React support to Webpack and Roc (Development) 39 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react-dev/docs/Hooks.md: -------------------------------------------------------------------------------- 1 | # Hooks for `roc-package-web-app-react-dev` 2 | 3 | ## Hooks 4 | * [roc](#roc) 5 | * [update-settings](#update-settings) 6 | * [roc-abstract-package-base-dev](#roc-abstract-package-base-dev) 7 | * [after-clean](#after-clean) 8 | * [before-clean](#before-clean) 9 | * [run-build-command](#run-build-command) 10 | * [run-dev-command](#run-dev-command) 11 | * [roc-package-web-app-dev](#roc-package-web-app-dev) 12 | * [server-started](#server-started) 13 | * [roc-package-webpack-dev](#roc-package-webpack-dev) 14 | * [babel-config](#babel-config) 15 | * [build-webpack](#build-webpack) 16 | * [create-watchers](#create-watchers) 17 | * [get-webpack-targets](#get-webpack-targets) 18 | * [roc-package-webpack-node-dev](#roc-package-webpack-node-dev) 19 | * [dev-process-created](#dev-process-created) 20 | * [dev-process-stopping](#dev-process-stopping) 21 | * [roc-plugin-style-css](#roc-plugin-style-css) 22 | * [add-style](#add-style) 23 | * [add-style-preloaders](#add-style-preloaders) 24 | 25 | ## roc 26 | 27 | ### update-settings 28 | 29 | Expected to return new settings that should be merged with the existing ones. 30 | 31 | Makes it possible to modify the settings object before a command is started and after potential arguments from the command line and configuration file have been parsed. This is a good point to default to some value if no was given or modify something in the settings. 32 | 33 | __Initial value:__ _Nothing_ 34 | __Expected return value:__ `Object()` 35 | 36 | #### Arguments 37 | 38 | | Name | Description | Type | Required | Can be empty | 39 | | ----------- | ---------------------------------------------------------------------------- | ---------- | -------- | ------------ | 40 | | getSettings | A function that returns the settings after the context has been initialized. | `Function` | No | | 41 | 42 | ## roc-abstract-package-base-dev 43 | 44 | ### after-clean 45 | 46 | Hook point for adding code that runs after the clean command is invoked. 47 | 48 | __Initial value:__ _Nothing_ 49 | __Expected return value:__ _Nothing_ 50 | 51 | ### before-clean 52 | 53 | Hook point for adding code that runs before the clean command is invoked. 54 | 55 | __Initial value:__ _Nothing_ 56 | __Expected return value:__ `Array(String)` 57 | 58 | ### run-build-command 59 | 60 | Use to add things that should react to the build command being called. 61 | 62 | __Initial value:__ _Nothing_ 63 | __Expected return value:__ `Function` 64 | 65 | #### Arguments 66 | 67 | | Name | Description | Type | Required | Can be empty | 68 | | ------- | -------------------------------------------------------------------------------------- | --------------- | -------- | ------------ | 69 | | targets | The targets to build for, will be based on settings or a possible argument if defined. | `Array(String)` | Yes | No | 70 | 71 | ### run-dev-command 72 | 73 | Use to add things that should react to the dev command being called. 74 | 75 | __Initial value:__ _Nothing_ 76 | __Expected return value:__ _Nothing_ 77 | 78 | #### Arguments 79 | 80 | | Name | Description | Type | Required | Can be empty | 81 | | ------- | ------------------------------------------------------------------------------------- | --------------- | -------- | ------------ | 82 | | targets | The targets use for dev, will be based on settings or a possible argument if defined. | `Array(String)` | Yes | No | 83 | 84 | ## roc-package-web-app-dev 85 | 86 | ### server-started 87 | 88 | Invoked when the server has started. 89 | 90 | __Initial value:__ _Nothing_ 91 | __Expected return value:__ _Nothing_ 92 | 93 | #### Arguments 94 | 95 | | Name | Description | Type | Required | Can be empty | 96 | | ---- | ---------------------------------------- | --------- | -------- | ------------ | 97 | | port | The port of the server. | `Integer` | Yes | No | 98 | | path | The path that the server has started on. | `String` | Yes | No | 99 | 100 | ## roc-package-webpack-dev 101 | 102 | ### babel-config 103 | 104 | Used to create a Babel configuration to be used in the Webpack build. 105 | 106 | __Initial value:__ `{}` 107 | __Expected return value:__ `Object()` 108 | 109 | #### Arguments 110 | 111 | | Name | Description | Type | Required | Can be empty | 112 | | ------ | ------------------------ | -------- | -------- | ------------ | 113 | | target | The target that is used. | `String` | No | Yes | 114 | 115 | ### build-webpack 116 | 117 | Used to create the final Webpack configuration object. 118 | 119 | __Initial value:__ `{}` 120 | __Expected return value:__ `Object()` 121 | 122 | #### Arguments 123 | 124 | | Name | Description | Type | Required | Can be empty | 125 | | ----------- | ------------------------------------------------------------------- | ---------- | -------- | ------------ | 126 | | target | The target for which the Webpack configuration should be build for. | `String` | No | Yes | 127 | | babelConfig | The Babel configuration that should be used for the Webpack build. | `Object()` | No | Yes | 128 | 129 | ### create-watchers 130 | 131 | Used to add watchers that should follow a specific format. 132 | 133 | __Initial value:__ `{}` 134 | __Expected return value:__ `Object(Function)` 135 | 136 | ### get-webpack-targets 137 | 138 | Used to inform which targets that should be considered as Webpack targets. Actions should concat the previousValue to build the complete value. 139 | 140 | __Initial value:__ `[]` 141 | __Expected return value:__ `Array(String)` 142 | 143 | ## roc-package-webpack-node-dev 144 | 145 | ### dev-process-created 146 | 147 | Used to react to when the development server has started. 148 | 149 | __Initial value:__ _Nothing_ 150 | __Expected return value:__ _Nothing_ 151 | 152 | #### Arguments 153 | 154 | | Name | Description | Type | Required | Can be empty | 155 | | ------------- | --------------------------- | ---- | -------- | ------------ | 156 | | serverProcess | The created server process. | | No | | 157 | 158 | ### dev-process-stopping 159 | 160 | Used to react before the development server is stopped. 161 | 162 | __Initial value:__ _Nothing_ 163 | __Expected return value:__ _Nothing_ 164 | 165 | #### Arguments 166 | 167 | | Name | Description | Type | Required | Can be empty | 168 | | ------------- | ----------------------------------------- | ---- | -------- | ------------ | 169 | | serverProcess | The server process that is being stopped. | | No | | 170 | 171 | ## roc-plugin-style-css 172 | 173 | ### add-style 174 | 175 | Used for adding additional style loaders. 176 | 177 | Important that the _actions_ return an object matching the following: 178 | 179 | `{ extensions: String/[String], loaders: String/[String] }` 180 | 181 | __Initial value:__ _Nothing_ 182 | __Expected return value:__ `Object(String / Array(String))` 183 | 184 | ### add-style-preloaders 185 | 186 | Used to add general loaders early in the chain, before the PostCSS loader. 187 | 188 | These loaders will be applied to all styles added from the `add-style` hook. 189 | 190 | __Initial value:__ _Nothing_ 191 | __Expected return value:__ `Array(String)` 192 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react-dev/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "roc-package-web-app-react-dev", 3 | "description": "Package for building React applications with Roc (Development)", 4 | "version": "1.0.0-beta.18", 5 | "main": "lib/index.js", 6 | "scripts": { 7 | "lint": "eslint .", 8 | "test": "npm run lint" 9 | }, 10 | "files": [ 11 | "lib" 12 | ], 13 | "keywords": [ 14 | "roc", 15 | "roc-package", 16 | "roc-dev", 17 | "react-router", 18 | "react", 19 | "redux" 20 | ], 21 | "repository": "https://github.com/rocjs/roc-package-web-app-react/tree/master/extensions/roc-package-web-app-react-dev", 22 | "author": "Verdens Gang AS", 23 | "contributors": [ 24 | { 25 | "name": "Gustaf Dalemar" 26 | } 27 | ], 28 | "license": "MIT", 29 | "dependencies": { 30 | "bundle-loader": "^0.5.4", 31 | "react-a11y": "~0.3.3", 32 | "redux-devtools": "~3.4.0", 33 | "redux-devtools-dock-monitor": "~1.1.2", 34 | "redux-devtools-log-monitor": "~1.3.0", 35 | "redux-logger": "~2.6.1", 36 | "roc": "^1.0.0-rc.12", 37 | "roc-package-web-app-dev": "^1.0.0-beta.3", 38 | "roc-plugin-react-dev": "^1.0.0-beta.2", 39 | "yellowbox-react": "~0.10.0" 40 | }, 41 | "devDependencies": { 42 | "babel-eslint": "~6.1.2", 43 | "eslint": "~3.0.1", 44 | "eslint-config-airbnb-base": "~4.0.0", 45 | "eslint-plugin-babel": "~3.3.0", 46 | "eslint-plugin-import": "~1.10.2" 47 | }, 48 | "roc": { 49 | "packages": [ 50 | "./lib/index.js" 51 | ] 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react-dev/src/config/roc.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | settings: { 3 | build: { 4 | input: { web: undefined, node: undefined }, 5 | 6 | redux: { 7 | useDefaultReducers: true, 8 | middlewares: 'src/redux/middlewares.js', 9 | enhancers: 'src/redux/enhancers.js', 10 | useDefaultMiddlewares: true, 11 | sagas: 'src/redux/sagas.js', 12 | }, 13 | 14 | // Will be moved to redux above eventually, now kept here to make the template upgradable 15 | reducers: 'src/redux/reducers.js', 16 | 17 | i18n: { 18 | usePolyfill: false, 19 | locales: [], 20 | }, 21 | 22 | useReactRouterScrollAsync: true, 23 | routes: 'src/routes/routes.js', 24 | useDefaultRoutes: true, 25 | 26 | clientLoading: undefined, 27 | // Consider using the init function to merge this with the previous 28 | resources: ['roc-package-web-app-react/styles/base.css'], 29 | 30 | templateValues: 'src/template-values.js', 31 | }, 32 | dev: { 33 | // A11Y not play nice with Redux Devtools at the moment 34 | a11y: false, 35 | 36 | redux: { 37 | devTools: { 38 | enabled: true, 39 | dockMonitor: { 40 | __raw: {}, 41 | defaultPosition: 'right', 42 | defaultSize: 0.3, 43 | toggleVisibilityKey: 'ctrl-h', 44 | changePositionKey: 'ctrl-q', 45 | defaultIsVisible: false, 46 | }, 47 | instrument: { 48 | __raw: {}, 49 | maxAge: undefined, 50 | }, 51 | logMonitor: { 52 | __raw: {}, 53 | theme: 'ocean', 54 | }, 55 | }, 56 | logger: { 57 | __raw: {}, 58 | level: 'info', 59 | collapsed: true, 60 | duration: true, 61 | timestamp: true, 62 | }, 63 | }, 64 | 65 | yellowbox: { 66 | enabled: true, 67 | ignore: ['[HMR]', 'Warning: React attempted to reuse markup in a container'], 68 | }, 69 | }, 70 | }, 71 | }; 72 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react-dev/src/config/roc.config.meta.js: -------------------------------------------------------------------------------- 1 | import { isString, isBoolean, isPath, isArray, notEmpty, isInteger, required } from 'roc/validators'; 2 | 3 | export default { 4 | settings: { 5 | build: { 6 | input: { 7 | web: { 8 | override: 'roc-package-web-app-dev', 9 | description: 'The web/client entry point file.', 10 | validator: notEmpty(isPath), 11 | }, 12 | node: { 13 | override: 'roc-package-web-app-dev', 14 | description: 'The node/server entry point file.', 15 | validator: notEmpty(isPath), 16 | }, 17 | }, 18 | useReactRouterScrollAsync: { 19 | description: 'Use react-router-scroll-async middleware to help with scroll behavior for ' + 20 | 'Single Page Applications. Disable this if SPA functionality is turned off.', 21 | validator: required(isBoolean), 22 | }, 23 | routes: { 24 | description: 'The routes to use if no entry file is given, will use default entry files internally.', 25 | validator: notEmpty(isPath), 26 | }, 27 | useDefaultRoutes: { 28 | description: 'If Roc should use an internal wrapper around the routes, please look at the ' + 29 | 'documentation for more details.', 30 | validator: required(isBoolean), 31 | }, 32 | reducers: { 33 | description: 'The reducers to use if no entry file is given, will use default entry ' + 34 | 'files internally.', 35 | validator: notEmpty(isPath), 36 | }, 37 | redux: { 38 | useDefaultReducers: { 39 | description: 'If Roc should use internally defined reducers, please look at the documentation ' + 40 | ' for what reducers that are included.', 41 | validator: required(isBoolean), 42 | }, 43 | middlewares: { 44 | description: 'The middlewares to use if no entry file is given, will use default entry files ' + 45 | 'internally.', 46 | validator: notEmpty(isPath), 47 | }, 48 | enhancers: { 49 | description: 'The enhancers to use if no entry file is given, will use default entry files ' + 50 | 'internally.', 51 | validator: notEmpty(isPath), 52 | }, 53 | useDefaultMiddlewares: { 54 | description: 'If Roc should use internally defined middlewares, please look at the ' + 55 | ' documentation for what middlewares that are included.', 56 | validator: required(isBoolean), 57 | }, 58 | sagas: { 59 | description: 'The Redux Saga to use as the root saga.', 60 | validator: notEmpty(isPath), 61 | }, 62 | }, 63 | i18n: { 64 | usePolyfill: { 65 | description: 'If Roc should load Intl polyfill and locales on client and server.', 66 | }, 67 | locales: { 68 | description: 'List of locales polyfills to load on the client - these are listed in the ' + 69 | 'intl package (see node_modules/intl/locale-date/jsonp/.', 70 | }, 71 | }, 72 | clientLoading: { 73 | description: 'The React component to use on the first client load while fetching data, will only ' + 74 | 'be used if some blocking hooks are defined.', 75 | validator: notEmpty(isPath), 76 | }, 77 | 78 | templateValues: { 79 | description: '[UNDOCUMENTED]', 80 | }, 81 | }, 82 | dev: { 83 | a11y: { 84 | description: 'If A11Y validation should be active. Currently it´s suggested to not ' + 85 | 'enable Redux Devtools with this.', 86 | validator: required(isBoolean), 87 | }, 88 | redux: { 89 | devTools: { 90 | enabled: { 91 | description: 'If Redux Devtools should be enabled.', 92 | validator: required(isBoolean), 93 | }, 94 | dockMonitor: { 95 | defaultPosition: { 96 | description: 'Starting position of the Devtools, can be left, right, top or bottom.', 97 | validator: required(/^left|right|top|bottom$/), 98 | }, 99 | defaultSize: { 100 | description: 'Default size of the Devtools, should be a number between 0 and 1.', 101 | validator: (input) => input >= 0 && input <= 1, 102 | }, 103 | toggleVisibilityKey: { 104 | description: 'The key that should toogle the Redux Devtools, will be combine with CTRL.', 105 | validator: required(isString), 106 | }, 107 | changePositionKey: { 108 | description: 'The key that should change position of the Redux Devtools.', 109 | validator: required(isString), 110 | }, 111 | defaultIsVisible: { 112 | description: 'If the Redux Devtools should be shown by default.', 113 | validator: required(isBoolean), 114 | }, 115 | }, 116 | instrument: { 117 | maxAge: { 118 | description: 'Maximum allowed actions to be stored on the history tree. Good if ' + 119 | 'the application generates a lot of actions.', 120 | validator: isInteger, 121 | }, 122 | }, 123 | logMonitor: { 124 | theme: { 125 | description: 'The theme to use for the Redux Devtools, see ' + 126 | 'https://github.com/gaearon/redux-devtools-themes for the available ones.', 127 | validator: isString, 128 | }, 129 | }, 130 | }, 131 | 132 | logger: { 133 | level: { 134 | description: 'The logging level for Redux Logger, can be either warn, error or info.', 135 | validator: required(/^warn|error|info$/), 136 | }, 137 | collapsed: { 138 | description: 'If the logged actions by Redux Logger should be collapsed by default.', 139 | validator: required(isBoolean), 140 | }, 141 | duration: { 142 | description: 'If Redux Logger should print the duration of each action.', 143 | validator: required(isBoolean), 144 | }, 145 | timestamp: { 146 | description: 'If Redux Logger should print the timestamp with each action.', 147 | validator: required(isBoolean), 148 | }, 149 | }, 150 | }, 151 | 152 | yellowbox: { 153 | enabled: { 154 | description: 'If YellowBox should be enabled.', 155 | validator: isBoolean, 156 | }, 157 | ignore: { 158 | description: 'Array of prefix strings that should be ignored by YellowBox.', 159 | validator: isArray(isString), 160 | }, 161 | }, 162 | }, 163 | }, 164 | }; 165 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react-dev/src/index.js: -------------------------------------------------------------------------------- 1 | export roc from './roc'; 2 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react-dev/src/roc/index.js: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | 3 | import { lazyFunctionRequire, generateDependencies } from 'roc'; 4 | 5 | import config from '../config/roc.config.js'; 6 | import meta from '../config/roc.config.meta.js'; 7 | 8 | import { packageJSON } from './util'; 9 | 10 | const lazyRequire = lazyFunctionRequire(require); 11 | 12 | export default { 13 | config, 14 | meta, 15 | dependencies: { 16 | exports: generateDependencies(packageJSON, [ 17 | 'react-a11y', 18 | 'redux-devtools', 19 | 'redux-devtools-log-monitor', 20 | 'redux-devtools-dock-monitor', 21 | 'redux-logger', 22 | 'yellowbox-react', 23 | ]), 24 | }, 25 | actions: [{ 26 | hook: 'build-webpack', 27 | action: lazyRequire('../webpack'), 28 | }, { 29 | extension: 'roc', 30 | hook: 'update-settings', 31 | action: ({ context: { usedExtensions } }) => (readSettings) => () => { 32 | const settings = readSettings(); 33 | const newSettings = { build: { input: {} } }; 34 | 35 | const rocPackageWebAppReact = usedExtensions.find(({ name }) => name === 'roc-package-web-app-react'); 36 | 37 | if (rocPackageWebAppReact) { 38 | if (!settings.build.input.web) { 39 | newSettings.build.input.web = path.join(rocPackageWebAppReact.path, 'app/default/client.js'); 40 | } 41 | 42 | if (!settings.build.input.node) { 43 | newSettings.build.input.node = path.join(rocPackageWebAppReact.path, 'app/default/server.js'); 44 | } 45 | 46 | if (settings.build.resources.length > 0) { 47 | const resources = settings.build.resources.map((resource) => { 48 | const matches = /^roc-package-web-app-react\/(.*)/.exec(resource); 49 | if (matches && matches[1]) { 50 | return path.join(rocPackageWebAppReact.path, `/${matches[1]}`); 51 | } 52 | 53 | return resource; 54 | }); 55 | 56 | newSettings.build.resources = resources; 57 | } 58 | } 59 | 60 | // If a change has been done we will run the hook 61 | return newSettings; 62 | }, 63 | }], 64 | packages: [ 65 | require.resolve('roc-package-web-app-dev'), 66 | ], 67 | plugins: [ 68 | require.resolve('roc-plugin-react-dev'), 69 | ], 70 | }; 71 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react-dev/src/roc/util.js: -------------------------------------------------------------------------------- 1 | import { runHook } from 'roc'; 2 | 3 | // eslint-disable-next-line 4 | export const packageJSON = require('../../package.json'); 5 | 6 | /** 7 | * Helper function for invoking/running a hook, pre-configured for the current package. 8 | * 9 | * @param {...Object} args - The arguments to pass along to the action. 10 | * 11 | * @returns {Object|function} - Either a object, the final value from the actions or a function if callback is used. 12 | */ 13 | export function invokeHook(...args) { 14 | return runHook(packageJSON.name)(...args); 15 | } 16 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react-dev/src/webpack/index.js: -------------------------------------------------------------------------------- 1 | import { join } from 'path'; 2 | 3 | import { getAbsolutePath, fileExists } from 'roc'; 4 | import webpack from 'webpack'; 5 | import ContextReplacementPlugin from 'webpack/lib/ContextReplacementPlugin'; 6 | 7 | export default ({ 8 | context: { config: { settings: { build: buildSettings } } }, 9 | previousValue: webpackConfig, 10 | }) => (target) => () => { 11 | const newWebpackConfig = { ...webpackConfig }; 12 | 13 | const WEB = (target === 'web'); 14 | 15 | if (WEB) { 16 | newWebpackConfig.plugins.push( 17 | new webpack.IgnorePlugin(/^roc$/) 18 | ); 19 | } 20 | 21 | if (buildSettings.routes) { 22 | const routes = getAbsolutePath(buildSettings.routes); 23 | 24 | newWebpackConfig.plugins.push( 25 | new webpack.DefinePlugin({ 26 | REACT_ROUTER_ROUTES: JSON.stringify(routes), 27 | }) 28 | ); 29 | } 30 | 31 | const hasReducers = !!(buildSettings.reducers && fileExists(buildSettings.reducers)); 32 | if (hasReducers) { 33 | const reducers = getAbsolutePath(buildSettings.reducers); 34 | 35 | newWebpackConfig.plugins.push( 36 | new webpack.DefinePlugin({ 37 | REDUX_REDUCERS: JSON.stringify(reducers), 38 | }) 39 | ); 40 | } 41 | 42 | const hasMiddlewares = !!(buildSettings.redux.middlewares && fileExists(buildSettings.redux.middlewares)); 43 | if (hasMiddlewares) { 44 | const middlewares = getAbsolutePath(buildSettings.redux.middlewares); 45 | 46 | newWebpackConfig.plugins.push( 47 | new webpack.DefinePlugin({ 48 | REDUX_MIDDLEWARES: JSON.stringify(middlewares), 49 | }) 50 | ); 51 | } 52 | 53 | const hasEnhancers = !!(buildSettings.redux.enhancers && fileExists(buildSettings.redux.enhancers)); 54 | if (hasEnhancers) { 55 | const enhancers = getAbsolutePath(buildSettings.redux.enhancers); 56 | 57 | newWebpackConfig.plugins.push( 58 | new webpack.DefinePlugin({ 59 | REDUX_ENHANCERS: JSON.stringify(enhancers), 60 | }) 61 | ); 62 | } 63 | 64 | const hasSagas = !!(buildSettings.redux.sagas && fileExists(buildSettings.redux.sagas)); 65 | if (hasSagas) { 66 | const sagas = getAbsolutePath(buildSettings.redux.sagas); 67 | 68 | newWebpackConfig.plugins.push( 69 | new webpack.DefinePlugin({ 70 | REDUX_SAGAS: JSON.stringify(sagas), 71 | }) 72 | ); 73 | } 74 | 75 | const hasClientLoading = !!(buildSettings.clientLoading && fileExists(buildSettings.clientLoading)); 76 | if (hasClientLoading) { 77 | const clientLoading = getAbsolutePath(buildSettings.clientLoading); 78 | 79 | newWebpackConfig.plugins.push( 80 | new webpack.DefinePlugin({ 81 | ROC_CLIENT_LOADING: JSON.stringify(clientLoading), 82 | }) 83 | ); 84 | } 85 | 86 | const hasTemplateValues = !!(buildSettings.templateValues && fileExists(buildSettings.templateValues)); 87 | if (hasTemplateValues) { 88 | const templateValues = getAbsolutePath(buildSettings.templateValues); 89 | 90 | newWebpackConfig.plugins.push( 91 | new webpack.DefinePlugin({ 92 | TEMPLATE_VALUES: JSON.stringify(templateValues), 93 | }) 94 | ); 95 | } 96 | 97 | const hasI18nLocales = !!(buildSettings.i18n.locales && buildSettings.i18n.locales.length); 98 | if (hasI18nLocales) { 99 | const locales = buildSettings.i18n.locales; 100 | 101 | newWebpackConfig.plugins.push( 102 | new webpack.DefinePlugin({ 103 | I18N_LOCALES: JSON.stringify(locales), 104 | }), 105 | new ContextReplacementPlugin( 106 | /intl[\/\\]locale-data[\/\\]jsonp$/, 107 | new RegExp(`^\.\/(${locales.join('|')})$`) 108 | ) 109 | ); 110 | } 111 | 112 | newWebpackConfig.plugins.push( 113 | new webpack.DefinePlugin({ 114 | USE_DEFAULT_REDUX_REDUCERS: buildSettings.redux.useDefaultReducers, 115 | USE_DEFAULT_REDUX_MIDDLEWARES: buildSettings.redux.useDefaultMiddlewares, 116 | USE_DEFAULT_REACT_ROUTER_ROUTES: buildSettings.useDefaultRoutes, 117 | USE_I18N_POLYFILL: buildSettings.i18n.usePolyfill, 118 | USE_REACT_ROUTER_SCROLL_ASYNC: buildSettings.useReactRouterScrollAsync, 119 | 120 | HAS_REDUX_REDUCERS: hasReducers, 121 | HAS_REDUX_MIDDLEWARES: hasMiddlewares, 122 | HAS_REDUX_ENHANCERS: hasEnhancers, 123 | HAS_REDUX_SAGA: hasSagas, 124 | HAS_CLIENT_LOADING: hasClientLoading, 125 | HAS_TEMPLATE_VALUES: hasTemplateValues, 126 | }) 127 | ); 128 | 129 | newWebpackConfig.resolveLoader.root.push(join(__dirname, '..', '..', 'node_modules')); 130 | 131 | return newWebpackConfig; 132 | }; 133 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["react"] 3 | } 4 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/.eslintignore: -------------------------------------------------------------------------------- 1 | lib 2 | esdocs 3 | docs 4 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "airbnb", 3 | 4 | "parser": "babel-eslint", 5 | 6 | "plugins": ["eslint-plugin-babel"], 7 | 8 | "rules": { 9 | "indent": [2, 4, { "SwitchCase": 1 }], 10 | "max-len": [2, 120, 4], 11 | "no-warning-comments": 1, 12 | "class-methods-use-this": 0, 13 | "arrow-parens": ["off", "as-needed"], 14 | 15 | "generator-star-spacing": 0, 16 | "babel/generator-star-spacing": [2, { "before": false, "after": true }], 17 | 18 | "import/order": [2, { "groups": ["builtin", "external", "internal", "parent", "sibling", "index"], "newlines-between": "always"}], 19 | "import/newline-after-import": [2], 20 | "import/no-extraneous-dependencies": [1], 21 | "import/no-unresolved": [1], 22 | 23 | "react/jsx-indent": [2, 4], 24 | "react/jsx-indent-props": [2, 4], 25 | "react/jsx-filename-extension": 0 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Verdens Gang AS 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/README.md: -------------------------------------------------------------------------------- 1 | # roc-package-web-app-react 2 | 3 | Package for building React applications with Roc 4 | 5 | Read the comprehensive user-guide on how to best utilize the tools and libraries provided by this Roc extension[here](https://github.com/rocjs/roc-package-web-app-react/blob/master/GUIDE.md). 6 | 7 | ## Documentation 8 | - [Actions](docs/Actions.md) 9 | - [Commands](docs/Commands.md) 10 | - [Configuration](docs/Configuration.md) 11 | - [Dependencies](docs/Dependencies.md) 12 | - [Hooks](docs/Hooks.md) 13 | - [Settings](docs/Settings.md) 14 | - [Extensions](docs/Extensions.md) 15 | 16 | --- 17 | _Generated by [Roc](https://github.com/rocjs/roc)_ 18 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/app/client/create-client.js: -------------------------------------------------------------------------------- 1 | /* global __DEV__, HAS_CLIENT_LOADING, ROC_CLIENT_LOADING, ROC_PATH, HAS_REDUX_REDUCERS, document, window, 2 | HAS_REDUX_SAGA, REDUX_SAGAS, I18N_LOCALES, USE_I18N_POLYFILL, USE_REACT_ROUTER_SCROLL_ASYNC */ 3 | /* eslint-disable global-require */ 4 | import React from 'react'; 5 | import ReactDOM from 'react-dom'; 6 | import useRouterHistory from 'react-router/lib/useRouterHistory'; 7 | import applyRouterMiddleware from 'react-router/lib/applyRouterMiddleware'; 8 | import createHistory from 'history/lib/createBrowserHistory'; 9 | import { supportsHistory } from 'history/lib/DOMUtils'; 10 | import debug from 'debug'; 11 | import { useRedial } from 'react-router-redial'; 12 | 13 | import { rocConfig } from '../shared/universal-config'; 14 | 15 | import renderToDOM from './render-to-dom'; 16 | 17 | const clientDebug = debug('roc:client'); 18 | 19 | const basename = ROC_PATH === '/' ? '' : ROC_PATH; 20 | 21 | function compose(funcs) { 22 | if (funcs.length === 0) { 23 | return (arg) => arg; 24 | } 25 | 26 | const last = funcs[funcs.length - 1]; 27 | const rest = funcs.slice(0, -1); 28 | return (...args) => rest.reduceRight((composed, f) => f(composed), last(...args)); 29 | } 30 | 31 | 32 | /** 33 | * Client entry point for React applications. 34 | * 35 | * @example 36 | * import { createClient } from 'roc-web-react/app/client'; 37 | * 38 | * const server = createClient({ 39 | * createRoutes: routes, 40 | * createStore: store, 41 | * mountNode: 'application', 42 | * routerMiddlewareConfig, 43 | * }); 44 | * 45 | * @param {rocClientOptions} options - Options for the client 46 | */ 47 | export default function createClient({ 48 | createRoutes, 49 | createStore, 50 | mountNode, 51 | routerMiddlewareConfig, 52 | }) { 53 | if (!createRoutes) { 54 | throw new Error('createRoutes needs to be defined'); 55 | } 56 | 57 | if (!mountNode) { 58 | throw new Error('mountNode needs to be defined'); 59 | } 60 | 61 | if (rocConfig) { 62 | debug.enable(rocConfig.runtime.debug.client); 63 | } 64 | 65 | if (__DEV__ && rocConfig.dev.a11y) { 66 | if (rocConfig.runtime.ssr) { 67 | clientDebug('You will see a "Warning: React attempted to reuse markup in a container but the checksum was' + 68 | ' invalid." message. That\'s because a11y is enabled.'); 69 | } 70 | 71 | require('react-a11y')(React, { 72 | ReactDOM, 73 | // These needs to be added for Redux Devtools to be ignored by A11Y 74 | filterFn: (name) => [ 75 | 'LogMonitorButton', 76 | 'LogMonitorAction', 77 | 'JSONValueNode', 78 | 'JSONNestedNode', 79 | 'JSONArrow', 80 | ].indexOf(name) === -1, 81 | }); 82 | } 83 | 84 | const render = () => { 85 | const forceRefreshSetting = rocConfig.runtime.history.forceRefresh; 86 | let history = useRouterHistory(createHistory)({ 87 | basename, 88 | forceRefresh: typeof forceRefreshSetting === 'function' 89 | ? forceRefreshSetting() 90 | : forceRefreshSetting, 91 | }); 92 | 93 | let routes; 94 | let locals = { 95 | history, 96 | }; 97 | const createComponent = [(component) => component]; 98 | const createDevComponent = [(component) => component]; 99 | 100 | if (HAS_REDUX_REDUCERS && createStore) { 101 | const { Provider } = require('react-redux'); 102 | const { syncHistoryWithStore } = require('react-router-redux'); 103 | 104 | const store = createStore(history, window.FLUX_STATE); 105 | 106 | if (HAS_REDUX_SAGA) { 107 | store.runSaga(require(REDUX_SAGAS).default); 108 | } 109 | 110 | history = syncHistoryWithStore(history, store, { 111 | // We do not want to use adjustUrlOnReplay if the browser does 112 | // not support the history API with pushState since this can lead 113 | // to redirect loops https://github.com/reactjs/react-router-redux/issues/285 114 | adjustUrlOnReplay: supportsHistory(), 115 | }); 116 | 117 | routes = createRoutes(store); 118 | locals = { 119 | dispatch: store.dispatch, 120 | getState: store.getState, 121 | history, 122 | }; 123 | 124 | createComponent.push((component) => ( 125 | 126 | {component} 127 | 128 | )); 129 | 130 | if (__DEV__) { 131 | if (rocConfig.dev.redux.devTools.enabled && !window.devToolsExtension) { 132 | const DevTools = require('./dev-tools').default; 133 | 134 | createDevComponent.push((component) => ( 135 | 136 | 137 | {component} 138 | 139 | 140 | 141 | )); 142 | } else if (rocConfig.dev.redux.devTools.enabled) { 143 | console.log('Found Redux Devtools Chrome extension, will use that over default one.'); 144 | } 145 | } 146 | } else { 147 | routes = createRoutes(); 148 | } 149 | 150 | if (__DEV__ && rocConfig.dev.yellowbox.enabled) { 151 | const YellowBox = require('yellowbox-react').default; 152 | 153 | /* eslint-disable no-console */ 154 | console.ignoredYellowBox = rocConfig.dev.yellowbox.ignore; 155 | /* eslint-enable */ 156 | 157 | createDevComponent.push((component) => ( 158 | 159 | {component} 160 | 161 | 162 | )); 163 | } 164 | 165 | const node = document.getElementById(mountNode); 166 | let updateScroll = () => {}; 167 | 168 | const middlewares = [ 169 | useRedial({ 170 | ...routerMiddlewareConfig['react-router-redial'], 171 | locals, 172 | initialLoading: HAS_CLIENT_LOADING ? require(ROC_CLIENT_LOADING).default : undefined, 173 | beforeTransition: rocConfig.runtime.fetch.client.beforeTransition, 174 | afterTransition: rocConfig.runtime.fetch.client.afterTransition, 175 | parallel: rocConfig.runtime.fetch.client.parallel, 176 | onCompleted: (type) => { 177 | if (type === 'beforeTransition') { 178 | updateScroll(); 179 | } 180 | 181 | if (routerMiddlewareConfig['react-router-redial'].onCompleted) { 182 | routerMiddlewareConfig['react-router-redial'].onCompleted(type); 183 | } 184 | }, 185 | }), 186 | ]; 187 | 188 | if (USE_REACT_ROUTER_SCROLL_ASYNC) { 189 | const useScroll = require('react-router-scroll-async/lib/useScroll'); 190 | 191 | middlewares.unshift( 192 | useScroll({ 193 | ...routerMiddlewareConfig['react-router-scroll-async'], 194 | updateScroll: (cb) => { updateScroll = cb; }, 195 | }) 196 | ); 197 | } 198 | 199 | renderToDOM( 200 | { 201 | createComponent: compose(createComponent), 202 | history, 203 | routes, 204 | routerRenderFn: applyRouterMiddleware(...middlewares), 205 | }, 206 | node 207 | ); 208 | 209 | if (__DEV__) { 210 | const devNode = document.createElement('div'); 211 | node.parentNode.insertBefore(devNode, node.nextSibling); 212 | ReactDOM.render(compose(createDevComponent)(null), devNode); 213 | } 214 | }; 215 | 216 | if (USE_I18N_POLYFILL) { 217 | const intlLoader = !global.Intl ? 218 | require('bundle?name=intl!intl') : 219 | (cb) => cb(); 220 | 221 | // intl's locale data identifies locales by the shortest ISO 639 language code. 222 | // https://tools.ietf.org/html/rfc5646 223 | const language = (locale) => /^([^-]+)/.exec(locale)[0]; 224 | 225 | intlLoader(() => { 226 | const areIntlLocalesSupported = require('intl-locales-supported'); 227 | 228 | const localeModules = I18N_LOCALES.map(locale => new Promise((resolve) => { 229 | if (!areIntlLocalesSupported(locale)) { 230 | // eslint-disable-next-line 231 | require('bundle!intl/locale-data/jsonp/' + language(locale))(resolve); 232 | } else { 233 | resolve(); 234 | } 235 | })); 236 | 237 | Promise.all(localeModules).then(render); 238 | }); 239 | } else { 240 | render(); 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/app/client/dev-tools.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { createDevTools } from 'redux-devtools'; 3 | import LogMonitor from 'redux-devtools-log-monitor'; 4 | import DockMonitor from 'redux-devtools-dock-monitor'; 5 | 6 | import { rocConfig } from '../shared/universal-config'; 7 | 8 | export default createDevTools( 9 | 10 | 11 | 12 | ); 13 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/app/client/index.js: -------------------------------------------------------------------------------- 1 | export createClient from './create-client'; 2 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/app/client/render-to-dom.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable global-require */ 2 | import React from 'react'; 3 | import ReactDOM from 'react-dom'; 4 | import Router from 'react-router/lib/Router'; 5 | import match from 'react-router/lib/match'; 6 | 7 | function renderSync({ renderProps, createComponent, routerRenderFn }, node) { 8 | const finalComponent = createComponent( 9 | 13 | ); 14 | 15 | ReactDOM.render(finalComponent, node); 16 | } 17 | 18 | export default function renderAsync({ history, routes, ...rest }, node) { 19 | match({ history, routes }, (error, redirectLocation, renderProps) => { 20 | renderSync({ 21 | ...rest, 22 | renderProps, 23 | }, node); 24 | }); 25 | } 26 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/app/default/client.js: -------------------------------------------------------------------------------- 1 | import { createClient } from '../client'; 2 | 3 | import getRoutesAndStore from './get-routes-and-store'; 4 | 5 | const { store, routes, routerMiddlewareConfig } = getRoutesAndStore(); 6 | 7 | createClient({ 8 | createRoutes: routes, 9 | createStore: store, 10 | mountNode: 'application', 11 | routerMiddlewareConfig, 12 | }); 13 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/app/default/get-routes-and-store.js: -------------------------------------------------------------------------------- 1 | /* global REACT_ROUTER_ROUTES, REDUX_REDUCERS, HAS_REDUX_REDUCERS, HAS_REDUX_MIDDLEWARES, REDUX_MIDDLEWARES, 2 | USE_DEFAULT_REDUX_REDUCERS, USE_DEFAULT_REDUX_MIDDLEWARES, USE_DEFAULT_REACT_ROUTER_ROUTES, __WEB__, 3 | HAS_REDUX_ENHANCERS, REDUX_ENHANCERS 4 | */ 5 | /* eslint-disable global-require */ 6 | 7 | export default function getRoutesAndStore() { 8 | let store = null; 9 | let routes = null; 10 | 11 | if (HAS_REDUX_REDUCERS) { 12 | const { createStore } = require('../shared'); 13 | 14 | let defaultReducers = {}; 15 | if (USE_DEFAULT_REDUX_REDUCERS) { 16 | defaultReducers = require('../shared').defaultReducers; 17 | } 18 | 19 | let middlewares = []; 20 | if (USE_DEFAULT_REDUX_MIDDLEWARES) { 21 | middlewares = middlewares.concat(require('../shared').defaultMiddlewares); 22 | } 23 | 24 | if (HAS_REDUX_MIDDLEWARES) { 25 | middlewares = middlewares.concat(require(REDUX_MIDDLEWARES).default()); 26 | } 27 | 28 | let enhancers; 29 | if (HAS_REDUX_ENHANCERS) { 30 | enhancers = require(REDUX_ENHANCERS).default(); 31 | } 32 | 33 | const reducers = { 34 | ...defaultReducers, 35 | ...require(REDUX_REDUCERS), 36 | }; 37 | 38 | const storeCreator = createStore( 39 | reducers, 40 | middlewares, 41 | enhancers 42 | ); 43 | 44 | let replaceReducers = null; 45 | if (__WEB__) { 46 | replaceReducers = (replaceReducer) => { 47 | module.hot.accept(require.resolve(REDUX_REDUCERS), () => { 48 | replaceReducer({ 49 | ...defaultReducers, 50 | ...require(REDUX_REDUCERS), 51 | }); 52 | }); 53 | }; 54 | } 55 | 56 | store = storeCreator(replaceReducers); 57 | } 58 | 59 | const { default: projectRoutes, middlewareConfig = {} } = require(REACT_ROUTER_ROUTES); 60 | 61 | if (USE_DEFAULT_REACT_ROUTER_ROUTES) { 62 | const { createRoutes } = require('../shared'); 63 | 64 | routes = createRoutes(projectRoutes); 65 | } else { 66 | routes = require(REACT_ROUTER_ROUTES).default; 67 | } 68 | 69 | return { 70 | routerMiddlewareConfig: { 71 | 'react-router-scroll-async': {}, 72 | 'react-router-redial': {}, 73 | ...middlewareConfig, 74 | }, 75 | routes, 76 | store, 77 | }; 78 | } 79 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/app/default/server.js: -------------------------------------------------------------------------------- 1 | import { createServer, useReact } from '../server'; 2 | 3 | useReact(createServer)().start(); 4 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/app/server/index.js: -------------------------------------------------------------------------------- 1 | export useReact from './useReact'; 2 | export createServer from 'roc-package-web-app/app/server'; 3 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/app/server/useReact.js: -------------------------------------------------------------------------------- 1 | /* global __DIST__, __DEV__ HAS_TEMPLATE_VALUES, TEMPLATE_VALUES, ROC_PATH, HAS_REDUX_SAGA, REDUX_SAGAS, 2 | I18N_LOCALES, USE_I18N_POLYFILL */ 3 | 4 | import useReactLib from 'roc-package-web-app-react/lib/app/server/useReact'; 5 | 6 | import Header from '../shared/header'; 7 | import getRoutesAndStore from '../default/get-routes-and-store'; 8 | 9 | const { store, routes } = getRoutesAndStore(); 10 | 11 | export default function useReact(createServer) { 12 | // eslint-disable-next-line 13 | const templateValues = HAS_TEMPLATE_VALUES ? require(TEMPLATE_VALUES) : undefined; 14 | let reduxSagas; 15 | 16 | if (HAS_REDUX_SAGA) { 17 | reduxSagas = require(REDUX_SAGAS).default; // eslint-disable-line 18 | } 19 | 20 | if (USE_I18N_POLYFILL) { 21 | // eslint-disable-next-line 22 | const areIntlLocalesSupported = require('intl-locales-supported'); 23 | 24 | if (!areIntlLocalesSupported(I18N_LOCALES)) { 25 | // eslint-disable-next-line 26 | const IntlPolyfill = require('intl'); 27 | 28 | Intl.NumberFormat = IntlPolyfill.NumberFormat; 29 | Intl.DateTimeFormat = IntlPolyfill.DateTimeFormat; 30 | } 31 | } 32 | 33 | return ({ createRoutes = routes, createStore = store, ...rest } = {}, beforeUserMiddlewares) => 34 | useReactLib(createServer, { 35 | dev: __DEV__, 36 | dist: __DIST__, 37 | hasTemplateValues: HAS_TEMPLATE_VALUES, 38 | templateValues, 39 | rocPath: ROC_PATH, 40 | Header, 41 | reduxSagas, 42 | })( 43 | { 44 | createRoutes, 45 | createStore, 46 | ...rest, 47 | }, 48 | beforeUserMiddlewares 49 | ); 50 | } 51 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/app/shared/application.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import React from 'react'; 3 | 4 | import Header from './header'; 5 | 6 | // eslint-disable-next-line 7 | export default class Application extends React.Component { 8 | 9 | static propTypes = { 10 | children: PropTypes.node, 11 | }; 12 | 13 | render() { 14 | return ( 15 |
16 |
17 | {this.props.children} 18 |
19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/app/shared/create-routes.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Route from 'react-router/lib/Route'; 3 | 4 | import Application from './application'; 5 | 6 | /** 7 | * Route creator 8 | * 9 | * @param {!function} routes - A function that takes a reference to potential store and returns a React Router route 10 | * @returns {function} A function that takes a reference to a potential store, runs the `routes` function and wrapps the 11 | * result in a _Application component_ wrapper. See the README.md for more information on what it does. 12 | */ 13 | export default function createRoutes(routes) { 14 | return store => { 15 | const appRoutes = routes(store); 16 | 17 | return ( 18 | 19 | {appRoutes} 20 | 21 | ); 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/app/shared/flux/create-store.js: -------------------------------------------------------------------------------- 1 | /* globals __DEV__, __WEB__, window, HAS_REDUX_SAGA */ 2 | 3 | import { createStore, applyMiddleware, combineReducers, compose } from 'redux'; 4 | import { routerMiddleware, routerReducer } from 'react-router-redux'; 5 | 6 | import { rocConfig } from '../universal-config'; 7 | 8 | /** 9 | * Redux store creator 10 | * 11 | * @param {!object} reducers - Reducers that should be added to the store 12 | * @param {function[]} middlewares - Redux middlewares that should be added to the store 13 | * @param {function[]} enhancers - Redux enhancers that should be added to the store 14 | * @returns {function} A function that has the following interface: 15 | * `(callback) => (reduxReactRouter, getRoutes, createHistory, initialState)`. 16 | * The callback will be called when the application is in _DEV_ mode on the client as a way to add hot module update of 17 | * the reducers. The callback itself will take a function as the parameter that in turn takes the reducers to update. 18 | */ 19 | export default function createReduxStore(reducers, middlewares = [], enhancers = []) { 20 | return (callback) => 21 | (history, initialState) => { 22 | let finalCreateStore; 23 | const normalMiddlewares = [].concat(middlewares); 24 | let sagaMiddleware; 25 | 26 | // redux-saga 27 | if (HAS_REDUX_SAGA) { 28 | const createSagaMiddleware = require('redux-saga').default; // eslint-disable-line 29 | sagaMiddleware = createSagaMiddleware(); 30 | normalMiddlewares.push(sagaMiddleware); 31 | } 32 | 33 | // Add the react-router-redux middleware 34 | normalMiddlewares.push(routerMiddleware(history)); 35 | 36 | if (__DEV__ && __WEB__) { 37 | const { persistState } = require('redux-devtools'); // eslint-disable-line 38 | const createLogger = require('redux-logger'); // eslint-disable-line 39 | const logger = createLogger({ ...rocConfig.dev.redux.logger }); 40 | 41 | const debugMiddlewares = [logger]; 42 | 43 | let devTools = (input) => input; 44 | if (rocConfig.dev.redux.devTools.enabled) { 45 | devTools = window.devToolsExtension 46 | ? window.devToolsExtension() 47 | // eslint-disable-next-line 48 | : require('../../client/dev-tools').default.instrument(rocConfig.dev.redux.devTools.instrument); 49 | } 50 | 51 | finalCreateStore = compose( 52 | applyMiddleware(...normalMiddlewares, ...debugMiddlewares), 53 | devTools, 54 | persistState(window.location.href.match(/[?&]debug_session=([^&]+)\b/)), 55 | ...enhancers 56 | )(createStore); 57 | } else { 58 | finalCreateStore = compose( 59 | applyMiddleware(...normalMiddlewares), 60 | ...enhancers 61 | )(createStore); 62 | } 63 | 64 | const reducer = combineReducers({ 65 | routing: routerReducer, 66 | ...reducers, 67 | }); 68 | 69 | const store = finalCreateStore(reducer, initialState); 70 | 71 | if (__DEV__ && __WEB__ && module.hot) { 72 | // Enable Webpack hot module replacement for reducers 73 | callback((newReducers) => { 74 | const nextRootReducer = combineReducers({ 75 | routing: routerReducer, 76 | ...newReducers, 77 | }); 78 | store.replaceReducer(nextRootReducer); 79 | }); 80 | } 81 | 82 | if (sagaMiddleware) { 83 | store.runSaga = sagaMiddleware.run; 84 | } 85 | 86 | return store; 87 | }; 88 | } 89 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/app/shared/flux/middlewares/index.js: -------------------------------------------------------------------------------- 1 | import thunk from 'redux-thunk'; 2 | 3 | export default [thunk]; 4 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/app/shared/flux/reducers/errors.js: -------------------------------------------------------------------------------- 1 | export default function errors(state = [], action) { 2 | const { type, error, payload } = action; 3 | 4 | if (type === 'RESET_ERROR_MESSAGES') { 5 | return []; 6 | } else if (error) { 7 | return [ 8 | ...state, 9 | payload, 10 | ]; 11 | } 12 | 13 | return state; 14 | } 15 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/app/shared/flux/reducers/index.js: -------------------------------------------------------------------------------- 1 | export errors from './errors'; 2 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/app/shared/header.js: -------------------------------------------------------------------------------- 1 | /* global ROC_PATH */ 2 | 3 | import React from 'react'; 4 | import Helmet from 'react-helmet'; 5 | 6 | import { rocConfig } from './universal-config'; 7 | 8 | // eslint-disable-next-line 9 | export default class Header extends React.Component { 10 | render() { 11 | const path = ROC_PATH === '/' ? '' : ROC_PATH + '/'; // eslint-disable-line 12 | const base = rocConfig.runtime.head.base.href ? { 13 | ...rocConfig.runtime.head.base, 14 | href: rocConfig.runtime.head.base.href.replace(/^ROC_PATH$/, path), 15 | } : {}; 16 | 17 | return ( 18 | 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/app/shared/index.js: -------------------------------------------------------------------------------- 1 | export { rocConfig } from './universal-config'; 2 | export { appConfig } from './universal-config'; 3 | export createRoutes from './create-routes'; 4 | export createStore from './flux/create-store'; 5 | export defaultReducers from './flux/reducers'; 6 | export defaultMiddlewares from './flux/middlewares'; 7 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/app/shared/universal-config.js: -------------------------------------------------------------------------------- 1 | /* globals window */ 2 | /** 3 | * Universal Configuration Manager 4 | * 5 | * Manages both __application__ configuration and __Roc__ configuration. 6 | * On the server the configurations will be fetched directly and on the client it's expected that the configuration 7 | * is available on `window` as `ROC_CONFIG` and `APP_CONFIG`. 8 | * 9 | * appConfig will only contain what has been selected by `runtime.configWhitelistProperty`. That means if you want 10 | * to read the full configuration on the server you will need to read it directly from node-config. 11 | */ 12 | 13 | export const rocConfig = (function getRocConfig() { 14 | return typeof window !== 'undefined' ? window.ROC_CONFIG : require('roc').getSettings(); // eslint-disable-line 15 | }()); 16 | 17 | const whiteListed = () => ( 18 | rocConfig.runtime.configWhitelistProperty ? 19 | require('config')[rocConfig.runtime.configWhitelistProperty] : // eslint-disable-line 20 | undefined 21 | ); 22 | 23 | export const appConfig = (function getAppConfig() { 24 | return typeof window !== 'undefined' ? window.APP_CONFIG : whiteListed(); 25 | }()); 26 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/docs/Actions.md: -------------------------------------------------------------------------------- 1 | # Actions for `roc-package-web-app-react` 2 | 3 | ## Actions 4 | * [roc-plugin-start](#roc-plugin-start) 5 | * [register-runtime](#register-runtime) 6 | * [roc-package-web-app](#roc-package-web-app) 7 | * [register-runtime](#register-runtime-1) 8 | 9 | ## roc-plugin-start 10 | 11 | ### register-runtime 12 | 13 | Adds the base runtime. Will resolve node paths and enable source map support. 14 | 15 | __Connects to extension:__ `roc-plugin-start` 16 | __Connects to hook:__ `register-runtime` 17 | __Have post:__ No 18 | 19 | ## roc-package-web-app 20 | 21 | ### register-runtime 22 | 23 | __Connects to extension:__ `roc-plugin-start` 24 | __Connects to hook:__ `register-runtime` 25 | __Have post:__ No 26 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/docs/Commands.md: -------------------------------------------------------------------------------- 1 | # Commands for `roc-package-web-app-react` 2 | 3 | ## General Information 4 | All commands can be called with some additional options illustrated in the table below. 5 | 6 | ### General options 7 | 8 | | Name | Description | Required | 9 | | --------------------- | ---------------------------------------------- | -------- | 10 | | -b, --better-feedback | Enables source-map-support and loud-rejection. | No | 11 | | -c, --config | Path to configuration file. | No | 12 | | -d, --directory | Path to working directory. | No | 13 | | -h, --help | Output usage information. | No | 14 | | -V, --verbose | Enable verbose mode. | No | 15 | | -v, --version | Output version number. | No | 16 | 17 | ## Commands 18 | * [start](#start) 19 | * [meta](#meta) 20 | * [docs](#docs) 21 | * [list-settings](#list-settings) 22 | 23 | ## start 24 | __Starts the current project.__ 25 | 26 | ``` 27 | roc start [artifact] 28 | ``` 29 | 30 | ### Arguments 31 | 32 | | Name | Description | Default | Type | Required | Can be empty | 33 | | -------- | ----------------------------- | ------- | ---------- | -------- | ------------ | 34 | | artifact | Path to an artifact to start. | | `Filepath` | No | Yes | 35 | 36 | ### Settings options 37 | * [runtime](docs/Settings.md#runtime) 38 | 39 | ### Defined by extensions 40 | roc-plugin-start 41 | 42 | ## meta 43 | __Meta commands__ 44 | 45 | ``` 46 | roc meta 47 | ``` 48 | Meta commands that can be used to generate meta data about the current project. 49 | 50 | 51 | ### docs 52 | __Generates documentation for the current project.__ 53 | 54 | ``` 55 | roc meta docs 56 | ``` 57 | 58 | #### Command options 59 | 60 | | Name | Description | Default | Type | Required | Can be empty | 61 | | ---------- | ------------------------------------------------------------- | -------------- | ----------------------------------------------------------------- | -------- | ------------ | 62 | | --html | If HTML should be generated. (Not supported yet) | `false` | `Boolean` | No | | 63 | | --markdown | If markdown should be generated. | `true` | `Boolean` | No | | 64 | | --mode | The platform that is to be used, for link generation. | `"github.com"` | `/github\.com|nodejs\.org|bitbucket\.org|ghost\.org|gitlab\.com/` | No | | 65 | | --output | A directory to place the generated documentation inside of. | `"docs"` | `String` | No | No | 66 | | --project | If the projects configuration and actions should be included. | `false` | `Boolean` | No | | 67 | 68 | #### Defined by extensions 69 | roc 70 | 71 | ### list-settings 72 | __Prints all the available settings that can be changed.__ 73 | 74 | ``` 75 | roc meta list-settings 76 | ``` 77 | 78 | #### Defined by extensions 79 | roc 80 | 81 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/docs/Configuration.md: -------------------------------------------------------------------------------- 1 | # Config for `roc-package-web-app-react` 2 | 3 | Configuration that can be defined in `roc.config.js`, other than settings and project. 4 | 5 | __No config available.__ 6 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/docs/Dependencies.md: -------------------------------------------------------------------------------- 1 | # Dependencies for `roc-package-web-app-react` 2 | 3 | The dependencies that are available in the project. 4 | 5 | ## Exported 6 | ### [config](https://www.npmjs.com/package/config) 7 | __Version__: ~1.16.0 8 | __Extension__: roc-package-web-app 9 | __Custom resolve function__: No 10 | 11 | ### [history](https://www.npmjs.com/package/history) 12 | __Version__: ^3.0.0 13 | __Extension__: roc-package-web-app-react 14 | __Custom resolve function__: No 15 | 16 | ### [intl](https://www.npmjs.com/package/intl) 17 | __Version__: ^1.2.5 18 | __Extension__: roc-package-web-app-react 19 | __Custom resolve function__: No 20 | 21 | ### [intl-locales-supported](https://www.npmjs.com/package/intl-locales-supported) 22 | __Version__: ^1.0.0 23 | __Extension__: roc-package-web-app-react 24 | __Custom resolve function__: No 25 | 26 | ### [prop-types](https://www.npmjs.com/package/prop-types) 27 | __Version__: ^15.5.8 28 | __Extension__: roc-plugin-react 29 | __Custom resolve function__: No 30 | 31 | ### [react](https://www.npmjs.com/package/react) 32 | __Version__: ^15.5.4 33 | __Extension__: roc-plugin-react 34 | __Custom resolve function__: No 35 | 36 | ### [react-dom](https://www.npmjs.com/package/react-dom) 37 | __Version__: ^15.5.4 38 | __Extension__: roc-plugin-react 39 | __Custom resolve function__: No 40 | 41 | ### [react-helmet](https://www.npmjs.com/package/react-helmet) 42 | __Version__: ~5.0.3 43 | __Extension__: roc-package-web-app-react 44 | __Custom resolve function__: No 45 | 46 | ### [react-redux](https://www.npmjs.com/package/react-redux) 47 | __Version__: ^5.0.4 48 | __Extension__: roc-package-web-app-react 49 | __Custom resolve function__: No 50 | 51 | ### [react-router](https://www.npmjs.com/package/react-router) 52 | __Version__: ^3.0.5 53 | __Extension__: roc-package-web-app-react 54 | __Custom resolve function__: No 55 | 56 | ### [react-router-redial](https://www.npmjs.com/package/react-router-redial) 57 | __Version__: ~0.3.5 58 | __Extension__: roc-package-web-app-react 59 | __Custom resolve function__: No 60 | 61 | ### [react-router-redux](https://www.npmjs.com/package/react-router-redux) 62 | __Version__: ^4.0.8 63 | __Extension__: roc-package-web-app-react 64 | __Custom resolve function__: No 65 | 66 | ### [react-router-scroll](https://www.npmjs.com/package/react-router-scroll) 67 | __Version__: DEPRECATED - Use react-router-scroll-async 68 | __Extension__: roc-package-web-app-react 69 | __Custom resolve function__: Yes 70 | 71 | ### [react-router-scroll-async](https://www.npmjs.com/package/react-router-scroll-async) 72 | __Version__: ~0.5.1 73 | __Extension__: roc-package-web-app-react 74 | __Custom resolve function__: No 75 | 76 | ### [react-server-status](https://www.npmjs.com/package/react-server-status) 77 | __Version__: ~1.1.0 78 | __Extension__: roc-package-web-app-react 79 | __Custom resolve function__: No 80 | 81 | ### [redial](https://www.npmjs.com/package/redial) 82 | __Version__: ~0.5.0 83 | __Extension__: roc-package-web-app-react 84 | __Custom resolve function__: No 85 | 86 | ### [redux](https://www.npmjs.com/package/redux) 87 | __Version__: ^3.6.0 88 | __Extension__: roc-package-web-app-react 89 | __Custom resolve function__: No 90 | 91 | ### [redux-saga](https://www.npmjs.com/package/redux-saga) 92 | __Version__: 0.12.0 93 | __Extension__: roc-package-web-app-react 94 | __Custom resolve function__: No 95 | 96 | ### [redux-thunk](https://www.npmjs.com/package/redux-thunk) 97 | __Version__: ^2.2.0 98 | __Extension__: roc-package-web-app-react 99 | __Custom resolve function__: No 100 | 101 | ### [roc-package-web-app](https://www.npmjs.com/package/roc-package-web-app) 102 | __Version__: ^1.0.0-beta.7 103 | __Extension__: roc-package-web-app-react 104 | __Custom resolve function__: No 105 | 106 | ## Requires 107 | Nothing is required. 108 | 109 | ## Uses 110 | ### roc-package-web-app 111 | #### [koa](https://www.npmjs.com/package/koa) 112 | __Version__: ~1.1.1 113 | 114 | #### [koa-accesslog](https://www.npmjs.com/package/koa-accesslog) 115 | __Version__: ~0.0.2 116 | 117 | #### [koa-add-trailing-slashes](https://www.npmjs.com/package/koa-add-trailing-slashes) 118 | __Version__: ~1.1.0 119 | 120 | #### [koa-compressor](https://www.npmjs.com/package/koa-compressor) 121 | __Version__: ~1.0.3 122 | 123 | #### [koa-errors](https://www.npmjs.com/package/koa-errors) 124 | __Version__: ~1.0.1 125 | 126 | #### [koa-etag](https://www.npmjs.com/package/koa-etag) 127 | __Version__: ~2.0.0 128 | 129 | #### [koa-favicon](https://www.npmjs.com/package/koa-favicon) 130 | __Version__: ~1.2.0 131 | 132 | #### [koa-helmet](https://www.npmjs.com/package/koa-helmet) 133 | __Version__: ~0.3.0 134 | 135 | #### [koa-logger](https://www.npmjs.com/package/koa-logger) 136 | __Version__: ~1.3.0 137 | 138 | #### [koa-lowercase-path](https://www.npmjs.com/package/koa-lowercase-path) 139 | __Version__: ~1.0.0 140 | 141 | #### [koa-normalize-path](https://www.npmjs.com/package/koa-normalize-path) 142 | __Version__: ~1.0.0 143 | 144 | #### [koa-remove-trailing-slashes](https://www.npmjs.com/package/koa-remove-trailing-slashes) 145 | __Version__: ~1.0.0 146 | 147 | #### [koa-static](https://www.npmjs.com/package/koa-static) 148 | __Version__: ~2.0.0 149 | 150 | ### roc-package-web-app-react 151 | #### [nunjucks](https://www.npmjs.com/package/nunjucks) 152 | __Version__: ~2.4.2 153 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/docs/Extensions.md: -------------------------------------------------------------------------------- 1 | # Extensions for `roc-package-web-app-react` 2 | 3 | The extensions that are used in the project, indirect and direct, in the order that they were added. 4 | 5 | ## Packages 6 | ### roc-abstract-package-base — [v1.0.0-beta.2](https://www.npmjs.com/package/roc-abstract-package-base) 7 | Package forming an abstract foundation of the Roc ecosystem. 8 | 9 | The package serves as a base from which other packages within the ecosystem are to be constructed. 10 | It is therefore _never to be included_ as a direct dependency in app or component projects. 11 | 12 | ### roc-package-webpack — [v1.0.0-beta.8](https://www.npmjs.com/package/roc-package-webpack) 13 | Package providing Webpack support for Roc 14 | 15 | ### roc-package-webpack-node — [v1.0.0-beta.3](https://www.npmjs.com/package/roc-package-webpack-node) 16 | Package providing Node support through Webpack. 17 | 18 | ### roc-package-webpack-web — [v1.0.0-beta.3](https://www.npmjs.com/package/roc-package-webpack-web) 19 | Package providing support bundling for Browser runtimes. 20 | 21 | ### roc-package-web-app — [v1.0.0-beta.7](https://www.npmjs.com/package/roc-package-web-app) 22 | Package for building web applications using Roc 23 | 24 | ## Plugins 25 | ### roc-plugin-start — [v1.0.0-beta.2](https://www.npmjs.com/package/roc-plugin-start) 26 | Adds start command with a way to modify the runtime 27 | 28 | ### roc-plugin-react — [v1.0.0-beta.4](https://www.npmjs.com/package/roc-plugin-react) 29 | Adds React support to Webpack and Roc 30 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/docs/Hooks.md: -------------------------------------------------------------------------------- 1 | # Hooks for `roc-package-web-app-react` 2 | 3 | ## Hooks 4 | * [roc](#roc) 5 | * [update-settings](#update-settings) 6 | * [roc-package-web-app-react](#roc-package-web-app-react) 7 | * [extend-template](#extend-template) 8 | * [get-template-values](#get-template-values) 9 | * [roc-plugin-start](#roc-plugin-start) 10 | * [get-potential-target](#get-potential-target) 11 | * [register-runtime](#register-runtime) 12 | 13 | ## roc 14 | 15 | ### update-settings 16 | 17 | Expected to return new settings that should be merged with the existing ones. 18 | 19 | Makes it possible to modify the settings object before a command is started and after potential arguments from the command line and configuration file have been parsed. This is a good point to default to some value if no was given or modify something in the settings. 20 | 21 | __Initial value:__ _Nothing_ 22 | __Expected return value:__ `Object()` 23 | 24 | #### Arguments 25 | 26 | | Name | Description | Type | Required | Can be empty | 27 | | ----------- | ---------------------------------------------------------------------------- | ---------- | -------- | ------------ | 28 | | getSettings | A function that returns the settings after the context has been initialized. | `Function` | No | | 29 | 30 | ## roc-package-web-app-react 31 | 32 | ### extend-template 33 | 34 | Used to add template paths, namespace and template file to render. 35 | 36 | __Initial value:__ _Nothing_ 37 | __Expected return value:__ `Object(path?: Path, namespace: String, template: String)` 38 | 39 | ### get-template-values 40 | 41 | Used to add extra values to the templates when they render. Actions should merge their props with the previousValue 42 | 43 | __Initial value:__ `{}` 44 | __Expected return value:__ `Object()` 45 | 46 | ## roc-plugin-start 47 | 48 | ### get-potential-target 49 | 50 | Use to define for what target that it should try to find a resource for too start with. 51 | 52 | __Initial value:__ `"node"` 53 | __Expected return value:__ `String` 54 | 55 | ### register-runtime 56 | 57 | Can be used to modify the runtime before an application starts. 58 | 59 | __Initial value:__ _Nothing_ 60 | __Expected return value:__ _Nothing_ 61 | 62 | #### Arguments 63 | 64 | | Name | Description | Type | Required | Can be empty | 65 | | ------- | ----------- | --------- | -------- | ------------ | 66 | | verbose | | `Boolean` | No | | 67 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "roc-package-web-app-react", 3 | "description": "Package for building React applications with Roc", 4 | "version": "1.0.0-beta.18", 5 | "main": "lib/index.js", 6 | "scripts": { 7 | "lint": "eslint .", 8 | "test": "npm run lint" 9 | }, 10 | "files": [ 11 | "lib", 12 | "styles", 13 | "views", 14 | "app" 15 | ], 16 | "keywords": [ 17 | "roc", 18 | "roc-package", 19 | "react-router", 20 | "react", 21 | "redux" 22 | ], 23 | "repository": "https://github.com/rocjs/roc-package-web-app-react/tree/master/extensions/roc-package-web-app-react", 24 | "author": "Verdens Gang AS", 25 | "contributors": [ 26 | { 27 | "name": "Gustaf Dalemar" 28 | } 29 | ], 30 | "license": "MIT", 31 | "dependencies": { 32 | "debug": "~2.2.0", 33 | "error": "~7.0.2", 34 | "history": "^3.0.0", 35 | "intl": "^1.2.5", 36 | "intl-locales-supported": "^1.0.0", 37 | "nunjucks": "~2.4.2", 38 | "pretty-error": "^2.1.0", 39 | "react-helmet": "~5.0.3", 40 | "react-redux": "^5.0.4", 41 | "react-router": "^3.0.5", 42 | "react-router-redial": "~0.3.5", 43 | "react-router-redux": "^4.0.8", 44 | "react-router-scroll-async": "~0.5.1", 45 | "react-server-status": "~1.1.0", 46 | "redial": "~0.5.0", 47 | "redux": "^3.6.0", 48 | "redux-saga": "^0.15.6", 49 | "redux-thunk": "^2.2.0", 50 | "roc": "^1.0.0-rc.20", 51 | "roc-package-web-app": "^1.0.0-beta.7", 52 | "roc-plugin-react": "^1.0.0-beta.4", 53 | "serialize-javascript": "~1.2.0" 54 | }, 55 | "devDependencies": { 56 | "babel-eslint": "~6.1.2", 57 | "babel-preset-react": "6.11.1", 58 | "eslint": "~3.6.0", 59 | "eslint-config-airbnb": "~11.1.0", 60 | "eslint-plugin-babel": "~3.3.0", 61 | "eslint-plugin-import": "^1.16.0", 62 | "eslint-plugin-jsx-a11y": "2.2.1", 63 | "eslint-plugin-react": "6.2.0" 64 | }, 65 | "roc": { 66 | "packages": [ 67 | "./lib/index.js" 68 | ] 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/src/app/server/helpers/myPath.js: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | 3 | /** 4 | * Exports the path to the root of the project 5 | */ 6 | export default path.join(__dirname, '..', '..', '..', '..'); 7 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/src/app/server/helpers/readStats.js: -------------------------------------------------------------------------------- 1 | import { getSettings, getAbsolutePath } from 'roc'; 2 | 3 | /** 4 | * Read stats from build 5 | * 6 | * @param {string} stats - Path to a stats file from the client build 7 | * @returns {object} The stats object in the stats file 8 | */ 9 | export default function readStats(stats) { 10 | const settings = getSettings('runtime'); 11 | 12 | // eslint-disable-next-line 13 | return require(getAbsolutePath(stats || settings.stats)); 14 | } 15 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/src/app/server/reactRenderer.js: -------------------------------------------------------------------------------- 1 | import config from 'config'; 2 | import debug from 'debug'; 3 | import nunjucks from 'nunjucks'; 4 | import serialize from 'serialize-javascript'; 5 | import PrettyError from 'pretty-error'; 6 | import React from 'react'; 7 | import { renderToString, renderToStaticMarkup } from 'react-dom/server'; 8 | import { match, applyRouterMiddleware } from 'react-router'; 9 | import { Provider } from 'react-redux'; 10 | import Helmet from 'react-helmet'; 11 | import { triggerHooks, useRedial } from 'react-router-redial'; 12 | import { getAbsolutePath, getSettings } from 'roc'; 13 | import ServerStatus from 'react-server-status'; 14 | 15 | import { invokeHook } from '../../roc/util'; 16 | 17 | import myPath from './helpers/myPath'; 18 | 19 | const pretty = new PrettyError(); 20 | const log = debug('roc:react-render'); 21 | 22 | const rocConfig = getSettings(); 23 | const defaultTemplatePath = `${myPath}/views`; 24 | 25 | const whiteListed = () => ( 26 | rocConfig.runtime.configWhitelistProperty ? 27 | config[rocConfig.runtime.configWhitelistProperty] : 28 | undefined 29 | ); 30 | 31 | const appConfig = whiteListed(); 32 | 33 | function setupTemplate(devMode) { 34 | let templatePaths = [].concat( 35 | // Combine paths from highest priority to lowest 36 | rocConfig.runtime.template.path || [], 37 | defaultTemplatePath 38 | ).map(path => getAbsolutePath(path)); 39 | 40 | const baseTemplate = 'roc-package-web-app-react/main.njk'; 41 | let parentTemplate = rocConfig.runtime.template.root ? 42 | rocConfig.runtime.template.name : 43 | baseTemplate; 44 | const inheritance = {}; 45 | invokeHook('extend-template')(({ path = [], namespace, template }) => { 46 | templatePaths = templatePaths.concat(path); 47 | inheritance[namespace] = parentTemplate; 48 | parentTemplate = template; 49 | }); 50 | 51 | const nunjucksEnv = nunjucks.configure(templatePaths, { 52 | watch: devMode, 53 | }); 54 | 55 | const mainTemplate = rocConfig.runtime.template.root ? 56 | parentTemplate : 57 | rocConfig.runtime.template.name; 58 | 59 | // If we have root = true we will set parentTemplate to be baseTemplate 60 | // This will make it impossible to create a loop in the template system 61 | parentTemplate = rocConfig.runtime.template.root ? 62 | baseTemplate : 63 | parentTemplate; 64 | 65 | return { 66 | mainTemplate, 67 | nunjucksEnv, 68 | nunjucksContext: { 69 | baseTemplate, 70 | inheritance, 71 | parentTemplate, 72 | }, 73 | }; 74 | } 75 | 76 | export function initRenderPage({ script, css }, distMode, devMode, Header) { 77 | const { 78 | nunjucksEnv, 79 | nunjucksContext, 80 | mainTemplate, 81 | } = setupTemplate(devMode); 82 | const bundleName = script[0]; 83 | const styleName = css[0]; 84 | 85 | return ({ 86 | content = '', 87 | customTemplateValues = {}, 88 | error, 89 | head, 90 | redialProps = [], 91 | reduxState = {}, 92 | request, 93 | status, 94 | } = {}) => { 95 | const { dev, build, ...rest } = rocConfig; // eslint-disable-line 96 | 97 | const rocConfigClient = distMode ? rest : { ...rest, dev }; 98 | 99 | // If we have no head we will generate it 100 | if (!head) { 101 | // Render to trigger React Helmet 102 | renderToStaticMarkup(
); 103 | head = Helmet.rewind(); // eslint-disable-line 104 | } 105 | 106 | return nunjucksEnv.render(mainTemplate, { 107 | ...nunjucksContext, 108 | bundleName, 109 | content, 110 | custom: customTemplateValues, 111 | dist: distMode, 112 | error, 113 | fluxState: serialize(reduxState), 114 | head, 115 | redialProps: serialize(redialProps), 116 | request, 117 | serializedAppConfig: serialize(appConfig), 118 | serializedRocConfig: serialize(rocConfigClient), 119 | status, 120 | styleName, 121 | }); 122 | }; 123 | } 124 | 125 | export function reactRender({ 126 | url, 127 | history, 128 | store, 129 | createRoutes, 130 | renderPage, 131 | koaState, 132 | request, 133 | staticRender = false, 134 | hasTemplateValues, 135 | templateValues, 136 | reduxSagas, 137 | }) { 138 | return new Promise((resolve) => { 139 | let currentLocation; 140 | 141 | history.listen((location) => { 142 | currentLocation = location; 143 | }); 144 | 145 | match({ history, routes: createRoutes(store), location: url }, 146 | (error, redirect, renderProps) => { 147 | if (redirect) { 148 | const base = redirect.basename || ''; 149 | const redirectUrl = `${base}${redirect.pathname}${redirect.search}`; 150 | log(`Redirect request to ${redirectUrl} due to React Router`); 151 | 152 | return resolve({ 153 | redirect: redirectUrl, 154 | }); 155 | } else if (error) { 156 | log('Router error', pretty.render(error)); 157 | return resolve({ 158 | status: 500, 159 | body: renderPage({ error, request, status: 500 }), 160 | }); 161 | } else if (!renderProps) { 162 | log('No renderProps, most likely the path does not exist'); 163 | return resolve({ 164 | status: 404, 165 | body: renderPage({ request, status: 404 }), 166 | }); 167 | } 168 | 169 | const locals = store ? { 170 | dispatch: store.dispatch, 171 | getState: store.getState, 172 | history, 173 | } : { 174 | history, 175 | }; 176 | 177 | const hooks = rocConfig.runtime.fetch.server; 178 | 179 | let sagaPromise; 180 | if (reduxSagas) { 181 | sagaPromise = store.runSaga(reduxSagas).done; 182 | } 183 | 184 | return triggerHooks({ 185 | renderProps, 186 | hooks, 187 | locals, 188 | }).then((result) => { 189 | if (sagaPromise) { 190 | store.dispatch(require('redux-saga').END); // eslint-disable-line 191 | return sagaPromise.then(() => result); 192 | } 193 | return result; 194 | }).then(({ redialMap, redialProps }) => { 195 | if (currentLocation) { 196 | const currentUrl = `${currentLocation.pathname}${currentLocation.search}`; 197 | 198 | if (currentUrl !== url) { 199 | const base = currentLocation.basename || ''; 200 | const redirectUrl = `${base}${currentUrl}`; 201 | 202 | log(`Redirect request to ${redirectUrl} due to history location modification`); 203 | return resolve({ 204 | redirect: `${redirectUrl}`, 205 | }); 206 | } 207 | } 208 | 209 | let component = applyRouterMiddleware(useRedial({ redialMap }))(renderProps); 210 | 211 | if (store) { 212 | component = ( 213 | 214 | {component} 215 | 216 | ); 217 | } 218 | 219 | const content = staticRender ? renderToStaticMarkup(component) : renderToString(component); 220 | const head = Helmet.rewind(); 221 | const reduxState = store ? store.getState() : {}; 222 | const status = ServerStatus.rewind() || 200; 223 | 224 | const customTemplateValues = invokeHook('get-template-values', { 225 | koaState, 226 | settings: rocConfig, 227 | reduxState, 228 | }); 229 | 230 | if (hasTemplateValues) { 231 | // Provides settings, Redux state and Koa state 232 | Object.assign( 233 | customTemplateValues, 234 | templateValues.default({ 235 | koaState, 236 | settings: rocConfig, 237 | reduxState, 238 | }), 239 | ); 240 | } 241 | 242 | return resolve({ 243 | body: renderPage({ 244 | customTemplateValues, 245 | content, 246 | head, 247 | redialProps, 248 | reduxState, 249 | request, 250 | status, 251 | }), 252 | status, 253 | }); 254 | }) 255 | .catch((err) => { 256 | if (err) { 257 | log('General error', pretty.render(err)); 258 | } 259 | return resolve({ 260 | status: 500, 261 | body: renderPage({ error: err, request, status: 500 }), 262 | }); 263 | }); 264 | }); 265 | }); 266 | } 267 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/src/app/server/reactRouter.js: -------------------------------------------------------------------------------- 1 | import { getSettings } from 'roc'; 2 | import debug from 'debug'; 3 | import PrettyError from 'pretty-error'; 4 | 5 | import setupForRender from './setupForRender'; 6 | import { initRenderPage, reactRender } from './reactRenderer'; 7 | 8 | const pretty = new PrettyError(); 9 | const log = debug('roc:server'); 10 | 11 | export default function reactRouter({ 12 | createRoutes, 13 | createStore, 14 | stats, 15 | dist, 16 | dev, 17 | hasTemplateValues, 18 | templateValues, 19 | rocPath, 20 | Header, 21 | reduxSagas, 22 | }) { 23 | const rocConfig = getSettings(); 24 | 25 | if (!createRoutes) { 26 | throw new Error('createRoutes needs to be defined'); 27 | } 28 | 29 | if (!stats) { 30 | throw new Error('stats needs to be defined'); 31 | } 32 | 33 | const renderPage = initRenderPage(stats, dist, dev, Header); 34 | 35 | return function* (next) { 36 | try { 37 | // If server side rendering is disabled we do everything on the client 38 | if (!rocConfig.runtime.ssr) { 39 | yield next; 40 | 41 | // If response already is managed we will not do anything 42 | if (this.body || this.status !== 404) { 43 | return; 44 | } 45 | 46 | this.status = 200; 47 | this.body = renderPage(); 48 | } else { 49 | const { store, history, url } = setupForRender(createStore, this.url, rocPath); 50 | 51 | // Give Koa middlewares a chance to interact with the reduxStore 52 | // This can be used to dynamically pass some data to the client. 53 | this.state.reduxStore = store; 54 | yield next; 55 | 56 | // If response already is managed we will not do anything 57 | if (this.body || this.status !== 404) { 58 | return; 59 | } 60 | 61 | const { 62 | body, 63 | redirect, 64 | status = 200, 65 | } = yield reactRender({ 66 | url, 67 | history, 68 | store, 69 | createRoutes, 70 | renderPage, 71 | koaState: this.state, 72 | request: this.request, 73 | hasTemplateValues, 74 | templateValues, 75 | reduxSagas, 76 | }); 77 | 78 | if (redirect) { 79 | this.redirect(redirect); 80 | } else { 81 | this.status = status; 82 | this.body = body; 83 | } 84 | } 85 | } catch (error) { 86 | log('Render error', pretty.render(error)); 87 | this.status = 500; 88 | this.body = renderPage(); 89 | } 90 | }; 91 | } 92 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/src/app/server/setupForRender.js: -------------------------------------------------------------------------------- 1 | /* global ROC_PATH */ 2 | 3 | import { createMemoryHistory } from 'react-router'; 4 | import { syncHistoryWithStore } from 'react-router-redux'; 5 | 6 | export default function setupForRender(createStore, url, rocPath) { 7 | const basename = rocPath === '/' ? '' : rocPath; 8 | 9 | const completeUrl = basename + url; 10 | const memoryHistory = createMemoryHistory({ 11 | entries: [completeUrl], 12 | basename, 13 | }); 14 | 15 | const store = createStore ? createStore(memoryHistory) : null; 16 | const history = store ? syncHistoryWithStore(memoryHistory, store) : memoryHistory; 17 | 18 | return { 19 | store, 20 | history, 21 | url, 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/src/app/server/useReact.js: -------------------------------------------------------------------------------- 1 | import readStats from './helpers/readStats'; 2 | import reactRouter from './reactRouter'; 3 | 4 | /** 5 | * Enhances a server instance with React support. 6 | * 7 | * Extends the options object from _roc-web-app_. See {@link rocServerOptions} for what the new options are. 8 | * 9 | * @example 10 | * import { createServer } from 'roc-package-web-app/app'; 11 | * import { useReact } from 'roc-package-web-app-react/app/server'; 12 | * 13 | * const server = useReact(createServer)({ 14 | * serve: 'files', 15 | * createRoutes: routes, 16 | * createStore: store, 17 | * stats: './stats.json' 18 | * }); 19 | 20 | * server.start(); 21 | * 22 | * @param {function} createServer - A createServer function to wrap and add extra functionality to 23 | * @returns {function} Returns a new createServer that can be used to create server instances that can manage React 24 | * applications 25 | */ 26 | export default function useReact(createServer, params) { 27 | return function (options = {}, beforeUserMiddlewares = []) { 28 | const { stats, createRoutes, createStore, ...serverOptions } = options; 29 | 30 | return createServer(serverOptions, beforeUserMiddlewares.concat(reactRouter({ 31 | ...params, 32 | createRoutes, 33 | createStore, 34 | stats: readStats(stats), 35 | }))); 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/src/config/roc.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | settings: { 3 | runtime: { 4 | stats: 'build/client/webpack-stats.json', 5 | applicationName: undefined, 6 | head: { 7 | __raw: {}, 8 | titleTemplate: undefined, 9 | htmlAttributes: { 10 | lang: 'en', 11 | }, 12 | meta: [{ 13 | name: 'viewport', 14 | content: 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0', 15 | }], 16 | link: [{ 17 | rel: 'icon', 18 | href: 'favicon.png', 19 | }], 20 | // ROC_PATH will be replaced with what is defined in build.path 21 | base: { 22 | href: 'ROC_PATH', 23 | target: undefined, 24 | }, 25 | script: [], 26 | style: [], 27 | }, 28 | ssr: true, 29 | template: { 30 | path: undefined, 31 | name: 'main.html', 32 | root: false, 33 | }, 34 | debug: { 35 | client: 'roc:*', 36 | }, 37 | history: { 38 | forceRefresh: undefined, 39 | }, 40 | configWhitelistProperty: 'DANGEROUSLY_EXPOSE_TO_CLIENT', 41 | fetch: { 42 | server: ['fetch'], 43 | client: { 44 | beforeTransition: ['fetch'], 45 | afterTransition: ['defer'], 46 | parallel: false, 47 | }, 48 | }, 49 | }, 50 | }, 51 | }; 52 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/src/config/roc.config.meta.js: -------------------------------------------------------------------------------- 1 | import { isString, isBoolean, isPath, isArray, isObject, notEmpty, required, oneOf, isFunction } from 'roc/validators'; 2 | 3 | export default { 4 | settings: { 5 | runtime: { 6 | head: { 7 | __meta: { 8 | description: 'Settings that will be used with React Helmet. https://github.com/nfl/react-helmet', 9 | }, 10 | base: { 11 | __meta: { 12 | description: 'Base tag to be used in .', 13 | }, 14 | href: { 15 | description: 'The document base address from which relative links are made.', 16 | validator: notEmpty(isString), 17 | }, 18 | target: { 19 | description: 'The browsing context in which the links should open.', 20 | validator: notEmpty(isString), 21 | }, 22 | }, 23 | htmlAttributes: { 24 | description: 'Attributes that should be added to the tag.', 25 | validator: required(isObject({ 26 | unmanaged: true, 27 | })), 28 | }, 29 | meta: { 30 | description: 'Meta tags to be used in , should be formatted as objects.', 31 | validator: required(isArray(isObject(isString))), 32 | }, 33 | link: { 34 | description: 'Link tags to be used in , should be formatted as objects. ', 35 | validator: required(isArray(isObject(isString))), 36 | }, 37 | script: { 38 | description: 'Script tags to be used in , should be formatted as objects.', 39 | validator: required(isArray(isObject(isString))), 40 | }, 41 | style: { 42 | description: 'Style tags to be used in , should be formatted as objects.', 43 | validator: required(isArray(isObject(isString))), 44 | }, 45 | titleTemplate: { 46 | description: 'Template to be used for .', 47 | validator: notEmpty(isString), 48 | }, 49 | }, 50 | stats: { 51 | description: 'Path to client stats file from build.', 52 | validator: required(notEmpty(isPath)), 53 | }, 54 | applicationName: { 55 | description: 'Default application name to use for <title>.', 56 | validator: required(isString), 57 | }, 58 | ssr: { 59 | description: 'If server side rendering should be enabled.', 60 | validator: required(isBoolean), 61 | }, 62 | template: { 63 | path: { 64 | description: 'A directory, or array of directories, where the template for the application ' + 65 | 'can be found. Internal path with default templates will be appended to the array, ' + 66 | 'so it\'s possible to extend them.', 67 | validator: notEmpty(oneOf(isPath, isArray(notEmpty(isPath)))), 68 | }, 69 | name: { 70 | description: 'Name of the template file that will be used. Uses Nunjucks, please see ' + 71 | 'documentation for more info.', 72 | validator: required(notEmpty(isString)), 73 | }, 74 | root: { 75 | description: 'If the project template should be used as the root template instead of the default ' + 76 | 'one. When true `parentTemplate` will be the main template in `roc-package-web-app-react`, ' + 77 | 'also called `baseTemplate`. Important that blocks are maintained for extensions to be able ' + 78 | 'to add their logic.', 79 | validator: required(isBoolean), 80 | }, 81 | }, 82 | debug: { 83 | client: { 84 | description: 'Filter for debug messages that should be shown for the client, see ' + 85 | 'https://npmjs.com/package/debug.', 86 | validator: isString, 87 | }, 88 | }, 89 | configWhitelistProperty: { 90 | description: 'A single property to expose to the client from node-config. Make sure that ' + 91 | 'this property does NOT contain any secrets that should not be exposed to the world.', 92 | validator: notEmpty(isString), 93 | }, 94 | fetch: { 95 | server: { 96 | description: 'What redial hooks that should run on the server and in what order.', 97 | validator: required(isArray(oneOf(isString, isArray(isString)))), 98 | }, 99 | client: { 100 | beforeTransition: { 101 | description: 'What redial hooks that should run on the client that blocks route transitions ' + 102 | 'and in what order.', 103 | validator: required(isArray(oneOf(isString, isArray(isString)))), 104 | }, 105 | afterTransition: { 106 | description: 'What redial hooks that should run on the client that should not block route ' + 107 | 'transitions and in what order.', 108 | validator: required(isArray(oneOf(isString, isArray(isString)))), 109 | }, 110 | parallel: { 111 | description: 'If defer hooks should be started at the same time as the blocking ones.', 112 | validator: required(isBoolean), 113 | }, 114 | }, 115 | }, 116 | history: { 117 | forceRefresh: { 118 | description: 'Whether to force load from server rather than do single page navigation', 119 | validator: oneOf(isBoolean, isFunction), 120 | }, 121 | }, 122 | }, 123 | }, 124 | }; 125 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/src/index.js: -------------------------------------------------------------------------------- 1 | export roc from './roc'; 2 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/src/roc/index.js: -------------------------------------------------------------------------------- 1 | import { generateDependencies } from 'roc'; 2 | import { warn } from 'roc/log/default/large'; 3 | import { isObject } from 'roc/validators'; 4 | 5 | import config from '../config/roc.config'; 6 | import meta from '../config/roc.config.meta'; 7 | 8 | const packageJSON = require('../../package.json'); 9 | 10 | let warnForReactRouterScroll = true; 11 | 12 | const extendTemplateSignature = (input, info) => { 13 | if (info) { 14 | return { 15 | type: 'Object(path?: Path, namespace: String, template: String)', 16 | }; 17 | } 18 | 19 | // Don't do any validation for now, use for documentation purposes only 20 | return true; 21 | }; 22 | 23 | const currentExtension = extension => extension.name === 'roc-package-web-app-react'; 24 | 25 | export default { 26 | config, 27 | meta, 28 | description: ({ context: { usedExtensions } }) => { 29 | const { packageJSON: { description } } = usedExtensions.find(currentExtension); 30 | return `${description}\n\nRead the comprehensive user-guide on how to best utilize the tools ` + 31 | 'and libraries provided by this Roc extension' + 32 | '[here](https://github.com/rocjs/roc-package-web-app-react/blob/master/GUIDE.md).'; 33 | }, 34 | hooks: { 35 | 'extend-template': { 36 | description: 'Used to add template paths, namespace and template file to render.', 37 | hasCallback: true, 38 | returns: extendTemplateSignature, 39 | }, 40 | 'get-template-values': { 41 | description: 42 | 'Used to add extra values to the templates when they render. ' + 43 | 'Actions should merge their props with the previousValue', 44 | initialValue: {}, 45 | returns: isObject(), 46 | }, 47 | }, 48 | packages: [ 49 | require.resolve('roc-package-web-app'), 50 | ], 51 | plugins: [ 52 | require.resolve('roc-plugin-react'), 53 | ], 54 | dependencies: { 55 | exports: { 56 | ...generateDependencies(packageJSON, [ 57 | 'history', 58 | 'intl', 59 | 'intl-locales-supported', 60 | 'react-helmet', 61 | 'react-redux', 62 | 'react-router', 63 | 'react-router-redux', 64 | 'react-server-status', 65 | 'redial', 66 | 'redux-saga', 67 | 'react-router-redial', 68 | 'react-router-scroll-async', 69 | 'redux', 70 | 'redux-thunk', 71 | 'roc-package-web-app', 72 | ]), 73 | 'react-router-scroll': { 74 | version: 'DEPRECATED - Use react-router-scroll-async', 75 | resolve: ({ request }) => { 76 | // We will currently write out this two times, once when we build the application with webpack 77 | // and once when we run it in Node. A nice way to give the warnings we print out more substance 78 | // is to provide the instance that the function is running in, something we could provide. 79 | if (warnForReactRouterScroll) { 80 | warn( 81 | 'react-router-scroll is deprecated, please change references to react-router-scroll-async', 82 | 'Deprecation' 83 | ); 84 | } 85 | warnForReactRouterScroll = false; 86 | return require.resolve( 87 | request.replace('react-router-scroll', 'react-router-scroll-async') 88 | ); 89 | }, 90 | }, 91 | }, 92 | uses: generateDependencies(packageJSON, [ 93 | 'nunjucks', 94 | ]), 95 | }, 96 | }; 97 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/src/roc/util.js: -------------------------------------------------------------------------------- 1 | import { runHook } from 'roc'; 2 | 3 | // eslint-disable-next-line 4 | export const packageJSON = require('../../package.json'); 5 | 6 | /** 7 | * Helper function for invoking/running a hook, pre-configured for the current package. 8 | * 9 | * @param {...Object} args - The arguments to pass along to the action. 10 | * 11 | * @returns {Object|function} - Either a object, the final value from the actions or a function if callback is used. 12 | */ 13 | export function invokeHook(...args) { 14 | return runHook(packageJSON.name)(...args); 15 | } 16 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/styles/base.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | margin: 0px; 4 | padding: 0px; 5 | } 6 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/views/main.html: -------------------------------------------------------------------------------- 1 | {% extends parentTemplate %} 2 | -------------------------------------------------------------------------------- /extensions/roc-package-web-app-react/views/roc-package-web-app-react/main.njk: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html {{ head.htmlAttributes.toString() | safe }}> 3 | <head> 4 | <meta charset="utf-8"> 5 | <meta http-equiv="x-ua-compatible" content="ie=edge"> 6 | {{ head.title.toString() | safe }} 7 | {{ head.base.toString() | safe }} 8 | {{ head.meta.toString() | safe }} 9 | 10 | {% block head %}{% endblock %} 11 | 12 | {{ head.script.toString() | safe }} 13 | {{ head.link.toString() | safe }} 14 | {{ head.style.toString() | safe }} 15 | 16 | {% if dist %} 17 | <link rel="stylesheet" href="{{ styleName }}"> 18 | {% endif %} 19 | </head> 20 | {% if custom.bodyClass %} 21 | <body class="{{ custom.bodyClass | safe }}"> 22 | {% else %} 23 | <body {{ head.bodyAttributes.toString() | safe }}> 24 | {% endif %} 25 | 26 | {% block bodyPreApplication %}{% endblock %} 27 | <div id="application">{{ content | safe }}</div> 28 | {% block bodyPostApplication %}{% endblock %} 29 | 30 | {% block bodyScripts %} 31 | <script>window.ROC_CONFIG = {{ serializedRocConfig | safe }}</script> 32 | <script>window.APP_CONFIG = {{ serializedAppConfig | safe }}</script> 33 | <script>window.FLUX_STATE = {{ fluxState | safe }}</script> 34 | <script>window.__REDIAL_PROPS__ = {{ redialProps | safe }}</script> 35 | 36 | <script src="{{ bundleName }}"></script> 37 | {% endblock %} 38 | </body> 39 | </html> 40 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "roc-package-web-app-react", 3 | "private": true, 4 | "license": "MIT", 5 | "scripts": { 6 | "start": "rid", 7 | "rid": "rid", 8 | "build": "rid build", 9 | "lint": "rid lint:alias", 10 | "link": "rid link", 11 | "link:all": "rid link roc,roc-package-web-app,roc-package-web-app-dev,roc-plugin-react-dev,roc-plugin-react", 12 | "test": "npm run lint" 13 | }, 14 | "devDependencies": { 15 | "@rocjs/roc-internal-dev": "^2.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /rocdev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rocjs/roc-package-web-app-react/26cd2b51acbfcaf3a61267ded00afb3a19907198/rocdev.png -------------------------------------------------------------------------------- /roctest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rocjs/roc-package-web-app-react/26cd2b51acbfcaf3a61267ded00afb3a19907198/roctest.png --------------------------------------------------------------------------------