Merge branch 'master' into raf

This commit is contained in:
Yoshua Wuyts
2016-07-12 17:51:44 +02:00
committed by GitHub
10 changed files with 236 additions and 32 deletions
+5 -4
View File
@@ -1,10 +1,11 @@
node_modules/ node_modules/
coverage/ coverage/
coverage.json dist/
tmp/ tmp/
npm-debug.log*
.DS_Store
.sauce-credentials.json .sauce-credentials.json
*.swp
sauce_connect.log sauce_connect.log
npm-debug.log*
coverage.json
.DS_Store
*.swp
.zuulrc .zuulrc
+33 -16
View File
@@ -43,11 +43,6 @@
<img src="https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square" <img src="https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square"
alt="Standard" /> alt="Standard" />
</a> </a>
<!-- IRC -->
<a href="https://webchat.freenode.net/?channels=choo">
<img src="https://img.shields.io/badge/irc-freenode-blue.svg?style=flat-square"
alt="IRC - Freenode" />
</a>
</div> </div>
<div align="center"> <div align="center">
@@ -55,12 +50,16 @@
<a href="https://github.com/yoshuawuyts/choo-handbook"> <a href="https://github.com/yoshuawuyts/choo-handbook">
Handbook Handbook
</a> </a>
<span>|</span> <span> | </span>
Packages Packages
<span>|</span> <span> | </span>
<a href="https://github.com/yoshuawuyts/choo/blob/master/.github/CONTRIBUTING.md"> <a href="https://github.com/yoshuawuyts/choo/blob/master/.github/CONTRIBUTING.md">
Contributing Contributing
</a> </a>
<span> | </span>
<a href="https://webchat.freenode.net/?channels=choo">
Chat
</a>
</h3> </h3>
</div> </div>
@@ -80,6 +79,7 @@
<li><a href="#example">Example</a></li> <li><a href="#example">Example</a></li>
<li><a href="#philosophy">Philosophy</a></li> <li><a href="#philosophy">Philosophy</a></li>
<li><a href="#concepts">Concepts</a></li> <li><a href="#concepts">Concepts</a></li>
<li><a href="#badges">Badges</a></li>
<li><a href="#api">API</a></li> <li><a href="#api">API</a></li>
<li><a href="#faq">FAQ</a></li> <li><a href="#faq">FAQ</a></li>
<li><a href="#installation">Installation</a></li> <li><a href="#installation">Installation</a></li>
@@ -148,7 +148,7 @@ To run it, save it as `client.js` and run with [budo][budo] and
[es2020][es2020]. These tools are convenient but any [browserify][browserify] [es2020][es2020]. These tools are convenient but any [browserify][browserify]
based tool should do: based tool should do:
```sh ```sh
$ budo 'client.js' -p 8080 --open -- -t es2020 $ budo client.js -p 8080 --open -- -t es2020
``` ```
And to save the output to files so it can be deployed, open a new terminal and And to save the output to files so it can be deployed, open a new terminal and
@@ -236,17 +236,17 @@ namespaced or not. Namespacing means that only state within the model can be
accessed. Models can still trigger actions on other models, though it's accessed. Models can still trigger actions on other models, though it's
recommended to keep that to a minimum. recommended to keep that to a minimum.
So say we have a `myTodos` namespace, an `add` reducer and a `todos` model. So say we have a `todos` namespace, an `add` reducer and a `todos` model.
Outside the model they're called by `send('todos:add')` and Outside the model they're called by `send('todos:add')` and
`state.todos.todos`. Inside the namespaced model they're called by `state.todos.items`. Inside the namespaced model they're called by
`send('todos:add')` and `state.todos`. An example namespaced model: `send('todos:add')` and `state.items`. An example namespaced model:
```js ```js
const app = choo() const app = choo()
app.model({ app.model({
namespace: 'myTodos', namespace: 'todos',
state: { todos: [] }, state: { items: [] },
reducers: { reducers: {
add: (data, state) => ({ todos: state.todos.concat(data.payload) }) add: (data, state) => ({ items: state.items.concat(data.payload) })
} }
}) })
``` ```
@@ -302,7 +302,11 @@ app.model({
namespace: 'app', namespace: 'app',
subscriptions: [ subscriptions: [
(send, done) => { (send, done) => {
setInterval(() => send('app:print', { payload: 'dog?' }), 1000) setInterval(() => {
send('app:print', { payload: 'dog?', myOtherValue: 1000 }, (err) => {
if (err) return done(err)
})
}, 1000)
} }
], ],
effects: { effects: {
@@ -357,6 +361,15 @@ const view = (state, prev, send) => {
``` ```
In this example, when the `Add` button is clicked, the view will dispatch an `add` action that the models `add` reducer will receive. [As seen above](#models), the reducer will add an item to the states `todos` array. The state change will cause this view to be run again with the new state, and the resulting DOM tree will be used to [efficiently patch the DOM](#does-choo-use-a-virtual-dom). In this example, when the `Add` button is clicked, the view will dispatch an `add` action that the models `add` reducer will receive. [As seen above](#models), the reducer will add an item to the states `todos` array. The state change will cause this view to be run again with the new state, and the resulting DOM tree will be used to [efficiently patch the DOM](#does-choo-use-a-virtual-dom).
## Badges
Using `choo` in a project? Show off which version you've used using a badge:
[![built with choo v3](https://img.shields.io/badge/built%20with%20choo-v3-ffc3e4.svg?style=flat-square)](https://github.com/yoshuawuyts/choo)
```md
[![built with choo v3](https://img.shields.io/badge/built%20with%20choo-v3-ffc3e4.svg?style=flat-square)](https://github.com/yoshuawuyts/choo)
```
## API ## API
This section provides documentation on how each function in `choo` works. It's This section provides documentation on how each function in `choo` works. It's
intended to be a technical reference. If you're interested in learning choo for intended to be a technical reference. If you're interested in learning choo for
@@ -399,11 +412,13 @@ arguments:
- __subscriptions:__ asynchronous read-only operations that don't modify state - __subscriptions:__ asynchronous read-only operations that don't modify state
directly. Can call `actions`. Signature of `(send, done)`. directly. Can call `actions`. Signature of `(send, done)`.
#### send(actionName, data?) #### send(actionName, data?[,callback])
Send a new action to the models with optional data attached. Namespaced models Send a new action to the models with optional data attached. Namespaced models
can be accessed by prefixing the name with the namespace separated with a `:`, can be accessed by prefixing the name with the namespace separated with a `:`,
e.g. `namespace:name`. e.g. `namespace:name`.
When sending data from inside a `model` it expects exactly three arguments: the name of the action you're calling, the data you want to send, and finally a callback to handle errors through the global `onError()` hook. So if you want to send two values, you'd have to either send an array or object containing them.
#### done(err?, res?) #### done(err?, res?)
When an `effect` or `subscription` is done executing, or encounters an error, When an `effect` or `subscription` is done executing, or encounters an error,
it should call the final `done(err, res)` callback. If an `effect` was called it should call the final `done(err, res)` callback. If an `effect` was called
@@ -624,6 +639,8 @@ $ npm install choo
## See Also ## See Also
- [choo-handbook](https://github.com/yoshuawuyts/choo-handbook) - the little - [choo-handbook](https://github.com/yoshuawuyts/choo-handbook) - the little
`choo` guide `choo` guide
- [awesome-choo](https://github.com/YerkoPalma/awesome-choo) - Awesome things
related with choo framework
- [budo](https://github.com/mattdesl/budo) - quick prototyping tool for - [budo](https://github.com/mattdesl/budo) - quick prototyping tool for
`browserify` `browserify`
- [stack.gl](http://stack.gl/) - open software ecosystem for WebGL - [stack.gl](http://stack.gl/) - open software ecosystem for WebGL
+1
View File
@@ -11,6 +11,7 @@
"dependencies": { "dependencies": {
"css-wipe": "^4.2.1", "css-wipe": "^4.2.1",
"dateformat": "^1.0.12", "dateformat": "^1.0.12",
"pathname-match": "^1.1.3",
"tachyons": "^4.0.0-beta.33" "tachyons": "^4.0.0-beta.33"
}, },
"devDependencies": { "devDependencies": {
+42
View File
@@ -0,0 +1,42 @@
<html>
<head>
<title>Vanilla example</title>
</head>
<body>
<script src="../../dist/choo.min.js"></script>
<script>
const app = choo()
app.model({
namespace: 'counter',
state: {
count: 0
},
reducers: {
increment: (action, state) => ({count: state.count + 1}),
decrement: (action, state) => ({count: state.count - 1})
}
})
const mainView = (params, state, send) => {
return choo.view`
<main class="app">
<h1>Counter example</h1>
<div>
Count: ${state.counter.count}
<button onclick=${(e) => send('counter:increment')}>+</button>
<button onclick=${(e) => send('counter:decrement')}>-</button>
</div>
</main>
`
}
app.router((route) => [
route('/', mainView)
])
const tree = app.start()
document.body.appendChild(tree)
</script>
</body>
</html>
+1 -1
View File
@@ -124,7 +124,7 @@ function choo (opts) {
} }
function wrap (child, route) { function wrap (child, route) {
const send = createSend(route, true) const send = createSend('view: ' + route, true)
return function chooWrap (params, state) { return function chooWrap (params, state) {
const nwPrev = prev const nwPrev = prev
const nwState = prev = xtend(state, { params: params }) const nwState = prev = xtend(state, { params: params })
+20 -8
View File
@@ -1,17 +1,20 @@
{ {
"name": "choo", "name": "choo",
"version": "3.0.1", "version": "3.0.2",
"description": "A 5kb framework for creating sturdy frontend applications", "description": "A 5kb framework for creating sturdy frontend applications",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"deps": "dependency-check . && dependency-check . --extra --no-dev -i xhr", "deps": "./scripts/test deps",
"test:electron": "browserify tests/**/*.js -t es2020 -p proxyquire-universal | tape-run", "test:electron": "./scripts/test electron",
"test:cov": "browserify tests/**/*.js -t es2020 -p proxyquire-universal -p tape-istanbul/plugin | tape-run | tape-istanbul && istanbul report", "test:cov": "./scripts/test cov",
"test:server": "standard && npm run deps && NODE_ENV=test node tests/server/*", "test:server": "./scripts/test server",
"test:browser": "standard && npm run deps && NODE_ENV=test zuul tests/browser/*", "test:browser": "./scripts/test browser",
"test:browser:local": "standard && npm run deps && NODE_ENV=test zuul --local 8080 -- tests/browser/*", "test:browser-local": "./scripts/test browser-local",
"preversion": "if [ ! -z $SKIP_TEST ]; then npm run test:browser; fi", "preversion": "if [ ! -z $SKIP_TEST ]; then npm run test:browser; fi",
"test": "npm run test:electron" "test": "npm run test:electron",
"build:dev": "./scripts/build dev",
"build:min": "./scripts/build min",
"prepublish": "npm run build:dev && npm run build:min"
}, },
"repository": "yoshuawuyts/choo", "repository": "yoshuawuyts/choo",
"keywords": [ "keywords": [
@@ -22,6 +25,11 @@
"composable", "composable",
"tiny" "tiny"
], ],
"files": [
"index.js",
"http.js",
"dist"
],
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"barracks": "^8.0.0", "barracks": "^8.0.0",
@@ -41,6 +49,7 @@
"browserify-istanbul": "^2.0.0", "browserify-istanbul": "^2.0.0",
"bundle-collapser": "^1.2.1", "bundle-collapser": "^1.2.1",
"dependency-check": "^2.5.1", "dependency-check": "^2.5.1",
"envify": "^3.4.1",
"es2020": "^1.0.1", "es2020": "^1.0.1",
"geval": "~2.1.1", "geval": "~2.1.1",
"insert-css": "^0.2.0", "insert-css": "^0.2.0",
@@ -57,6 +66,9 @@
"tape": "^4.5.1", "tape": "^4.5.1",
"tape-istanbul": "~1.0.2", "tape-istanbul": "~1.0.2",
"tape-run": "~2.1.4", "tape-run": "~2.1.4",
"uglifyify": "^3.0.2",
"uglifyjs": "^2.4.10",
"unassertify": "^2.0.3",
"yo-yoify": "^3.1.0", "yo-yoify": "^3.1.0",
"zuul": "toddself/zuul" "zuul": "toddself/zuul"
} }
Executable
+44
View File
@@ -0,0 +1,44 @@
#!/bin/sh
dirname=$(dirname "$(readlink -f "$0")")
browserify="$dirname/../node_modules/.bin/browserify"
uglify="$dirname/../node_modules/.bin/uglifyjs"
usage () {
printf "Usage: build-umd <argument>\n"
}
build_dev () {
mkdir -p dist/
NODE_ENV=development "$browserify" index.js \
--standalone=choo \
-t envify \
> dist/choo.js
}
build_min () {
mkdir -p dist/
NODE_ENV=production "$browserify" index.js \
--standalone=choo \
-t envify \
-g unassertify \
-g uglifyify \
| "$uglify" \
> dist/choo.min.js
}
# parse CLI flags
while true; do
case "$1" in
-h|--help) usage && exit 1 ;;
-- ) shift; break ;;
* ) break ;;
esac
done
case "$1" in
d|dev) shift; build_dev "$@" ;;
m|min) shift; build_min "$@" ;;
*) shift; build_min "$@" ;;
esac
+3 -1
View File
@@ -48,7 +48,9 @@ run_discify () {
getopt -T > /dev/null getopt -T > /dev/null
if [ "$?" -eq 4 ]; then if [ "$?" -eq 4 ]; then
args="$(getopt --long help discify minified --options hmdg -- "$*")" args="$(getopt --long help discify minified --options hmdg -- "$*")"
else args="$(getopt h "$*")"; fi else
args="$(getopt h "$*")";
fi
[ ! $? -eq 0 ] && { usage && exit 2; } [ ! $? -eq 0 ] && { usage && exit 2; }
eval set -- "$args" eval set -- "$args"
Executable
+85
View File
@@ -0,0 +1,85 @@
#!/bin/sh
# setting exit because we're linting and need to exit on failure
set -e
dirname=$(dirname "$(readlink -f "$0")")
dependency_check="$dirname/../node_modules/.bin/dependency-check"
tape_istanbul="$dirname/../node_modules/.bin/tape-istanbul"
browserify="$dirname/../node_modules/.bin/browserify"
standard="$dirname/../node_modules/.bin/standard"
tape_run="$dirname/../node_modules/.bin/tape-run"
istanbul="$dirname/../node_modules/.bin/istanbul"
zuul="$dirname/../node_modules/.bin/zuul"
usage () {
printf "Usage: test\n"
}
lint () {
"$standard"
}
test_electron () {
check_deps
lint
"$browserify" tests/**/*.js \
-t es2020 \
-p proxyquire-universal \
| "$tape_run"
}
test_cov () {
check_deps
lint
"$browserify" tests/**/*.js \
-t es2020 \
-p proxyquire-universal \
-p tape-istanbul/plugin \
| "$tape_run" \
| "$tape_istanbul" \
&& "$istanbul" report
}
test_server () {
lint
standard
check_deps
NODE_ENV=test node tests/server/*
}
test_browser () {
NODE_ENV=test "$zuul" tests/browser/*
}
test_browser_local () {
lint
check_deps
NODE_ENV=test "$zuul" --local 8080 -- tests/browser/*
}
check_deps () {
"$dependency_check" . --entry 'index.js'
"$dependency_check" . --entry 'index.js' --extra --no-dev \
-i xhr
}
# set CLI flags
# parse CLI flags
while true; do
case "$1" in
-h|--help) usage && exit 1 ;;
-- ) shift; break ;;
* ) break ;;
esac
done
case "$1" in
e|electron) shift; test_electron "$@" && exit ;;
b|browser) shift; test_browser "$@" && exit ;;
l|browser-local) shift; test_browser_local "$@" && exit ;;
s|server) shift; test_server "$@" && exit ;;
c|cov) shift; test_cov "$@" && exit ;;
d|deps) shift; check_deps "$@" && exit ;;
esac
+1 -1
View File
@@ -15,7 +15,7 @@ test('hooks', function (t) {
t.deepEqual(action, {foo: 'bar'}, 'onAction: action data') t.deepEqual(action, {foo: 'bar'}, 'onAction: action data')
t.equal(state.clicks, 0, 'onAction: current state: 0 clicks') t.equal(state.clicks, 0, 'onAction: current state: 0 clicks')
t.equal(name, 'click', 'onAction: action name') t.equal(name, 'click', 'onAction: action name')
t.equal(caller, '/', 'onAction: caller name') t.equal(caller, 'view: /', 'onAction: caller name')
t.equal(typeof createSend, 'function', 'onAction: createSend fn') t.equal(typeof createSend, 'function', 'onAction: createSend fn')
}, },
onStateChange: function (action, state, prev, createSend) { onStateChange: function (action, state, prev, createSend) {