├── sass
├── dependencies
│ └── _theme.scss
├── _vendor.scss
├── vendor
│ ├── _tomorrow.scss
│ └── _normalize.scss
└── app.scss
├── slides
├── 28.md
├── 11.md
├── 5.md
├── 3.md
├── 6.md
├── 7.md
├── 17.md
├── 29.md
├── 1.md
├── 10.md
├── 25.md
├── 30.md
├── 21.md
├── 15.md
├── 31.md
├── 18.md
├── 8.md
├── 12.md
├── 22.md
├── 16.md
├── 2.md
├── 33.md
├── 35.md
├── 32.md
├── 19.md
├── 13.md
├── 20.md
├── 24.md
├── 34.md
├── 26.md
├── 27.md
├── 9.md
├── 23.md
├── 4.md
└── 14.md
├── preview.png
├── src
├── shared
│ ├── theme.js
│ ├── init.js
│ ├── actions
│ │ └── SlideActions.js
│ ├── components
│ │ ├── View.js
│ │ ├── Button.js
│ │ ├── PLLogo.js
│ │ ├── Markdown.js
│ │ ├── AppHandler.js
│ │ ├── SlideHandler.js
│ │ ├── Slide.js
│ │ └── SlideProgressBar.js
│ ├── routes.js
│ ├── Flux.js
│ └── stores
│ │ └── SlideStore.js
├── server
│ ├── init.js
│ ├── app.js
│ ├── routes
│ │ ├── public
│ │ │ └── index.js
│ │ ├── index.js
│ │ ├── middleware.js
│ │ └── utils
│ │ │ └── renderAppToString.js
│ ├── index.js
│ └── webpack.js
├── client
│ └── app.js
└── scripts
│ └── buildSlides.js
├── nodemon.json
├── views
├── base.jade
└── app.jade
├── .gitignore
├── webpack.config.js
├── .eslintrc
├── webpack.config.dev.js
├── package.json
├── README.md
├── Makefile
└── npm-shrinkwrap.json
/sass/dependencies/_theme.scss:
--------------------------------------------------------------------------------
1 | $theme: (
2 |
3 | );
4 |
--------------------------------------------------------------------------------
/slides/28.md:
--------------------------------------------------------------------------------
1 | ---
2 | centered: true
3 | ---
4 |
5 | # State is evil
6 |
--------------------------------------------------------------------------------
/slides/11.md:
--------------------------------------------------------------------------------
1 | ---
2 | centered: true
3 | ---
4 |
5 | # Before React...
6 |
--------------------------------------------------------------------------------
/slides/5.md:
--------------------------------------------------------------------------------
1 | ---
2 | centered: true
3 | ---
4 |
5 | ## React is *weird*
6 |
--------------------------------------------------------------------------------
/preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acdlite/the-react-way/HEAD/preview.png
--------------------------------------------------------------------------------
/sass/_vendor.scss:
--------------------------------------------------------------------------------
1 | @import 'vendor/normalize';
2 | @import 'vendor/tomorrow';
3 |
--------------------------------------------------------------------------------
/slides/3.md:
--------------------------------------------------------------------------------
1 | ---
2 | centered: true
3 | ---
4 |
5 | ## React is *different*
6 |
--------------------------------------------------------------------------------
/slides/6.md:
--------------------------------------------------------------------------------
1 | ---
2 | centered: true
3 | ---
4 |
5 | ## `different !== better`
6 |
--------------------------------------------------------------------------------
/slides/7.md:
--------------------------------------------------------------------------------
1 | ---
2 | centered: true
3 | ---
4 |
5 | ## `conventionalWisdom !== good`
6 |
--------------------------------------------------------------------------------
/slides/17.md:
--------------------------------------------------------------------------------
1 | ---
2 | centered: true
3 | ---
4 |
5 | ## It doesn't have to be this way
6 |
--------------------------------------------------------------------------------
/slides/29.md:
--------------------------------------------------------------------------------
1 | ## "Shared mutable state is the root of all evil"
2 |
3 | Sound familiar?
4 |
--------------------------------------------------------------------------------
/src/shared/theme.js:
--------------------------------------------------------------------------------
1 | const theme = {
2 | colors: {
3 | red: '#f00'
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/slides/1.md:
--------------------------------------------------------------------------------
1 | The React Way
2 | =============
3 |
4 | Frontend Awesome Meetup
5 | March 19, 2015
6 |
--------------------------------------------------------------------------------
/src/server/init.js:
--------------------------------------------------------------------------------
1 | import sourceMapSupport from 'source-map-support';
2 | sourceMapSupport.install();
3 |
--------------------------------------------------------------------------------
/slides/10.md:
--------------------------------------------------------------------------------
1 | ---
2 | centered: true
3 | ---
4 |
5 | # React: a new and better way to create web applications
6 |
--------------------------------------------------------------------------------
/slides/25.md:
--------------------------------------------------------------------------------
1 | ---
2 | centered: true
3 | ---
4 |
5 | # Separation of concerns
6 |
7 | *Not* technologies
8 |
--------------------------------------------------------------------------------
/slides/30.md:
--------------------------------------------------------------------------------
1 | ## The DOM is a giant pile of global state
2 |
3 | Don't tie your application logic to the DOM
4 |
--------------------------------------------------------------------------------
/src/shared/init.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Polyfills
3 | */
4 | require('babel/external-helpers');
5 | import 'babel/polyfill';
6 |
--------------------------------------------------------------------------------
/slides/21.md:
--------------------------------------------------------------------------------
1 | ## The power of `render()`
2 | - No more update logic!
3 | - Views are functions of their props and state
4 |
--------------------------------------------------------------------------------
/slides/15.md:
--------------------------------------------------------------------------------
1 | ## At the very least, you're wrangling three separate technologies
2 |
3 | Only point of communication is the DOM
4 |
--------------------------------------------------------------------------------
/slides/31.md:
--------------------------------------------------------------------------------
1 | ## The problem with two-way data binding
2 |
3 | - Hard to tell where state "lives"
4 | - Implicit dependencies
5 |
--------------------------------------------------------------------------------
/slides/18.md:
--------------------------------------------------------------------------------
1 | ---
2 | centered: true
3 | ---
4 |
5 | # Declarative user interfaces
6 |
7 | Tell the computer what to do, not how to do it
8 |
--------------------------------------------------------------------------------
/slides/8.md:
--------------------------------------------------------------------------------
1 | ## Conventions are useful...
2 |
3 | - Benefit from the experience of others
4 | - Learn from their mistakes
5 | - Don't reinvent the wheel
6 |
--------------------------------------------------------------------------------
/slides/12.md:
--------------------------------------------------------------------------------
1 | ## Web development is really complicated
2 |
3 | - Many different technologies at different layers
4 | - Even "simple" tasks require lots of coordination
5 |
--------------------------------------------------------------------------------
/slides/22.md:
--------------------------------------------------------------------------------
1 | ## Props vs. state
2 |
3 | - props: passed down by the owner
4 | - "immutable"
5 | - unidirectional data flow
6 | - state: local state
7 | - state changes trigger re-renders
8 |
--------------------------------------------------------------------------------
/src/shared/actions/SlideActions.js:
--------------------------------------------------------------------------------
1 | import { Actions } from 'flummox';
2 |
3 | export default class SlideActions extends Actions {
4 | loadSlides(slides) {
5 | return slides;
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/slides/16.md:
--------------------------------------------------------------------------------
1 | ## Current "best practices"
2 |
3 | - Object-oriented patterns
4 | - MVC
5 | - Events
6 | - Keep style, logic, and markup isolated
7 | - Use two-way data binding
8 | - Fat models
9 |
--------------------------------------------------------------------------------
/slides/2.md:
--------------------------------------------------------------------------------
1 | Andrew Clark
2 | ------------
3 |
4 | Web Developer at [Parisleaf](http://parisleaf.com)
5 |
6 | [Twitter](https://twitter.com/acdlite)/[GitHub](https://github.com/acdlite): @acdlite
7 |
--------------------------------------------------------------------------------
/slides/33.md:
--------------------------------------------------------------------------------
1 | ## Functional programming concepts in React
2 | - Immutable state
3 | - No defensive copying
4 | - More efficient renders
5 | - Components are functions
6 | - Manage side-effects
7 |
--------------------------------------------------------------------------------
/src/server/app.js:
--------------------------------------------------------------------------------
1 | // Create koa app
2 | import koa from 'koa';
3 | const app = koa();
4 |
5 | // Add routes
6 | import routes from './routes';
7 | routes(app);
8 |
9 | export default app;
10 |
--------------------------------------------------------------------------------
/slides/35.md:
--------------------------------------------------------------------------------
1 | ## Give it a try
2 |
3 | - React is really easy to get started with
4 | - Very simple API
5 | - Everything is a component
6 | - props and state
7 | - Use it in your existing apps today
8 |
--------------------------------------------------------------------------------
/nodemon.json:
--------------------------------------------------------------------------------
1 | {
2 | "watch": [
3 | "lib/",
4 | "views/",
5 | "public/slides.json"
6 | ],
7 | "ext": "js json jade yaml",
8 | "env": {
9 | "NODE_ENV": "development"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/slides/32.md:
--------------------------------------------------------------------------------
1 | ## Most of the time, you don't need two-way data binding
2 |
3 | - The exception, not the rule
4 | - Make it explicit
5 | - Some things are harder, like forms
6 | - But the trade-off is worth it
7 |
--------------------------------------------------------------------------------
/src/server/routes/public/index.js:
--------------------------------------------------------------------------------
1 | import Router from 'koa-router';
2 | const router = new Router();
3 |
4 | import login from './login';
5 | import appView from './appView';
6 |
7 | login(router);
8 | appView(router);
9 |
10 | export default router;
11 |
--------------------------------------------------------------------------------
/slides/19.md:
--------------------------------------------------------------------------------
1 | ### A simple React component
2 |
3 | ```js
4 | class Hello extends React.Component {
5 | render() {
6 | return (
7 | Hello, {this.props.name}
8 | );
9 | }
10 | }
11 |
12 | React.render(, el);
13 | ```
14 |
--------------------------------------------------------------------------------
/src/server/index.js:
--------------------------------------------------------------------------------
1 | // Initialization
2 | require('../shared/init');
3 | import './init';
4 |
5 | import app from './app';
6 |
7 | // Start listening
8 | const port = process.env.PORT || 3000;
9 | app.listen(port);
10 | console.log(`App started listening on port ${port}`);
11 |
--------------------------------------------------------------------------------
/slides/13.md:
--------------------------------------------------------------------------------
1 | ## Example: image carousel
2 |
3 | - Data loaded from a database
4 | - Server-side language renders to an HTML string
5 | - HTML is loaded into DOM
6 | - JavaScript reads DOM and recognizes markup
7 | - JavaScript manipulates DOM to animate slider
8 | - Assisted by external CSS
9 |
--------------------------------------------------------------------------------
/views/base.jade:
--------------------------------------------------------------------------------
1 | doctype html
2 | html(class='no-js')
3 | head
4 | meta(charset='utf-8')
5 | meta(http-equiv='X-UA-Compatible', content='IE=edge')
6 |
7 | meta(name='viewport', content='width=device-width, initial-scale=1')
8 |
9 | block css
10 |
11 | body
12 | block body
13 |
--------------------------------------------------------------------------------
/slides/20.md:
--------------------------------------------------------------------------------
1 | ### A simple React component
2 |
3 | ```js
4 | class Hello extends React.Component {
5 | render() {
6 | return (
7 | React.createElement("span", null, "Hello, ", this.props.name)
8 | );
9 | }
10 | }
11 |
12 | React.render(React.createElement(Hello, {name: "world"}), el);
13 | ```
14 |
--------------------------------------------------------------------------------
/slides/24.md:
--------------------------------------------------------------------------------
1 | ## Everything is a component
2 |
3 | - No distinction between views and controllers
4 | - No models necessary: just use plain objects and arrays
5 | - Components are *composable*
6 | - A React app is one big component:
7 |
8 | ```js
9 | React.render(, document.getElementById('#app'));
10 | ```
11 |
--------------------------------------------------------------------------------
/slides/34.md:
--------------------------------------------------------------------------------
1 | ## Flux
2 | - An alternative to MVC
3 | - Flux stores act as centralized global state
4 | - No cascading events
5 | - Shameless plug: [Flummox](https://github.com/acdlite/flummox), a minimal isomorphic Flux library
6 | - No singletons = server-side rendering for free
7 | - Just like vanilla Flux, only better :)
8 |
--------------------------------------------------------------------------------
/slides/26.md:
--------------------------------------------------------------------------------
1 | ## The proper separation of concerns is between components, not technologies
2 |
3 | - Everything you need to know about a component is in one module
4 | - Unidirectional data flow is predictable, easy to follow
5 | - Data comes from the owner
6 | - No cascading events, no querying the DOM
7 | - But you can if you want to using lifecycle methods
8 |
--------------------------------------------------------------------------------
/src/shared/components/View.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const View = React.createClass({
4 | render() {
5 | const { className, ...props } = this.props;
6 |
7 | return (
8 |
12 | );
13 | }
14 | });
15 |
16 | export default View;
17 |
--------------------------------------------------------------------------------
/slides/27.md:
--------------------------------------------------------------------------------
1 | ### DOM is abstracted away completely
2 |
3 | - Synthetic event system
4 | - `components !== domElements`
5 | - Use components for [routing](https://github.com/rackt/react-router), or for [side-loading data](https://github.com/acdlite/flummox/blob/master/docs/api/FluxComponent.md).
6 | - Use React in non-browser environments
7 | - Server-side rendering
8 | - React Native (!!!)
9 |
--------------------------------------------------------------------------------
/src/shared/routes.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Route, Redirect } from 'react-router';
3 | import AppHandler from './components/AppHandler';
4 | import SlideHandler from './components/SlideHandler';
5 |
6 | export default (
7 |
8 |
9 |
10 |
11 | );
12 |
--------------------------------------------------------------------------------
/slides/9.md:
--------------------------------------------------------------------------------
1 | ## ...but sometimes they get in the way
2 |
3 | - Avoid filter bubbles
4 | - Keep an open mind
5 | - Don't let "best practices" become dogma
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/shared/Flux.js:
--------------------------------------------------------------------------------
1 | import { Flummox } from 'flummox';
2 | import SlideActions from './actions/SlideActions';
3 | import SlideStore from './stores/SlideStore';
4 |
5 | export default class Flux extends Flummox {
6 | constructor({ slides }) {
7 | super();
8 |
9 | const slideActions = this.createActions('slides', SlideActions);
10 | this.createStore('slides', SlideStore, this);
11 |
12 | slideActions.loadSlides(slides);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/shared/stores/SlideStore.js:
--------------------------------------------------------------------------------
1 | import { Store } from 'flummox';
2 |
3 | export default class SlideStore extends Store {
4 | constructor(flux) {
5 | super();
6 |
7 | const actions = flux.getActions('slides');
8 | this.register(actions.loadSlides, this.handleLoadSlides);
9 |
10 | this.state = {
11 | slides: [],
12 | }
13 | }
14 |
15 | handleLoadSlides(newSlides) {
16 | this.setState({
17 | slides: newSlides,
18 | });
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/views/app.jade:
--------------------------------------------------------------------------------
1 | extends ./base.jade
2 |
3 | block css
4 | if (env.NODE_ENV !== 'development')
5 | style
6 | include ../public/css/app.min.css
7 |
8 | block body
9 | #app!=appString
10 | script#slides-data(type='application/json')!=slidesString
11 |
12 | if (env.NODE_ENV == 'development')
13 | script(src='http://0.0.0.0:8081/js/app.js', defer)
14 | else
15 | script(src='/js/app.min.js', defer)
16 |
17 | script(src='//platform.twitter.com/widgets.js', async)
18 |
--------------------------------------------------------------------------------
/src/shared/components/Button.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const Button = React.createClass({
4 | getDefaultProps() {
5 | return {
6 | component: 'button',
7 | };
8 | },
9 |
10 | render() {
11 | const { className, component: Component, ...props } = this.props;
12 |
13 | return (
14 |
19 | );
20 | }
21 | });
22 |
23 | export default Button;
24 |
--------------------------------------------------------------------------------
/src/server/webpack.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | require('../shared/init');
4 |
5 | // Start webpack server
6 | import webpack from 'webpack';
7 | import WebpackDevServer from 'webpack-dev-server';
8 | import config from '../../webpack.config.dev';
9 |
10 | new WebpackDevServer(webpack(config), {
11 | publicPath: config.output.publicPath,
12 | hot: true,
13 | })
14 | .listen(8081, 'localhost', function (err, result) {
15 | if (err) console.log(err);
16 |
17 | console.log('Dev server listening at localhost:8081');
18 | });
19 |
--------------------------------------------------------------------------------
/src/shared/components/PLLogo.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import View from './View';
3 | import Button from './Button';
4 |
5 | const PLLogo = React.createClass({
6 | render() {
7 | return (
8 |
12 |
18 |
19 | );
20 | }
21 | });
22 |
23 | export default PLLogo;
24 |
--------------------------------------------------------------------------------
/slides/23.md:
--------------------------------------------------------------------------------
1 | ### A stateful component
2 |
3 | ```js
4 | class Timer extends React.Component {
5 | constructor(props) {
6 | super(props);
7 | this.state = { secondsElapsed: 0 };
8 | }
9 |
10 | tick() {
11 | this.setState({secondsElapsed: this.state.secondsElapsed + 1});
12 | }
13 |
14 | componentDidMount() {
15 | this.interval = setInterval(this.tick.bind(this), 1000);
16 | }
17 |
18 | componentWillUnmount() {
19 | clearInterval(this.interval);
20 | }
21 |
22 | render() {
23 | return (
24 | Seconds Elapsed: {this.state.secondsElapsed}
25 | );
26 | }
27 | });
28 |
29 | React.render(, el);
30 | ```
31 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # Runtime data
6 | pids
7 | *.pid
8 | *.seed
9 |
10 | # Directory for instrumented libs generated by jscoverage/JSCover
11 | lib-cov
12 |
13 | # Coverage directory used by tools like istanbul
14 | coverage
15 |
16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
17 | .grunt
18 |
19 | # node-waf configuration
20 | .lock-wscript
21 |
22 | # Compiled binary addons (http://nodejs.org/api/addons.html)
23 | build/Release
24 |
25 | # Dependency directory
26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git-
27 | node_modules
28 |
29 | /lib
30 | /public
31 |
--------------------------------------------------------------------------------
/slides/4.md:
--------------------------------------------------------------------------------
1 | ## Whaaa?
2 |
3 | ```jsx
4 | render() {
5 | const { currentSlide, totalSlides } = this.getSlidePositions();
6 |
7 | return (
8 |
9 |
10 |
11 |
12 | {currentSlide} / {totalSlides}
13 |
14 |
15 |
16 |
17 | );
18 | }
19 | ```
20 |
--------------------------------------------------------------------------------
/src/client/app.js:
--------------------------------------------------------------------------------
1 | require('../shared/init');
2 |
3 | import React from 'react';
4 | import Router from 'react-router';
5 | import FluxComponent from 'flummox/component';
6 | import Flux from '../shared/Flux';
7 | import routes from '../shared/routes';
8 |
9 | const slides = JSON.parse(
10 | document.getElementById('slides-data').innerText
11 | );
12 |
13 | // Initialize flux
14 | const flux = new Flux({ slides });
15 |
16 | // Render app
17 | Router.run(routes, Router.HistoryLocation, async (Handler, state) => {
18 | React.render(
19 |
20 |
21 | ,
22 | document.getElementById('app')
23 | );
24 | });
25 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var webpack = require('webpack');
4 | var path = require('path');
5 |
6 | module.exports = {
7 | entry: './src/client/app',
8 | output: {
9 | path: path.join(__dirname, '/public/js/'),
10 | filename: 'app.min.js',
11 | publicPath: '/js/'
12 | },
13 | plugins: [
14 | new webpack.DefinePlugin({
15 | 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
16 | }),
17 | new webpack.optimize.UglifyJsPlugin({
18 | compress: {
19 | warnings: false
20 | }
21 | }),
22 | ],
23 | resolve: {
24 | extensions: ['', '.js']
25 | },
26 | module: {
27 | loaders: [
28 | { test: /\.jsx?$/, loaders: ['babel-loader?experimental&externalHelpers'], exclude: /node_modules/ }
29 | ]
30 | }
31 | };
32 |
--------------------------------------------------------------------------------
/src/server/routes/index.js:
--------------------------------------------------------------------------------
1 | import middleware from './middleware';
2 | import router from 'koa-router';
3 | import renderAppToString from './utils/renderAppToString';
4 |
5 | export default function(app) {
6 | middleware(app);
7 |
8 | app.use(router(app));
9 |
10 | app.get(/.*/, function *() {
11 | let appString, slidesString;
12 |
13 | try {
14 | const result = yield renderAppToString({
15 | initialPath: this.url,
16 | });
17 |
18 | appString = result.appString;
19 | slidesString = result.slidesString;
20 | } catch (error) {
21 | if (error.redirect) {
22 | return this.redirect(error.redirect);
23 | }
24 |
25 | throw error;
26 | }
27 |
28 | yield this.render('app', {
29 | appString,
30 | slidesString,
31 | env: process.env,
32 | });
33 | });
34 | }
35 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "babel-eslint",
3 | "env": {
4 | "browser": true,
5 | "node": true,
6 | "mocha": true
7 | },
8 | "rules": {
9 | "strict": 0,
10 | "quotes": [2, "single"],
11 | "curly": [2, "multi-line"],
12 | "no-underscore-dangle": 0,
13 | "comma-dangle": 0,
14 | "consistent-return": 0,
15 |
16 | // Buggy with JSX
17 | // https://github.com/babel/babel-eslint/issues/29
18 | "no-undef": 1,
19 |
20 | // Doesn't work with chai expect assertions
21 | "no-unused-expressions": 0,
22 |
23 | // Doesn't work inside ES6 template strings
24 | "comma-spacing": 0,
25 |
26 | // Doesn't work with ES6 classes
27 | // https://github.com/babel/babel-eslint/issues/8
28 | "no-unused-vars": 0,
29 |
30 | "no-empty": 0,
31 | "no-use-before-define": 0
32 | },
33 | "globals": {
34 | "expect": true,
35 | "fetch": true
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/webpack.config.dev.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var webpack = require('webpack');
4 | var path = require('path');
5 |
6 | module.exports = {
7 | devtool: 'inline-source-map',
8 | entry: [
9 | 'webpack-dev-server/client?http://localhost:8081',
10 | 'webpack/hot/only-dev-server',
11 | './public/css/app.css',
12 | './src/client/app',
13 | ],
14 | output: {
15 | path: path.join(__dirname, '/public/js/'),
16 | filename: 'app.js',
17 | publicPath: 'http://localhost:8081/js/',
18 | },
19 | plugins: [
20 | new webpack.HotModuleReplacementPlugin(),
21 | new webpack.NoErrorsPlugin(),
22 | new webpack.DefinePlugin({
23 | 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
24 | 'process.env.BASE_URL': JSON.stringify(process.env.BASE_URL),
25 | }),
26 | ],
27 | resolve: {
28 | extensions: ['', '.js']
29 | },
30 | module: {
31 | loaders: [
32 | { test: /\.jsx?$/, loaders: ['react-hot', 'babel-loader?experimental&externalHelpers'], exclude: /node_modules/ },
33 | { test: /\.css/, loader: "style-loader!css-loader" },
34 | ]
35 | }
36 | };
37 |
--------------------------------------------------------------------------------
/src/shared/components/Markdown.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Remarkable from 'remarkable';
3 | import hljs from 'highlight.js';
4 |
5 | const md = new Remarkable({
6 | html: true,
7 | linkify: true,
8 | typographer: true,
9 | highlight: (str, lang) => {
10 | if (lang && hljs.getLanguage(lang)) {
11 | try {
12 | return hljs.highlight(lang, str).value;
13 | } catch (err) {}
14 | }
15 |
16 | try {
17 | return hljs.highlightAuto(str).value;
18 | } catch (err) {}
19 |
20 | return ''; // use external default escaping
21 | }
22 | });
23 |
24 | const Markdown = React.createClass({
25 | getDefaultProps() {
26 | return {
27 | src: '',
28 | };
29 | },
30 |
31 | componentDidMount() {
32 | if (typeof twttr !== 'undefined') twttr.widgets.load();
33 | },
34 |
35 | render() {
36 | const { src, ...props } = this.props;
37 | const html = md.render(src);
38 |
39 | return (
40 |
44 | );
45 | }
46 | });
47 |
48 | export default Markdown;
49 |
--------------------------------------------------------------------------------
/src/shared/components/AppHandler.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Flux from 'flummox/component';
3 | import { RouteHandler } from 'react-router';
4 | import SlideProgressBar from './SlideProgressBar';
5 | import PLLogo from './PLLogo';
6 | import View from './View';
7 |
8 | const AppHandler = React.createClass({
9 | render() {
10 | return (
11 |
17 |
18 | ({
20 | slide: store.state.slides[this.props.params.currentSlide - 1],
21 | })
22 | }}>
23 |
24 |
25 |
26 | ({
28 | totalSlides: store.state.slides.length,
29 | })
30 | }}>
31 |
32 |
33 |
34 | );
35 | }
36 | });
37 |
38 | export default AppHandler;
39 |
--------------------------------------------------------------------------------
/src/shared/components/SlideHandler.js:
--------------------------------------------------------------------------------
1 | import React from 'react/addons';
2 | import Flux from 'flummox/component';
3 | import Slide from './Slide';
4 | import View from './View';
5 |
6 | const { CSSTransitionGroup } = React.addons;
7 |
8 | const SlideHandler = React.createClass({
9 |
10 | statics: {
11 | willTransitionTo(transition, params, query) {
12 | const { currentSlide } = params;
13 | const integerCurrentSlide = parseInt(currentSlide);
14 |
15 | if (`${integerCurrentSlide}` !== currentSlide) {
16 | return transition.redirect(Number.isNaN(integerCurrentSlide)
17 | ? '/1'
18 | : `/${integerCurrentSlide}`
19 | );
20 | }
21 | }
22 | },
23 |
24 | render() {
25 | const { slide } = this.props;
26 |
27 | return (
28 |
36 |
37 |
38 | );
39 | }
40 | });
41 |
42 | export default SlideHandler;
43 |
--------------------------------------------------------------------------------
/src/scripts/buildSlides.js:
--------------------------------------------------------------------------------
1 | require('../shared/init');
2 |
3 | import frontmatter from 'front-matter';
4 | import fs from 'fs';
5 | import path from 'path';
6 |
7 | const slideDir = 'slides';
8 |
9 | const outline = fs.createWriteStream('public/outline.txt');
10 |
11 | const slides = fs.readdirSync('slides')
12 | .filter(filename => filename.endsWith('.md'))
13 | .sort(sortAlphabetically)
14 | .map((filename, i, filenames) => {
15 | const slideNumber = i + 1;
16 | const fullFilename = path.join(slideDir, filename);
17 |
18 | const contents = fs.readFileSync(fullFilename, 'utf8');
19 |
20 | const { attributes, body } = frontmatter(contents);
21 |
22 | outline.write(contents);
23 | if (slideNumber !== filenames.length) {
24 | outline.write(`\n\n*** ${slideNumber} ***\n\n`);
25 | }
26 |
27 | return {
28 | body,
29 | slideNumber,
30 | ...attributes,
31 | }
32 | });
33 |
34 | const output = fs.writeFileSync('public/slides.json', JSON.stringify(slides));
35 |
36 | function sortAlphabetically(a, b) {
37 | a = parseInt(a);
38 | b = parseInt(b);
39 | if (a < b) return -1;
40 | if (a > b) return 1;
41 | return 0;
42 | }
43 |
--------------------------------------------------------------------------------
/src/server/routes/middleware.js:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 |
3 | import bodyParser from 'koa-bodyparser';
4 | import gzip from 'koa-gzip';
5 | import fresh from 'koa-fresh';
6 | import conditional from 'koa-conditional-get';
7 | import etag from 'koa-etag';
8 | import serve from 'koa-static';
9 | import json from 'koa-json';
10 | import qs from 'koa-qs';
11 | import views from 'koa-views';
12 |
13 | export default function(app) {
14 | // Error handling
15 | app.use(function *(next) {
16 | try {
17 | yield next;
18 | } catch (error) {
19 | this.status = error.status || 500;
20 | this.body = error.message;
21 | this.app.emit('error', error, this);
22 | }
23 | });
24 |
25 | // Body parsing
26 | app.use(bodyParser());
27 |
28 | // gzip compression
29 | app.use(gzip());
30 |
31 | // Conditional GET
32 | app.use(conditional());
33 |
34 | // Freshness testing
35 | app.use(fresh());
36 |
37 | // etags
38 | app.use(etag());
39 |
40 | // Serve static assets from `public` directory
41 | app.use(serve('public'));
42 |
43 | // Pretty-print JSON responses
44 | if (process.env.NODE_ENV === 'development') app.use(json());
45 |
46 | // Add nesting support to query strings
47 | qs(app);
48 |
49 | // View rendering
50 | app.use(views(path.join(process.cwd(), 'views'), {
51 | cache: true,
52 | default: 'jade',
53 | }));
54 | }
55 |
--------------------------------------------------------------------------------
/src/shared/components/Slide.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import View from './View';
3 | import Markdown from './Markdown';
4 |
5 | const style = {
6 | slide: {
7 | flexGrow: 1,
8 | justifyContent: 'center',
9 | padding: '3em',
10 | backgroundSize: 'cover',
11 | backgroundPosition: 'center',
12 | }
13 | };
14 |
15 | const Slide = React.createClass({
16 | render() {
17 | const { slide } = this.props;
18 |
19 | if (!slide) return null;
20 |
21 | const {
22 | slideNumber,
23 | body,
24 | verticalAlign,
25 | centered,
26 | image,
27 | ...props } = slide;
28 |
29 | let alignItems;
30 | switch (verticalAlign) {
31 | case 'bottom':
32 | alignItems = 'flex-end';
33 | break;
34 | case 'top':
35 | alignItems = 'flex-start';
36 | break;
37 | default:
38 | alignItems = 'center';
39 | }
40 |
41 | const slideStyle = {
42 | textAlign: centered ? 'center' : 'left',
43 | alignItems
44 | };
45 |
46 | if (image) slideStyle.backgroundImage = `url(${image})`;
47 |
48 | return (
49 |
53 |
56 |
57 | );
58 | }
59 | });
60 |
61 | export default Slide;
62 |
--------------------------------------------------------------------------------
/slides/14.md:
--------------------------------------------------------------------------------
1 | Even for this "simple" task, update logic is complicated:
2 |
3 | ```js
4 | Slick.prototype.addSlide = Slick.prototype.slickAdd = function(markup, index, addBefore) {
5 |
6 | var _ = this;
7 |
8 | if (typeof(index) === 'boolean') {
9 | addBefore = index;
10 | index = null;
11 | } else if (index < 0 || (index >= _.slideCount)) {
12 | return false;
13 | }
14 |
15 | _.unload();
16 |
17 | if (typeof(index) === 'number') {
18 | if (index === 0 && _.$slides.length === 0) {
19 | $(markup).appendTo(_.$slideTrack);
20 | } else if (addBefore) {
21 | $(markup).insertBefore(_.$slides.eq(index));
22 | } else {
23 | $(markup).insertAfter(_.$slides.eq(index));
24 | }
25 | } else {
26 | if (addBefore === true) {
27 | $(markup).prependTo(_.$slideTrack);
28 | } else {
29 | $(markup).appendTo(_.$slideTrack);
30 | }
31 | }
32 |
33 | _.$slides = _.$slideTrack.children(this.options.slide);
34 |
35 | _.$slideTrack.children(this.options.slide).detach();
36 |
37 | _.$slideTrack.append(_.$slides);
38 |
39 | _.$slides.each(function(index, element) {
40 | $(element).attr('data-slick-index', index);
41 | });
42 |
43 | _.$slidesCache = _.$slides;
44 |
45 | _.reinit();
46 |
47 | };
48 | ```
49 |
50 | (I'm not picking on the Slick library — it's actually really good.)
51 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "the-react-way",
3 | "version": "0.0.0",
4 | "description": "Presentation for Frontend Awesome Meetup, March 2015",
5 | "main": "lib/server",
6 | "scripts": {
7 | "prestart": "make fast-build",
8 | "start": "node lib/server"
9 | },
10 | "author": "Andrew Clark ",
11 | "license": "ISC",
12 | "devDependencies": {
13 | "autoprefixer": "~5.1.0",
14 | "babel": "~4.7.16",
15 | "babel-core": "~4.7.16",
16 | "babel-eslint": "~2.0.2",
17 | "babel-loader": "~4.2.0",
18 | "clean-css": "~3.1.8",
19 | "css-loader": "~0.9.1",
20 | "eslint": "~0.17.1",
21 | "front-matter": "~1.0.0",
22 | "json-sass": "~1.3.3",
23 | "react-hot-loader": "~1.2.3",
24 | "source-map-support": "~0.2.10",
25 | "style-loader": "~0.8.3",
26 | "watch": "~0.14.0",
27 | "webpack": "~1.7.3",
28 | "webpack-dev-server": "~1.7.0"
29 | },
30 | "dependencies": {
31 | "flummox": "~2.13.2",
32 | "highlight.js": "~8.4.0",
33 | "htmlescape": "~1.0.0",
34 | "keymaster": "~1.6.2",
35 | "koa": "~0.18.1",
36 | "koa-bodyparser": "~1.4.1",
37 | "koa-conditional-get": "~1.0.2",
38 | "koa-etag": "~2.0.0",
39 | "koa-fresh": "0.0.3",
40 | "koa-gzip": "~0.1.0",
41 | "koa-json": "~1.1.1",
42 | "koa-qs": "~2.0.0",
43 | "koa-router": "~4.2.0",
44 | "koa-static": "~1.4.9",
45 | "koa-views": "~2.1.2",
46 | "react": "~0.12.2",
47 | "react-router": "~0.12.4",
48 | "remarkable": "~1.6.0",
49 | "then-jade": "~2.2.1"
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/server/routes/utils/renderAppToString.js:
--------------------------------------------------------------------------------
1 | import fs from 'fs';
2 | import React from 'react';
3 | import Router from 'react-router';
4 | import FluxComponent from 'flummox/component';
5 | import routes from '../../../shared/routes';
6 | import Flux from '../../../shared/Flux';
7 | import htmlescape from 'htmlescape';
8 |
9 | const slidesString = fs.readFileSync('public/slides.json', 'utf8');
10 | const slides = JSON.parse(slidesString);
11 |
12 | const escapedSlidesString = htmlescape(slides);
13 |
14 | export default async ({ initialPath }) => {
15 |
16 | const router = Router.create({
17 | routes: routes,
18 | location: initialPath,
19 | onError: error => {
20 | throw error;
21 | },
22 | onAbort: abortReason => {
23 | const error = new Error();
24 |
25 | if (abortReason.constructor.name === 'Redirect') {
26 | const { to, params, query } = abortReason;
27 | const url = router.makePath(to, params, query);
28 | error.redirect = url;
29 | }
30 |
31 | throw error;
32 | }
33 | });
34 |
35 | const flux = new Flux({ slides });
36 |
37 | const { Handler, state } = await new Promise((resolve, reject) => {
38 | router.run((_Handler, _state) =>
39 | resolve({ Handler: _Handler, state: _state })
40 | );
41 | });
42 |
43 | const appString = React.renderToString(
44 |
45 |
46 |
47 | );
48 |
49 | return {
50 | appString,
51 | slidesString: escapedSlidesString,
52 | };
53 | }
54 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | The React Way
2 | =============
3 |
4 | An isomorphic React slide deck, about React.
5 |
6 | [Watch the video.](https://www.youtube.com/watch?v=HOpyRiXB5WQ)
7 |
8 | Presented at [Frontend Awesome Meetup](http://www.meetup.com/Gainesville-Front-End-Dev-Meetup/)
9 | March 19, 2015
10 |
11 | 
12 |
13 | Running the slide deck
14 | ----------------------
15 |
16 | Only tested in Chrome. Probably won't work in Safari because I didn't care about adding prefixes to flexbox properties.
17 |
18 | Run `npm start` to start the server. Then navigate to http://localhost:3000. (You could use wget to convert this to a static site.)
19 |
20 | Run `make watch` instead to start the server in development mode, with hot reloading.
21 |
22 | How it's made
23 | -------------
24 |
25 | The slides are generated from Markdown documents located in `slides`. A build task combines the slides into a JSON document, which is embedded into the page by the server to be loaded by the React app.
26 |
27 | - [React](http://facebook.github.io/react/)
28 | - [Flummox](https://github.com/acdlite/flummox)
29 | - Overkill in this case, but used for illustration purposes.
30 | - [React Router](https://github.com/rackt/react-router)
31 | - [React Hot Loader](http://gaearon.github.io/react-hot-loader/)
32 | - [Remarkable](https://github.com/jonschlinkert/remarkable)
33 | - [front-matter](https://github.com/jxson/front-matter)
34 | - [Sass/Libsass](http://sass-lang.com/)
35 | - [Make](http://www.gnu.org/software/make/manual/make.html)
36 | - [Babel](https://babeljs.io/)
37 | - [iojs](https://iojs.org)
38 | - [koa](http://koajs.com/)
39 |
40 | ...and more.
41 |
--------------------------------------------------------------------------------
/sass/vendor/_tomorrow.scss:
--------------------------------------------------------------------------------
1 | /* http://jmblog.github.com/color-themes-for-google-code-highlightjs */
2 |
3 | /* Tomorrow Comment */
4 | .hljs-comment {
5 | color: #8e908c;
6 | }
7 |
8 | /* Tomorrow Red */
9 | .hljs-variable,
10 | .hljs-attribute,
11 | .hljs-tag,
12 | .hljs-regexp,
13 | .ruby .hljs-constant,
14 | .xml .hljs-tag .hljs-title,
15 | .xml .hljs-pi,
16 | .xml .hljs-doctype,
17 | .html .hljs-doctype,
18 | .css .hljs-id,
19 | .css .hljs-class,
20 | .css .hljs-pseudo {
21 | color: #c82829;
22 | }
23 |
24 | /* Tomorrow Orange */
25 | .hljs-number,
26 | .hljs-preprocessor,
27 | .hljs-pragma,
28 | .hljs-built_in,
29 | .hljs-literal,
30 | .hljs-params,
31 | .hljs-constant {
32 | color: #f5871f;
33 | }
34 |
35 | /* Tomorrow Yellow */
36 | .ruby .hljs-class .hljs-title,
37 | .css .hljs-rules .hljs-attribute {
38 | color: #eab700;
39 | }
40 |
41 | /* Tomorrow Green */
42 | .hljs-string,
43 | .hljs-value,
44 | .hljs-inheritance,
45 | .hljs-header,
46 | .ruby .hljs-symbol,
47 | .xml .hljs-cdata {
48 | color: #718c00;
49 | }
50 |
51 | /* Tomorrow Aqua */
52 | .hljs-title,
53 | .css .hljs-hexcolor {
54 | color: #3e999f;
55 | }
56 |
57 | /* Tomorrow Blue */
58 | .hljs-function,
59 | .python .hljs-decorator,
60 | .python .hljs-title,
61 | .ruby .hljs-function .hljs-title,
62 | .ruby .hljs-title .hljs-keyword,
63 | .perl .hljs-sub,
64 | .javascript .hljs-title,
65 | .coffeescript .hljs-title {
66 | color: #4271ae;
67 | }
68 |
69 | /* Tomorrow Purple */
70 | .hljs-keyword,
71 | .javascript .hljs-function {
72 | color: #8959a8;
73 | }
74 |
75 | .hljs {
76 | display: block;
77 | overflow-x: auto;
78 | background: white;
79 | color: #4d4d4c;
80 | padding: 0.5em;
81 | -webkit-text-size-adjust: none;
82 | }
83 |
84 | .coffeescript .javascript,
85 | .javascript .xml,
86 | .tex .hljs-formula,
87 | .xml .javascript,
88 | .xml .vbscript,
89 | .xml .css,
90 | .xml .hljs-cdata {
91 | opacity: 0.5;
92 | }
93 |
--------------------------------------------------------------------------------
/sass/app.scss:
--------------------------------------------------------------------------------
1 | @import "vendor";
2 | @import url(//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro);
3 |
4 | html {
5 | font-family: 'Source Sans Pro', sans-serif;
6 | background-color: #146cce;
7 | color: #fff;
8 | }
9 |
10 | a {
11 | color: #fff;
12 | }
13 |
14 | pre, code {
15 | font-family: 'Source Code Pro';
16 | }
17 |
18 | .Button {
19 | display: inline;
20 | background: transparent;
21 | -webkit-appearance: none;
22 | -moz-appearance: none;
23 | -webkit-tap-highlight-color: transparent;
24 | outline: none;
25 | border: none;
26 | padding: 0;
27 | margin: 0;
28 | overflow: visible;
29 | text-decoration: none;
30 | color: inherit;
31 | text-align: start;
32 | white-space: normal;
33 |
34 | &:hover {
35 | cursor: pointer;
36 | }
37 | }
38 |
39 | // Muahahahahaha
40 | .View {
41 | box-sizing: border-box;
42 | display: flex;
43 | position: relative;
44 | }
45 |
46 | .Slide {
47 | position: absolute;
48 | height: 100%;
49 | width: 100%;
50 | top: 0;
51 | left: 0;
52 |
53 | @media (min-width: 40em) {
54 | font-size: 2.5vw;
55 | }
56 |
57 | pre code {
58 | @extend .hljs;
59 | max-height: 16em;
60 | font-size: 80%;
61 | }
62 | }
63 |
64 | .SlideProgressBar {
65 | &-wrapper {
66 | transform: translateY(100%);
67 | transition: transform 150ms;
68 | }
69 |
70 | &:hover &-wrapper {
71 | transform: none;
72 | }
73 | }
74 |
75 | .SlideTransition--fade{
76 | $transition-duration: 150ms;
77 |
78 | &-enter {
79 | opacity: 0.01;
80 | transition: opacity $transition-duration ease-in;
81 | }
82 |
83 | &-enter.SlideTransition--fade-enter-active {
84 | opacity: 1;
85 | }
86 |
87 | &-leave {
88 | opacity: 1;
89 | transition: opacity $transition-duration ease-in;
90 | }
91 |
92 | &-leave.SlideTransition--fade-leave-active {
93 | opacity: 0.01;
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | BABEL_CMD = node_modules/.bin/babel
2 | ESLINT_CMD = node_modules/.bin/eslint
3 | WEBPACK_CMD = node_modules/.bin/webpack
4 | SASS_CMD = sassc
5 | WATCH_CMD = node_modules/.bin/watch
6 | AUTOPREFIXER_CMD = node_modules/.bin/autoprefixer
7 | CLEANCSS_CMD = node_modules/.bin/cleancss
8 | JSON_SASS_CMD = node_modules/.bin/json-sass
9 |
10 | BABEL_ARGS = --experimental --external-helpers --source-maps-inline --blacklist regenerator,es6.blockScoping --optional asyncToGenerator
11 |
12 | SRC_JS = $(shell find src -name "*.js")
13 | LIB_JS = $(patsubst src/%.js,lib/%.js,$(SRC_JS))
14 |
15 | # Build application
16 | build: build-dev minify-css
17 |
18 | build-dev: js webpack css slides
19 |
20 | # Build application quickly
21 | # Faster on first build, but not after that
22 | fast-build: fast-js build
23 |
24 | # Watch for changes
25 | watch: minify-css
26 | @NODE_ENV=development $(MAKE) -j5 dev-server webpack-server watch-css watch-js watch-slides
27 |
28 | dev-server: $(LIB_JS)
29 | nodemon ./lib/server | bunyan
30 |
31 | webpack-server: $(LIB_JS)
32 | node ./lib/server/webpack
33 |
34 | slides: public/slides.json
35 |
36 | public/slides.json: js
37 | node ./lib/scripts/buildSlides.js
38 |
39 | watch-slides:
40 | $(WATCH_CMD) "node ./lib/scripts/buildSlides.js" slides
41 |
42 | # Clean up
43 | clean:
44 | rm -rf lib
45 | rm -rf public/js/
46 | rm -rf public/css/
47 | rm -f sass/_theme.scss
48 | rm -f public/slides.json
49 |
50 | webpack: public/js/app.js
51 |
52 | public/js/app.js: $(SRC_JS)
53 | $(WEBPACK_CMD)
54 |
55 | # Transpile JavaScript using Babel
56 | js: $(LIB_JS)
57 |
58 | $(LIB_JS): lib/%.js: src/%.js
59 | mkdir -p $(dir $@) && $(BABEL_CMD) $< -o $@ $(BABEL_ARGS)
60 |
61 | fast-js:
62 | $(BABEL_CMD) src -d lib $(BABEL_ARGS)
63 |
64 | watch-js:
65 | $(BABEL_CMD) src -d lib $(BABEL_ARGS) -w
66 |
67 | # Compile Sass
68 | css: public/css/app.css
69 |
70 | minify-css: css public/css/app.min.css
71 |
72 | public/css/app.css: sass/app.scss theme
73 | mkdir -p $(dir $@) && $(SASS_CMD) -m $< | $(AUTOPREFIXER_CMD) > $@
74 |
75 | public/css/app.min.css: public/css/app.css
76 | $(CLEANCSS_CMD) $< > $@
77 |
78 | watch-css:
79 | $(WATCH_CMD) "mkdir -p public/css && $(SASS_CMD) -m sass/app.scss | $(AUTOPREFIXER_CMD) > public/css/app.css" sass
80 |
81 | theme: sass/dependencies/_theme.scss
82 |
83 | sass/dependencies/_theme.scss: lib/shared/theme.js
84 | mkdir -p $(dir $@) && $(JSON_SASS_CMD) -i $< \
85 | | sed '1s/^/$$theme: /' \
86 | > $@
87 |
88 | .PHONY: build build-dev test fast-build watch dev-server webpack-server clean
89 | .PHONY: webpack js fast-js weatch-js css minify-css watch-css theme
90 |
--------------------------------------------------------------------------------
/src/shared/components/SlideProgressBar.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Navigation, Link } from 'react-router';
3 | import View from './View';
4 | import Button from './Button';
5 |
6 | const style = {
7 | bar: {
8 | position: 'absolute',
9 | bottom: 0,
10 | width: '100%',
11 | },
12 |
13 | button: {
14 | padding: '0.75em',
15 | fontSize: '1.5em',
16 | position: 'relative',
17 | top: '0.125em',
18 | },
19 |
20 | wrapper: {
21 | justifyContent: 'space-between',
22 | flexGrow: 1,
23 | },
24 | };
25 |
26 | const SlideProgressBar = React.createClass({
27 | mixins: [Navigation],
28 |
29 | componentDidMount() {
30 | const key = require('keymaster');
31 | key('space', this.nextSlide);
32 | key('right', this.nextSlide);
33 | key('left', this.prevSlide);
34 | },
35 |
36 | componentWillUnmount() {
37 | const key = require('keymaster');
38 | key.unbind('space');
39 | key.unbind('right');
40 | key.unbind('left');
41 | },
42 |
43 | getNextSlide() {
44 | const { currentSlide, totalSlides } = this.getSlidePositions();
45 |
46 | return (currentSlide >= totalSlides) ? 1 : currentSlide + 1;
47 | },
48 |
49 | getPrevSlide() {
50 | const { currentSlide, totalSlides } = this.getSlidePositions();
51 |
52 | return (currentSlide <= 1) ? totalSlides : currentSlide - 1;
53 | },
54 |
55 | nextSlide(event) {
56 | event.preventDefault();
57 |
58 | this.goToSlide(this.getNextSlide());
59 | },
60 |
61 | prevSlide(event) {
62 | event.preventDefault();
63 |
64 | this.goToSlide(this.getPrevSlide());
65 | },
66 |
67 | goToSlide(slideNumber) {
68 | this.transitionTo(`/${slideNumber}`);
69 | },
70 |
71 | getSlidePositions() {
72 | const currentSlide = parseInt(this.props.currentSlide);
73 | const totalSlides = parseInt(this.props.totalSlides);
74 |
75 | return { currentSlide, totalSlides };
76 | },
77 |
78 | progress(currentSlide, totalSlides) {
79 | // let bullets = [];
80 | //
81 | // for (let i = 0; i < totalSlides; i++) {
82 | // const n = i + 1;
83 | //
84 | // bullets.push(
85 | //
86 | // );
87 | // }
88 | //
89 | // return bullets;
90 |
91 | return (
92 |
93 | {currentSlide} / {totalSlides}
94 |
95 | );
96 | },
97 |
98 | render() {
99 | const { currentSlide, totalSlides } = this.getSlidePositions();
100 |
101 | return (
102 |
103 |
104 |
105 | {this.progress(currentSlide, totalSlides)}
106 |
107 |
108 |
109 | );
110 | }
111 |
112 | });
113 |
114 | const Bullet = React.createClass({
115 | render() {
116 | const { currentSlide, slideNumber } = this.props;
117 |
118 | return (
119 |
128 | )
129 | }
130 | })
131 |
132 | export default SlideProgressBar;
133 |
--------------------------------------------------------------------------------
/sass/vendor/_normalize.scss:
--------------------------------------------------------------------------------
1 | /*! normalize.css v3.0.2 | MIT License | git.io/normalize */
2 |
3 | /**
4 | * 1. Set default font family to sans-serif.
5 | * 2. Prevent iOS text size adjust after orientation change, without disabling
6 | * user zoom.
7 | */
8 |
9 | html {
10 | font-family: sans-serif; /* 1 */
11 | -ms-text-size-adjust: 100%; /* 2 */
12 | -webkit-text-size-adjust: 100%; /* 2 */
13 | }
14 |
15 | /**
16 | * Remove default margin.
17 | */
18 |
19 | body {
20 | margin: 0;
21 | }
22 |
23 | /* HTML5 display definitions
24 | ========================================================================== */
25 |
26 | /**
27 | * Correct `block` display not defined for any HTML5 element in IE 8/9.
28 | * Correct `block` display not defined for `details` or `summary` in IE 10/11
29 | * and Firefox.
30 | * Correct `block` display not defined for `main` in IE 11.
31 | */
32 |
33 | article,
34 | aside,
35 | details,
36 | figcaption,
37 | figure,
38 | footer,
39 | header,
40 | hgroup,
41 | main,
42 | menu,
43 | nav,
44 | section,
45 | summary {
46 | display: block;
47 | }
48 |
49 | /**
50 | * 1. Correct `inline-block` display not defined in IE 8/9.
51 | * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
52 | */
53 |
54 | audio,
55 | canvas,
56 | progress,
57 | video {
58 | display: inline-block; /* 1 */
59 | vertical-align: baseline; /* 2 */
60 | }
61 |
62 | /**
63 | * Prevent modern browsers from displaying `audio` without controls.
64 | * Remove excess height in iOS 5 devices.
65 | */
66 |
67 | audio:not([controls]) {
68 | display: none;
69 | height: 0;
70 | }
71 |
72 | /**
73 | * Address `[hidden]` styling not present in IE 8/9/10.
74 | * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
75 | */
76 |
77 | [hidden],
78 | template {
79 | display: none;
80 | }
81 |
82 | /* Links
83 | ========================================================================== */
84 |
85 | /**
86 | * Remove the gray background color from active links in IE 10.
87 | */
88 |
89 | a {
90 | background-color: transparent;
91 | }
92 |
93 | /**
94 | * Improve readability when focused and also mouse hovered in all browsers.
95 | */
96 |
97 | a:active,
98 | a:hover {
99 | outline: 0;
100 | }
101 |
102 | /* Text-level semantics
103 | ========================================================================== */
104 |
105 | /**
106 | * Address styling not present in IE 8/9/10/11, Safari, and Chrome.
107 | */
108 |
109 | abbr[title] {
110 | border-bottom: 1px dotted;
111 | }
112 |
113 | /**
114 | * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
115 | */
116 |
117 | b,
118 | strong {
119 | font-weight: bold;
120 | }
121 |
122 | /**
123 | * Address styling not present in Safari and Chrome.
124 | */
125 |
126 | dfn {
127 | font-style: italic;
128 | }
129 |
130 | /**
131 | * Address variable `h1` font-size and margin within `section` and `article`
132 | * contexts in Firefox 4+, Safari, and Chrome.
133 | */
134 |
135 | h1 {
136 | font-size: 2em;
137 | margin: 0.67em 0;
138 | }
139 |
140 | /**
141 | * Address styling not present in IE 8/9.
142 | */
143 |
144 | mark {
145 | background: #ff0;
146 | color: #000;
147 | }
148 |
149 | /**
150 | * Address inconsistent and variable font size in all browsers.
151 | */
152 |
153 | small {
154 | font-size: 80%;
155 | }
156 |
157 | /**
158 | * Prevent `sub` and `sup` affecting `line-height` in all browsers.
159 | */
160 |
161 | sub,
162 | sup {
163 | font-size: 75%;
164 | line-height: 0;
165 | position: relative;
166 | vertical-align: baseline;
167 | }
168 |
169 | sup {
170 | top: -0.5em;
171 | }
172 |
173 | sub {
174 | bottom: -0.25em;
175 | }
176 |
177 | /* Embedded content
178 | ========================================================================== */
179 |
180 | /**
181 | * Remove border when inside `a` element in IE 8/9/10.
182 | */
183 |
184 | img {
185 | border: 0;
186 | }
187 |
188 | /**
189 | * Correct overflow not hidden in IE 9/10/11.
190 | */
191 |
192 | svg:not(:root) {
193 | overflow: hidden;
194 | }
195 |
196 | /* Grouping content
197 | ========================================================================== */
198 |
199 | /**
200 | * Address margin not present in IE 8/9 and Safari.
201 | */
202 |
203 | figure {
204 | margin: 1em 40px;
205 | }
206 |
207 | /**
208 | * Address differences between Firefox and other browsers.
209 | */
210 |
211 | hr {
212 | -moz-box-sizing: content-box;
213 | box-sizing: content-box;
214 | height: 0;
215 | }
216 |
217 | /**
218 | * Contain overflow in all browsers.
219 | */
220 |
221 | pre {
222 | overflow: auto;
223 | }
224 |
225 | /**
226 | * Address odd `em`-unit font size rendering in all browsers.
227 | */
228 |
229 | code,
230 | kbd,
231 | pre,
232 | samp {
233 | font-family: monospace, monospace;
234 | font-size: 1em;
235 | }
236 |
237 | /* Forms
238 | ========================================================================== */
239 |
240 | /**
241 | * Known limitation: by default, Chrome and Safari on OS X allow very limited
242 | * styling of `select`, unless a `border` property is set.
243 | */
244 |
245 | /**
246 | * 1. Correct color not being inherited.
247 | * Known issue: affects color of disabled elements.
248 | * 2. Correct font properties not being inherited.
249 | * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
250 | */
251 |
252 | button,
253 | input,
254 | optgroup,
255 | select,
256 | textarea {
257 | color: inherit; /* 1 */
258 | font: inherit; /* 2 */
259 | margin: 0; /* 3 */
260 | }
261 |
262 | /**
263 | * Address `overflow` set to `hidden` in IE 8/9/10/11.
264 | */
265 |
266 | button {
267 | overflow: visible;
268 | }
269 |
270 | /**
271 | * Address inconsistent `text-transform` inheritance for `button` and `select`.
272 | * All other form control elements do not inherit `text-transform` values.
273 | * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
274 | * Correct `select` style inheritance in Firefox.
275 | */
276 |
277 | button,
278 | select {
279 | text-transform: none;
280 | }
281 |
282 | /**
283 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
284 | * and `video` controls.
285 | * 2. Correct inability to style clickable `input` types in iOS.
286 | * 3. Improve usability and consistency of cursor style between image-type
287 | * `input` and others.
288 | */
289 |
290 | button,
291 | html input[type="button"], /* 1 */
292 | input[type="reset"],
293 | input[type="submit"] {
294 | -webkit-appearance: button; /* 2 */
295 | cursor: pointer; /* 3 */
296 | }
297 |
298 | /**
299 | * Re-set default cursor for disabled elements.
300 | */
301 |
302 | button[disabled],
303 | html input[disabled] {
304 | cursor: default;
305 | }
306 |
307 | /**
308 | * Remove inner padding and border in Firefox 4+.
309 | */
310 |
311 | button::-moz-focus-inner,
312 | input::-moz-focus-inner {
313 | border: 0;
314 | padding: 0;
315 | }
316 |
317 | /**
318 | * Address Firefox 4+ setting `line-height` on `input` using `!important` in
319 | * the UA stylesheet.
320 | */
321 |
322 | input {
323 | line-height: normal;
324 | }
325 |
326 | /**
327 | * It's recommended that you don't attempt to style these elements.
328 | * Firefox's implementation doesn't respect box-sizing, padding, or width.
329 | *
330 | * 1. Address box sizing set to `content-box` in IE 8/9/10.
331 | * 2. Remove excess padding in IE 8/9/10.
332 | */
333 |
334 | input[type="checkbox"],
335 | input[type="radio"] {
336 | box-sizing: border-box; /* 1 */
337 | padding: 0; /* 2 */
338 | }
339 |
340 | /**
341 | * Fix the cursor style for Chrome's increment/decrement buttons. For certain
342 | * `font-size` values of the `input`, it causes the cursor style of the
343 | * decrement button to change from `default` to `text`.
344 | */
345 |
346 | input[type="number"]::-webkit-inner-spin-button,
347 | input[type="number"]::-webkit-outer-spin-button {
348 | height: auto;
349 | }
350 |
351 | /**
352 | * 1. Address `appearance` set to `searchfield` in Safari and Chrome.
353 | * 2. Address `box-sizing` set to `border-box` in Safari and Chrome
354 | * (include `-moz` to future-proof).
355 | */
356 |
357 | input[type="search"] {
358 | -webkit-appearance: textfield; /* 1 */
359 | -moz-box-sizing: content-box;
360 | -webkit-box-sizing: content-box; /* 2 */
361 | box-sizing: content-box;
362 | }
363 |
364 | /**
365 | * Remove inner padding and search cancel button in Safari and Chrome on OS X.
366 | * Safari (but not Chrome) clips the cancel button when the search input has
367 | * padding (and `textfield` appearance).
368 | */
369 |
370 | input[type="search"]::-webkit-search-cancel-button,
371 | input[type="search"]::-webkit-search-decoration {
372 | -webkit-appearance: none;
373 | }
374 |
375 | /**
376 | * Define consistent border, margin, and padding.
377 | */
378 |
379 | fieldset {
380 | border: 1px solid #c0c0c0;
381 | margin: 0 2px;
382 | padding: 0.35em 0.625em 0.75em;
383 | }
384 |
385 | /**
386 | * 1. Correct `color` not being inherited in IE 8/9/10/11.
387 | * 2. Remove padding so people aren't caught out if they zero out fieldsets.
388 | */
389 |
390 | legend {
391 | border: 0; /* 1 */
392 | padding: 0; /* 2 */
393 | }
394 |
395 | /**
396 | * Remove default vertical scrollbar in IE 8/9/10/11.
397 | */
398 |
399 | textarea {
400 | overflow: auto;
401 | }
402 |
403 | /**
404 | * Don't inherit the `font-weight` (applied by a rule above).
405 | * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
406 | */
407 |
408 | optgroup {
409 | font-weight: bold;
410 | }
411 |
412 | /* Tables
413 | ========================================================================== */
414 |
415 | /**
416 | * Remove most spacing between table cells.
417 | */
418 |
419 | table {
420 | border-collapse: collapse;
421 | border-spacing: 0;
422 | }
423 |
424 | td,
425 | th {
426 | padding: 0;
427 | }
428 |
--------------------------------------------------------------------------------
/npm-shrinkwrap.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "the-react-way",
3 | "version": "0.0.0",
4 | "dependencies": {
5 | "flummox": {
6 | "version": "2.13.2",
7 | "from": "flummox@>=2.0.0 <3.0.0",
8 | "dependencies": {
9 | "eventemitter3": {
10 | "version": "0.1.6",
11 | "from": "eventemitter3@>=0.1.6 <0.2.0",
12 | "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-0.1.6.tgz"
13 | },
14 | "flux": {
15 | "version": "2.0.1",
16 | "from": "flux@>=2.0.1 <2.1.0",
17 | "resolved": "https://registry.npmjs.org/flux/-/flux-2.0.1.tgz"
18 | },
19 | "object-assign": {
20 | "version": "2.0.0",
21 | "from": "object-assign@>=2.0.0 <2.1.0",
22 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.0.0.tgz"
23 | },
24 | "uniqueid": {
25 | "version": "0.1.0",
26 | "from": "uniqueid@>=0.1.0 <0.2.0",
27 | "resolved": "https://registry.npmjs.org/uniqueid/-/uniqueid-0.1.0.tgz"
28 | }
29 | }
30 | },
31 | "highlight.js": {
32 | "version": "8.4.0",
33 | "from": "highlight.js@*",
34 | "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-8.4.0.tgz"
35 | },
36 | "htmlescape": {
37 | "version": "1.0.0",
38 | "from": "htmlescape@*",
39 | "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.0.0.tgz"
40 | },
41 | "keymaster": {
42 | "version": "1.6.2",
43 | "from": "keymaster@*",
44 | "resolved": "https://registry.npmjs.org/keymaster/-/keymaster-1.6.2.tgz"
45 | },
46 | "koa": {
47 | "version": "0.18.1",
48 | "from": "koa@*",
49 | "resolved": "https://registry.npmjs.org/koa/-/koa-0.18.1.tgz",
50 | "dependencies": {
51 | "accepts": {
52 | "version": "1.2.5",
53 | "from": "accepts@>=1.2.2 <2.0.0",
54 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.2.5.tgz",
55 | "dependencies": {
56 | "negotiator": {
57 | "version": "0.5.1",
58 | "from": "negotiator@0.5.1",
59 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.5.1.tgz"
60 | }
61 | }
62 | },
63 | "co": {
64 | "version": "4.5.1",
65 | "from": "co@>=4.4.0 <5.0.0",
66 | "resolved": "https://registry.npmjs.org/co/-/co-4.5.1.tgz"
67 | },
68 | "composition": {
69 | "version": "2.1.1",
70 | "from": "composition@>=2.1.1 <3.0.0",
71 | "resolved": "https://registry.npmjs.org/composition/-/composition-2.1.1.tgz",
72 | "dependencies": {
73 | "memorizer": {
74 | "version": "1.0.0",
75 | "from": "memorizer@>=1.0.0 <2.0.0",
76 | "resolved": "https://registry.npmjs.org/memorizer/-/memorizer-1.0.0.tgz"
77 | },
78 | "native-or-bluebird": {
79 | "version": "1.2.0",
80 | "from": "native-or-bluebird@>=1.1.2 <2.0.0",
81 | "resolved": "https://registry.npmjs.org/native-or-bluebird/-/native-or-bluebird-1.2.0.tgz"
82 | }
83 | }
84 | },
85 | "content-disposition": {
86 | "version": "0.5.0",
87 | "from": "content-disposition@>=0.5.0 <0.6.0",
88 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.0.tgz"
89 | },
90 | "content-type": {
91 | "version": "1.0.1",
92 | "from": "content-type@>=1.0.0 <2.0.0",
93 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.1.tgz"
94 | },
95 | "cookies": {
96 | "version": "0.5.0",
97 | "from": "cookies@>=0.5.0 <0.6.0",
98 | "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.5.0.tgz",
99 | "dependencies": {
100 | "keygrip": {
101 | "version": "1.0.1",
102 | "from": "keygrip@>=1.0.0 <1.1.0",
103 | "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.0.1.tgz"
104 | }
105 | }
106 | },
107 | "debug": {
108 | "version": "2.1.3",
109 | "from": "debug@*",
110 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.1.3.tgz",
111 | "dependencies": {
112 | "ms": {
113 | "version": "0.7.0",
114 | "from": "ms@0.7.0",
115 | "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.0.tgz"
116 | }
117 | }
118 | },
119 | "delegates": {
120 | "version": "0.1.0",
121 | "from": "delegates@0.1.0",
122 | "resolved": "https://registry.npmjs.org/delegates/-/delegates-0.1.0.tgz"
123 | },
124 | "destroy": {
125 | "version": "1.0.3",
126 | "from": "destroy@>=1.0.3 <2.0.0",
127 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.3.tgz"
128 | },
129 | "error-inject": {
130 | "version": "1.0.0",
131 | "from": "error-inject@>=1.0.0 <1.1.0",
132 | "resolved": "https://registry.npmjs.org/error-inject/-/error-inject-1.0.0.tgz"
133 | },
134 | "escape-html": {
135 | "version": "1.0.1",
136 | "from": "escape-html@>=1.0.1 <1.1.0",
137 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.1.tgz"
138 | },
139 | "fresh": {
140 | "version": "0.2.4",
141 | "from": "fresh@>=0.2.4 <0.3.0",
142 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.2.4.tgz"
143 | },
144 | "http-assert": {
145 | "version": "1.1.1",
146 | "from": "http-assert@>=1.1.0 <2.0.0",
147 | "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.1.1.tgz",
148 | "dependencies": {
149 | "deep-equal": {
150 | "version": "1.0.0",
151 | "from": "deep-equal@>=1.0.0 <1.1.0",
152 | "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.0.tgz"
153 | }
154 | }
155 | },
156 | "http-errors": {
157 | "version": "1.3.1",
158 | "from": "http-errors@>=1.2.8 <2.0.0",
159 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz",
160 | "dependencies": {
161 | "inherits": {
162 | "version": "2.0.1",
163 | "from": "inherits@>=2.0.1 <2.1.0",
164 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
165 | }
166 | }
167 | },
168 | "koa-compose": {
169 | "version": "2.3.0",
170 | "from": "koa-compose@>=2.3.0 <3.0.0",
171 | "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-2.3.0.tgz"
172 | },
173 | "koa-is-json": {
174 | "version": "1.0.0",
175 | "from": "koa-is-json@>=1.0.0 <2.0.0",
176 | "resolved": "https://registry.npmjs.org/koa-is-json/-/koa-is-json-1.0.0.tgz"
177 | },
178 | "mime-types": {
179 | "version": "2.0.10",
180 | "from": "mime-types@>=2.0.7 <3.0.0",
181 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.10.tgz",
182 | "dependencies": {
183 | "mime-db": {
184 | "version": "1.8.0",
185 | "from": "mime-db@>=1.8.0 <1.9.0",
186 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.8.0.tgz"
187 | }
188 | }
189 | },
190 | "on-finished": {
191 | "version": "2.2.0",
192 | "from": "on-finished@>=2.1.0 <3.0.0",
193 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.2.0.tgz",
194 | "dependencies": {
195 | "ee-first": {
196 | "version": "1.1.0",
197 | "from": "ee-first@1.1.0",
198 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.0.tgz"
199 | }
200 | }
201 | },
202 | "only": {
203 | "version": "0.0.2",
204 | "from": "only@0.0.2",
205 | "resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz"
206 | },
207 | "parseurl": {
208 | "version": "1.3.0",
209 | "from": "parseurl@>=1.3.0 <2.0.0",
210 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.0.tgz"
211 | },
212 | "statuses": {
213 | "version": "1.2.1",
214 | "from": "statuses@>=1.2.0 <2.0.0",
215 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz"
216 | },
217 | "type-is": {
218 | "version": "1.6.1",
219 | "from": "type-is@>=1.5.5 <2.0.0",
220 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.1.tgz",
221 | "dependencies": {
222 | "media-typer": {
223 | "version": "0.3.0",
224 | "from": "media-typer@0.3.0",
225 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz"
226 | }
227 | }
228 | },
229 | "vary": {
230 | "version": "1.0.0",
231 | "from": "vary@>=1.0.0 <2.0.0",
232 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.0.0.tgz"
233 | }
234 | }
235 | },
236 | "koa-bodyparser": {
237 | "version": "1.4.1",
238 | "from": "koa-bodyparser@*",
239 | "resolved": "https://registry.npmjs.org/koa-bodyparser/-/koa-bodyparser-1.4.1.tgz",
240 | "dependencies": {
241 | "co-body": {
242 | "version": "1.1.0",
243 | "from": "co-body@>=1.1.0 <1.2.0",
244 | "resolved": "https://registry.npmjs.org/co-body/-/co-body-1.1.0.tgz",
245 | "dependencies": {
246 | "qs": {
247 | "version": "2.3.3",
248 | "from": "qs@>=2.3.3 <2.4.0",
249 | "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz"
250 | },
251 | "raw-body": {
252 | "version": "1.3.3",
253 | "from": "raw-body@>=1.3.3 <1.4.0",
254 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.3.3.tgz",
255 | "dependencies": {
256 | "bytes": {
257 | "version": "1.0.0",
258 | "from": "bytes@1.0.0",
259 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz"
260 | },
261 | "iconv-lite": {
262 | "version": "0.4.7",
263 | "from": "iconv-lite@0.4.7",
264 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.7.tgz"
265 | }
266 | }
267 | }
268 | }
269 | },
270 | "copy-to": {
271 | "version": "2.0.1",
272 | "from": "copy-to@>=2.0.1 <2.1.0",
273 | "resolved": "https://registry.npmjs.org/copy-to/-/copy-to-2.0.1.tgz"
274 | }
275 | }
276 | },
277 | "koa-conditional-get": {
278 | "version": "1.0.2",
279 | "from": "koa-conditional-get@*",
280 | "resolved": "https://registry.npmjs.org/koa-conditional-get/-/koa-conditional-get-1.0.2.tgz"
281 | },
282 | "koa-etag": {
283 | "version": "2.0.0",
284 | "from": "koa-etag@*",
285 | "resolved": "https://registry.npmjs.org/koa-etag/-/koa-etag-2.0.0.tgz",
286 | "dependencies": {
287 | "etag": {
288 | "version": "1.5.1",
289 | "from": "etag@>=1.3.0 <2.0.0",
290 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.5.1.tgz",
291 | "dependencies": {
292 | "crc": {
293 | "version": "3.2.1",
294 | "from": "crc@3.2.1",
295 | "resolved": "https://registry.npmjs.org/crc/-/crc-3.2.1.tgz"
296 | }
297 | }
298 | },
299 | "mz": {
300 | "version": "1.3.0",
301 | "from": "mz@>=1.0.1 <2.0.0",
302 | "resolved": "https://registry.npmjs.org/mz/-/mz-1.3.0.tgz",
303 | "dependencies": {
304 | "native-or-bluebird": {
305 | "version": "1.2.0",
306 | "from": "native-or-bluebird@>=1.0.0 <2.0.0",
307 | "resolved": "https://registry.npmjs.org/native-or-bluebird/-/native-or-bluebird-1.2.0.tgz"
308 | },
309 | "thenify": {
310 | "version": "3.1.0",
311 | "from": "thenify@>=3.0.0 <4.0.0",
312 | "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.1.0.tgz"
313 | },
314 | "thenify-all": {
315 | "version": "1.6.0",
316 | "from": "thenify-all@>=1.0.0 <2.0.0",
317 | "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz"
318 | }
319 | }
320 | }
321 | }
322 | },
323 | "koa-fresh": {
324 | "version": "0.0.3",
325 | "from": "koa-fresh@*",
326 | "resolved": "https://registry.npmjs.org/koa-fresh/-/koa-fresh-0.0.3.tgz"
327 | },
328 | "koa-gzip": {
329 | "version": "0.1.0",
330 | "from": "koa-gzip@*",
331 | "resolved": "https://registry.npmjs.org/koa-gzip/-/koa-gzip-0.1.0.tgz",
332 | "dependencies": {
333 | "thunkify-wrap": {
334 | "version": "0.1.1",
335 | "from": "thunkify-wrap@0.1.1",
336 | "resolved": "https://registry.npmjs.org/thunkify-wrap/-/thunkify-wrap-0.1.1.tgz"
337 | }
338 | }
339 | },
340 | "koa-json": {
341 | "version": "1.1.1",
342 | "from": "koa-json@*",
343 | "resolved": "https://registry.npmjs.org/koa-json/-/koa-json-1.1.1.tgz",
344 | "dependencies": {
345 | "koa-is-json": {
346 | "version": "1.0.0",
347 | "from": "koa-is-json@>=1.0.0 <2.0.0",
348 | "resolved": "https://registry.npmjs.org/koa-is-json/-/koa-is-json-1.0.0.tgz"
349 | },
350 | "streaming-json-stringify": {
351 | "version": "1.0.1",
352 | "from": "streaming-json-stringify@>=1.0.0 <2.0.0",
353 | "resolved": "https://registry.npmjs.org/streaming-json-stringify/-/streaming-json-stringify-1.0.1.tgz"
354 | }
355 | }
356 | },
357 | "koa-qs": {
358 | "version": "2.0.0",
359 | "from": "koa-qs@*",
360 | "resolved": "https://registry.npmjs.org/koa-qs/-/koa-qs-2.0.0.tgz",
361 | "dependencies": {
362 | "merge-descriptors": {
363 | "version": "0.0.2",
364 | "from": "merge-descriptors@>=0.0.2 <0.1.0",
365 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-0.0.2.tgz"
366 | },
367 | "qs": {
368 | "version": "2.3.3",
369 | "from": "qs@>=2.3.3 <2.4.0",
370 | "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz"
371 | }
372 | }
373 | },
374 | "koa-router": {
375 | "version": "4.2.0",
376 | "from": "koa-router@*",
377 | "resolved": "https://registry.npmjs.org/koa-router/-/koa-router-4.2.0.tgz",
378 | "dependencies": {
379 | "debug": {
380 | "version": "2.1.3",
381 | "from": "debug@>=2.1.0 <3.0.0",
382 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.1.3.tgz",
383 | "dependencies": {
384 | "ms": {
385 | "version": "0.7.0",
386 | "from": "ms@0.7.0",
387 | "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.0.tgz"
388 | }
389 | }
390 | },
391 | "http-errors": {
392 | "version": "1.3.1",
393 | "from": "http-errors@>=1.3.1 <2.0.0",
394 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz",
395 | "dependencies": {
396 | "inherits": {
397 | "version": "2.0.1",
398 | "from": "inherits@>=2.0.1 <2.1.0",
399 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
400 | },
401 | "statuses": {
402 | "version": "1.2.1",
403 | "from": "statuses@>=1.0.0 <2.0.0",
404 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz"
405 | }
406 | }
407 | },
408 | "koa-compose": {
409 | "version": "2.3.0",
410 | "from": "koa-compose@>=2.3.0 <3.0.0",
411 | "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-2.3.0.tgz"
412 | },
413 | "methods": {
414 | "version": "1.1.1",
415 | "from": "methods@>=1.0.1 <2.0.0",
416 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.1.tgz"
417 | },
418 | "path-to-regexp": {
419 | "version": "1.0.3",
420 | "from": "path-to-regexp@>=1.0.0 <2.0.0",
421 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.0.3.tgz",
422 | "dependencies": {
423 | "isarray": {
424 | "version": "0.0.1",
425 | "from": "isarray@0.0.1",
426 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz"
427 | }
428 | }
429 | }
430 | }
431 | },
432 | "koa-static": {
433 | "version": "1.4.9",
434 | "from": "koa-static@*",
435 | "resolved": "https://registry.npmjs.org/koa-static/-/koa-static-1.4.9.tgz",
436 | "dependencies": {
437 | "debug": {
438 | "version": "2.1.3",
439 | "from": "debug@*",
440 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.1.3.tgz",
441 | "dependencies": {
442 | "ms": {
443 | "version": "0.7.0",
444 | "from": "ms@0.7.0",
445 | "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.0.tgz"
446 | }
447 | }
448 | },
449 | "koa-send": {
450 | "version": "1.3.1",
451 | "from": "koa-send@>=1.3.1 <2.0.0",
452 | "resolved": "https://registry.npmjs.org/koa-send/-/koa-send-1.3.1.tgz",
453 | "dependencies": {
454 | "mz": {
455 | "version": "1.3.0",
456 | "from": "mz@>=1.0.1 <2.0.0",
457 | "resolved": "https://registry.npmjs.org/mz/-/mz-1.3.0.tgz",
458 | "dependencies": {
459 | "native-or-bluebird": {
460 | "version": "1.2.0",
461 | "from": "native-or-bluebird@>=1.0.0 <2.0.0",
462 | "resolved": "https://registry.npmjs.org/native-or-bluebird/-/native-or-bluebird-1.2.0.tgz"
463 | },
464 | "thenify": {
465 | "version": "3.1.0",
466 | "from": "thenify@>=3.0.0 <4.0.0",
467 | "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.1.0.tgz"
468 | },
469 | "thenify-all": {
470 | "version": "1.6.0",
471 | "from": "thenify-all@>=1.0.0 <2.0.0",
472 | "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz"
473 | }
474 | }
475 | }
476 | }
477 | }
478 | }
479 | },
480 | "koa-views": {
481 | "version": "2.1.2",
482 | "from": "koa-views@>=2.1.2 <2.2.0",
483 | "resolved": "https://registry.npmjs.org/koa-views/-/koa-views-2.1.2.tgz",
484 | "dependencies": {
485 | "co-views": {
486 | "version": "0.2.0",
487 | "from": "co-views@>=0.2.0 <0.3.0",
488 | "resolved": "https://registry.npmjs.org/co-views/-/co-views-0.2.0.tgz",
489 | "dependencies": {
490 | "co-render": {
491 | "version": "0.0.1",
492 | "from": "co-render@0.0.1",
493 | "resolved": "https://registry.npmjs.org/co-render/-/co-render-0.0.1.tgz",
494 | "dependencies": {
495 | "consolidate": {
496 | "version": "0.9.1",
497 | "from": "consolidate@>=0.9.1 <0.10.0",
498 | "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.9.1.tgz"
499 | }
500 | }
501 | }
502 | }
503 | },
504 | "debug": {
505 | "version": "0.7.4",
506 | "from": "debug@>=0.7.4 <0.8.0",
507 | "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz"
508 | },
509 | "koa-send": {
510 | "version": "1.3.1",
511 | "from": "koa-send@>=1.2.4 <2.0.0",
512 | "resolved": "https://registry.npmjs.org/koa-send/-/koa-send-1.3.1.tgz",
513 | "dependencies": {
514 | "mz": {
515 | "version": "1.3.0",
516 | "from": "mz@>=1.0.1 <2.0.0",
517 | "resolved": "https://registry.npmjs.org/mz/-/mz-1.3.0.tgz",
518 | "dependencies": {
519 | "native-or-bluebird": {
520 | "version": "1.2.0",
521 | "from": "native-or-bluebird@>=1.0.0 <2.0.0",
522 | "resolved": "https://registry.npmjs.org/native-or-bluebird/-/native-or-bluebird-1.2.0.tgz"
523 | },
524 | "thenify": {
525 | "version": "3.1.0",
526 | "from": "thenify@>=3.0.0 <4.0.0",
527 | "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.1.0.tgz"
528 | },
529 | "thenify-all": {
530 | "version": "1.6.0",
531 | "from": "thenify-all@>=1.0.0 <2.0.0",
532 | "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz"
533 | }
534 | }
535 | }
536 | }
537 | },
538 | "object-assign": {
539 | "version": "2.0.0",
540 | "from": "object-assign@>=2.0.0 <3.0.0",
541 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.0.0.tgz"
542 | }
543 | }
544 | },
545 | "react": {
546 | "version": "0.12.2",
547 | "from": "react@>=0.12.0 <0.13.0",
548 | "resolved": "https://registry.npmjs.org/react/-/react-0.12.2.tgz",
549 | "dependencies": {
550 | "envify": {
551 | "version": "3.4.0",
552 | "from": "envify@>=3.0.0 <4.0.0",
553 | "resolved": "https://registry.npmjs.org/envify/-/envify-3.4.0.tgz",
554 | "dependencies": {
555 | "through": {
556 | "version": "2.3.6",
557 | "from": "through@>=2.3.4 <2.4.0",
558 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.6.tgz"
559 | },
560 | "jstransform": {
561 | "version": "10.1.0",
562 | "from": "jstransform@>=10.0.1 <11.0.0",
563 | "resolved": "https://registry.npmjs.org/jstransform/-/jstransform-10.1.0.tgz",
564 | "dependencies": {
565 | "base62": {
566 | "version": "0.1.1",
567 | "from": "base62@0.1.1",
568 | "resolved": "https://registry.npmjs.org/base62/-/base62-0.1.1.tgz"
569 | },
570 | "esprima-fb": {
571 | "version": "13001.1001.0-dev-harmony-fb",
572 | "from": "esprima-fb@13001.1001.0-dev-harmony-fb",
573 | "resolved": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-13001.1001.0-dev-harmony-fb.tgz"
574 | },
575 | "source-map": {
576 | "version": "0.1.31",
577 | "from": "source-map@0.1.31",
578 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.31.tgz",
579 | "dependencies": {
580 | "amdefine": {
581 | "version": "0.1.0",
582 | "from": "amdefine@>=0.0.4",
583 | "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz"
584 | }
585 | }
586 | }
587 | }
588 | }
589 | }
590 | }
591 | }
592 | },
593 | "react-router": {
594 | "version": "0.12.4",
595 | "from": "react-router@*",
596 | "resolved": "https://registry.npmjs.org/react-router/-/react-router-0.12.4.tgz",
597 | "dependencies": {
598 | "qs": {
599 | "version": "2.3.3",
600 | "from": "qs@2.3.3",
601 | "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz"
602 | }
603 | }
604 | },
605 | "remarkable": {
606 | "version": "1.6.0",
607 | "from": "remarkable@*",
608 | "resolved": "https://registry.npmjs.org/remarkable/-/remarkable-1.6.0.tgz",
609 | "dependencies": {
610 | "argparse": {
611 | "version": "0.1.16",
612 | "from": "argparse@>=0.1.15 <0.2.0",
613 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-0.1.16.tgz",
614 | "dependencies": {
615 | "underscore": {
616 | "version": "1.7.0",
617 | "from": "underscore@>=1.7.0 <1.8.0",
618 | "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz"
619 | },
620 | "underscore.string": {
621 | "version": "2.4.0",
622 | "from": "underscore.string@>=2.4.0 <2.5.0",
623 | "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.4.0.tgz"
624 | }
625 | }
626 | },
627 | "autolinker": {
628 | "version": "0.15.2",
629 | "from": "autolinker@>=0.15.0 <0.16.0",
630 | "resolved": "https://registry.npmjs.org/autolinker/-/autolinker-0.15.2.tgz"
631 | }
632 | }
633 | },
634 | "then-jade": {
635 | "version": "2.2.1",
636 | "from": "then-jade@*",
637 | "resolved": "https://registry.npmjs.org/then-jade/-/then-jade-2.2.1.tgz",
638 | "dependencies": {
639 | "regenerator": {
640 | "version": "0.4.12",
641 | "from": "regenerator@>=0.4.0 <0.5.0",
642 | "resolved": "https://registry.npmjs.org/regenerator/-/regenerator-0.4.12.tgz",
643 | "dependencies": {
644 | "commander": {
645 | "version": "2.1.0",
646 | "from": "commander@2.1.0",
647 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.1.0.tgz"
648 | },
649 | "esprima": {
650 | "version": "1.1.0-dev-harmony",
651 | "from": "../../../../var/folders/sc/wwsv685s0zv1xnrkcnk05qv00000gn/T/npm-6989-afbd13f7/git-cache-e6749c1efa13/a41a40b49046747b3af57341cda048bbd3d9df79",
652 | "resolved": "git://github.com/ariya/esprima.git#a41a40b49046747b3af57341cda048bbd3d9df79"
653 | },
654 | "recast": {
655 | "version": "0.6.10",
656 | "from": "recast@>=0.6.5 <0.7.0",
657 | "resolved": "https://registry.npmjs.org/recast/-/recast-0.6.10.tgz",
658 | "dependencies": {
659 | "esprima": {
660 | "version": "1.1.0-dev-harmony",
661 | "from": "../../../../var/folders/sc/wwsv685s0zv1xnrkcnk05qv00000gn/T/npm-6989-afbd13f7/git-cache-20f8a2bf2fea/a41a40b49046747b3af57341cda048bbd3d9df79",
662 | "resolved": "git+https://github.com/ariya/esprima.git#a41a40b49046747b3af57341cda048bbd3d9df79"
663 | },
664 | "source-map": {
665 | "version": "0.1.32",
666 | "from": "source-map@0.1.32",
667 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.32.tgz",
668 | "dependencies": {
669 | "amdefine": {
670 | "version": "0.1.0",
671 | "from": "amdefine@>=0.0.4",
672 | "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz"
673 | }
674 | }
675 | },
676 | "cls": {
677 | "version": "0.1.5",
678 | "from": "cls@>=0.1.3 <0.2.0",
679 | "resolved": "https://registry.npmjs.org/cls/-/cls-0.1.5.tgz"
680 | },
681 | "ast-types": {
682 | "version": "0.4.13",
683 | "from": "ast-types@>=0.4.7 <0.5.0",
684 | "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.4.13.tgz",
685 | "dependencies": {
686 | "depd": {
687 | "version": "1.0.0",
688 | "from": "depd@>=1.0.0 <1.1.0",
689 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.0.0.tgz"
690 | }
691 | }
692 | }
693 | }
694 | },
695 | "private": {
696 | "version": "0.1.6",
697 | "from": "private@>=0.1.5 <0.2.0",
698 | "resolved": "https://registry.npmjs.org/private/-/private-0.1.6.tgz"
699 | },
700 | "defs": {
701 | "version": "0.6.2",
702 | "from": "defs@>=0.6.2 <0.7.0",
703 | "resolved": "https://registry.npmjs.org/defs/-/defs-0.6.2.tgz",
704 | "dependencies": {
705 | "alter": {
706 | "version": "0.2.0",
707 | "from": "alter@>=0.2.0 <0.3.0",
708 | "resolved": "https://registry.npmjs.org/alter/-/alter-0.2.0.tgz",
709 | "dependencies": {
710 | "stable": {
711 | "version": "0.1.5",
712 | "from": "stable@>=0.1.3 <0.2.0",
713 | "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.5.tgz"
714 | }
715 | }
716 | },
717 | "breakable": {
718 | "version": "0.1.0",
719 | "from": "breakable@>=0.1.0 <0.2.0",
720 | "resolved": "https://registry.npmjs.org/breakable/-/breakable-0.1.0.tgz"
721 | },
722 | "ast-traverse": {
723 | "version": "0.1.1",
724 | "from": "ast-traverse@>=0.1.1 <0.2.0",
725 | "resolved": "https://registry.npmjs.org/ast-traverse/-/ast-traverse-0.1.1.tgz"
726 | },
727 | "simple-fmt": {
728 | "version": "0.1.0",
729 | "from": "simple-fmt@>=0.1.0 <0.2.0",
730 | "resolved": "https://registry.npmjs.org/simple-fmt/-/simple-fmt-0.1.0.tgz"
731 | },
732 | "simple-is": {
733 | "version": "0.2.0",
734 | "from": "simple-is@>=0.2.0 <0.3.0",
735 | "resolved": "https://registry.npmjs.org/simple-is/-/simple-is-0.2.0.tgz"
736 | },
737 | "stringmap": {
738 | "version": "0.2.2",
739 | "from": "stringmap@>=0.2.2 <0.3.0",
740 | "resolved": "https://registry.npmjs.org/stringmap/-/stringmap-0.2.2.tgz"
741 | },
742 | "stringset": {
743 | "version": "0.2.1",
744 | "from": "stringset@>=0.2.1 <0.3.0",
745 | "resolved": "https://registry.npmjs.org/stringset/-/stringset-0.2.1.tgz"
746 | },
747 | "tryor": {
748 | "version": "0.1.2",
749 | "from": "tryor@>=0.1.2 <0.2.0",
750 | "resolved": "https://registry.npmjs.org/tryor/-/tryor-0.1.2.tgz"
751 | },
752 | "esprima": {
753 | "version": "1.0.4",
754 | "from": "esprima@>=1.0.0 <1.1.0",
755 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz"
756 | }
757 | }
758 | }
759 | }
760 | },
761 | "then-yield": {
762 | "version": "0.0.1",
763 | "from": "then-yield@0.0.1",
764 | "resolved": "https://registry.npmjs.org/then-yield/-/then-yield-0.0.1.tgz"
765 | },
766 | "barrage": {
767 | "version": "1.1.0",
768 | "from": "barrage@>=1.1.0 <1.2.0",
769 | "resolved": "https://registry.npmjs.org/barrage/-/barrage-1.1.0.tgz"
770 | },
771 | "promise": {
772 | "version": "6.0.1",
773 | "from": "promise@>=6.0.0 <6.1.0",
774 | "resolved": "https://registry.npmjs.org/promise/-/promise-6.0.1.tgz",
775 | "dependencies": {
776 | "asap": {
777 | "version": "1.0.0",
778 | "from": "asap@>=1.0.0 <1.1.0",
779 | "resolved": "https://registry.npmjs.org/asap/-/asap-1.0.0.tgz"
780 | }
781 | }
782 | },
783 | "with": {
784 | "version": "4.0.1",
785 | "from": "with@>=4.0.0 <4.1.0",
786 | "resolved": "https://registry.npmjs.org/with/-/with-4.0.1.tgz",
787 | "dependencies": {
788 | "acorn": {
789 | "version": "0.11.0",
790 | "from": "acorn@>=0.11.0 <0.12.0",
791 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-0.11.0.tgz"
792 | },
793 | "acorn-globals": {
794 | "version": "1.0.2",
795 | "from": "acorn-globals@>=1.0.1 <2.0.0",
796 | "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-1.0.2.tgz"
797 | }
798 | }
799 | },
800 | "jade": {
801 | "version": "1.3.0",
802 | "from": "jade@1.3.0",
803 | "resolved": "https://registry.npmjs.org/jade/-/jade-1.3.0.tgz",
804 | "dependencies": {
805 | "commander": {
806 | "version": "2.1.0",
807 | "from": "commander@2.1.0",
808 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.1.0.tgz"
809 | },
810 | "mkdirp": {
811 | "version": "0.3.5",
812 | "from": "mkdirp@>=0.3.5 <0.4.0",
813 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz"
814 | },
815 | "transformers": {
816 | "version": "2.1.0",
817 | "from": "transformers@2.1.0",
818 | "resolved": "https://registry.npmjs.org/transformers/-/transformers-2.1.0.tgz",
819 | "dependencies": {
820 | "promise": {
821 | "version": "2.0.0",
822 | "from": "promise@>=2.0.0 <2.1.0",
823 | "resolved": "https://registry.npmjs.org/promise/-/promise-2.0.0.tgz",
824 | "dependencies": {
825 | "is-promise": {
826 | "version": "1.0.1",
827 | "from": "is-promise@>=1.0.0 <2.0.0",
828 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-1.0.1.tgz"
829 | }
830 | }
831 | },
832 | "css": {
833 | "version": "1.0.8",
834 | "from": "css@>=1.0.8 <1.1.0",
835 | "resolved": "https://registry.npmjs.org/css/-/css-1.0.8.tgz",
836 | "dependencies": {
837 | "css-parse": {
838 | "version": "1.0.4",
839 | "from": "css-parse@1.0.4",
840 | "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-1.0.4.tgz"
841 | },
842 | "css-stringify": {
843 | "version": "1.0.5",
844 | "from": "css-stringify@1.0.5",
845 | "resolved": "https://registry.npmjs.org/css-stringify/-/css-stringify-1.0.5.tgz"
846 | }
847 | }
848 | },
849 | "uglify-js": {
850 | "version": "2.2.5",
851 | "from": "uglify-js@>=2.2.5 <2.3.0",
852 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.2.5.tgz",
853 | "dependencies": {
854 | "source-map": {
855 | "version": "0.1.43",
856 | "from": "source-map@>=0.1.7 <0.2.0",
857 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz",
858 | "dependencies": {
859 | "amdefine": {
860 | "version": "0.1.0",
861 | "from": "amdefine@>=0.0.4",
862 | "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz"
863 | }
864 | }
865 | },
866 | "optimist": {
867 | "version": "0.3.7",
868 | "from": "optimist@>=0.3.5 <0.4.0",
869 | "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz",
870 | "dependencies": {
871 | "wordwrap": {
872 | "version": "0.0.2",
873 | "from": "wordwrap@>=0.0.2 <0.1.0",
874 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz"
875 | }
876 | }
877 | }
878 | }
879 | }
880 | }
881 | },
882 | "character-parser": {
883 | "version": "1.2.0",
884 | "from": "character-parser@1.2.0",
885 | "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-1.2.0.tgz"
886 | },
887 | "monocle": {
888 | "version": "1.1.51",
889 | "from": "monocle@1.1.51",
890 | "resolved": "https://registry.npmjs.org/monocle/-/monocle-1.1.51.tgz",
891 | "dependencies": {
892 | "readdirp": {
893 | "version": "0.2.5",
894 | "from": "readdirp@>=0.2.3 <0.3.0",
895 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-0.2.5.tgz",
896 | "dependencies": {
897 | "minimatch": {
898 | "version": "2.0.4",
899 | "from": "minimatch@>=0.2.4",
900 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.4.tgz",
901 | "dependencies": {
902 | "brace-expansion": {
903 | "version": "1.1.0",
904 | "from": "brace-expansion@>=1.0.0 <2.0.0",
905 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.0.tgz",
906 | "dependencies": {
907 | "balanced-match": {
908 | "version": "0.2.0",
909 | "from": "balanced-match@>=0.2.0 <0.3.0",
910 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.0.tgz"
911 | },
912 | "concat-map": {
913 | "version": "0.0.1",
914 | "from": "concat-map@0.0.1",
915 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
916 | }
917 | }
918 | }
919 | }
920 | }
921 | }
922 | }
923 | }
924 | },
925 | "with": {
926 | "version": "3.0.1",
927 | "from": "with@>=3.0.0 <3.1.0",
928 | "resolved": "https://registry.npmjs.org/with/-/with-3.0.1.tgz",
929 | "dependencies": {
930 | "uglify-js": {
931 | "version": "2.4.17",
932 | "from": "uglify-js@>=2.4.12 <2.5.0",
933 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.17.tgz",
934 | "dependencies": {
935 | "async": {
936 | "version": "0.2.10",
937 | "from": "async@>=0.2.6 <0.3.0",
938 | "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz"
939 | },
940 | "source-map": {
941 | "version": "0.1.34",
942 | "from": "source-map@0.1.34",
943 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.34.tgz",
944 | "dependencies": {
945 | "amdefine": {
946 | "version": "0.1.0",
947 | "from": "amdefine@>=0.0.4",
948 | "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz"
949 | }
950 | }
951 | },
952 | "yargs": {
953 | "version": "1.3.3",
954 | "from": "yargs@>=1.3.3 <1.4.0",
955 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-1.3.3.tgz"
956 | },
957 | "uglify-to-browserify": {
958 | "version": "1.0.2",
959 | "from": "uglify-to-browserify@>=1.0.0 <1.1.0",
960 | "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz"
961 | }
962 | }
963 | }
964 | }
965 | },
966 | "constantinople": {
967 | "version": "2.0.1",
968 | "from": "constantinople@>=2.0.0 <2.1.0",
969 | "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-2.0.1.tgz",
970 | "dependencies": {
971 | "uglify-js": {
972 | "version": "2.4.17",
973 | "from": "uglify-js@>=2.4.12 <2.5.0",
974 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.17.tgz",
975 | "dependencies": {
976 | "async": {
977 | "version": "0.2.10",
978 | "from": "async@>=0.2.6 <0.3.0",
979 | "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz"
980 | },
981 | "source-map": {
982 | "version": "0.1.34",
983 | "from": "source-map@0.1.34",
984 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.34.tgz",
985 | "dependencies": {
986 | "amdefine": {
987 | "version": "0.1.0",
988 | "from": "amdefine@>=0.0.4",
989 | "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz"
990 | }
991 | }
992 | },
993 | "yargs": {
994 | "version": "1.3.3",
995 | "from": "yargs@>=1.3.3 <1.4.0",
996 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-1.3.3.tgz"
997 | },
998 | "uglify-to-browserify": {
999 | "version": "1.0.2",
1000 | "from": "uglify-to-browserify@>=1.0.0 <1.1.0",
1001 | "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz"
1002 | }
1003 | }
1004 | }
1005 | }
1006 | }
1007 | }
1008 | }
1009 | }
1010 | }
1011 | }
1012 | }
1013 |
--------------------------------------------------------------------------------