Skip to content

Commit 40f4b45

Browse files
committed
Merge remote-tracking branch 'upstream/master' into init-stores-with-state
* upstream/master: 6.12.1 6.12.0 typings: add app to app.use cb (#665) update dependencies (#663) ci: Node 7 → Node 10 (#661) Update bel and yo-yoify references in docs to nanohtml. (#660) Build for UMD (#617) 6.11.0 Use nanoassert in the browser (#651) Switch to nanohtml (#644) v6.11.0-preview1 choo components (#639)
2 parents 44d3b9c + c3a6401 commit 40f4b45

File tree

23 files changed

+433
-277
lines changed

23 files changed

+433
-277
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
node_js:
22
- '6'
3-
- '7'
43
- '8'
4+
- '10'
55
sudo: false
66
language: node_js
77
env:

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -382,9 +382,9 @@ We use the `require('assert')` module from Node core to provide helpful error
382382
messages in development. In production you probably want to strip this using
383383
[unassertify][unassertify].
384384

385-
To convert inlined HTML to valid DOM nodes we use `require('bel')`. This has
385+
To convert inlined HTML to valid DOM nodes we use `require('nanohtml')`. This has
386386
overhead during runtime, so for production environments we should unwrap this
387-
using [yo-yoify][yo-yoify].
387+
using the [nanohtml transform][nanohtml].
388388

389389
Setting up browserify transforms can sometimes be a bit of hassle; to make this
390390
more convenient we recommend using [bankai build][bankai] to build your assets for production.
@@ -414,9 +414,9 @@ answer short: we're using something even better.
414414
### How can I support older browsers?
415415
Template strings aren't supported in all browsers, and parsing them creates
416416
significant overhead. To optimize we recommend running `browserify` with
417-
[yo-yoify][yo-yoify] as a global transform or using [bankai][bankai] directly.
417+
[nanohtml][nanohtml] as a global transform or using [bankai][bankai] directly.
418418
```sh
419-
$ browserify -g yo-yoify
419+
$ browserify -g nanohtml
420420
```
421421

422422
### Is choo production ready?
@@ -479,11 +479,11 @@ Render the application to a string. Useful for rendering on the server.
479479

480480
### `choo/html`
481481
Create DOM nodes from template string literals. Exposes
482-
[bel](https://github.com/shama/bel). Can be optimized using
483-
[yo-yoify][yo-yoify].
482+
[nanohtml](https://github.com/choojs/nanohtml). Can be optimized using
483+
[nanohtml][nanohtml].
484484

485485
### `choo/html/raw`
486-
Exposes [bel/raw](https://github.com/shama/bel#unescaping) helper for rendering raw HTML content.
486+
Exposes [nanohtml/raw](https://github.com/shama/nanohtml#unescaping) helper for rendering raw HTML content.
487487

488488
## Installation
489489
```sh
@@ -585,6 +585,7 @@ Become a backer, and buy us a coffee (or perhaps lunch?) every month or so.
585585

586586
[bankai]: https://github.com/choojs/bankai
587587
[bel]: https://github.com/shama/bel
588+
[nanohtml]: https://github.com/choojs/nanohtml
588589
[browserify]: https://github.com/substack/node-browserify
589590
[budo]: https://github.com/mattdesl/budo
590591
[es2020]: https://github.com/yoshuawuyts/es2020
@@ -594,6 +595,5 @@ Become a backer, and buy us a coffee (or perhaps lunch?) every month or so.
594595
[nanomorph]: https://github.com/choojs/nanomorph
595596
[nanorouter]: https://github.com/choojs/nanorouter
596597
[yo-yo]: https://github.com/maxogden/yo-yo
597-
[yo-yoify]: https://github.com/shama/yo-yoify
598598
[unassertify]: https://github.com/unassert-js/unassertify
599599
[window-performance]: https://developer.mozilla.org/en-US/docs/Web/API/Performance

component/cache.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
var assert = require('assert')
2+
var LRU = require('nanolru')
3+
4+
module.exports = ChooComponentCache
5+
6+
function ChooComponentCache (state, emit, lru) {
7+
assert.ok(this instanceof ChooComponentCache, 'ChooComponentCache should be created with `new`')
8+
9+
assert.equal(typeof state, 'object', 'ChooComponentCache: state should be type object')
10+
assert.equal(typeof emit, 'function', 'ChooComponentCache: emit should be type function')
11+
12+
if (typeof lru === 'number') this.cache = new LRU(lru)
13+
else this.cache = lru || new LRU(100)
14+
this.state = state
15+
this.emit = emit
16+
}
17+
18+
// Get & create component instances.
19+
ChooComponentCache.prototype.render = function (Component, id) {
20+
assert.equal(typeof Component, 'function', 'ChooComponentCache.render: Component should be type function')
21+
assert.ok(typeof id === 'string' || typeof id === 'number', 'ChooComponentCache.render: id should be type string or type number')
22+
23+
var el = this.cache.get(id)
24+
if (!el) {
25+
var args = []
26+
for (var i = 2, len = arguments.length; i < len; i++) {
27+
args.push(arguments[i])
28+
}
29+
args.unshift(Component, id, this.state, this.emit)
30+
el = newCall.apply(newCall, args)
31+
this.cache.set(id, el)
32+
}
33+
34+
return el
35+
}
36+
37+
// Because you can't call `new` and `.apply()` at the same time. This is a mad
38+
// hack, but hey it works so we gonna go for it. Whoop.
39+
function newCall (Cls) {
40+
return new (Cls.bind.apply(Cls, arguments)) // eslint-disable-line
41+
}

component/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = require('nanocomponent')
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
var html = require('bel')
2+
3+
module.exports = deleteCompleted
4+
5+
function deleteCompleted (emit) {
6+
return html`
7+
<button class="clear-completed" onclick=${deleteAllCompleted}>
8+
Clear completed
9+
</button>
10+
`
11+
12+
function deleteAllCompleted () {
13+
emit('todos:deleteCompleted')
14+
}
15+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
var html = require('bel')
2+
3+
module.exports = filterButton
4+
5+
function filterButton (name, filter, currentFilter, emit) {
6+
var filterClass = filter === currentFilter
7+
? 'selected'
8+
: ''
9+
10+
var uri = '#' + name.toLowerCase()
11+
if (uri === '#all') uri = '/'
12+
13+
return html`<li>
14+
<a href=${uri} class=${filterClass}>
15+
${name}
16+
</a>
17+
</li>`
18+
}

example/components/footer/index.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
var Component = require('../../../component')
2+
var html = require('bel')
3+
4+
var clearButton = require('./clear-button')
5+
var filterButton = require('./filter-button')
6+
7+
module.exports = class Footer extends Component {
8+
constructor (name, state, emit) {
9+
super(name)
10+
this.state = state
11+
this.emit = emit
12+
13+
this.local = this.state.components.footer = {}
14+
this.setState()
15+
}
16+
17+
setState () {
18+
this.local.rawTodos = this.state.todos.clock
19+
this.local.rawHref = this.state.href
20+
21+
this.local.filter = this.state.href.replace(/^\//, '') || ''
22+
this.local.activeCount = this.state.todos.active.length
23+
this.local.hasDone = this.state.todos.done.length || null
24+
}
25+
26+
update () {
27+
if (this.local.rawTodos !== this.state.todos.clock ||
28+
this.local.rawHref !== this.state.href) {
29+
this.setState()
30+
return true
31+
} else {
32+
return false
33+
}
34+
}
35+
36+
createElement () {
37+
return html`<footer class="footer">
38+
<span class="todo-count">
39+
<strong>${this.local.activeCount}</strong>
40+
item${this.state.todos.all === 1 ? '' : 's'} left
41+
</span>
42+
<ul class="filters">
43+
${filterButton('All', '', this.local.filter, this.emit)}
44+
${filterButton('Active', 'active', this.local.filter, this.emit)}
45+
${filterButton('Completed', 'completed', this.local.filter, this.emit)}
46+
</ul>
47+
${this.local.hasDone && clearButton(this.emit)}
48+
</footer>`
49+
}
50+
}

example/components/header.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
var Component = require('../../component')
2+
var html = require('bel')
3+
4+
module.exports = class Header extends Component {
5+
constructor (name, state, emit) {
6+
super(name)
7+
this.state = state
8+
this.emit = emit
9+
}
10+
11+
update () {
12+
return false
13+
}
14+
15+
createElement () {
16+
return html`<header class="header">
17+
<h1>todos</h1>
18+
<input class="new-todo"
19+
autofocus
20+
placeholder="What needs to be done?"
21+
onkeydown=${this.createTodo.bind(this)} />
22+
</header>`
23+
}
24+
25+
createTodo (e) {
26+
var value = e.target.value
27+
if (e.keyCode === 13) {
28+
e.target.value = ''
29+
this.emit('todos:create', value)
30+
}
31+
}
32+
}

example/components/info.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
var Component = require('../../component')
2+
var html = require('bel')
3+
4+
module.exports = class Info extends Component {
5+
update () {
6+
return false
7+
}
8+
9+
createElement () {
10+
return html`<footer class="info">
11+
<p>Double-click to edit a todo</p>
12+
<p>choo by <a href="https://yoshuawuyts.com/">Yoshua Wuyts</a></p>
13+
<p>Created by <a href="http://shuheikagawa.com">Shuhei Kagawa</a></p>
14+
</footer>`
15+
}
16+
}

example/components/todos/index.js

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
var Component = require('../../../component')
2+
var html = require('bel')
3+
4+
var Todo = require('./todo')
5+
6+
module.exports = class Header extends Component {
7+
constructor (name, state, emit) {
8+
super(name)
9+
this.state = state
10+
this.emit = emit
11+
this.local = this.state.components[name] = {}
12+
this.setState()
13+
}
14+
15+
setState () {
16+
this.local.rawTodos = this.state.todos.clock
17+
this.local.rawHref = this.state.href
18+
19+
this.local.allDone = this.state.todos.done.length === this.state.todos.all.length
20+
this.local.filter = this.state.href.replace(/^\//, '') || ''
21+
this.local.todos = this.local.filter === 'completed'
22+
? this.state.todos.done
23+
: this.local.filter === 'active'
24+
? this.state.todos.active
25+
: this.state.todos.all
26+
}
27+
28+
update () {
29+
if (this.local.rawTodos !== this.state.todos.clock ||
30+
this.local.rawHref !== this.state.href) {
31+
this.setState()
32+
return true
33+
} else {
34+
return false
35+
}
36+
}
37+
38+
createElement () {
39+
return html`<section class="main">
40+
<input
41+
class="toggle-all"
42+
type="checkbox"
43+
checked=${this.local.allDone}
44+
onchange=${() => this.toggleAll()}/>
45+
<label for="toggle-all" style="display: none;">
46+
Mark all as done
47+
</label>
48+
<ul class="todo-list">
49+
${this.local.todos.map(todo => Todo(todo, this.emit))}
50+
</ul>
51+
</section>`
52+
}
53+
54+
createTodo (e) {
55+
var value = e.target.value
56+
if (e.keyCode === 13) {
57+
e.target.value = ''
58+
this.emit('todos:create', value)
59+
}
60+
}
61+
62+
toggleAll () {
63+
this.emit('todos:toggleAll')
64+
}
65+
}

0 commit comments

Comments
 (0)