Skip to content

Commit 33aa1fa

Browse files
committed
docs: merge docs from next to master
1 parent 2a61e17 commit 33aa1fa

19 files changed

+285
-72
lines changed

Diff for: docs/CNAME

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
mithril.js.org

Diff for: docs/change-log.md

+62-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,38 @@
11
# Change log
22

3+
- [v1.0.2](#v101)
4+
- [v1.0.1](#v101)
35
- [Migrating from v0.2.x](#migrating-from-v02x)
4-
- [Older docs](http://mithril.js.org/archive/v0.2.5/change-log.html)
6+
- [Older docs](http://mithril.js.org/archive/v0.2.5/index.html)
7+
8+
---
9+
10+
### v1.0.2
11+
12+
#### News
13+
14+
- support for ES6 class components
15+
- updated typescript definitions
16+
17+
#### Bug fixes
18+
19+
- fix IE11 input[type] error - [#1610](https://github.com/lhorie/mithril.js/issues/1610)
20+
- apply [#1609](https://github.com/lhorie/mithril.js/issues/1609) to unkeyed children case
21+
- fix abort detection [#1612](https://github.com/lhorie/mithril.js/issues/1612)
22+
- fix input value focus issue when value is loosely equal to old value [#1593](https://github.com/lhorie/mithril.js/issues/1593)
23+
24+
---
25+
26+
### v1.0.1
27+
28+
#### News
29+
30+
- performance improvements in IE [#1598](https://github.com/lhorie/mithril.js/pull/1598)
31+
32+
#### Bug fixes
33+
34+
- prevent infinite loop in non-existent default route - [#1579](https://github.com/lhorie/mithril.js/issues/1579)
35+
- call correct lifecycle methods on children of recycled keyed vnodes - [#1609](https://github.com/lhorie/mithril.js/issues/1609)
536

637
---
738

@@ -28,6 +59,7 @@ If you are migrating, consider using the [mithril-codemods](https://www.npmjs.co
2859
- [`m.route` and anchor tags](#mroute-and-anchor-tags)
2960
- [Reading/writing the current route](#readingwriting-the-current-route)
3061
- [Accessing route params](#accessing-route-params)
62+
- [Building/Parsing query strings](#buildingparsing-query-strings)
3163
- [Preventing unmounting](#preventing-unmounting)
3264
- [Run code on component removal](#run-code-on-component-removal)
3365
- [`m.request`](#mrequest)
@@ -459,6 +491,28 @@ m.route(document.body, "/booga", {
459491

460492
---
461493

494+
## Building/Parsing query strings
495+
496+
`v0.2.x` used methods hanging off of `m.route`, `m.route.buildQueryString()` and `m.route.parseQueryString()`. In `v1.x` these have been broken out and attached to the root `m`.
497+
498+
### `v0.2.x`
499+
500+
```javascript
501+
var qs = m.route.buildQueryString({ a : 1 });
502+
503+
var obj = m.route.parseQueryString("a=1");
504+
```
505+
506+
### `v1.x`
507+
508+
```javascript
509+
var qs = m.buildQueryString({ a : 1 });
510+
511+
var obj = m.parseQueryString("a=1");
512+
```
513+
514+
---
515+
462516
## Preventing unmounting
463517

464518
It is no longer possible to prevent unmounting via `onunload`'s `e.preventDefault()`. Instead you should explicitly call `m.route.set` when the expected conditions are met.
@@ -588,11 +642,13 @@ greetAsync()
588642
### `v1.x`
589643

590644
```javascript
591-
var greetAsync = new Promise(function(resolve){
592-
setTimeout(function() {
593-
resolve("hello")
594-
}, 1000)
595-
})
645+
var greetAsync = function() {
646+
return new Promise(function(resolve){
647+
setTimeout(function() {
648+
resolve("hello")
649+
}, 1000)
650+
})
651+
}
596652

597653
greetAsync()
598654
.then(function(value) {return value + " world"})

Diff for: docs/components.md

+40-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
- [Structure](#structure)
44
- [Lifecycle methods](#lifecycle-methods)
55
- [State](#state)
6+
- [ES6 classes](#es6-classes)
67
- [Avoid-anti-patterns](#avoid-anti-patterns)
78

89
### Structure
@@ -108,7 +109,7 @@ The state of a component can be accessed three ways: as a blueprint at initializ
108109

109110
#### At initialization
110111

111-
Any property attached to the component object is copied for every instance of the component. This allows simple state initialization.
112+
The component object is the prototype of each component instance, so any property defined on the component object will be accessible as a property of `vnode.state`. This allows simple state initialization.
112113

113114
In the example below, `data` is a property of the `ComponentWithInitialState` component's state object.
114115

@@ -170,6 +171,44 @@ Be aware that when using ES5 functions, the value of `this` in nested anonymous
170171

171172
---
172173

174+
### ES6 classes
175+
176+
Components can also be written using ES6 class syntax:
177+
178+
```javascript
179+
class ES6ClassComponent {
180+
view() {
181+
return m("div", "Hello from an ES6 class")
182+
}
183+
}
184+
```
185+
186+
They can be consumed in the same way regular components can.
187+
188+
```javascript
189+
// EXAMPLE: via m.render
190+
m.render(document.body, m(ES6ClassComponent))
191+
192+
// EXAMPLE: via m.mount
193+
m.mount(document.body, ES6ClassComponent)
194+
195+
// EXAMPLE: via m.route
196+
m.route(document.body, "/", {
197+
"/": ES6ClassComponent
198+
})
199+
200+
// EXAMPLE: component composition
201+
class AnotherES6ClassComponent {
202+
view() {
203+
return m("main", [
204+
m(ES6ClassComponent)
205+
])
206+
}
207+
}
208+
```
209+
210+
---
211+
173212
### Avoid anti-patterns
174213

175214
Although Mithril is flexible, some code patterns are discouraged:

Diff for: docs/credits.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ Special thanks to:
1717
- Leon Sorokin, for writing a DOM instrumentation tool that helped improve performance in Mithril 1.0
1818
- Jordan Walke, whose work on React was prior art to the implementation of keys in Mithril
1919
- Pierre-Yves Gérardy, who consistently makes high quality contributions
20+
- Gyandeep Singh, who contributed significant IE performance improvements
2021

2122
Other people who also deserve recognition:
2223

2324
- Arthur Clemens - creator of [Polythene](https://github.com/ArthurClemens/Polythene) and the [HTML-to-Mithril converter](http://arthurclemens.github.io/mithril-template-converter/index.html)
2425
- Stephan Hoyer - creator of [mithril-node-render](https://github.com/StephanHoyer/mithril-node-render), [mithril-query](https://github.com/StephanHoyer/mithril-query) and [mithril-source-hint](https://github.com/StephanHoyer/mithril-source-hint)
2526
- the countless people who have reported and fixed bugs, participated in discussions, and helped promote Mithril
26-

Diff for: docs/fragment.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ Generates a fragment [vnode](vnodes.md)
3535

3636
`vnode = m.fragment(attrs, children)`
3737

38-
Argument | Type | Required | Description
39-
----------- | ------------------------------------ | -------- | ---
40-
`attrs` | `Object` | Yes | A map of attributes
41-
`children` | `Array<Vnode>|String|Number|Boolean` | Yes | A list of vnodes
42-
**returns** | `Vnode` | | A fragment [vnode](vnodes.md)
38+
Argument | Type | Required | Description
39+
----------- | --------------------------------------------------- | -------- | ---
40+
`attrs` | `Object` | Yes | A map of attributes
41+
`children` | `Array<Vnode|String|Number|Boolean|null|undefined>` | Yes | A list of vnodes
42+
**returns** | `Vnode` | | A fragment [vnode](vnodes.md)
4343

4444
[How to read signatures](signatures.md)
4545

Diff for: docs/framework-comparison.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ However, if you're starting something new, do consider giving Mithril a try, if
2222

2323
## Why use Mithril?
2424

25-
In one sentence: because **Mithril is pragmatic**. The 10 minutes [guide](index.md) is a good example: that's how long it takes to learn components, XHR and routing - and that's just about the right amount of knowledge needed to build useful applications.
25+
In one sentence: because **Mithril is pragmatic**. This [10 minute guide](index.md) is a good example: that's how long it takes to learn components, XHR and routing - and that's just about the right amount of knowledge needed to build useful applications.
2626

2727
Mithril is all about getting meaningful work done efficiently. Doing file uploads? [The docs show you how](request.md#file-uploads). Authentication? [Documented too](route.md#authentication). Exit animations? [You got it](animation.md). No extra libraries, no magic.
2828

Diff for: docs/generate.js

+16-14
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
1+
"use strict"
2+
13
var fs = require("fs")
24
var path = require("path")
35
var marked = require("marked")
46
var layout = fs.readFileSync("./docs/layout.html", "utf-8")
57
var version = JSON.parse(fs.readFileSync("./package.json", "utf-8")).version
6-
try {fs.mkdirSync("../mithril")} catch (e) {}
7-
try {fs.mkdirSync("../mithril/archive")} catch (e) {}
8-
try {fs.mkdirSync("../mithril/archive/v" + version)} catch (e) {}
9-
try {fs.mkdirSync("../mithril/archive/v" + version + "/lib")} catch (e) {}
10-
try {fs.mkdirSync("../mithril/archive/v" + version + "/lib/prism")} catch (e) {}
11-
try {fs.mkdirSync("../mithril/lib")} catch (e) {}
12-
try {fs.mkdirSync("../mithril/lib/prism")} catch (e) {}
8+
try {fs.mkdirSync("./dist")} catch (e) {/* ignore */}
9+
try {fs.mkdirSync("./dist/archive")} catch (e) {/* ignore */}
10+
try {fs.mkdirSync("./dist/archive/v" + version)} catch (e) {/* ignore */}
11+
try {fs.mkdirSync("./dist/archive/v" + version + "/lib")} catch (e) {/* ignore */}
12+
try {fs.mkdirSync("./dist/archive/v" + version + "/lib/prism")} catch (e) {/* ignore */}
13+
try {fs.mkdirSync("./dist/lib")} catch (e) {/* ignore */}
14+
try {fs.mkdirSync("./dist/lib/prism")} catch (e) {/* ignore */}
1315

1416
var guides = fs.readFileSync("docs/guides.md", "utf-8")
1517
var methods = fs.readFileSync("docs/methods.md", "utf-8")
@@ -25,15 +27,15 @@ function generate(pathname) {
2527
generate(pathname + "/" + filename)
2628
})
2729
}
28-
else if (!pathname.match(/tutorials|archive/)) {
30+
else if (!pathname.match(/tutorials|archive|guides|methods/)) {
2931
if (pathname.match(/\.md$/)) {
3032
var outputFilename = pathname.replace(/\.md$/, ".html")
3133
var markdown = fs.readFileSync(pathname, "utf-8")
3234
var fixed = markdown
3335
.replace(/`((?:\S| -> |, )+)(\|)(\S+)`/gim, function(match, a, b, c) { // fix pipes in code tags
3436
return "<code>" + (a + b + c).replace(/\|/g, "&#124;") + "</code>"
3537
})
36-
.replace(/(^# .+?(?:\r?\n){2,}?)(?:(-(?:.|\r|\n)+?)((?:\r?\n){2,})|)/m, function(match, title, nav, space) { // inject menu
38+
.replace(/(^# .+?(?:\r?\n){2,}?)(?:(-(?:.|\r|\n)+?)((?:\r?\n){2,})|)/m, function(match, title, nav) { // inject menu
3739
var file = path.basename(pathname)
3840
var link = new RegExp("([ \t]*)(- )(\\[.+?\\]\\(" + file + "\\))")
3941
var replace = function(match, space, li, link) {
@@ -53,14 +55,14 @@ function generate(pathname) {
5355
.replace(/\[version\]/, version) // update version
5456
.replace(/\[body\]/, markedHtml)
5557
.replace(/<h(.) id="([^"]+?)">(.+?)<\/h.>/gim, function(match, n, id, text) { // fix anchors
56-
return "<h" + n + " id=\"" + text.toLowerCase().replace(/<(\/?)code>/g, "").replace(/<a.*?>.+?<\/a>/g, "").replace(/\.|\[|\]|&quot;|\/|\(|\)/g, "").replace(/\s/g, "-") + "\">" + text + "</h" + n + ">"
58+
return "<h" + n + ' id="' + text.toLowerCase().replace(/<(\/?)code>/g, "").replace(/<a.*?>.+?<\/a>/g, "").replace(/\.|\[|\]|&quot;|\/|\(|\)/g, "").replace(/\s/g, "-") + '">' + text + "</h" + n + ">"
5759
})
58-
fs.writeFileSync("../mithril/archive/v" + version + "/" + outputFilename.replace(/^docs\//, ""), html, "utf-8")
59-
fs.writeFileSync("../mithril/" + outputFilename.replace(/^docs\//, ""), html, "utf-8")
60+
fs.writeFileSync("./dist/archive/v" + version + "/" + outputFilename.replace(/^docs\//, ""), html, "utf-8")
61+
fs.writeFileSync("./dist/" + outputFilename.replace(/^docs\//, ""), html, "utf-8")
6062
}
6163
else if (!pathname.match(/lint|generate/)) {
62-
fs.writeFileSync("../mithril/archive/v" + version + "/" + pathname.replace(/^docs\//, ""), fs.readFileSync(pathname, "utf-8"), "utf-8")
63-
fs.writeFileSync("../mithril/" + pathname.replace(/^docs\//, ""), fs.readFileSync(pathname, "utf-8"), "utf-8")
64+
fs.writeFileSync("./dist/archive/v" + version + "/" + pathname.replace(/^docs\//, ""), fs.readFileSync(pathname, "utf-8"), "utf-8")
65+
fs.writeFileSync("./dist/" + pathname.replace(/^docs\//, ""), fs.readFileSync(pathname, "utf-8"), "utf-8")
6466
}
6567
}
6668
}

Diff for: docs/index.md

+5-3
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ Mithril is used by companies like Vimeo and Nike, and open source platforms like
4444

4545
If you are an experienced developer and want to know how Mithril compares to other frameworks, see the [framework comparison](framework-comparison.md) page.
4646

47+
Mithril supports browsers all the way back to IE9, no polyfills required.
48+
4749
---
4850

4951
### Getting started
@@ -54,7 +56,7 @@ Let's create an HTML file to follow along:
5456

5557
```markup
5658
<body>
57-
<script src="http://unpkg.com/mithril/mithril.js"></script>
59+
<script src="//unpkg.com/mithril/mithril.js"></script>
5860
<script>
5961
var root = document.body
6062
@@ -93,7 +95,7 @@ Let's wrap our text in an `<h1>` tag.
9395
m.render(root, m("h1", "My first app"))
9496
```
9597

96-
The `m()` function can be used to describe any HTML structure you want. So if you to add a class to the `<h1>`:
98+
The `m()` function can be used to describe any HTML structure you want. So if you need to add a class to the `<h1>`:
9799

98100
```javascript
99101
m("h1", {class: "title"}, "My first app")
@@ -231,7 +233,7 @@ var count = 0
231233
var increment = function() {
232234
m.request({
233235
method: "PUT",
234-
url: "http://rem-rest-api.herokuapp.com/api/tutorial/1",
236+
url: "//rem-rest-api.herokuapp.com/api/tutorial/1",
235237
data: {count: count + 1},
236238
withCredentials: true,
237239
})

Diff for: docs/jsonp.md

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ Argument | Type | Required | Descript
3636
`options.type` | `any = Function(any)` | No | A constructor to be applied to each object in the response. Defaults to the [identity function](https://en.wikipedia.org/wiki/Identity_function).
3737
`options.callbackName` | `String` | No | The name of the function that will be called as the callback. Defaults to a randomized string (e.g. `_mithril_6888197422121285_0({a: 1})`
3838
`options.callbackKey` | `String` | No | The name of the querystring parameter name that specifies the callback name. Defaults to `callback` (e.g. `/someapi?callback=_mithril_6888197422121285_0`)
39+
`options.background` | `Boolean` | No | If `false`, redraws mounted components upon completion of the request. If `true`, it does not. Defaults to `false`.
3940
**returns** | `Promise` | | A promise that resolves to the response data, after it has been piped through `type` method
4041

4142
[How to read signatures](signatures.md)

Diff for: docs/jsx.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ var link = <a href={url}>{greeting + "!"}</a>
4545
Components can be used by using a convention of uppercasing the first letter of the component name:
4646

4747
```jsx
48-
m.mount(document.body, <MyComponent />)
49-
// equivalent to m.mount(document.body, m(MyComponent))
48+
m.render(document.body, <MyComponent />)
49+
// equivalent to m.render(document.body, m(MyComponent))
5050
```
5151

5252
---

Diff for: docs/keys.md

+53-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
- [What are keys](#what-are-keys)
44
- [How to use](#how-to-use)
55
- [Debugging key related issues](#debugging-key-related-issues)
6-
- [Avoid anti-patterns](#avoid-anti-patterns)
76

87
---
98

@@ -152,3 +151,56 @@ var things = [
152151
]
153152
```
154153

154+
#### Avoid mixing keyed and non-keyed vnodes in the same array
155+
156+
An array of vnodes must have only keyed vnodes or non-keyed vnodes, but not both. If you need to mix them, create a nested array.
157+
158+
```javascript
159+
// AVOID
160+
m("div", [
161+
m("div", "a"),
162+
m("div", {key: 1}, "b"),
163+
])
164+
165+
// PREFER
166+
m("div", [
167+
m("div", {key: 0}, "a"),
168+
m("div", {key: 1}, "b"),
169+
])
170+
171+
172+
// PREFER
173+
m("div", [
174+
m("div", "a"),
175+
[
176+
m("div", {key: 1}, "b"),
177+
]
178+
])
179+
```
180+
181+
#### Avoid passing model data directly to components if the model uses `key` as a data property
182+
183+
The `key` property may appear in your data model in a way that conflicts with Mithril's key logic. For example, a component may represent an entity whose `key` property is expected to change over time. This can lead to components receiving the wrong data, re-initialise, or change positions unexpectedly. If your data model uses the `key` property, make sure to wrap the data such that Mithril doesn't misinterpret it as a rendering instruction:
184+
185+
```javascript
186+
// Data model
187+
var users = [
188+
{id: 1, name: "John", key: 'a'},
189+
{id: 2, name: "Mary", key: 'b'},
190+
]
191+
192+
// Later on...
193+
users[0].key = 'c'
194+
195+
// AVOID
196+
users.map(function(user){
197+
// The component for John will be destroyed and recreated
198+
return m(UserComponent, user)
199+
})
200+
201+
// PREFER
202+
users.map(function(user){
203+
// Key is specifically extracted: data model is given its own property
204+
return m(UserComponent, {key: user.id, model: user})
205+
})
206+
```

0 commit comments

Comments
 (0)