diff --git a/README.md b/README.md
index e9b9cd3..b03cb18 100644
--- a/README.md
+++ b/README.md
@@ -5,6 +5,10 @@
A library for finite state machines.
+一个有限状态机库.
+
+查看[中文文档](README_zh-cn.md)
+
![matter state machine](examples/matter.png)
@@ -14,6 +18,9 @@ A library for finite state machines.
> **VERSION 3.0** Is a significant rewrite from earlier versions.
Existing 2.x users should be sure to read the [Upgrade Guide](docs/upgrading-from-v2.md).
+> 值得注意的是**VERSION 3.0** 已经重写了。
+ 现有2.x用户应该阅读[升级指南](docs/upgrading-from-v2.md).
+
# Installation
diff --git a/README_zh-cn.md b/README_zh-cn.md
new file mode 100644
index 0000000..5b540e4
--- /dev/null
+++ b/README_zh-cn.md
@@ -0,0 +1,151 @@
+# Javascript State Machine
+
+[![NPM version](https://badge.fury.io/js/javascript-state-machine.svg)](https://badge.fury.io/js/javascript-state-machine)
+[![Build Status](https://travis-ci.org/jakesgordon/javascript-state-machine.svg?branch=master)](https://travis-ci.org/jakesgordon/javascript-state-machine)
+
+一个有限状态机库.
+
+![matter state machine](examples/matter.png)
+
+
+
+### 现有用户注意
+
+> 值得关注的是**VERSION 3.0** 已经重写了。
+ 现有2.x用户应该阅读[升级指南](docs/upgrading-from-v2.md).
+
+
+
+# 安装
+
+在浏览器中使用:
+
+```html
+
+```
+
+> 在下载[js文件](dist/state-machine.js)或者[压缩版js文件](dist/state-machine.min.js)之后引用。
+
+在Node中使用npm安装:
+
+```shell
+ npm install --save-dev javascript-state-machine
+ or
+ npm install --save javascript-state-machine
+```
+
+在Node的js文件中导入:
+
+```javascript
+ var StateMachine = require('javascript-state-machine');
+```
+
+# 用法
+
+一个状态机可以这样构建:
+
+```javascript
+ var fsm = new StateMachine({
+ init: 'solid',
+ transitions: [
+ { name: 'melt', from: 'solid', to: 'liquid' },
+ { name: 'freeze', from: 'liquid', to: 'solid' },
+ { name: 'vaporize', from: 'liquid', to: 'gas' },
+ { name: 'condense', from: 'gas', to: 'liquid' }
+ ],
+ methods: {
+ onMelt: function() { console.log('I melted') },
+ onFreeze: function() { console.log('I froze') },
+ onVaporize: function() { console.log('I vaporized') },
+ onCondense: function() { console.log('I condensed') }
+ }
+ });
+```
+
+... 创建的对象上有包含当前状态的的属性:
+
+ * `fsm.state`
+
+... 创建的对象上有转换到不同状态的方法:
+
+ * `fsm.melt()`
+ * `fsm.freeze()`
+ * `fsm.vaporize()`
+ * `fsm.condense()`
+
+... 观察方法在生命周期中自动被调用:
+
+ * `onMelt()`
+ * `onFreeze()`
+ * `onVaporize()`
+ * `onCondense()`
+
+... 还有下面的帮助方法:
+
+|方法|注释|
+|---|---|
+|fsm.is(s)|如果当前状态`s`是当前状态则返回true|
+|fsm.can(t)|如果转换`t`在当前状态下`可以`发生则返回true|
+|fsm.cannot(t)|如果转换`t`在当前状态下`不可以`发生则返回true|
+|fsm.transitions()|返回当前状态下可以发生的转换的列表|
+|fsm.allTransitions()|返回所有可以发生的转换的列表|
+|fsm.allStates()|返回所有可以出现的状态的列表|
+
+# 术语
+
+一个状态机由一组[**States状态**](docs/states-and-transitions.md)组成
+
+ * solid
+ * liquid
+ * gas
+
+一个状态机可以通过[**Transitions转换**](docs/states-and-transitions.md)改变状态
+
+ * melt
+ * freeze
+ * vaporize
+ * condense
+
+一个状态机在转换期间可以通过观察[**Lifecycle Events生命周期事件**](docs/lifecycle-events.md)执行操作
+
+ * onBeforeMelt
+ * onAfterMelt
+ * onLeaveSolid
+ * onEnterLiquid
+ * ...
+
+一个状态机可以有任意的[**Data 数据 and Methods 方法**](docs/data-and-methods.md).
+
+多个状态机实例可以通过使用[**State Machine Factory**](docs/state-machine-factory.md)来创建.
+
+# 文档
+
+阅读更多有关的文档
+
+ * [States and Transitions状态和转换](docs/zh-cn/states-and-transitions.md)
+ * [Data and Methods数据和方法](docs/zh-cn/data-and-methods.md)
+ * [Lifecycle Events生命周期事件](docs/zh-cn/lifecycle-events.md)
+ * [Asynchronous Transitions异步转换](docs/zh-cn/async-transitions.md)
+ * [Initialization初始化](docs/zh-cn/initialization.md)
+ * [Error Handling错误处理](docs/zh-cn/error-handling.md)
+ * [State History状态历史](docs/zh-cn/state-history.md)
+ * [Visualization可视化](docs/zh-cn/visualization.md)
+ * [State Machine Factory状态机工厂](docs/state-machine-factory.md)
+ * [Upgrading from 2.x从2.x升级](docs/zh-cn/upgrading-from-v2.md)
+
+# 贡献(〜^㉨^)〜
+
+你可以通过创建issues或者pr来给项目[贡献](docs/contributing.md)
+
+# 发行记录
+
+查看 [发行记录](RELEASE_NOTES.md) 文件.
+
+# 协议
+
+查看[MIT协议](https://github.com/jakesgordon/javascript-state-machine/blob/master/LICENSE) 文件.
+
+# 联系
+
+如果你有想法, 反馈, 需求 或者bugs报告, 你可以联系我
+[jake@codeincomplete.com](mailto:jake@codeincomplete.com), 或通过我的网站: [Code inComplete](http://codeincomplete.com/)
diff --git a/docs/zh-cn/async-transitions.md b/docs/zh-cn/async-transitions.md
new file mode 100644
index 0000000..0ef9889
--- /dev/null
+++ b/docs/zh-cn/async-transitions.md
@@ -0,0 +1,54 @@
+# 异步转换
+
+在阅读本文之前,您应该先熟悉状态机[生命周期事件](lifecycle-events.md)。
+
+有时,您需要在状态转换期间执行一些异步代码,并确保直到代码完成,才进入下一状态。
+
+例如:希望逐渐淡化UI组件后改变状态,在动画完成前不要转换到下一个状态,在动画完成后转换到下一个状态。
+你可以通过从任意[生命周期事件](lifecycle-events.md)中返回[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/._Objects/Promise)对象
+
+从生命周期事件返回`Promise`将导致该转变的生命周期暂停。它可以通过解决`Promise`来继续,或者通过拒绝`Promise`来取消。
+
+例如(使用jQuery的效果):
+
+```javascript
+ var fsm = new StateMachine({
+
+ init: 'menu',
+
+ transitions: [
+ { name: 'play', from: 'menu', to: 'game' },
+ { name: 'quit', from: 'game', to: 'menu' }
+ ],
+
+ methods: {
+
+ onEnterMenu: function() {
+ return new Promise(function(resolve, reject) {
+ $('#menu').fadeIn('fast', resolve)
+ })
+ },
+
+ onEnterGame: function() {
+ return new Promise(function(resolve, reject) {
+ $('#game').fadeIn('fast', resolve)
+ })
+ },
+
+ onLeaveMenu: function() {
+ return new Promise(function(resolve, reject) {
+ $('#menu').fadeOut('fast', resolve)
+ })
+ },
+
+ onLeaveGame: function() {
+ return new Promise(function(resolve, reject) {
+ $('#game').fadeOut('fast', resolve)
+ })
+ }
+ }
+
+ })
+```
+
+> 确保你最终总是解决(或拒绝)你的`Promise`,否则状态机将永远停留在那个挂起的转换中。
\ No newline at end of file
diff --git a/docs/zh-cn/contributing.md b/docs/zh-cn/contributing.md
new file mode 100644
index 0000000..01e5e74
--- /dev/null
+++ b/docs/zh-cn/contributing.md
@@ -0,0 +1,59 @@
+# Contributing
+
+The `javascript-state-machine` library is built using:
+
+ * [Webpack 2](https://webpack.js.org/concepts/) - for bundling javascript modules together
+ * [UglifyJS2](https://github.com/mishoo/UglifyJS2) - for minifying bundled javascript files
+ * [Ava](https://github.com/avajs/ava) - for testing
+
+The directory structure includes:
+
+```shell
+ /bin # - build scripts
+ /dist # - minified bundles for distribution
+ /docs # - documentation
+ /examples # - example visualizations
+ /lib # - bundled source code for npm
+ /src # - source code
+ /test # - unit tests
+
+ package.json # - npm configuration
+ webpack.config.js # - webpack configuration
+
+ LICENSE # - the project licensing terms
+ README.md # - the project readme
+ RELEASE_NOTES.md # - the project release notes
+
+```
+
+Build time dependencies can be installed using npm:
+
+```shell
+ > npm install
+```
+
+A number of npm scripts are available:
+
+```shell
+ > npm run test # run unit tests
+ > npm run build # bundle and minify files for distribution
+ > npm run watch # run tests if source files change
+```
+
+## Source Code
+
+The source code is written in es5 syntax and should be supported by all [es5 compatible browsers](http://caniuse.com/#feat=es5).
+[Babel](https://babeljs.io/) is **NOT** used for this project. Webpack is used to
+bundle modules together for distribution.
+
+## Submitting Pull Requests
+
+Generally speaking, please raise an issue first and lets discuss the problem and the
+proposed solution. The next step would be a pull-request - fantastic and thank you for helping out - but
+please try to...
+
+ * ensure the tests pass (`npm test`).
+ * rebuild distribution files (`npm run build`).
+ * include tests for your changes.
+ * include documentation for your changes.
+ * include a great commit message.
diff --git a/docs/zh-cn/data-and-methods.md b/docs/zh-cn/data-and-methods.md
new file mode 100644
index 0000000..7b91462
--- /dev/null
+++ b/docs/zh-cn/data-and-methods.md
@@ -0,0 +1,62 @@
+# 数据和函数
+
+除了[状态和转换](states-and-transitions.md),一个状态机也可以包含任意的数据和方法。
+
+```javascript
+ var fsm = new StateMachine({
+ init: 'A',
+ transitions: [
+ { name: 'step', from: 'A', to: 'B' }
+ ],
+ data: {
+ color: 'red'
+ },
+ methods: {
+ describe: function() {
+ console.log('I am ' + this.color);
+ }
+ }
+ });
+
+ fsm.state; // 'A'
+ fsm.color; // 'red'
+ fsm.describe(); // 'I am red'
+```
+
+## 数据和状态机工厂
+
+如果你想通过[状态机工厂](state-machine-factory.md)创建多个实例,那么`data`对象将会在多个实例之间共享,这可能不是你想要的。为确保每一个实例获得唯一的`data`你应该使用`data`函数代替。
+
+```javascript
+ var FSM = StateMachine.factory({
+ init: 'A',
+ transitions: [
+ { name: 'step', from: 'A', to: 'B' }
+ ],
+ data: function(color) { // <-- use a method that can be called for each instance
+ return {
+ color: color
+ }
+ },
+ methods: {
+ describe: function() {
+ console.log('I am ' + this.color);
+ }
+ }
+ });
+
+ var a = new FSM('red'),
+ b = new FSM('blue');
+
+ a.state; // 'A'
+ b.state; // 'A'
+
+ a.color; // 'red'
+ b.color; // 'blue'
+
+ a.describe(); // 'I am red'
+ b.describe(); // 'I am blue'
+```
+
+> 注意: 在构造每个实例时使用的参数直接传递到“data”函数。
+
diff --git a/docs/zh-cn/error-handling.md b/docs/zh-cn/error-handling.md
new file mode 100644
index 0000000..c301f65
--- /dev/null
+++ b/docs/zh-cn/error-handling.md
@@ -0,0 +1,52 @@
+# 错误处理
+
+## 无效转换
+
+默认情况下,如果尝试触发当前状态中不允许的转换,则状态机将引发异常。如果您喜欢自己处理这个问题,可以定义一个自定义的“onInvalidTransition”处理程序:
+
+```javascript
+ var fsm = new StateMachine({
+ init: 'A',
+ transitions: [
+ { name: 'step', from: 'A', to: 'B' },
+ { name: 'reset', from: 'B', to: 'A' }
+ ],
+ methods: {
+ onInvalidTransition: function(transition, from, to) {
+ throw new Exception("transition not allowed from that state");
+ }
+ }
+ });
+
+ fsm.state; // 'A'
+ fsm.can('step'); // true
+ fsm.can('reset'); // false
+
+ fsm.reset(); // <-- throws "transition not allowed from that state"
+```
+
+## 悬而未决的转换
+
+默认情况下,如果在[Lifecycle Event生命周期事件](lifecycle-events.md)期间为挂起的转换尝试触发其他转换,则状态机将抛出异常。如果你喜欢自己处理这个问题,你可以定义一个自定义的“onPendingTransition”处理程序:
+
+```javascript
+ var fsm = new StateMachine({
+ init: 'A',
+ transitions: [
+ { name: 'step', from: 'A', to: 'B' },
+ { name: 'step', from: 'B', to: 'C' }
+ ],
+ methods: {
+ onLeaveA: function() {
+ this.step(); // <-- uh oh, trying to transition from within a lifecycle event is not allowed
+ },
+ onPendingTransition: function(transition, from, to) {
+ throw new Exception("transition already in progress");
+ }
+ }
+ });
+
+ fsm.state; // 'A'
+ fsm.can('step'), // true
+ fsm.step(); // <-- throws "transition already in progress"
+```
diff --git a/docs/zh-cn/initialization.md b/docs/zh-cn/initialization.md
new file mode 100644
index 0000000..a71c686
--- /dev/null
+++ b/docs/zh-cn/initialization.md
@@ -0,0 +1,55 @@
+# 初始化选项
+
+## 显式初始化
+
+默认情况下,如果你不特别的初始化状态,状态机将会处于`none`状态,在创建期间没有生命周期事件触发,并且你需要提供一个显示转换来跳出这个状态。
+
+```javascript
+ var fsm = new StateMachine({
+ transitions: [
+ { name: 'init', from: 'none', to: 'A' },
+ { name: 'step', from: 'A', to: 'B' },
+ { name: 'step', from: 'B', to: 'C' }
+ ]
+ });
+ fsm.state; // 'none'
+ fsm.init(); // 'init()' transition is fired explicitly
+ fsm.state; // 'A'
+```
+
+## 隐式初始化
+
+如果你指定初始状态的名称,那么将会在创建状态机的时候创建隐式的转换并触发(还会触发响应的生命周期事件)
+
+>这是最常见的初始化策略,绝大多数(90%)时候你应该使用这个方法。
+
+```javascript
+ var fsm = new StateMachine({
+ init: 'A',
+ transitions: [
+ { name: 'step', from: 'A', to: 'B' },
+ { name: 'step', from: 'B', to: 'C' }
+ ]
+ }); // 'init()' transition fires from 'none' to 'A' during construction
+ fsm.state; // 'A'
+```
+
+## 用状态机工厂初始化
+
+For [State Machine Factories](state-machine-factory.md), the `init` transition
+is triggered for each constructed instance.
+
+ [State Machine Factories状态机工厂](state-machine-factory.md),为每个状态机触发初始化转换。
+
+```javascript
+ var FSM = StateMachine.factory({
+ init: 'A',
+ transitions: [
+ { name: 'step', from: 'A', to: 'B' },
+ { name: 'step', from: 'B', to: 'C' }
+ ]
+ });
+
+ var fsm1 = new FSM(), // 'init()' transition fires from 'none' to 'A' for fsm1
+ fsm2 = new FSM(); // 'init()' transition fires from 'none' to 'A' for fsm2
+```
diff --git a/docs/zh-cn/lifecycle-events.md b/docs/zh-cn/lifecycle-events.md
new file mode 100644
index 0000000..adfe268
--- /dev/null
+++ b/docs/zh-cn/lifecycle-events.md
@@ -0,0 +1,148 @@
+# 生命周期事件
+
+当转换发生时,为了追踪或执行某些动作,可以观察五个通用的生命周期事件:
+
+ * `onBeforeTransition` - 转换之前调用
+ * `onLeaveState` - 离开一个状态时调用
+ * `onTransition` - 转换期间调用
+ * `onEnterState` - 进入一个状态时调用
+ * `onAfterTransition` - 转换之后调用
+
+In addition to the general-purpose events, transitions can be observed
+using your specific transition and state names:
+
+除了通用事件之外,还可以使用特定的转换和状态名称来观察转换:
+
+ * `onBefore` - 在一个特定的`TRANSITION`转换开始之前
+ * `onLeave` - 在离开一个特定的`STATE`状态时调用
+ * `onEnter` - 在进入一个特定的`STATE`状态时调用
+ * `onAfter` - 在一个特定的`TRANSITION`转换之后调用
+
+为了便利起见,两个最有用的事件可以缩短为:
+
+ * `on` - 等价于`onAfter`
+ * `on` - 等价于`onEnter`
+
+## 观察生命周期事件
+
+个体生命周期事件可以`observe()`方法观察到
+
+```javascript
+ fsm.observe('onStep', function() {
+ console.log('stepped');
+ });
+```
+
+可以使用观察者对象观察多个事件
+
+```javascript
+ fsm.observe({
+ onStep: function() { console.log('stepped'); }
+ onA: function() { console.log('entered state A'); }
+ onB: function() { console.log('entered state B'); }
+ });
+```
+
+一个状态机总是观察它自己的生命周期事件。
+
+```javascript
+ var fsm = new StateMachine({
+ init: 'A',
+ transitions: [
+ { name: 'step', from: 'A', to: 'B' }
+ ],
+ methods: {
+ onStep: function() { console.log('stepped'); }
+ onA: function() { console.log('entered state A'); }
+ onB: function() { console.log('entered state B'); }
+ }
+ });
+```
+
+## 生命周期事件参数
+
+观察者将传递一个包含“生命周期”对象的单个参数,该属性具有以下属性
+
+ * **transition** - 转换名称
+ * **from** - 先前的状态
+ * **to** - 接下来的状态
+
+除了“生命周期”参数,观察者还将接收传递到转换方法中的其他参数。
+
+```javascript
+ var fsm = new StateMachine({
+ transitions: [
+ { name: 'step', from: 'A', to: 'B' }
+ ],
+ methods: {
+ onTransition: function(lifecycle, arg1, arg2) {
+ console.log(lifecycle.transition); // 'step'
+ console.log(lifecycle.from); // 'A'
+ console.log(lifecycle.to); // 'B'
+ console.log(arg1); // 42
+ console.log(arg2); // 'hello'
+ }
+ }
+ });
+
+ fsm.step(42, 'hello');
+```
+
+## 生命周期事件名称
+
+Lifecycle event names always use standard javascipt camelCase, even if your transition and
+state names do not:
+生命周期事件名称总是使用标准的js驼峰命名法,即使你的转换和状态名称不是按照驼峰命名法命名的:
+
+```javascript
+ var fsm = new StateMachine({
+ transitions: [
+ { name: 'do-with-dash', from: 'has-dash', to: 'has_underscore' },
+ { name: 'do_with_underscore', from: 'has_underscore', to: 'alreadyCamelized' },
+ { name: 'doAlreadyCamelized', from: 'alreadyCamelize', to: 'has-dash' }
+ ],
+ methods: {
+ onBeforeDoWithDash: function() { /* ... */ },
+ onBeforeDoWithUnderscore: function() { /* ... */ },
+ onBeforeDoAlreadyCamelized: function() { /* ... */ },
+ onLeaveHasDash: function() { /* ... */ },
+ onLeaveHasUnderscore: function() { /* ... */ },
+ onLeaveAlreadyCamelized: function() { /* ... */ },
+ onEnterHasDash: function() { /* ... */ },
+ onEnterHasUnderscore: function() { /* ... */ },
+ onEnterAlreadyCamelized: function() { /* ... */ },
+ onAfterDoWithDash: function() { /* ... */ },
+ onAfterDoWithUnderscore: function() { /* ... */ },
+ onAfterDoAlreadyCamelized: function() { /* ... */ }
+ }
+ });
+```
+
+# 按顺序列出的生命周期事件
+
+重申,转换生命周期按以下顺序发生:
+
+ * `onBeforeTransition` - fired before any transition
+ * `onBefore` - fired before a specific TRANSITION
+ * `onLeaveState` - fired when leaving any state
+ * `onLeave` - fired when leaving a specific STATE
+ * `onTransition` - fired during any transition
+ * `onEnterState` - fired when entering any state
+ * `onEnter` - fired when entering a specific STATE
+ * `on` - convenience shorthand for `onEnter`
+ * `onAfterTransition` - fired after any transition
+ * `onAfter` - fired after a specific TRANSITION
+ * `on` - convenience shorthand for `onAfter`
+
+# 取消转换
+
+任何观察者可以通过在任何生命周期事件中显式地返回“false”来取消转换:
+
+ * `onBeforeTransition`
+ * `onBefore`
+ * `onLeaveState`
+ * `onLeave`
+ * `onTransition`
+
+所有后续生命周期事件将被取消,状态将保持不变。
+
diff --git a/docs/zh-cn/state-history.md b/docs/zh-cn/state-history.md
new file mode 100644
index 0000000..3f4f5a2
--- /dev/null
+++ b/docs/zh-cn/state-history.md
@@ -0,0 +1,123 @@
+# 状态历史
+
+默认情况下,一个状态机只追踪当前状态,如果希望追踪状态历史,你可以用`state-machine-history`插件扩展状态机。
+
+```javascript
+ var StateMachineHistory = require('javascript-state-machine/lib/history')
+```
+
+```javascript
+
+ var fsm = new StateMachine({
+ init: 'A',
+ transitions: [
+ { name: 'step', from: 'A', to: 'B' },
+ { name: 'step', from: 'B', to: 'C' },
+ { name: 'step', from: 'C', to: 'D' }
+ ],
+ plugins: [
+ new StateMachineHistory() // <-- plugin enabled here
+ ]
+ })
+
+ fsm.history; // [ 'A' ]
+ fsm.step();
+ fsm.history; // [ 'A', 'B' ]
+ fsm.step();
+ fsm.history; // [ 'A', 'B', 'C' ]
+
+ fsm.clearHistory();
+
+ fsm.history; // [ ]
+
+```
+## 穿越历史
+
+你可以使用`historyBack`和`historyForward`穿越历史。
+
+```javascript
+ var fsm = new StateMachine({
+ init: 'A',
+ transitions: [
+ { name: 'step', from: 'A', to: 'B' },
+ { name: 'step', from: 'B', to: 'C' },
+ { name: 'step', from: 'C', to: 'D' }
+ ]
+ })
+
+ fsm.step();
+ fsm.step();
+ fsm.step();
+
+ fsm.state; // 'D'
+ fsm.history; // [ 'A', 'B', 'C', 'D' ]
+
+ fsm.historyBack();
+
+ fsm.state; // 'C'
+ fsm.history; // [ 'A', 'B', 'C' ]
+
+ fsm.historyBack();
+
+ fsm.state; // 'B'
+ fsm.history; // [ 'A', 'B' ]
+
+ fsm.historyForward();
+
+ fsm.state; // 'C'
+ fsm.history; // [ 'A', 'B', 'C' ]
+```
+
+你可以使用下面方法测试穿越历史是否被允许:
+
+```javascript
+ fsm.canHistoryBack; // true/false
+ fsm.canHistoryForward; // true/false
+```
+
+一组 [Lifecycle Events生命周期事件](lifecycle-events.md) 将仍旧在穿越历史时应用。
+
+## 限制历史记录数量
+
+默认情况下,状态机的历史知道被清除是无限增长的。你可以通过配置来限制只存储最后的N条状态。
+
+``` javascript
+ var fsm = new StateMachine({
+ plugins: [
+ new StateMachineHistory({ max: 100 }) // <-- plugin configuration
+ ]
+ })
+```
+
+## 自定义历史
+
+如果`history`和你存在的状态机属性或方法发生术语冲突,你可以用一个不同的名字打开`state-machine-history`插件。
+
+```javascript
+ var fsm = new StateMachine({
+ init: 'A',
+ transitions: [
+ { name: 'step', from: 'A', to: 'B' },
+ { name: 'step', from: 'B', to: 'C' },
+ { name: 'step', from: 'C', to: 'D' }
+ ],
+ plugins: [
+ new StateMachineHistory({ name: 'memory' })
+ ]
+ })
+
+ fsm.step();
+ fsm.step();
+
+ fsm.memory; // [ 'A', 'B', 'C' ]
+
+ fsm.memoryBack();
+ fsm.memory; // [ 'A', 'B' ]
+
+ fsm.memoryForward();
+ fsm.memory; // [ 'A', 'B', 'C' ]
+
+ fsm.clearMemory();
+ fsm.memory; // [ ]
+```
+
diff --git a/docs/zh-cn/state-machine-factory.md b/docs/zh-cn/state-machine-factory.md
new file mode 100644
index 0000000..f484f33
--- /dev/null
+++ b/docs/zh-cn/state-machine-factory.md
@@ -0,0 +1,98 @@
+# 状态机工厂
+
+此文档中的大多数示例构造了单个状态机实例,例如:
+
+```javascript
+ var fsm = new StateMachine({
+ init: 'solid',
+ transitions: [
+ { name: 'melt', from: 'solid', to: 'liquid' },
+ { name: 'freeze', from: 'liquid', to: 'solid' },
+ { name: 'vaporize', from: 'liquid', to: 'gas' },
+ { name: 'condense', from: 'gas', to: 'liquid' }
+ ]
+ });
+```
+
+如果你希望创建用相同的配置创建多个状态机,你应该使用状态机工厂。状态机工厂提供可以用来多次实例化的JS构造函数。
+
+```javascript
+ var Matter = StateMachine.factory({ // <-- the factory is constructed here
+ init: 'solid',
+ transitions: [
+ { name: 'melt', from: 'solid', to: 'liquid' },
+ { name: 'freeze', from: 'liquid', to: 'solid' },
+ { name: 'vaporize', from: 'liquid', to: 'gas' },
+ { name: 'condense', from: 'gas', to: 'liquid' }
+ ]
+ });
+
+ var a = new Matter(), // <-- instances are constructed here
+ b = new Matter(),
+ c = new Matter();
+
+ b.melt();
+ c.melt();
+ c.vaporize();
+
+ a.state; // solid
+ b.state; // liquid
+ c.state; // gas
+```
+
+使用这个工厂,每一个状态机实例都有一个唯一的实例。每一个状态机管理他自己的`state`属性,但是方法是被通过JS原型机制(原型链)共享的。
+
+> 注意:了解特殊案例处理需求 [Data and State Machine Factories数据和状态机工厂](data-and-methods.md#data-and-state-machine-factories)
+
+## 应用状态机工厂行为到现有对象
+
+有时,您可能希望将状态机行为应用到已经存在的对象(例如,反作用组件)。你可以用“StateMachine.apply”方法来实现这一点:
+
+```javascript
+ var component = { /* ... */ };
+
+ StateMachine.apply(component, {
+ init: 'A',
+ transitions: {
+ { name: 'step', from: 'A', to: 'B' }
+ }
+ });
+```
+
+> 小心的使用状态和转换名称,否则可能会和对象属性冲突。
+
+## 应用状态机工厂行为到现有的类
+
+还可以将状态机工厂行为应用于现有类,但是现在必须通过在类构造函数方法中调用`this._fsm()'来负责初始化:
+
+```javascript
+ function Person(name) {
+ this.name = name;
+ this._fsm(); // <-- IMPORTANT
+ }
+
+ Person.prototype = {
+ speak: function() {
+ console.log('my name is ' + this.name + ' and I am ' + this.state);
+ }
+ }
+
+ StateMachine.factory(Person, {
+ init: 'idle',
+ transitions: {
+ { name: 'sleep', from: 'idle', to: 'sleeping' },
+ { name: 'wake', from: 'sleeping', to: 'idle' }
+ }
+ });
+
+ var amy = new Person('amy'),
+ bob = new Person('bob');
+
+ bob.sleep();
+
+ amy.state; // 'idle'
+ bob.state; // 'sleeping'
+
+ amy.speak(); // 'my name is amy and I am idle'
+ bob.speak(); // 'my name is bob and I am sleeping'
+```
diff --git a/docs/zh-cn/states-and-transitions.md b/docs/zh-cn/states-and-transitions.md
new file mode 100644
index 0000000..fe5b7bb
--- /dev/null
+++ b/docs/zh-cn/states-and-transitions.md
@@ -0,0 +1,156 @@
+# 状态和转换
+
+![matter state machine](../../examples/matter.png)
+
+一个状态机由一组**States状态**组成, 例如:
+
+ * solid
+ * liquid
+ * gas
+
+.. 和一组**转换**, 例如:
+
+ * melt
+ * freeze
+ * vaporize
+ * condense
+
+```javascript
+ var fsm = new StateMachine({
+ init: 'solid',
+ transitions: [
+ { name: 'melt', from: 'solid', to: 'liquid' },
+ { name: 'freeze', from: 'liquid', to: 'solid' },
+ { name: 'vaporize', from: 'liquid', to: 'gas' },
+ { name: 'condense', from: 'gas', to: 'liquid' }
+ ]
+ });
+
+ fsm.state; // 'solid'
+ fsm.melt();
+ fsm.state; // 'liquid'
+ fsm.vaporize();
+ fsm.state; // 'gas'
+```
+
+## 多种状态和转换
+
+![wizard state machine](../../examples/wizard.png)
+
+如果一个转换被允许`从`多种状态开始,那么用同一个名称定义这些转换。
+
+```javascript
+ { name: 'step', from: 'A', to: 'B' },
+ { name: 'step', from: 'B', to: 'C' },
+ { name: 'step', from: 'C', to: 'D' }
+```
+
+如果一个转换是从多个不同的状态开始被转换到相同的状态,例如:
+
+```javascript
+ { name: 'reset', from: 'B', to: 'A' },
+ { name: 'reset', from: 'C', to: 'A' },
+ { name: 'reset', from: 'D', to: 'A' }
+```
+
+... 那么他可以被简写为从`数组`状态开始:
+
+```javascript
+ { name: 'reset', from: [ 'B', 'C', 'D' ], to: 'A' }
+```
+
+把他们组合到一起,例如:
+
+```javascript
+ var fsm = new StateMachine({
+ init: 'A',
+ transitions: [
+ { name: 'step', from: 'A', to: 'B' },
+ { name: 'step', from: 'B', to: 'C' },
+ { name: 'step', from: 'C', to: 'D' },
+ { name: 'reset', from: [ 'B', 'C', 'D' ], to: 'A' }
+ ]
+ })
+```
+
+这个例子将会创建一个有两个转换方法的对象:
+
+ * `fsm.step()`
+ * `fsm.reset()`
+
+`reset`转换将总是转换到`A`状态, `step`转换的结果取决于当前的状态.
+
+## 通配符转换
+
+If a transition is appropriate from **any** state, then a wildcard '*' `from` state can be used:
+
+如果一个转换可以从任意状态开始,那么可以使用通配符`*`。
+
+```javascript
+ var fsm = new StateMachine({
+ transitions: [
+ // ...
+ { name: 'reset', from: '*', to: 'A' }
+ ]
+ });
+```
+
+## 条件转换
+
+一个转换可以通过提供一个函数到`to`属性来在运行时选择目标状态。
+
+```javascript
+ var fsm = new StateMachine({
+ init: 'A',
+ transitions: [
+ { name: 'step', from: '*', to: function(n) { return increaseCharacter(this.state, n || 1) } }
+ ]
+ });
+
+ fsm.state; // A
+ fsm.step();
+ fsm.state; // B
+ fsm.step(5);
+ fsm.state; // G
+
+ // helper method to perform (c = c + n) on the 1st character in str
+ function increaseCharacter(str, n) {
+ return String.fromCharCode(str.charCodeAt(0) + n);
+ }
+```
+
+`allStates`方法的返回列表只会包含运行时已经出现过的状态。
+
+```javascript
+ fsm.state; // A
+ fsm.allStates(); // [ 'A' ]
+ fsm.step();
+ fsm.state; // B
+ fsm.allStates(); // [ 'A', 'B' ]
+ fsm.step(5);
+ fsm.state; // G
+ fsm.allStates(); // [ 'A', 'B', 'G' ]
+```
+
+## 跳转 - `不通过转换改变状态`
+
+你可以使用条件转换构造出一个`跳转`转换。
+
+```javascript
+ var fsm = new StateMachine({
+ init: 'A'
+ transitions: [
+ { name: 'step', from: 'A', to: 'B' },
+ { name: 'step', from: 'B', to: 'C' },
+ { name: 'step', from: 'C', to: 'D' },
+ { name: 'goto', from: '*', to: function(s) { return s } }
+ ]
+ })
+
+ fsm.state; // 'A'
+ fsm.goto('D');
+ fsm.state; // 'D'
+```
+
+一组完整的[Lifecycle Events生命周期事件](lifecycle-events.md)仍旧在应用`goto`时可用.
+
diff --git a/docs/zh-cn/upgrading-from-v2.md b/docs/zh-cn/upgrading-from-v2.md
new file mode 100644
index 0000000..42f8150
--- /dev/null
+++ b/docs/zh-cn/upgrading-from-v2.md
@@ -0,0 +1,378 @@
+# Upgrading from Version 2.x
+
+Version 3.0 is a significant rewrite from earlier versions in order to support more
+advanced use cases and to improve the existing use cases. Unfortunately, many of these
+updates are incompatible with earlier versions, so changes are required in your code when you upgrade
+to version 3.x. We want to tackle those all in one swoop and avoid any more big-bang changes
+in the future.
+
+Please read this article carefully if you are upgrading from version 2.x to 3.x.
+
+> A [summary](#upgrade-summary) of the changes required can be found at the end of the article.
+
+### Table of Contents
+
+ * [**Construction**](#construction) - constructing single instances follows a more idomatic javascript pattern.
+ * [**State Machine Factory**](#state-machine-factory) - constructing multiple instances from a class has been simplified.
+ * [**Data and Methods**](#data-and-methods) - A state machine can now have additional data and methods.
+ * [**Renamed Terminology**](#renamed-terminology) - A more consistent terminology has been applied.
+ * [**Lifecycle Events**](#lifecycle-events) - (previously called 'callbacks') are camelCased and observable.
+ * [**Async Transitions**](#promise-based-asynchronous-transitions) - Asynchronous transitions now use standard Promises.
+ * [**Conditional Transitions**](#conditional-transitions) - A transition can now dynamically choose its target state at run-time.
+ * [**Goto**](#goto) - The state can be changed without a defined transition using `goto`.
+ * [**State History**](#state-history) - The state history can now be retained and traversed with back/forward semantics.
+ * [**Visualization**](#visualization) - A state machine can now be visualized using GraphViz.
+ * [**Build System**](#build-system) - A new webpack-based build system has been implemented.
+
+## Construction
+
+Constructing a single state machine now follows a more idiomatic javascript pattern:
+
+Version 2.x:
+
+```javascript
+ var fsm = StateMachine.create({ /* ... */ })
+```
+
+**Version 3.x**:
+
+```javascript
+ var fsm = new StateMachine({ /* ... */ }) // <-- more idomatic
+```
+
+## State Machine Factory
+
+Constructing multiple instances from a state machine 'class' has been simplified:
+
+Version 2.x:
+
+```javascript
+ function FSM() { }
+
+ StateMachine.create({
+ target: FSM.prototype,
+ // ...
+ })
+
+ var a = new FSM(),
+ b = new FSM();
+```
+
+**Version 3.x**:
+
+```javascript
+ var FSM = StateMachine.factory({ /* ... */ }), // <-- generate a factory (a constructor function)
+ a = new FSM(), // <-- then create instances
+ b = new FSM();
+```
+
+## Data and Methods
+
+A state machine can now have additional (arbitrary) data and methods defined:
+
+Version 2.x: _not supported_.
+
+**Version 3.x**:
+
+```javascript
+ var fsm = new StateMachine({
+ data: {
+ color: 'red'
+ },
+ methods: {
+ speak: function() { console.log('hello') }
+ }
+ });
+
+ fsm.color; // 'red'
+ fsm.speak(); // 'hello'
+```
+
+## Renamed Terminology
+
+A more consistent terminology has been applied:
+
+ * A state machine consists of a set of [**States**](states-and-transitions.md).
+ * A state machine changes state by using [**Transitions**](states-and-transitions.md).
+ * A state machine can perform actions during a transition by observing [**Lifecycle Events**](lifecycle-events.md).
+ * A state machine can also have arbitrary [**Data and Methods**](data-and-methods.md).
+
+Version 2.x:
+
+```javascript
+ var fsm = StateMachine.create({
+ initial: 'ready',
+ events: [ /* ... */ ],
+ callbacks: { /* ... */ }
+ });
+
+ fsm.current; // 'ready'
+```
+
+**Version 3.x**:
+
+```javascript
+ var fsm = new StateMachine({
+ init: 'ready', // <-- renamed s/initial/init/
+ transitions: [ /* ... */ ], // <-- renamed s/events/transitions/
+ data: { /* ... */ }, // <-- new
+ methods: { /* ... */ } // <-- renamed s/callbacks/methods/
+ // ... which can contain arbitrary methods AND lifecycle event callbacks
+ });
+
+ fsm.state; // 'ready' // <-- renamed s/current/state/
+```
+
+## Lifecycle Events
+
+**Callbacks** have been renamed **Lifecycle Events** and are now declared as `methods` on the
+state machine using a more traditional javascript camelCase for the method names:
+
+Version 2.x:
+
+```javascript
+ var fsm = StateMachine.create({
+ initial: 'initial-state',
+ events: [
+ { name: 'do-something', from: 'initial-state', to: 'final-state' }
+ ],
+ callbacks: {
+ onbeforedosomething: function() { /* ... */ },
+ onleaveinitialstate: function() { /* ... */ },
+ onenterfinalstate: function() { /* ... */ },
+ onafterdosomething: function() { /* ... */ }
+ }
+ })
+```
+
+**Version 3.x**:
+
+```javascript
+ var fsm = new StateMachine({
+ init: 'initial-state',
+ transitions: [
+ { name: 'do-something', from: 'initial-state', to: 'final-state' }
+ ],
+ methods: { // <-- renamed s/callbacks/methods/
+ onBeforeDoSomething: function() { /* ... */ }, // <-- camelCase naming convention
+ onLeaveInitialState: function() { /* ... */ }, // <--
+ onEnterFinalState: function() { /* ... */ }, // <--
+ onAfterDoSomething: function() { /* ... */ } // <--
+ }
+ })
+```
+
+
+Lifecycle events are now passed information in a single `lifecycle` argument:
+
+Version 2.x:
+
+```javascript
+ var fsm = StateMachine.create({
+ events: [
+ { name: 'step', from: 'none', to: 'complete' }
+ ],
+ callbacks: {
+ onbeforestep: function(event, from, to) {
+ console.log('event: ' + event); // 'step'
+ console.log('from: ' + from); // 'none'
+ console.log('to: ' + to); // 'complete'
+ },
+ }
+ });
+```
+
+**Version 3.x**:
+
+```javascript
+ var fsm = new StateMachine({
+ transitions: [
+ { name: 'step', from: 'none', to: 'complete' }
+ ],
+ methods: {
+ onBeforeStep: function(lifecycle) { // <-- combined into a single argument
+ console.log('transition: ' + lifecycle.transition); // 'step'
+ console.log('from: ' + lifecycle.from); // 'none'
+ console.log('to: ' + lifecycle.to); // 'complete'
+ }
+ }
+ });
+```
+
+> This change allows us to include additional information in the future without having to have a ridiculous
+number of arguments to lifecycle event observer methods
+
+
+Lifecycle events are also now observable by others:
+
+Version 2.x: _not supported_.
+
+**Version 3.x**:
+
+```javascript
+ var fsm = new StateMachine({ /* ... */ });
+
+ // observe individual lifecycle events with observer methods
+ fsm.observe('onBeforeTransition', function() { /* ... */ });
+ fsm.observe('onLeaveState', function() { /* ... */ });
+
+ // or observe multiple lifecycle events with an observer object
+ fsm.observe({
+ onBeforeTransition: function() { /* ... */ },
+ onLeaveState: function() { /* ... */ }
+ });
+```
+
+
+The general purpose lifecycle events now use the word `transition` instead of `event` and
+occur **before** their specialized versions:
+
+Version 2.x, the lifecycle order was:
+
+ * `onbefore`
+ * `onbeforeevent`
+ * `onleave`
+ * `onleavestate`
+ * `onenter`
+ * `onenterstate`
+ * `on`
+ * `onafter`
+ * `onafterevent`
+ * `on`
+
+**Version 3.x**, the lifecycle order is:
+
+ * `onBeforeTransition` - fired before any transition
+ * `onBefore` - fired before a specific TRANSITION
+ * `onLeaveState` - fired when leaving any state
+ * `onLeave` - fired when leaving a specific STATE
+ * `onTransition` - fired during any transition
+ * `onEnterState` - fired when entering any state
+ * `onEnter` - fired when entering a specific STATE
+ * `on` - convenience shorthand for `onEnter`
+ * `onAfterTransition` - fired after any transition
+ * `onAfter` - fired after a specific TRANSITION
+ * `on` - convenience shorthand for `onAfter`
+
+> For more details, read [Lifecycle Events](lifecycle-events.md)
+
+## Promise-Based Asynchronous Transitions
+
+Asynchronous transitions are now implemented using standard javascript [Promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).
+
+If you return a Promise from **any** lifecycle event then the entire lifecycle for that transition
+is put on hold until that Promise gets resolved. If the promise is rejected then the transition
+is cancelled.
+
+Version 2.x:
+
+```javascript
+ var fsm = StateMachine.create({
+ events: [
+ { name: 'step', from: 'none', to: 'complete' }
+ ],
+ callbacks: {
+ onbeforestep: function() {
+ $('#ui').fadeOut('fast', function() {
+ fsm.transition();
+ });
+ return StateMachine.ASYNC;
+ }
+ }
+ });
+```
+
+**Version 3.x**:
+
+```javascript
+ var fsm = new StateMachine({
+ transitions: [
+ { name: 'step', from: 'none', to: 'complete' }
+ ],
+ methods: {
+ onBeforeStep: function() {
+ return new Promise(function(resolve, reject) { // <-- return a Promise instead of StateMachine.ASYNC
+ $('#ui').fadeOut('fast', resolve); // <-- resolve the promise instead of calling .transition()
+ });
+ }
+ }
+ });
+```
+
+> For more details, read [Asynchronous Transitions](async-transitions.md)
+
+## Conditional Transitions
+
+A transition can now be conditional and choose the target state at run-time by providing a function
+as the `to` attribute.
+
+Version 2.x: _not supported_.
+
+**Version 3.x**: See [Conditional Transitions](states-and-transitions.md#conditional-transitions)
+
+## Goto
+
+The state can now be changed without the need for a predefined transition using a conditional `goto`
+transition:
+
+Version 2.x: _not_supported_.
+
+**Version 3.x**: See [Goto](states-and-transitions.md#goto---changing-state-without-a-transition)
+
+## State History
+
+A state machine can now track and traverse (back/forward) its state history.
+
+Version 2.x: _not supported_.
+
+**Version 3.x**: See [State History](state-history.md)
+
+## Visualization
+
+A state machine can now be visualized as a directed graph using GraphViz `.dot` syntax.
+
+Version 2.x: _not_supported_.
+
+**Version 3.x**: See [Visualization](visualization.md)
+
+## Build System
+
+A new [Webpack](https://webpack.js.org/concepts/) based build system has been provided along
+with an [Ava](https://github.com/avajs/ava) based unit test suite.
+
+Version 2.x: _not_supported_.
+
+**Version 3.x**: See [Contributing](contributing.md)
+
+## Other Breaking Changes in Version 3.0
+
+`isFinished` is no longer built-in, you can easily add it to your state machine with a custom method:
+
+```javascript
+ var fsm = new StateMachine({
+ methods: {
+ isFinished: function() { return this.state === 'done' }
+ }
+ })
+```
+
+# UPGRADE SUMMARY
+
+The following list summarizes the above changes you might need when upgrading to version 3.0
+
+ * replace `StateMachine.create()` with `new StateMachine()`
+ * rename:
+ * `initial` to `init`
+ * `events` to `transitions`
+ * `callbacks` to `methods`
+ * `fsm.current` to `fsm.state`
+ * update your callback methods:
+ * rename them to use traditional javascript `camelCasing`
+ * refactor them to use the single `lifecycle` argument instead of individual `event,from,to` arguments
+ * update any asynchronous callback methods:
+ * return a `Promise` instead of `StateMachine.ASYNC`
+ * `resolve()` the promise when ready instead of calling `fsm.transition()`
+ * replace `StateMachine.create({ target: FOO })` with:
+ * if FOO is a class - `StateMachine.factory(FOO, {})`
+ * if FOO is an object - `StateMachine.apply(FOO, {})`
+
diff --git a/docs/zh-cn/visualization.md b/docs/zh-cn/visualization.md
new file mode 100644
index 0000000..65695ad
--- /dev/null
+++ b/docs/zh-cn/visualization.md
@@ -0,0 +1,213 @@
+# 可视化
+
+想流程图一样可视化你的状态机可能非常有用,如果我们使用`visualize`方法转化我们的状态机配置到`.dot`语言,那么可以使用开源的[GraphViz](http://www.graphviz.org/)库来可视化。
+
+```javascript
+ var visualize = require('javascript-state-machine/lib/visualize');
+
+ var fsm = new StateMachine({
+ init: 'open',
+ transitions: [
+ { name: 'close', from: 'open', to: 'closed' },
+ { name: 'open', from: 'closed', to: 'open' }
+ ]
+ });
+
+ visualize(fsm)
+ console.log(visualize(fsm));
+```
+
+生成下面的 .dot 语句:
+
+```dot
+ digraph "fsm" {
+ "closed";
+ "open";
+ "closed" -> "open" [ label=" open " ];
+ "open" -> "closed" [ label=" close " ];
+ }
+```
+
+GraphViz会像这样显示:
+
+![door](../../examples/vertical_door.png)
+
+## 增强显示
+
+You can customize the generated `.dot` output - and hence the graphviz visualization - by attaching
+`dot` attributes to your transitions and (optionally) declaring an `orientation`:
+
+```javascript
+ var fsm = new StateMachine({
+ init: 'closed',
+ transitions: [
+ { name: 'open', from: 'closed', to: 'open', dot: { color: 'blue', headport: 'n', tailport: 'n' } },
+ { name: 'close', from: 'open', to: 'closed', dot: { color: 'red', headport: 's', tailport: 's' } }
+ ]
+ });
+ visualize(fsm, { name: 'door', orientation: 'horizontal' });
+ console.log(visualize(fsm, { name: 'door', orientation: 'horizontal' }));
+```
+
+生成下面的.dot 语句:
+
+```dot
+ digraph "door" {
+ rankdir=LR;
+ "closed";
+ "open";
+ "closed" -> "open" [ color="blue" ; headport="n" ; label=" open " ; tailport="n" ];
+ "open" -> "closed" [ color="red" ; headport="s" ; label=" close " ; tailport="s" ];
+ }
+```
+
+GraphViz会像这样显示:
+
+![door](../../examples/horizontal_door.png)
+
+## 可视化状态机工厂
+
+You can use the same `visualize` method to generate `.dot` output for a state machine factory:
+
+```javascript
+ var Matter = StateMachine.factory({
+ init: 'solid',
+ transitions: [
+ { name: 'melt', from: 'solid', to: 'liquid', dot: { headport: 'nw' } },
+ { name: 'freeze', from: 'liquid', to: 'solid', dot: { headport: 'se' } },
+ { name: 'vaporize', from: 'liquid', to: 'gas', dot: { headport: 'nw' } },
+ { name: 'condense', from: 'gas', to: 'liquid', dot: { headport: 'se' } }
+ ]
+ });
+
+ visualize(Matter, { name: 'matter', orientation: 'horizontal' })
+ console.log(visualize(Matter, { name: 'matter', orientation: 'horizontal' }))
+```
+
+生成下面的.dot 语句:
+
+```dot
+ digraph "matter" {
+ rankdir=LR;
+ "solid";
+ "liquid";
+ "gas";
+ "solid" -> "liquid" [ headport="nw" ; label=" melt " ];
+ "liquid" -> "solid" [ headport="se" ; label=" freeze " ];
+ "liquid" -> "gas" [ headport="nw" ; label=" vaporize " ];
+ "gas" -> "liquid" [ headport="se" ; label=" condense " ];
+ }
+```
+
+GraphViz会像这样显示:
+
+![matter](../../examples/matter.png)
+
+## 其他示例
+
+```javascript
+ var Wizard = StateMachine.factory({
+ init: 'A',
+ transitions: [
+ { name: 'step', from: 'A', to: 'B', dot: { headport: 'w', tailport: 'ne' } },
+ { name: 'step', from: 'B', to: 'C', dot: { headport: 'w', tailport: 'e' } },
+ { name: 'step', from: 'C', to: 'D', dot: { headport: 'w', tailport: 'e' } },
+ { name: 'reset', from: [ 'B', 'C', 'D' ], to: 'A', dot: { headport: 'se', tailport: 's' } }
+ ]
+ });
+
+ visualize(Wizard, { orientation: 'horizontal' })
+ console.log(visualize(Wizard, { orientation: 'horizontal' }))
+```
+
+生成下面的.dot 语句:
+
+```dot
+ digraph "wizard" {
+ rankdir=LR;
+ "A";
+ "B";
+ "C";
+ "D";
+ "A" -> "B" [ headport="w" ; label=" step " ; tailport="ne" ];
+ "B" -> "C" [ headport="w" ; label=" step " ; tailport="e" ];
+ "C" -> "D" [ headport="w" ; label=" step " ; tailport="e" ];
+ "B" -> "A" [ headport="se" ; label=" reset " ; tailport="s" ];
+ "C" -> "A" [ headport="se" ; label=" reset " ; tailport="s" ];
+ "D" -> "A" [ headport="se" ; label=" reset " ; tailport="s" ];
+ }
+```
+
+GraphViz会像这样显示:
+
+![wizard](../../examples/wizard.png)
+
+```javascript
+ var ATM = StateMachine.factory({
+ init: 'ready',
+ transitions: [
+ { name: 'insert-card', from: 'ready', to: 'pin' },
+ { name: 'confirm', from: 'pin', to: 'action' },
+ { name: 'reject', from: 'pin', to: 'return-card' },
+ { name: 'withdraw', from: 'return-card', to: 'ready' },
+
+ { name: 'deposit', from: 'action', to: 'deposit-account' },
+ { name: 'provide', from: 'deposit-account', to: 'deposit-amount' },
+ { name: 'provide', from: 'deposit-amount', to: 'confirm-deposit' },
+ { name: 'confirm', from: 'confirm-deposit', to: 'collect-envelope' },
+ { name: 'provide', from: 'collect-envelope', to: 'continue' },
+
+ { name: 'withdraw', from: 'action', to: 'withdrawal-account' },
+ { name: 'provide', from: 'withdrawal-account', to: 'withdrawal-amount' },
+ { name: 'provide', from: 'withdrawal-amount', to: 'confirm-withdrawal' },
+ { name: 'confirm', from: 'confirm-withdrawal', to: 'dispense-cash' },
+ { name: 'withdraw', from: 'dispense-cash', to: 'continue' },
+
+ { name: 'continue', from: 'continue', to: 'action' },
+ { name: 'finish', from: 'continue', to: 'return-card' }
+ ]
+ })
+
+ visualize(ATM)
+ console.log(visualize(ATM))
+```
+
+生成下面的.dot 语句:
+
+```dot
+ digraph "ATM" {
+ "ready";
+ "pin";
+ "action";
+ "return-card";
+ "deposit-account";
+ "deposit-amount";
+ "confirm-deposit";
+ "collect-envelope";
+ "continue";
+ "withdrawal-account";
+ "withdrawal-amount";
+ "confirm-withdrawal";
+ "dispense-cash";
+ "ready" -> "pin" [ label=" insert-card " ];
+ "pin" -> "action" [ label=" confirm " ];
+ "pin" -> "return-card" [ label=" reject " ];
+ "return-card" -> "ready" [ label=" withdraw " ];
+ "action" -> "deposit-account" [ label=" deposit " ];
+ "deposit-account" -> "deposit-amount" [ label=" provide " ];
+ "deposit-amount" -> "confirm-deposit" [ label=" provide " ];
+ "confirm-deposit" -> "collect-envelope" [ label=" confirm " ];
+ "collect-envelope" -> "continue" [ label=" provide " ];
+ "action" -> "withdrawal-account" [ label=" withdraw " ];
+ "withdrawal-account" -> "withdrawal-amount" [ label=" provide " ];
+ "withdrawal-amount" -> "confirm-withdrawal" [ label=" provide " ];
+ "confirm-withdrawal" -> "dispense-cash" [ label=" confirm " ];
+ "dispense-cash" -> "continue" [ label=" withdraw " ];
+ "continue" -> "action" [ label=" continue " ];
+ "continue" -> "return-card" [ label=" finish " ];
+ }
+```
+
+GraphViz会像这样显示:
+
+![atm](../../examples/atm.png)