root 2 éve
szülő
commit
40435d453e
100 módosított fájl, 15438 hozzáadás és 0 törlés
  1. 5 0
      kityminder-editor/.bowerrc
  2. 7 0
      kityminder-editor/.gitignore
  3. 103 0
      kityminder-editor/.jscsrc
  4. 16 0
      kityminder-editor/.jshintrc
  5. 202 0
      kityminder-editor/Gruntfile.js
  6. 340 0
      kityminder-editor/LICENSE
  7. 87 0
      kityminder-editor/README.md
  8. 67 0
      kityminder-editor/bower.json
  9. BIN
      kityminder-editor/dist/favicon.ico
  10. BIN
      kityminder-editor/dist/images/iconpriority.png
  11. BIN
      kityminder-editor/dist/images/iconprogress.png
  12. BIN
      kityminder-editor/dist/images/icons.png
  13. BIN
      kityminder-editor/dist/images/template.png
  14. 90 0
      kityminder-editor/dist/index.html
  15. 1528 0
      kityminder-editor/dist/kityminder.editor.css
  16. 0 0
      kityminder-editor/dist/kityminder.editor.css.map
  17. 2102 0
      kityminder-editor/dist/kityminder.editor.js
  18. 0 0
      kityminder-editor/dist/kityminder.editor.min.css
  19. 10 0
      kityminder-editor/dist/kityminder.editor.min.js
  20. BIN
      kityminder-editor/favicon.ico
  21. 119 0
      kityminder-editor/index.html
  22. 127 0
      kityminder-editor/less/_navigator.less
  23. 24 0
      kityminder-editor/less/_tool_group.less
  24. 7 0
      kityminder-editor/less/_vars.less
  25. 135 0
      kityminder-editor/less/editor.less
  26. 8 0
      kityminder-editor/less/imageDialog.less
  27. 77 0
      kityminder-editor/less/topTab/appearance/colorPanel.less
  28. 160 0
      kityminder-editor/less/topTab/appearance/fontOperator.less
  29. 65 0
      kityminder-editor/less/topTab/appearance/layout.less
  30. 83 0
      kityminder-editor/less/topTab/appearance/styleOperator.less
  31. 71 0
      kityminder-editor/less/topTab/appearance/templatePanel.less
  32. 53 0
      kityminder-editor/less/topTab/appearance/themePanel.less
  33. 21 0
      kityminder-editor/less/topTab/idea/appendNode.less
  34. 15 0
      kityminder-editor/less/topTab/idea/arrange.less
  35. 43 0
      kityminder-editor/less/topTab/idea/hyperlink.less
  36. 129 0
      kityminder-editor/less/topTab/idea/image.less
  37. 48 0
      kityminder-editor/less/topTab/idea/note.less
  38. 168 0
      kityminder-editor/less/topTab/idea/noteEditor.less
  39. 15 0
      kityminder-editor/less/topTab/idea/operation.less
  40. 26 0
      kityminder-editor/less/topTab/idea/priority.less
  41. 26 0
      kityminder-editor/less/topTab/idea/progress.less
  42. 83 0
      kityminder-editor/less/topTab/idea/resource.less
  43. 15 0
      kityminder-editor/less/topTab/idea/undoRedo.less
  44. 59 0
      kityminder-editor/less/topTab/searchBox.less
  45. 89 0
      kityminder-editor/less/topTab/topTab.less
  46. 39 0
      kityminder-editor/less/topTab/view/expand.less
  47. 39 0
      kityminder-editor/less/topTab/view/search.less
  48. 38 0
      kityminder-editor/less/topTab/view/select.less
  49. 5885 0
      kityminder-editor/package-lock.json
  50. 59 0
      kityminder-editor/package.json
  51. BIN
      kityminder-editor/relations.png
  52. 67 0
      kityminder-editor/server/imageUpload.php
  53. 40 0
      kityminder-editor/src/editor.js
  54. 11 0
      kityminder-editor/src/expose-editor.js
  55. 3 0
      kityminder-editor/src/hotbox.js
  56. 3 0
      kityminder-editor/src/lang.js
  57. 3 0
      kityminder-editor/src/minder.js
  58. 123 0
      kityminder-editor/src/runtime/clipboard-mimetype.js
  59. 188 0
      kityminder-editor/src/runtime/clipboard.js
  60. 33 0
      kityminder-editor/src/runtime/container.js
  61. 140 0
      kityminder-editor/src/runtime/drag.js
  62. 121 0
      kityminder-editor/src/runtime/fsm.js
  63. 133 0
      kityminder-editor/src/runtime/history.js
  64. 56 0
      kityminder-editor/src/runtime/hotbox.js
  65. 395 0
      kityminder-editor/src/runtime/input.js
  66. 184 0
      kityminder-editor/src/runtime/jumping.js
  67. 31 0
      kityminder-editor/src/runtime/minder.js
  68. 112 0
      kityminder-editor/src/runtime/node.js
  69. 51 0
      kityminder-editor/src/runtime/priority.js
  70. 52 0
      kityminder-editor/src/runtime/progress.js
  71. 146 0
      kityminder-editor/src/runtime/receiver.js
  72. 47 0
      kityminder-editor/src/tool/debug.js
  73. 11 0
      kityminder-editor/src/tool/format.js
  74. 54 0
      kityminder-editor/src/tool/innertext.js
  75. 91 0
      kityminder-editor/src/tool/jsondiff.js
  76. 69 0
      kityminder-editor/src/tool/key.js
  77. 82 0
      kityminder-editor/src/tool/keymap.js
  78. 47 0
      kityminder-editor/ui/dialog/hyperlink/hyperlink.ctrl.js
  79. 26 0
      kityminder-editor/ui/dialog/hyperlink/hyperlink.tpl.html
  80. 95 0
      kityminder-editor/ui/dialog/imExportNode/imExportNode.ctrl.js
  81. 16 0
      kityminder-editor/ui/dialog/imExportNode/imExportNode.tpl.html
  82. 114 0
      kityminder-editor/ui/dialog/image/image.ctrl.js
  83. 69 0
      kityminder-editor/ui/dialog/image/image.tpl.html
  84. 31 0
      kityminder-editor/ui/directive/appendNode/appendNode.directive.js
  85. 23 0
      kityminder-editor/ui/directive/appendNode/appendNode.html
  86. 16 0
      kityminder-editor/ui/directive/arrange/arrange.directive.js
  87. 16 0
      kityminder-editor/ui/directive/arrange/arrange.html
  88. 33 0
      kityminder-editor/ui/directive/colorPanel/colorPanel.directive.js
  89. 16 0
      kityminder-editor/ui/directive/colorPanel/colorPanel.html
  90. 15 0
      kityminder-editor/ui/directive/expandLevel/expandLevel.directive.js
  91. 21 0
      kityminder-editor/ui/directive/expandLevel/expandLevel.html
  92. 83 0
      kityminder-editor/ui/directive/fontOperator/fontOperator.directive.js
  93. 51 0
      kityminder-editor/ui/directive/fontOperator/fontOperator.html
  94. 35 0
      kityminder-editor/ui/directive/hyperLink/hyperLink.directive.js
  95. 27 0
      kityminder-editor/ui/directive/hyperLink/hyperLink.html
  96. 35 0
      kityminder-editor/ui/directive/imageBtn/imageBtn.directive.js
  97. 27 0
      kityminder-editor/ui/directive/imageBtn/imageBtn.html
  98. 71 0
      kityminder-editor/ui/directive/kityminderEditor/kityminderEditor.directive.js
  99. 8 0
      kityminder-editor/ui/directive/kityminderEditor/kityminderEditor.html
  100. 34 0
      kityminder-editor/ui/directive/kityminderViewer/kityminderViewer.directive.js

+ 5 - 0
kityminder-editor/.bowerrc

@@ -0,0 +1,5 @@
+{
+    "directory": "bower_components",
+    "allow_root": true,
+    "registry": "https://registry.bower.io"
+}

+ 7 - 0
kityminder-editor/.gitignore

@@ -0,0 +1,7 @@
+.idea
+.DS_Store
+bower_components/
+node_modules/
+ui/templates.js
+.tmp/
+upload/

+ 103 - 0
kityminder-editor/.jscsrc

@@ -0,0 +1,103 @@
+/**
+ * FEX Style Guide (Javascript)
+ *
+ * TODO:
+ *
+ * 1. 找不到选项:每行只允许一个语句
+ * 2. 找不到选项:块状代码需要用大括号括起来
+ */
+{
+    // 缩进「MUST」使用 4 个空格
+    "validateIndentation": 4,
+
+    // 大括号(块状代码)前「MUST」使用空格
+    "requireSpaceBeforeBlockStatements": true,
+
+    // 下列关键字「MUST」使用空格
+    "requireSpaceAfterKeywords": ["if", "else", "for", "while",
+        "do", "try", "catch", "finally"
+    ],
+
+    // `,` 和 `;` 前面不允许「MUST NOT」使用空格。
+    "requireLeftStickedOperators": [",", ";"],
+
+    // 二元运算符前后「MUST」使用空格
+    "requireSpaceBeforeBinaryOperators": [
+        "+",
+        "-",
+        "*",
+        "/",
+        "=",
+        "==",
+        "===",
+        "!=",
+        "!==",
+        "|",
+        "||",
+        "&",
+        "&&"
+    ],
+    "requireSpaceAfterBinaryOperators": [
+        "+",
+        "-",
+        "*",
+        "/",
+        "=",
+        "==",
+        "===",
+        "!=",
+        "!==",
+        "|",
+        "||",
+        "&",
+        "&&",
+        ":"
+    ],
+
+    // 一元运算符与操作对象间「MUST NOT」使用空格
+    "disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~", "!"],
+
+    // 函数参数小括号前「MUST NOT」使用空格
+    "disallowSpacesInFunctionExpression": {
+        "beforeOpeningRoundBrace": true
+    },
+
+    // 小括号里面「MUST NOT」使用空格
+    "disallowSpacesInsideParentheses": true,
+
+    // 行尾「MUST NOT」使用空格
+    "disallowTrailingWhitespace": true,
+
+    // 每行「MUST NOT」超过 120 个字符
+    "maximumLineLength": 120,
+
+    // 一下操作符「MUST NOT」放在一行的最前面,需要放在上一行的后面
+    "requireOperatorBeforeLineBreak": [
+        "?",
+        "+",
+        "-",
+        "/",
+        "*",
+        "=",
+        "==",
+        "===",
+        "!=",
+        "!==",
+        ">",
+        ">=",
+        "<",
+        "<=",
+        ",",
+        ";",
+        "&&",
+        "&",
+        "||",
+        "|"
+    ],
+
+    // 字符串统一「MUST」使用单引号
+    "validateQuoteMarks": "'",
+
+    // 「MUST NOT」使用多行字符串
+    "disallowMultipleLineStrings": true
+}

+ 16 - 0
kityminder-editor/.jshintrc

@@ -0,0 +1,16 @@
+{
+    "undef" : true,
+    "unused" : false,
+    "strict" : false,
+    "curly" : false,
+    "newcap" : true,
+    "trailing" : true,
+    "white": false,
+    "quotmark": false,
+    "browser": true,
+    "boss": true,
+    "indent": 4,
+    "predef" : [
+        "define"
+    ]
+}

+ 202 - 0
kityminder-editor/Gruntfile.js

@@ -0,0 +1,202 @@
+/* global require, module */
+
+var path = require('path');
+
+module.exports = function(grunt) {
+    'use strict';
+
+	// Load grunt tasks automatically
+	require('load-grunt-tasks')(grunt);
+    grunt.loadNpmTasks('grunt-browser-sync');
+    grunt.loadNpmTasks('grunt-contrib-watch');
+
+    var pkg = grunt.file.readJSON('package.json');
+
+	var appConfig = {
+		app: require('./bower.json').appPath || 'app',
+		dist: 'dist'
+	};
+
+    var banner = '/*!\n' +
+        ' * ====================================================\n' +
+        ' * <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' +
+        '<%= grunt.template.today("yyyy-mm-dd") %>\n' +
+        '<%= pkg.homepage ? " * " + pkg.homepage + "\\n" : "" %>' +
+        ' * GitHub: <%= pkg.repository.url %> \n' +
+        ' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
+        ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %>\n' +
+        ' * ====================================================\n' +
+        ' */\n\n';
+
+    var expose = '\nuse(\'expose-editor\');\n';
+
+    // Project configuration.
+    grunt.initConfig({
+
+        // Metadata.
+        pkg: pkg,
+
+	    yeoman: appConfig,
+
+        clean: {
+            last: [
+	            '.tmp',
+	            'dist/*.js',
+	            'dist/*.css',
+	            'dist/*.css.map'
+            ],
+	        clstmp: ['.tmp']
+        },
+
+        // resolve dependence
+        dependence: {
+            options: {
+                base: 'src',
+                entrance: 'expose-editor'
+            },
+            merge: {
+                files: [{
+                    src: [
+                        'src/**/*.js'
+                    ],
+                    dest: '.tmp/scripts/kityminder.editor.logic.js'
+                }]
+            }
+        },
+
+        // browser sync for dev
+		browserSync: {
+            bsFiles: {
+                dist: 'dist/css/*.css',
+                src: 'src/**'
+            },
+            options: {
+                server: {
+                    baseDir: './',
+                    index: 'index.html',
+                    watchTask: true
+                }
+            }
+		},
+
+        // concat
+        concat: {
+            closure: {
+                options: {
+                    banner: banner + '(function () {\n',
+                    footer: expose + '})();'
+                },
+                files: {
+	                'dist/kityminder.editor.js': [
+		                '.tmp/scripts/kityminder.editor.logic.js',
+		                '.tmp/scripts/kityminder.app.annotated.js',
+		                '.tmp/scripts/templates.annotated.js',
+		                '.tmp/scripts/service/*.js',
+		                '.tmp/scripts/filter/*.js',
+                        '.tmp/scripts/dialog/**/*.js',
+		                '.tmp/scripts/directive/**/*.js'
+	                ]
+                }
+            }
+        },
+
+        uglify: {
+            options: {
+                banner: banner
+            },
+            minimize: {
+                files: [{
+	                src: 'dist/kityminder.editor.js',
+	                dest: 'dist/kityminder.editor.min.js'
+                }]
+            }
+        },
+
+        less: {
+            compile: {
+                options: {
+                    sourceMap: true,
+	                sourceMapURL: 'kityminder.editor.css.map',
+                    sourceMapFilename: 'dist/kityminder.editor.css.map'
+                },
+                files: [{
+                    dest: 'dist/kityminder.editor.css',
+                    src: 'less/editor.less'
+                }]
+            }
+        },
+
+	    cssmin: {
+	        dist: {
+	            files: {
+	                'dist/kityminder.editor.min.css': 'dist/kityminder.editor.css'
+	         }
+	       }
+	    },
+
+	    ngtemplates: {
+		    kityminderEditor: {
+			    src: ['ui/directive/**/*.html', 'ui/dialog/**/*.html'],
+			    dest: 'ui/templates.js',
+			    options: {
+				    htmlmin: {
+					    collapseBooleanAttributes: true,
+					    collapseWhitespace: true,
+					    removeComments: true
+				    }
+			    }
+		    }
+	    },
+
+	    // Automatically inject Bower components into the app
+	    wiredep: {
+		    dev: {
+			    src: ['index.html'],
+			    devDependencies: true
+		    },
+		    dist: {
+			    src: ['dist/index.html']
+		    }
+	    },
+
+	    // Copies remaining files to places other tasks can use
+	    copy: {
+		    dist: {
+				files: [{
+				    expand: true,
+				    cwd: 'ui',
+					src: 'images/*',
+				    dest: 'dist'
+
+			    }]
+		    }
+	    },
+
+
+	    // ng-annotate tries to make the code safe for minification automatically
+	    // by using the Angular long form for dependency injection.
+	    ngAnnotate: {
+		    dist: {
+			    files: [{
+				    expand: true,
+				    cwd: 'ui/',
+				    src: '**/*.js',
+				    ext: '.annotated.js',
+				    extDot: 'last',
+				    dest: '.tmp/scripts/'
+			    }]
+		    }
+	    }
+
+
+    });
+
+    // Build task(s).
+	grunt.registerTask('build', ['clean:last',
+		//'wiredep:dist',
+        'ngtemplates', 'dependence', 'ngAnnotate', 'concat', 'uglify', 'less', 'cssmin', 'copy', 'clean:clstmp']);
+
+	grunt.registerTask('dev', ['clean:last',
+        //'wiredep:dev',
+        'ngtemplates', 'dependence', 'ngAnnotate', 'concat', 'uglify', 'less', 'cssmin', 'copy', 'clean:clstmp', 'browserSync', 'watch']);
+};

+ 340 - 0
kityminder-editor/LICENSE

@@ -0,0 +1,340 @@
+GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    {description}
+    Copyright (C) {year}  {fullname}
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  {signature of Ty Coon}, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
+

+ 87 - 0
kityminder-editor/README.md

@@ -0,0 +1,87 @@
+KityMinder Editor
+==========
+
+## 简介
+
+KityMinder Editor 是一款强大、简洁、体验优秀的脑图编辑工具,适合用于编辑树/图/网等结构的数据。
+
+编辑器由百度 [FEX](https://github.com/fex-team) 基于 [kityminder-core](https://github.com/fex-team/kityminder-core) 搭建,并且在[百度脑图](http://naotu.baidu.com)中使用。
+
+他们的区别与联系如下:
+
+![KityMinder 联系](relations.png "KityMinder 联系")
+
+- [kityminder-core](https://github.com/fex-team/kityminder-core) 是 kityminder 的核心部分,基于百度 [FEX](https://github.com/fex-team) 开发的矢量图形库 [kity](https://github.com/fex-team/kity)。包含了脑图数据的可视化展现,简单编辑功能等所有底层支持。
+- [kityminder-editor](https://github.com/fex-team/kityminder-editor) 基于 kityminder-core 搭建,依赖于 AngularJS,包含 UI 和热盒 [hotbox](https://github.com/fex-team/hotbox) 等方便用户输入的功能,简单来说,就是一款编辑器。
+- [百度脑图](http://naotu.baidu.com) 基于 kityminder-editor,加入了第三方格式导入导出 (FreeMind, XMind, MindManager) 、文件储存、用户认证、文件分享、历史版本等业务逻辑。
+
+## 功能
+
+- 基本操作:文本编辑,节点折叠、插入、删除、排序、归纳、复制、剪切、粘贴等
+- 样式控制:字体、加粗、斜体、颜色、样式拷贝、样式粘贴等
+- 图标:优先级、进度等
+- 历史:撤销/重做
+- 标签:多标签贴入
+- 备注:支持 Markdown 格式备注
+- 图片:支持本地/网络/搜索图片插入
+- 超链接:支持 HTTP/HTTPS/MAIL/FTP 链接插入
+- 布局:支持多种布局切换
+- 主题:支持多种主题切换
+- 数据导入导出:支持多种格式的导入,多种格式(包括图片)的导出
+- 缩略图:支持缩略图查看/导航
+
+## 开发使用
+根目录下的 `index.html` 为开发环境,`dist` 目录下的 `index.html` 使用打包好的代码,适用于线上环境。
+
+1. 安装 [nodejs](http://nodejs.org) 和 [npm](https://docs.npmjs.com/getting-started/installing-node)
+2. 初始化:切到 kityminder-editor 根目录下运行 `npm run init`
+3. 在 kityminder-editor 根目录下运行 `grunt dev` 即可启动项目
+4. 你可以基于根目录的 `index.html` 开发,或者查看 `dist` 目录下用于生产环境的 `index.html`,Enjoy it!
+
+另外,kityminder-editor 还提供了 bower 包,方便开发者直接使用。你可以在需要用到 kityminder-editor 的工程目录下
+运行 `bower install kityminder-editor`,接着手动引入 kityminder-editor 所依赖的 css 和 js 文件,具体文件见
+`dist` 目录下的 `index.html`,推荐使用 npm 包 [wireDep](https://www.npmjs.com/package/wiredep) 自动进行,
+可参考根目录下 `Gruntfile.js`。
+
+## 构建
+运行 `grunt build`,完成后 `dist` 目录里就是可用运行的 kityminder-editor, 双击 `index.html` 即可打开运行示例
+
+## 初始化配置
+用户可以根据需要,配置 `kityminder-editor`, 具体使用方法如下:
+```
+angular.module('kityminderDemo', ['kityminderEditor'])
+    .config(function (configProvider) {
+        configProvider.set('imageUpload', 'path/to/image/upload/handler');
+    });
+
+```
+
+## 数据导入导出
+由于 kityminder-editor 是基于 kityminder-core 搭建的,而 kityminder-core 内置了五种常见
+格式的导入或导出,在创建编辑器实例之后,可以使用四个接口进行数据的导入导出。
+
+* `editor.minder.exportJson()` - 导出脑图数据为 JSON 对象
+* `editor.minder.importJson(json)` - 导入 JSON 对象为当前脑图数据
+* `editor.minder.exportData(protocol, option)` - 导出脑图数据为指定的数据格式,返回一个 Promise,其值为导出的结果
+* `editor.minder.importData(protocol, data, option)` - 导入指定格式的数据为脑图数据,返回一个 Promise,其值为转换之后的脑图 Json 数据
+
+目前支持的数据格式包括:
+
+* `json` - JSON 字符串,支持导入和导出
+* `text` - 纯文本格式,支持导入和导出
+* `markdown` - Markdown 格式,支持导入和导出
+* `svg` - SVG 矢量格式,仅支持导出
+* `png` - PNG 位图格式,仅支持导出
+
+更多格式的支持,可以加载 [kityminder-protocol](https://github.com/fex-team/kityminder-protocol) 来扩展第三方格式支持。
+
+数据格式的具体信息,可参考 [kityminder-core-wiki 的中的说明](https://github.com/fex-team/kityminder-core/wiki)。
+
+## 联系我们
+问题和建议反馈:
+
+[Github issues](https://github.com/fex-team/kityminder-editor/issues)
+
+邮件组:kity@baidu.com
+
+QQ 讨论群:475962105

+ 67 - 0
kityminder-editor/bower.json

@@ -0,0 +1,67 @@
+{
+  "name": "kityminder-editor",
+  "version": "1.0.61",
+  "authors": [
+    "fex<fex@baidu.com>"
+  ],
+  "description": "Kity Minder Editor",
+  "main": [
+    "dist/kityminder.editor.js",
+    "dist/kityminder.editor.css"
+  ],
+  "keywords": [
+    "kityminder",
+    "fex",
+    "ui",
+    "javascript",
+    "html5",
+    "svg"
+  ],
+  "license": "BSD",
+  "homepage": "https://github.com/fex-team/kityminder-editor",
+  "ignore": [
+    "**/.*",
+    "node_modules",
+    "bower_components",
+    "test",
+    "tests",
+    "less",
+    "ui",
+    "src",
+    "Gruntfile.js",
+    "package.json"
+  ],
+  "devDependencies": {
+    "seajs": "~2.3.0"
+  },
+  "dependencies": {
+    "bootstrap": "~3.3.4",
+    "angular": "~1.3.15",
+    "angular-bootstrap": "~0.12.1",
+    "angular-ui-codemirror": "~0.2.3",
+    "codemirror": "~4.8.0",
+    "marked": "git://github.com/chjj/marked.git#master",
+    "hotbox": "~1.0.2",
+    "color-picker": "~1.0.2",
+    "kity": "^2.0.5",
+    "json-diff": "*"
+  },
+  "overrides": {
+    "codemirror": {
+      "main": [
+        "lib/codemirror.js",
+        "lib/codemirror.css",
+        "mode/xml/xml.js",
+        "mode/javascript/javascript.js",
+        "mode/css/css.js",
+        "mode/htmlmixed/htmlmixed.js",
+        "mode/markdown/markdown.js",
+        "addon/mode/overlay.js",
+        "mode/gfm/gfm.js"
+      ]
+    }
+  },
+  "resolutions": {
+    "angular": "~1.3.8"
+  }
+}

BIN
kityminder-editor/dist/favicon.ico


BIN
kityminder-editor/dist/images/iconpriority.png


BIN
kityminder-editor/dist/images/iconprogress.png


BIN
kityminder-editor/dist/images/icons.png


BIN
kityminder-editor/dist/images/template.png


+ 90 - 0
kityminder-editor/dist/index.html

@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<html>
+<head>
+	<meta charset="utf-8">
+	<title>KityMinder Editor - Powered By FEX</title>
+
+	<link href="favicon.ico" type="image/x-icon" rel="shortcut icon">
+
+	<!-- bower:css -->
+	<link rel="stylesheet" href="../bower_components/bootstrap/dist/css/bootstrap.css" />
+	<link rel="stylesheet" href="../bower_components/codemirror/lib/codemirror.css" />
+	<link rel="stylesheet" href="../bower_components/hotbox/hotbox.css" />
+	<link rel="stylesheet" href="../node_modules/kityminder-core/dist/kityminder.core.css" />
+	<link rel="stylesheet" href="../bower_components/color-picker/dist/color-picker.min.css" />
+	<!-- endbower -->
+
+	<link rel="stylesheet" href="kityminder.editor.min.css">
+
+	<style>
+		html, body {
+			margin: 0;
+			padding: 0;
+			height: 100%;
+			overflow: hidden;
+		}
+		h1.editor-title {
+			background: #393F4F;
+			color: white;
+			margin: 0;
+			height: 40px;
+			font-size: 14px;
+			line-height: 40px;
+			font-family: 'Hiragino Sans GB', 'Arial', 'Microsoft Yahei';
+			font-weight: normal;
+			padding: 0 20px;
+		}
+		div.minder-editor-container {
+			position: absolute;
+			top: 40px;
+			bottom: 0;
+			left: 0;
+			right: 0;
+		}
+	</style>
+</head>
+<body ng-app="kityminderDemo" ng-controller="MainController">
+<h1 class="editor-title">KityMinder Editor - Powered By FEX</h1>
+<kityminder-editor on-init="initEditor(editor, minder)"></kityminder-editor>
+</body>
+
+<!-- bower:js -->
+<script src="../bower_components/jquery/dist/jquery.js"></script>
+<script src="../bower_components/bootstrap/dist/js/bootstrap.js"></script>
+<script src="../bower_components/angular/angular.js"></script>
+<script src="../bower_components/angular-bootstrap/ui-bootstrap-tpls.js"></script>
+<script src="../bower_components/codemirror/lib/codemirror.js"></script>
+<script src="../bower_components/codemirror/mode/xml/xml.js"></script>
+<script src="../bower_components/codemirror/mode/javascript/javascript.js"></script>
+<script src="../bower_components/codemirror/mode/css/css.js"></script>
+<script src="../bower_components/codemirror/mode/htmlmixed/htmlmixed.js"></script>
+<script src="../bower_components/codemirror/mode/markdown/markdown.js"></script>
+<script src="../bower_components/codemirror/addon/mode/overlay.js"></script>
+<script src="../bower_components/codemirror/mode/gfm/gfm.js"></script>
+<script src="../bower_components/angular-ui-codemirror/ui-codemirror.js"></script>
+<script src="../bower_components/marked/lib/marked.js"></script>
+<script src="../bower_components/kity/dist/kity.min.js"></script>
+<script src="../bower_components/hotbox/hotbox.js"></script>
+<script src="../bower_components/json-diff/json-diff.js"></script>
+<script src="../node_modules/kityminder-core/dist/kityminder.core.min.js"></script>
+<script src="../bower_components/color-picker/dist/color-picker.min.js"></script>
+<!-- endbower -->
+
+<script src="kityminder.editor.min.js"></script>
+
+
+<script>
+	angular.module('kityminderDemo', ['kityminderEditor'])
+			.config(function (configProvider) {
+				configProvider.set('imageUpload', '../server/imageUpload.php');
+			})
+			.controller('MainController', function($scope) {
+				$scope.initEditor = function(editor, minder) {
+					window.editor = editor;
+					window.minder = minder;
+				};
+			});
+
+</script>
+
+</html>

+ 1528 - 0
kityminder-editor/dist/kityminder.editor.css

@@ -0,0 +1,1528 @@
+.km-editor {
+  overflow: hidden;
+  z-index: 2;
+}
+.km-editor > .mask {
+  display: block;
+  position: absolute;
+  left: 0;
+  right: 0;
+  top: 0;
+  bottom: 0;
+  background-color: transparent;
+}
+.km-editor > .receiver {
+  position: absolute;
+  background: white;
+  outline: none;
+  box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
+  left: 0;
+  top: 0;
+  padding: 3px 5px;
+  margin-left: -3px;
+  margin-top: -5px;
+  max-width: 300px;
+  width: auto;
+  font-size: 14px;
+  line-height: 1.4em;
+  min-height: 1.4em;
+  box-sizing: border-box;
+  overflow: hidden;
+  word-break: break-all;
+  word-wrap: break-word;
+  border: none;
+  -webkit-user-select: text;
+  pointer-events: none;
+  opacity: 0;
+  z-index: -1000;
+}
+.km-editor > .receiver.debug {
+  opacity: 1;
+  outline: 1px solid green;
+  background: none;
+  z-index: 0;
+}
+.km-editor > .receiver.input {
+  pointer-events: all;
+  opacity: 1;
+  z-index: 999;
+  background: white;
+  outline: none;
+}
+div.minder-editor-container {
+  position: absolute;
+  top: 40px;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  font-family: Arial, "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif;
+}
+.minder-editor {
+  position: absolute;
+  top: 92px;
+  left: 0;
+  right: 0;
+  bottom: 0;
+}
+.minder-viewer {
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+}
+.control-panel {
+  position: absolute;
+  top: 0;
+  right: 0;
+  width: 250px;
+  bottom: 0;
+  border-left: 1px solid #CCC;
+}
+.minder-divider {
+  position: absolute;
+  top: 0;
+  right: 250px;
+  bottom: 0;
+  width: 2px;
+  background-color: #fbfbfb;
+  cursor: ew-resize;
+}
+.panel-body {
+  padding: 10px;
+}
+.upload-image {
+  width: 0.1px;
+  height: 0.1px;
+  opacity: 0;
+  overflow: hidden;
+  position: absolute;
+  z-index: -1;
+}
+.top-tab .nav-tabs {
+  background-color: #e1e1e1;
+  border: 0;
+  height: 32px;
+}
+.top-tab .nav-tabs li {
+  margin: 0;
+}
+.top-tab .nav-tabs li a {
+  margin: 0;
+  border: 0;
+  padding: 6px 15px;
+  border-radius: 0;
+  vertical-align: middle;
+}
+.top-tab .nav-tabs li a:hover,
+.top-tab .nav-tabs li a:focus {
+  background: inherit;
+  border: 0;
+}
+.top-tab .nav-tabs li.active a {
+  border: 0;
+  background-color: #fff;
+}
+.top-tab .nav-tabs li.active a:hover,
+.top-tab .nav-tabs li.active a:focus {
+  border: 0;
+}
+.top-tab .tab-content {
+  height: 60px;
+  background-color: #fff;
+  border-bottom: 1px solid #dbdbdb;
+}
+.top-tab .tab-pane {
+  font-size: 0;
+}
+.km-btn-group {
+  display: inline-block;
+  margin: 5px 0;
+  padding: 0 5px;
+  vertical-align: middle;
+  border-right: 1px dashed #eee;
+}
+.km-btn-item {
+  display: inline-block;
+  margin: 0 3px;
+  font-size: 0;
+  cursor: default;
+}
+.km-btn-item[disabled] {
+  opacity: 0.5;
+}
+.km-btn-item[disabled]:hover,
+.km-btn-item[disabled]:active {
+  background-color: #fff;
+}
+.km-btn-item .km-btn-icon {
+  display: inline-block;
+  background: url(images/icons.png) no-repeat;
+  background-position: 0 20px;
+  width: 20px;
+  height: 20px;
+  padding: 2px;
+  margin: 1px;
+  vertical-align: middle;
+}
+.km-btn-item .km-btn-caption {
+  display: inline-block;
+  font-size: 12px;
+  vertical-align: middle;
+}
+.km-btn-item:hover {
+  background-color: #eff3fa;
+}
+.km-btn-item:active {
+  background-color: #c4d0ee;
+}
+.do-group {
+  width: 38px;
+}
+.undo .km-btn-icon {
+  background-position: 0 -1240px;
+}
+.redo .km-btn-icon {
+  background-position: 0 -1220px;
+}
+.append-group {
+  width: 212px;
+}
+.append-child-node .km-btn-icon {
+  background-position: 0 0;
+}
+.append-sibling-node .km-btn-icon {
+  background-position: 0 -20px;
+}
+.append-parent-node .km-btn-icon {
+  background-position: 0 -40px;
+}
+.arrange-group {
+  width: 64px;
+}
+.arrange-up .km-btn-icon {
+  background-position: 0 -280px;
+}
+.arrange-down .km-btn-icon {
+  background-position: 0 -300px;
+}
+.operation-group {
+  width: 64px;
+}
+.edit-node .km-btn-icon {
+  background-position: 0 -60px;
+}
+.remove-node .km-btn-icon {
+  background-position: 0 -80px;
+}
+.btn-group-vertical {
+  vertical-align: middle;
+  margin: 5px;
+}
+.btn-group-vertical .hyperlink,
+.btn-group-vertical .hyperlink-caption {
+  width: 40px;
+  margin: 0;
+  padding: 0;
+  border: none!important;
+  border-radius: 0!important;
+}
+.btn-group-vertical .hyperlink:hover,
+.btn-group-vertical .hyperlink-caption:hover {
+  background-color: #eff3fa;
+}
+.btn-group-vertical .hyperlink:active,
+.btn-group-vertical .hyperlink-caption:active {
+  background-color: #c4d0ee;
+}
+.btn-group-vertical .hyperlink.active,
+.btn-group-vertical .hyperlink-caption.active {
+  box-shadow: none;
+  background-color: #eff3fa;
+}
+.btn-group-vertical .hyperlink {
+  height: 25px;
+  background: url(images/icons.png) no-repeat center -100px;
+}
+.btn-group-vertical .hyperlink-caption {
+  height: 20px;
+}
+.btn-group-vertical .hyperlink-caption .caption {
+  font-size: 12px;
+}
+.open > .dropdown-toggle.btn-default {
+  background-color: #eff3fa;
+}
+.btn-group-vertical .image-btn,
+.btn-group-vertical .image-btn-caption {
+  width: 40px;
+  margin: 0;
+  padding: 0;
+  border: none!important;
+  border-radius: 0!important;
+}
+.btn-group-vertical .image-btn:hover,
+.btn-group-vertical .image-btn-caption:hover {
+  background-color: #eff3fa;
+}
+.btn-group-vertical .image-btn:active,
+.btn-group-vertical .image-btn-caption:active {
+  background-color: #c4d0ee;
+}
+.btn-group-vertical .image-btn.active,
+.btn-group-vertical .image-btn-caption.active {
+  box-shadow: none;
+  background-color: #eff3fa;
+}
+.btn-group-vertical .image-btn {
+  height: 25px;
+  background: url(images/icons.png) no-repeat center -125px;
+}
+.btn-group-vertical .image-btn-caption {
+  height: 20px;
+}
+.btn-group-vertical .image-btn-caption .caption {
+  font-size: 12px;
+}
+.image-preview {
+  display: block;
+  max-width: 50%;
+}
+.modal-body .tab-pane {
+  font-size: inherit;
+  padding-top: 15px;
+}
+.search-result {
+  margin-top: 15px;
+  height: 370px;
+  overflow: hidden;
+}
+.search-result ul {
+  margin: 0;
+  padding: 0;
+  list-style: none;
+  clear: both;
+  height: 100%;
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+.search-result ul li {
+  list-style: none;
+  float: left;
+  display: block;
+  width: 130px;
+  height: 130px;
+  line-height: 130px;
+  margin: 6px;
+  padding: 0;
+  font-size: 12px;
+  position: relative;
+  vertical-align: top;
+  text-align: center;
+  overflow: hidden;
+  cursor: pointer;
+  border: 2px solid #fcfcfc;
+}
+.search-result ul li.selected {
+  border: 2px solid #fc8383;
+}
+.search-result ul li img {
+  max-width: 126px;
+  max-height: 130px;
+  vertical-align: middle;
+}
+.search-result ul li span {
+  display: block;
+  position: absolute;
+  bottom: 0;
+  height: 20px;
+  background: rgba(0, 0, 0, 0.5);
+  left: 0;
+  right: 0;
+  color: white;
+  line-height: 20px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  word-break: break-all;
+  white-space: nowrap;
+  opacity: 0;
+  -webkit-transform: translate(0, 20px);
+  -ms-transform: translate(0, 20px);
+  transform: translate(0, 20px);
+  -webkit-transition: all .2s ease;
+  transition: all .2s ease;
+}
+.search-result ul li:hover span {
+  opacity: 1;
+  -webkit-transform: translate(0, 0);
+  -ms-transform: translate(0, 0);
+  transform: translate(0, 0);
+}
+@media (min-width: 768px) {
+  .form-inline .form-control {
+    width: 422px;
+  }
+}
+.btn-group-vertical {
+  vertical-align: top;
+  margin: 5px;
+}
+.btn-group-vertical.note-btn-group {
+  border-right: 1px dashed #eee;
+  padding-right: 5px;
+}
+.btn-group-vertical .note-btn,
+.btn-group-vertical .note-btn-caption {
+  width: 40px;
+  margin: 0;
+  padding: 0;
+  border: none!important;
+  border-radius: 0!important;
+}
+.btn-group-vertical .note-btn:hover,
+.btn-group-vertical .note-btn-caption:hover {
+  background-color: #eff3fa;
+}
+.btn-group-vertical .note-btn:active,
+.btn-group-vertical .note-btn-caption:active {
+  background-color: #c4d0ee;
+}
+.btn-group-vertical .note-btn.active,
+.btn-group-vertical .note-btn-caption.active {
+  box-shadow: none;
+  background-color: #eff3fa;
+}
+.btn-group-vertical .note-btn {
+  height: 25px;
+  background: url(images/icons.png) no-repeat center -1150px;
+}
+.btn-group-vertical .note-btn-caption {
+  height: 20px;
+}
+.btn-group-vertical .note-btn-caption .caption {
+  font-size: 12px;
+}
+.open > .dropdown-toggle.btn-default {
+  background-color: #eff3fa;
+}
+.gfm-render {
+  font-size: 12px;
+  -webkit-user-select: text;
+  color: #333;
+  line-height: 1.8em;
+}
+.gfm-render blockquote,
+.gfm-render ul,
+.gfm-render table,
+.gfm-render p,
+.gfm-render pre,
+.gfm-render hr {
+  margin: 1em 0;
+  cursor: text;
+}
+.gfm-render blockquote:first-child:last-child,
+.gfm-render ul:first-child:last-child,
+.gfm-render table:first-child:last-child,
+.gfm-render p:first-child:last-child,
+.gfm-render pre:first-child:last-child,
+.gfm-render hr:first-child:last-child {
+  margin: 0;
+}
+.gfm-render img {
+  max-width: 100%;
+}
+.gfm-render a {
+  color: blue;
+}
+.gfm-render a:hover {
+  color: red;
+}
+.gfm-render blockquote {
+  display: block;
+  border-left: 4px solid #E4AD91;
+  color: #da8e68;
+  padding-left: 10px;
+  font-style: italic;
+  margin-left: 2em;
+}
+.gfm-render ul,
+.gfm-render ol {
+  padding-left: 3em;
+}
+.gfm-render table {
+  width: 100%;
+  border-collapse: collapse;
+  margin: 1em 0;
+}
+.gfm-render table th,
+.gfm-render table td {
+  border: 1px solid #666;
+  padding: 2px 4px;
+}
+.gfm-render table th {
+  background: rgba(45, 141, 234, 0.2);
+}
+.gfm-render table tr:nth-child(even) td {
+  background: rgba(45, 141, 234, 0.03);
+}
+.gfm-render em {
+  color: red;
+}
+.gfm-render del {
+  color: #999;
+}
+.gfm-render pre {
+  background: rgba(45, 141, 234, 0.1);
+  padding: 5px;
+  border-radius: 5px;
+  word-break: break-all;
+  word-wrap: break-word;
+}
+.gfm-render code {
+  background: rgba(45, 141, 234, 0.1);
+  /*         display: inline-block; */
+  padding: 0 5px;
+  border-radius: 3px;
+}
+.gfm-render pre code {
+  background: none;
+}
+.gfm-render hr {
+  border: none;
+  border-top: 1px solid #CCC;
+}
+.gfm-render .highlight {
+  background: yellow;
+  color: red;
+}
+.km-note {
+  width: 300px;
+  border-left: 1px solid #babfcd;
+  padding: 5px 10px;
+  background: white;
+  position: absolute;
+  top: 92px;
+  right: 0;
+  bottom: 0;
+  left: auto;
+  z-index: 3;
+}
+.km-note.panel {
+  margin: 0;
+  padding: 0;
+}
+.km-note.panel .panel-heading h3 {
+  display: inline-block;
+}
+.km-note.panel .panel-heading .close-note-editor {
+  width: 15px;
+  height: 15px;
+  display: inline-block;
+  float: right;
+}
+.km-note.panel .panel-heading .close-note-editor:hover {
+  cursor: pointer;
+}
+.km-note.panel .panel-body {
+  padding: 0;
+}
+.km-note .CodeMirror {
+  position: absolute;
+  top: 41px;
+  bottom: 0;
+  height: auto;
+  cursor: text;
+  font-size: 14px;
+  line-height: 1.3em;
+  font-family: consolas;
+}
+.km-note-tips {
+  color: #ccc;
+  padding: 3px 8px;
+}
+#previewer-content {
+  position: absolute;
+  background: #FFD;
+  padding: 5px 15px;
+  border-radius: 5px;
+  max-width: 400px;
+  max-height: 200px;
+  overflow: auto;
+  z-index: 10;
+  box-shadow: 0 0 15px rgba(0, 0, 0, 0.5);
+  word-break: break-all;
+  font-size: 12px;
+  -webkit-user-select: text;
+  color: #333;
+  line-height: 1.8em;
+}
+#previewer-content blockquote,
+#previewer-content ul,
+#previewer-content table,
+#previewer-content p,
+#previewer-content pre,
+#previewer-content hr {
+  margin: 1em 0;
+  cursor: text;
+}
+#previewer-content blockquote:first-child:last-child,
+#previewer-content ul:first-child:last-child,
+#previewer-content table:first-child:last-child,
+#previewer-content p:first-child:last-child,
+#previewer-content pre:first-child:last-child,
+#previewer-content hr:first-child:last-child {
+  margin: 0;
+}
+#previewer-content img {
+  max-width: 100%;
+}
+#previewer-content a {
+  color: blue;
+}
+#previewer-content a:hover {
+  color: red;
+}
+#previewer-content blockquote {
+  display: block;
+  border-left: 4px solid #E4AD91;
+  color: #da8e68;
+  padding-left: 10px;
+  font-style: italic;
+  margin-left: 2em;
+}
+#previewer-content ul,
+#previewer-content ol {
+  padding-left: 3em;
+}
+#previewer-content table {
+  width: 100%;
+  border-collapse: collapse;
+  margin: 1em 0;
+}
+#previewer-content table th,
+#previewer-content table td {
+  border: 1px solid #666;
+  padding: 2px 4px;
+}
+#previewer-content table th {
+  background: rgba(45, 141, 234, 0.2);
+}
+#previewer-content table tr:nth-child(even) td {
+  background: rgba(45, 141, 234, 0.03);
+}
+#previewer-content em {
+  color: red;
+}
+#previewer-content del {
+  color: #999;
+}
+#previewer-content pre {
+  background: rgba(45, 141, 234, 0.1);
+  padding: 5px;
+  border-radius: 5px;
+  word-break: break-all;
+  word-wrap: break-word;
+}
+#previewer-content code {
+  background: rgba(45, 141, 234, 0.1);
+  /*         display: inline-block; */
+  padding: 0 5px;
+  border-radius: 3px;
+}
+#previewer-content pre code {
+  background: none;
+}
+#previewer-content hr {
+  border: none;
+  border-top: 1px solid #CCC;
+}
+#previewer-content .highlight {
+  background: yellow;
+  color: red;
+}
+#previewer-content.ng-hide {
+  display: block!important;
+  left: -99999px !important;
+  top: -99999px !important;
+}
+.panel-body {
+  padding: 10px;
+}
+.tab-content .km-priority {
+  vertical-align: middle;
+  font-size: inherit;
+  display: inline-block;
+  width: 140px;
+  margin: 5px;
+  border-right: 1px dashed #eee;
+}
+.tab-content .km-priority .km-priority-item {
+  margin: 0 1px;
+  padding: 1px;
+}
+.tab-content .km-priority .km-priority-item .km-priority-icon {
+  background: url(images/iconpriority.png) repeat-y;
+  background-color: transparent;
+}
+.tab-content .km-priority .km-priority-item .km-priority-icon.priority-0 {
+  background-position: 0 20px;
+}
+.tab-content .km-priority .km-priority-item .km-priority-icon.priority-1 {
+  background-position: 0 0px;
+}
+.tab-content .km-priority .km-priority-item .km-priority-icon.priority-2 {
+  background-position: 0 -20px;
+}
+.tab-content .km-priority .km-priority-item .km-priority-icon.priority-3 {
+  background-position: 0 -40px;
+}
+.tab-content .km-priority .km-priority-item .km-priority-icon.priority-4 {
+  background-position: 0 -60px;
+}
+.tab-content .km-priority .km-priority-item .km-priority-icon.priority-5 {
+  background-position: 0 -80px;
+}
+.tab-content .km-priority .km-priority-item .km-priority-icon.priority-6 {
+  background-position: 0 -100px;
+}
+.tab-content .km-priority .km-priority-item .km-priority-icon.priority-7 {
+  background-position: 0 -120px;
+}
+.tab-content .km-priority .km-priority-item .km-priority-icon.priority-8 {
+  background-position: 0 -140px;
+}
+.tab-content .km-priority .km-priority-item .km-priority-icon.priority-9 {
+  background-position: 0 -160px;
+}
+.tab-content .km-progress {
+  vertical-align: middle;
+  font-size: inherit;
+  display: inline-block;
+  width: 140px;
+  margin: 5px;
+  border-right: 1px dashed #eee;
+}
+.tab-content .km-progress .km-progress-item {
+  margin: 0 1px;
+  padding: 1px;
+}
+.tab-content .km-progress .km-progress-item .km-progress-icon {
+  background: url(images/iconprogress.png) repeat-y;
+  background-color: transparent;
+}
+.tab-content .km-progress .km-progress-item .km-progress-icon.progress-0 {
+  background-position: 0 20px;
+}
+.tab-content .km-progress .km-progress-item .km-progress-icon.progress-1 {
+  background-position: 0 0px;
+}
+.tab-content .km-progress .km-progress-item .km-progress-icon.progress-2 {
+  background-position: 0 -20px;
+}
+.tab-content .km-progress .km-progress-item .km-progress-icon.progress-3 {
+  background-position: 0 -40px;
+}
+.tab-content .km-progress .km-progress-item .km-progress-icon.progress-4 {
+  background-position: 0 -60px;
+}
+.tab-content .km-progress .km-progress-item .km-progress-icon.progress-5 {
+  background-position: 0 -80px;
+}
+.tab-content .km-progress .km-progress-item .km-progress-icon.progress-6 {
+  background-position: 0 -100px;
+}
+.tab-content .km-progress .km-progress-item .km-progress-icon.progress-7 {
+  background-position: 0 -120px;
+}
+.tab-content .km-progress .km-progress-item .km-progress-icon.progress-8 {
+  background-position: 0 -140px;
+}
+.tab-content .km-progress .km-progress-item .km-progress-icon.progress-9 {
+  background-position: 0 -160px;
+}
+.resource-editor {
+  vertical-align: middle;
+  display: inline-block;
+  margin: 5px;
+}
+.resource-editor .input-group,
+.resource-editor .km-resource {
+  font-size: 12px;
+}
+.resource-editor .input-group {
+  height: 20px;
+  width: 168px;
+}
+.resource-editor .resource-dropdown {
+  position: relative;
+  width: 168px;
+  border: 1px solid #ccc;
+  margin-top: -1px;
+  border-bottom-right-radius: 4px;
+  border-bottom-left-radius: 4px;
+}
+.resource-editor .resource-dropdown .km-resource {
+  position: absolute;
+  width: 154px;
+  margin-bottom: 3px;
+  padding: 0;
+  list-style-type: none;
+  overflow: scroll;
+  max-height: 500px;
+}
+.resource-editor .resource-dropdown .km-resource.open {
+  z-index: 3;
+  background-color: #fff;
+}
+.resource-editor .resource-dropdown .km-resource li {
+  display: inline-block;
+  padding: 1px 2px;
+  border-radius: 4px;
+  margin: 2px 3px;
+}
+.resource-editor .resource-dropdown .km-resource li[disabled] {
+  opacity: 0.5;
+}
+.resource-editor .resource-dropdown .resource-caret {
+  display: block;
+  float: right;
+  vertical-align: middle;
+  width: 12px;
+  height: 24px;
+  padding: 8px 1px;
+}
+.resource-editor .resource-dropdown .resource-caret:hover {
+  background-color: #eff3fa;
+}
+.resource-editor .resource-dropdown .resource-caret:active {
+  background-color: #c4d0ee;
+}
+.resource-editor input.form-control,
+.resource-editor .btn {
+  font-size: 12px;
+}
+.resource-editor input.form-control {
+  padding: 2px 4px;
+  height: 24px;
+  border-bottom-left-radius: 0;
+}
+.resource-editor .input-group-btn {
+  line-height: 24px;
+}
+.resource-editor .input-group-btn .btn {
+  padding: 2px 4px;
+  height: 24px;
+  border-bottom-right-radius: 0;
+}
+.temp-panel {
+  margin: 5px 5px 5px 10px;
+  border-right: 1px dashed #eee;
+  display: inline-block;
+  vertical-align: middle;
+}
+.temp-list {
+  min-width: 124px;
+}
+.temp-item-wrap {
+  width: 50px;
+  height: 40px;
+  padding: 0 2px;
+  margin: 5px;
+  display: inline-block;
+}
+.temp-item {
+  display: inline-block;
+  width: 50px;
+  height: 40px;
+  background-image: url(images/template.png);
+  background-repeat: no-repeat;
+}
+.temp-item.default {
+  background-position: 0 0;
+}
+.temp-item.structure {
+  background-position: -50px 0;
+}
+.temp-item.filetree {
+  background-position: -100px 0;
+}
+.temp-item.right {
+  background-position: -150px 0;
+}
+.temp-item.fish-bone {
+  background-position: -200px 0;
+}
+.temp-item.tianpan {
+  background-position: -250px 0;
+}
+.current-temp-item {
+  width: 74px;
+  padding: 0 0 0 5px;
+  border: 1px solid #fff;
+}
+.current-temp-item:hover {
+  background-color: #eff3fa;
+}
+.current-temp-item[disabled] {
+  opacity: 0.5;
+}
+.current-temp-item .caret {
+  margin-left: 5px;
+}
+.temp-item-selected {
+  background-color: #87a9da;
+}
+.theme-panel {
+  height: 42px;
+  margin: 5px;
+  padding: 0 5px 0 0;
+  border-right: 1px dashed #eee;
+  display: inline-block;
+  vertical-align: middle;
+}
+.theme-list {
+  min-width: 162px;
+}
+div a.theme-item {
+  display: inline-block;
+  width: 70px;
+  height: 30px;
+  text-align: center;
+  line-height: 30px;
+  padding: 0 5px;
+  font-size: 12px;
+  cursor: pointer;
+  text-decoration: none;
+  color: #000;
+}
+.theme-item-selected {
+  width: 100px;
+  padding: 6px 7px;
+  border: 1px solid #fff;
+}
+.theme-item-selected:hover {
+  background-color: #eff3fa;
+}
+.theme-item-selected .caret {
+  margin-left: 5px;
+}
+.theme-item-selected[disabled] {
+  opacity: 0.5;
+}
+.theme-item-wrap {
+  display: inline-block;
+  width: 80px;
+  height: 40px;
+  padding: 5px;
+}
+.theme-item-wrap:hover {
+  background-color: #eff3fa;
+}
+.readjust-layout {
+  display: inline-block;
+  vertical-align: middle;
+  padding: 0 10px 0 5px;
+  border-right: 1px dashed #eee;
+}
+.btn-icon {
+  width: 25px;
+  height: 25px;
+  margin-left: 12px;
+  display: block;
+}
+.btn-label {
+  font-size: 12px;
+}
+.btn-wrap {
+  width: 50px;
+  height: 42px;
+  cursor: pointer;
+  display: inline-block;
+  text-decoration: none;
+}
+.btn-wrap[disabled] span {
+  opacity: 0.5;
+}
+.btn-wrap[disabled] {
+  cursor: default;
+}
+.btn-wrap[disabled]:hover {
+  background-color: transparent;
+}
+.btn-wrap[disabled]:active {
+  background-color: transparent;
+}
+.btn-wrap:link {
+  text-decoration: none;
+}
+.btn-wrap:visited {
+  text-decoration: none;
+}
+.btn-wrap:hover {
+  background-color: #eff3fa;
+  text-decoration: none;
+}
+.btn-wrap:active {
+  background-color: #c4d0ee;
+}
+.reset-layout-icon {
+  background: url(images/icons.png) no-repeat;
+  background-position: 0 -150px;
+}
+.style-operator {
+  display: inline-block;
+  vertical-align: middle;
+  padding: 0 5px;
+  border-right: 1px dashed #eee;
+}
+.style-operator .clear-style {
+  vertical-align: middle;
+}
+.clear-style-icon {
+  background: url(images/icons.png) no-repeat;
+  background-position: 0 -175px;
+}
+.s-btn-group-vertical {
+  display: inline-block;
+  vertical-align: middle;
+}
+.s-btn-icon {
+  width: 20px;
+  height: 20px;
+  margin-right: 3px;
+  display: inline-block;
+  vertical-align: middle;
+}
+.s-btn-label {
+  font-size: 12px;
+  vertical-align: middle;
+  display: inline-block;
+}
+.s-btn-wrap {
+  padding: 0 5px 0 3px;
+  display: inline-block;
+  text-decoration: none;
+  font-size: 0;
+}
+.s-btn-wrap[disabled] span {
+  opacity: 0.5;
+}
+.s-btn-wrap[disabled] {
+  cursor: default;
+}
+.s-btn-wrap[disabled]:hover {
+  background-color: transparent;
+}
+.s-btn-wrap[disabled]:active {
+  background-color: transparent;
+}
+.s-btn-wrap:hover {
+  background-color: #eff3fa;
+  text-decoration: none;
+}
+.s-btn-wrap:active {
+  background-color: #c4d0ee;
+}
+.copy-style-icon {
+  background: url(images/icons.png) no-repeat;
+  background-position: 0 -200px;
+}
+.paste-style-wrap {
+  display: block;
+}
+.paste-style-icon {
+  background: url(images/icons.png) no-repeat;
+  background-position: 0 -220px;
+}
+.font-operator {
+  width: 170px;
+  display: inline-block;
+  vertical-align: middle;
+  font-size: 12px;
+  padding: 0 5px;
+}
+.font-operator .font-size-list {
+  display: inline-block;
+  border: 1px solid #eee;
+  padding: 2px 4px;
+}
+.font-operator .font-family-list {
+  display: inline-block;
+  border: 1px solid #eee;
+  padding: 2px 4px;
+}
+.current-font-item a {
+  text-decoration: none;
+  display: inline-block;
+}
+.current-font-family {
+  width: 75px;
+  height: 18px;
+  overflow: hidden;
+  vertical-align: bottom;
+}
+.current-font-size {
+  width: 32px;
+  height: 18px;
+  overflow: hidden;
+  vertical-align: bottom;
+}
+.current-font-item[disabled] {
+  opacity: 0.5;
+}
+.font-item {
+  line-height: 1em;
+  text-align: left;
+}
+.font-item-selected {
+  background-color: #87a9da;
+}
+.font-bold,
+.font-italics {
+  display: inline-block;
+  background: url(images/icons.png) no-repeat;
+  cursor: pointer;
+  margin: 0 3px;
+}
+.font-bold:hover,
+.font-italics:hover {
+  background-color: #eff3fa;
+}
+.font-bold:active,
+.font-italics:active {
+  background-color: #c4d0ee;
+}
+.font-bold[disabled],
+.font-italics[disabled] {
+  opacity: 0.5;
+}
+.font-bold {
+  background-position: 0 -240px;
+}
+.font-italics {
+  background-position: 0 -260px;
+}
+.font-bold-selected,
+.font-italics-selected {
+  background-color: #87a9da;
+}
+.font-color-wrap {
+  display: inline-block;
+  width: 30px;
+  height: 22px;
+  margin: 3px 3px 0 0;
+  border: 1px #efefef solid;
+  vertical-align: middle;
+  font-size: 0;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+.font-color-wrap[disabled] {
+  opacity: 0.5;
+}
+.font-color-wrap .quick-font-color {
+  display: inline-block;
+  width: 20px;
+  height: 16px;
+  font-size: 14px;
+  line-height: 16px;
+  vertical-align: top;
+  text-align: center;
+  cursor: default;
+  color: #000;
+}
+.font-color-wrap .quick-font-color:hover {
+  background-color: #eff3fa;
+}
+.font-color-wrap .quick-font-color:active {
+  background-color: #c4d0ee;
+}
+.font-color-wrap .quick-font-color[disabled] {
+  opacity: 0.5;
+}
+.font-color-wrap .font-color-preview {
+  display: inline-block;
+  width: 12px;
+  height: 2px;
+  margin: 0 4px 0;
+  background-color: #000;
+}
+.font-color-wrap .font-color-preview[disabled] {
+  opacity: 0.5;
+}
+.font-color {
+  display: inline-block;
+  width: 8px;
+  height: 16px;
+}
+.font-color:hover {
+  background-color: #eff3fa;
+}
+.font-color:active {
+  background-color: #c4d0ee;
+}
+.font-color[disabled] {
+  opacity: 0.5;
+}
+.font-color .caret {
+  margin-left: -2px;
+  margin-top: 7px;
+}
+.bg-color-wrap {
+  display: inline-block;
+  width: 30px;
+  height: 22px;
+  margin: 3px 3px 0 0;
+  border: 1px #efefef solid;
+  vertical-align: middle;
+  font-size: 0;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+.bg-color-wrap[disabled] {
+  opacity: 0.5;
+}
+.bg-color-wrap .quick-bg-color {
+  display: inline-block;
+  width: 20px;
+  height: 16px;
+  font-size: 14px;
+  line-height: 16px;
+  vertical-align: top;
+  text-align: center;
+  cursor: default;
+  color: #000;
+  background: url(images/icons.png) no-repeat center -1260px;
+}
+.bg-color-wrap .quick-bg-color:hover {
+  background-color: #eff3fa;
+}
+.bg-color-wrap .quick-bg-color:active {
+  background-color: #c4d0ee;
+}
+.bg-color-wrap .quick-bg-color[disabled] {
+  opacity: 0.5;
+}
+.bg-color-wrap .bg-color-preview {
+  display: inline-block;
+  width: 12px;
+  height: 2px;
+  margin: 0 4px 0;
+  background-color: #fff;
+}
+.bg-color-wrap .bg-color-preview[disabled] {
+  opacity: 0.5;
+}
+.bg-color {
+  display: inline-block;
+  width: 8px;
+  height: 16px;
+}
+.bg-color:hover {
+  background-color: #eff3fa;
+}
+.bg-color:active {
+  background-color: #c4d0ee;
+}
+.bg-color[disabled] {
+  opacity: 0.5;
+}
+.bg-color .caret {
+  margin-left: -2px;
+  margin-top: 7px;
+}
+.btn-group-vertical {
+  vertical-align: middle;
+  margin: 5px;
+}
+.btn-group-vertical .expand,
+.btn-group-vertical .expand-caption {
+  width: 40px;
+  margin: 0;
+  padding: 0;
+  border: none!important;
+  border-radius: 0!important;
+}
+.btn-group-vertical .expand:hover,
+.btn-group-vertical .expand-caption:hover {
+  background-color: #eff3fa;
+}
+.btn-group-vertical .expand:active,
+.btn-group-vertical .expand-caption:active {
+  background-color: #c4d0ee;
+}
+.btn-group-vertical .expand.active,
+.btn-group-vertical .expand-caption.active {
+  box-shadow: none;
+  background-color: #eff3fa;
+}
+.btn-group-vertical .expand {
+  height: 25px;
+  background: url(images/icons.png) no-repeat 0 -995px;
+  background-position-x: 50%;
+}
+.btn-group-vertical .expand-caption {
+  height: 20px;
+}
+.btn-group-vertical .expand-caption .caption {
+  font-size: 12px;
+}
+.btn-group-vertical {
+  vertical-align: middle;
+  margin: 5px;
+}
+.btn-group-vertical .select,
+.btn-group-vertical .select-caption {
+  width: 40px;
+  margin: 0;
+  padding: 0;
+  border: none!important;
+  border-radius: 0!important;
+}
+.btn-group-vertical .select:hover,
+.btn-group-vertical .select-caption:hover {
+  background-color: #eff3fa;
+}
+.btn-group-vertical .select:active,
+.btn-group-vertical .select-caption:active {
+  background-color: #c4d0ee;
+}
+.btn-group-vertical .select.active,
+.btn-group-vertical .select-caption.active {
+  box-shadow: none;
+  background-color: #eff3fa;
+}
+.btn-group-vertical .select {
+  height: 25px;
+  background: url(images/icons.png) no-repeat 7px -1175px;
+}
+.btn-group-vertical .select-caption {
+  height: 20px;
+}
+.btn-group-vertical .select-caption .caption {
+  font-size: 12px;
+}
+.btn-group-vertical {
+  vertical-align: middle;
+  margin: 5px;
+}
+.btn-group-vertical .search,
+.btn-group-vertical .search-caption {
+  width: 40px;
+  margin: 0;
+  padding: 0;
+  border: none!important;
+  border-radius: 0!important;
+}
+.btn-group-vertical .search:hover,
+.btn-group-vertical .search-caption:hover {
+  background-color: #eff3fa;
+}
+.btn-group-vertical .search:active,
+.btn-group-vertical .search-caption:active {
+  background-color: #c4d0ee;
+}
+.btn-group-vertical .search.active,
+.btn-group-vertical .search-caption.active {
+  box-shadow: none;
+  background-color: #eff3fa;
+}
+.btn-group-vertical .search {
+  height: 25px;
+  background: url(images/icons.png) no-repeat 0 -345px;
+  background-position-x: 50%;
+}
+.btn-group-vertical .search-caption {
+  height: 20px;
+}
+.btn-group-vertical .search-caption .caption {
+  font-size: 12px;
+}
+.search-box {
+  float: right;
+  background-color: #fff;
+  border: 1px solid #dbdbdb;
+  position: relative;
+  top: 0;
+  z-index: 3;
+  width: 360px;
+  height: 40px;
+  padding: 3px 6px;
+  opacity: 1;
+}
+.search-box .search-input-wrap,
+.search-box .prev-and-next-btn {
+  float: left;
+}
+.search-box .close-search {
+  float: right;
+  height: 16px;
+  width: 16px;
+  padding: 1px;
+  border-radius: 100%;
+  margin-top: 6px;
+  margin-right: 10px;
+}
+.search-box .close-search .glyphicon {
+  top: -1px;
+}
+.search-box .close-search:hover {
+  background-color: #efefef;
+}
+.search-box .close-search:active {
+  background-color: #999;
+}
+.search-box .search-input-wrap {
+  width: 240px;
+}
+.search-box .prev-and-next-btn {
+  margin-left: 5px;
+}
+.search-box .prev-and-next-btn .btn:focus {
+  outline: none;
+}
+.search-box .search-addon {
+  background-color: #fff;
+}
+.tool-group {
+  padding: 0;
+}
+.tool-group[disabled] {
+  opacity: 0.5;
+}
+.tool-group .tool-group-item {
+  display: inline-block;
+  border-radius: 4px;
+}
+.tool-group .tool-group-item .tool-group-icon {
+  width: 20px;
+  height: 20px;
+  padding: 2px;
+  margin: 1px;
+}
+.tool-group .tool-group-item:hover {
+  background-color: #eff3fa;
+}
+.tool-group .tool-group-item:active {
+  background-color: #c4d0ee;
+}
+.tool-group .tool-group-item.active {
+  background-color: #c4d0ee;
+}
+.nav-bar {
+  position: absolute;
+  width: 35px;
+  height: 240px;
+  padding: 5px 0;
+  left: 10px;
+  bottom: 10px;
+  background: #fc8383;
+  color: #fff;
+  border-radius: 4px;
+  z-index: 10;
+  box-shadow: 3px 3px 10px rgba(0, 0, 0, 0.2);
+  transition: -webkit-transform 0.7s 0.1s ease;
+  transition: transform .7s 0.1s ease;
+}
+.nav-bar .nav-btn {
+  width: 35px;
+  height: 24px;
+  line-height: 24px;
+  text-align: center;
+}
+.nav-bar .nav-btn .icon {
+  background: url(images/icons.png);
+  width: 20px;
+  height: 20px;
+  margin: 2px auto;
+  display: block;
+}
+.nav-bar .nav-btn.active {
+  background-color: #5A6378;
+}
+.nav-bar .zoom-in .icon {
+  background-position: 0 -730px;
+}
+.nav-bar .zoom-out .icon {
+  background-position: 0 -750px;
+}
+.nav-bar .hand .icon {
+  background-position: 0 -770px;
+  width: 25px;
+  height: 25px;
+  margin: 0 auto;
+}
+.nav-bar .camera .icon {
+  background-position: 0 -870px;
+  width: 25px;
+  height: 25px;
+  margin: 0 auto;
+}
+.nav-bar .nav-trigger .icon {
+  background-position: 0 -845px;
+  width: 25px;
+  height: 25px;
+  margin: 0 auto;
+}
+.nav-bar .zoom-pan {
+  width: 2px;
+  height: 70px;
+  box-shadow: 0 1px #E50000;
+  position: relative;
+  background: white;
+  margin: 3px auto;
+  overflow: visible;
+}
+.nav-bar .zoom-pan .origin {
+  position: absolute;
+  width: 20px;
+  height: 8px;
+  left: -9px;
+  margin-top: -4px;
+  background: transparent;
+}
+.nav-bar .zoom-pan .origin:after {
+  content: ' ';
+  display: block;
+  width: 6px;
+  height: 2px;
+  background: white;
+  left: 7px;
+  top: 3px;
+  position: absolute;
+}
+.nav-bar .zoom-pan .indicator {
+  position: absolute;
+  width: 8px;
+  height: 8px;
+  left: -3px;
+  background: white;
+  border-radius: 100%;
+  margin-top: -4px;
+}
+.nav-previewer {
+  background: #fff;
+  width: 140px;
+  height: 120px;
+  position: absolute;
+  left: 45px;
+  bottom: 30px;
+  box-shadow: 0 0 8px rgba(0, 0, 0, 0.2);
+  border-radius: 0 2px 2px 0;
+  padding: 1px;
+  z-index: 9;
+  cursor: crosshair;
+  transition: -webkit-transform 0.7s 0.1s ease;
+  transition: transform .7s 0.1s ease;
+}
+.nav-previewer.grab {
+  cursor: move;
+  cursor: -webkit-grabbing;
+  cursor: -moz-grabbing;
+  cursor: grabbing;
+}
+/*# sourceMappingURL=kityminder.editor.css.map */

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
kityminder-editor/dist/kityminder.editor.css.map


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 2102 - 0
kityminder-editor/dist/kityminder.editor.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
kityminder-editor/dist/kityminder.editor.min.css


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 10 - 0
kityminder-editor/dist/kityminder.editor.min.js


BIN
kityminder-editor/favicon.ico


+ 119 - 0
kityminder-editor/index.html

@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8">
+    <title>KityMinder Editor - Powered By FEX</title>
+
+	<link href="favicon.ico" type="image/x-icon" rel="shortcut icon">
+
+	<!-- bower:css -->
+    <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css" />
+    <link rel="stylesheet" href="bower_components/codemirror/lib/codemirror.css" />
+    <link rel="stylesheet" href="bower_components/hotbox/hotbox.css" />
+    <link rel="stylesheet" href="node_modules/kityminder-core/dist/kityminder.core.css" />
+    <link rel="stylesheet" href="bower_components/color-picker/dist/color-picker.css" />
+	<!-- endbower -->
+
+	<link rel="stylesheet" href="dist/kityminder.editor.css">
+
+    <style>
+        html, body {
+            margin: 0;
+            padding: 0;
+            height: 100%;
+            overflow: hidden;
+        }
+        h1.editor-title {
+            background: #393F4F;
+            color: white;
+            margin: 0;
+            height: 40px;
+            font-size: 14px;
+            line-height: 40px;
+            font-family: 'Hiragino Sans GB', 'Arial', 'Microsoft Yahei';
+            font-weight: normal;
+            padding: 0 20px;
+        }
+    </style>
+</head>
+<body ng-app="kityminderDemo" ng-controller="MainController">
+    <h1 class="editor-title">KityMinder Editor - Powered By FEX</h1>
+    <kityminder-editor on-init="initEditor(editor, minder)"></kityminder-editor>
+</body>
+
+<!-- bower:js -->
+<script src="bower_components/jquery/dist/jquery.js"></script>
+<script src="bower_components/bootstrap/dist/js/bootstrap.js"></script>
+<script src="bower_components/angular/angular.js"></script>
+<script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.js"></script>
+<script src="bower_components/codemirror/lib/codemirror.js"></script>
+<script src="bower_components/codemirror/mode/xml/xml.js"></script>
+<script src="bower_components/codemirror/mode/javascript/javascript.js"></script>
+<script src="bower_components/codemirror/mode/css/css.js"></script>
+<script src="bower_components/codemirror/mode/htmlmixed/htmlmixed.js"></script>
+<script src="bower_components/codemirror/mode/markdown/markdown.js"></script>
+<script src="bower_components/codemirror/addon/mode/overlay.js"></script>
+<script src="bower_components/codemirror/mode/gfm/gfm.js"></script>
+<script src="bower_components/angular-ui-codemirror/ui-codemirror.js"></script>
+<script src="bower_components/marked/lib/marked.js"></script>
+<script src="node_modules/kity/dist/kity.js"></script>
+<script src="bower_components/hotbox/hotbox.js"></script>
+<script src="bower_components/json-diff/json-diff.js"></script>
+<script src="node_modules/kityminder-core/dist/kityminder.core.js"></script>
+<script src="bower_components/color-picker/dist/color-picker.js"></script>
+<script src="bower_components/seajs/dist/sea.js"></script>
+<!-- endbower -->
+
+<script src="ui/kityminder.app.js"></script>
+<script src="ui/service/commandBinder.service.js"></script>
+<script src="ui/service/config.service.js"></script>
+<script src="ui/service/memory.service.js"></script>
+<script src="ui/service/lang.zh-cn.service.js"></script>
+<script src="ui/service/valueTransfer.service.js"></script>
+<script src="ui/service/minder.service.js"></script>
+<script src="ui/service/resource.service.js"></script>
+<script src="ui/service/revokeDialog.service.js"></script>
+<script src="ui/service/server.service.js"></script>
+<script src="ui/filter/lang.filter.js"></script>
+<script src="ui/dialog/hyperlink/hyperlink.ctrl.js"></script>
+<script src="ui/dialog/image/image.ctrl.js"></script>
+<script src="ui/dialog/imExportNode/imExportNode.ctrl.js"></script>
+<script src="ui/directive/topTab/topTab.directive.js"></script>
+<script src="ui/directive/undoRedo/undoRedo.directive.js"></script>
+<script src="ui/directive/appendNode/appendNode.directive.js"></script>
+<script src="ui/directive/arrange/arrange.directive.js"></script>
+<script src="ui/directive/operation/operation.directive.js"></script>
+<script src="ui/directive/hyperLink/hyperLink.directive.js"></script>
+<script src="ui/directive/imageBtn/imageBtn.directive.js"></script>
+<script src="ui/directive/noteBtn/noteBtn.directive.js"></script>
+<script src="ui/directive/resourceEditor/resourceEditor.directive.js"></script>
+<script src="ui/directive/priorityEditor/priorityEditor.directive.js"></script>
+<script src="ui/directive/progressEditor/progressEditor.directive.js"></script>
+<script src="ui/directive/noteEditor/noteEditor.directive.js"></script>
+<script src="ui/directive/notePreviewer/notePreviewer.directive.js"></script>
+<script src="ui/directive/kityminderEditor/kityminderEditor.directive.js"></script>
+<script src="ui/directive/templateList/templateList.directive.js"></script>
+<script src="ui/directive/themeList/themeList.directive.js"></script>
+<script src="ui/directive/layout/layout.directive.js"></script>
+<script src="ui/directive/styleOperator/styleOperator.directive.js"></script>
+<script src="ui/directive/fontOperator/fontOperator.directive.js"></script>
+<script src="ui/directive/expandLevel/expandLevel.directive.js"></script>
+<script src="ui/directive/selectAll/selectAll.directive.js"></script>
+<script src="ui/directive/colorPanel/colorPanel.directive.js"></script>
+<script src="ui/directive/navigator/navigator.directive.js"></script>
+<script src="ui/directive/searchBox/searchBox.directive.js"></script>
+<script src="ui/directive/searchBtn/searchBtn.directive.js"></script>
+
+
+<script>
+	angular.module('kityminderDemo', ['kityminderEditor'])
+			.controller('MainController', function($scope) {
+				$scope.initEditor = function(editor, minder) {
+					window.editor = editor;
+					window.minder = minder;
+				};
+			});
+
+</script>
+
+</html>

+ 127 - 0
kityminder-editor/less/_navigator.less

@@ -0,0 +1,127 @@
+.nav-bar {
+    position: absolute;
+    width: 35px;
+    height: 240px;
+    padding: 5px 0;
+    left: 10px;
+    bottom: 10px;
+    background: #fc8383;
+    color: #fff;
+    border-radius: 4px;
+    z-index: 10;
+    box-shadow: 3px 3px 10px rgba(0, 0, 0, 0.2);
+    transition: -webkit-transform .7s 0.1s ease;
+    transition: transform .7s 0.1s ease;
+
+    .nav-btn {
+        width: 35px;
+        height: 24px;
+        line-height: 24px;
+        text-align: center;
+
+        .icon {
+            background: url(images/icons.png);
+            width: 20px;
+            height: 20px;
+            margin: 2px auto;
+            display: block;
+        }
+
+        &.active {
+            background-color: #5A6378;
+        }
+    }
+
+    .zoom-in .icon {
+        background-position: 0 -730px;
+    }
+
+    .zoom-out .icon {
+        background-position: 0 -750px;
+    }
+
+    .hand .icon {
+        background-position: 0 -770px;
+        width: 25px;
+        height: 25px;
+        margin: 0 auto;
+    }
+
+    .camera .icon {
+        background-position: 0 -870px;
+        width: 25px;
+        height: 25px;
+        margin: 0 auto;
+    }
+
+    .nav-trigger .icon {
+        background-position: 0 -845px;
+        width: 25px;
+        height: 25px;
+        margin: 0 auto;
+    }
+
+    .zoom-pan {
+        width: 2px;
+        height: 70px;
+        box-shadow: 0 1px #E50000;
+        position: relative;
+        background: white;
+        margin: 3px auto;
+        overflow: visible;
+
+        .origin {
+            position: absolute;
+            width: 20px;
+            height: 8px;
+            left: -9px;
+            margin-top: -4px;
+            background: transparent;
+
+            &:after {
+                content: ' ';
+                display: block;
+                width: 6px;
+                height: 2px;
+                background: white;
+                left: 7px;
+                top: 3px;
+                position: absolute;
+            }
+        }
+
+        .indicator {
+            position: absolute;
+            width: 8px;
+            height: 8px;
+            left: -3px;
+            background: white;
+            border-radius: 100%;
+            margin-top: -4px;
+        }
+
+    }
+}
+
+.nav-previewer {
+    background: #fff;
+    width: 140px;
+    height: 120px;
+    position: absolute;
+    left: 45px;
+    bottom: 30px;
+    box-shadow: 0 0 8px rgba(0, 0, 0, 0.2);
+    border-radius: 0 2px 2px 0;
+    padding: 1px;
+    z-index: 9;
+    cursor: crosshair;
+    transition: -webkit-transform .7s 0.1s ease;
+    transition: transform .7s 0.1s ease;
+
+    &.grab {
+        cursor: move;
+        cursor: -webkit-grabbing;
+        cursor: -moz-grabbing;
+        cursor: grabbing;
+    }
+}

+ 24 - 0
kityminder-editor/less/_tool_group.less

@@ -0,0 +1,24 @@
+.tool-group {
+    padding: 0;
+
+    &[disabled] {
+        opacity: 0.5;
+    }
+
+    .tool-group-item {
+        display: inline-block;
+        border-radius: 4px;
+
+        .tool-group-icon {
+            width: 20px;
+            height: 20px;
+            padding: 2px;
+            margin: 1px;
+        }
+
+        &:hover {background-color: @button-hover;}
+        &:active {background-color: @button-active;}
+
+        &.active {background-color: @button-active;}
+    }
+}

+ 7 - 0
kityminder-editor/less/_vars.less

@@ -0,0 +1,7 @@
+@button-hover: hsl(222, 55%, 96%);
+@button-active: hsl(222, 55%, 85%);
+@button-pressed: hsl(222, 55%, 90%);
+
+@tool-hover: #eff3fa;
+@tool-active: #c4d0ee;
+@tool-selected: #87a9da;

+ 135 - 0
kityminder-editor/less/editor.less

@@ -0,0 +1,135 @@
+.km-editor {
+    overflow: hidden;
+    z-index: 2;
+}
+
+.km-editor > .mask {
+    display: block;
+    position: absolute;
+    left: 0;
+    right: 0;
+    top: 0;
+    bottom: 0;
+    background-color: transparent;
+}
+
+.km-editor > .receiver {
+    position: absolute;
+    background: white;
+    outline: none;
+    box-shadow: 0 0 20px fadeout(black, 50%);
+    left: 0;
+    top: 0;
+    padding: 3px 5px;
+    margin-left: -3px;
+    margin-top: -5px;
+    max-width: 300px;
+    width: auto;
+    overflow: hidden;
+    font-size: 14px;
+    line-height: 1.4em;
+    min-height: 1.4em;
+    box-sizing: border-box;
+    overflow: hidden;
+    word-break: break-all;
+    word-wrap: break-word;
+    border: none;
+    -webkit-user-select: text;
+    pointer-events: none;
+    opacity: 0;
+    z-index: -1000;
+    &.debug {
+        opacity: 1;
+        outline: 1px solid green;
+        background: none;
+        z-index: 0;
+    }
+
+    &.input {
+        pointer-events: all;
+        opacity: 1;
+        z-index: 999;
+        background: white;
+        outline: none;
+    }
+}
+
+div.minder-editor-container {
+    position: absolute;
+    top: 40px;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    font-family: Arial, "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif;
+}
+
+
+.minder-editor {
+    position: absolute;
+    top: 92px;
+    left: 0;
+    right: 0;
+    bottom: 0;
+}
+
+.minder-viewer {
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+}
+
+
+.control-panel {
+    position: absolute;
+    top: 0;
+    right: 0;
+    width: 250px;
+    bottom: 0;
+    border-left: 1px solid #CCC;
+}
+.minder-divider {
+    position: absolute;
+    top: 0;
+    right: 250px;
+    bottom: 0;
+    width: 2px;
+    background-color: rgb(251, 251, 251);
+    cursor: ew-resize;
+}
+
+// @override bootstrap
+.panel-body {
+    padding: 10px;
+}
+
+@import (less) "_vars.less";
+@import (less) "imageDialog.less";
+@import (less) "topTab/topTab.less";
+@import (less) "topTab/idea/undoRedo.less";
+@import (less) "topTab/idea/appendNode.less";
+@import (less) "topTab/idea/arrange.less";
+@import (less) "topTab/idea/operation.less";
+@import (less) "topTab/idea/hyperlink.less";
+@import (less) "topTab/idea/image.less";
+@import (less) "topTab/idea/note.less";
+@import (less) "topTab/idea/noteEditor.less";
+@import (less) "topTab/idea/priority.less";
+@import (less) "topTab/idea/progress.less";
+@import (less) "topTab/idea/resource.less";
+@import (less) "topTab/appearance/templatePanel.less";
+@import (less) "topTab/appearance/themePanel.less";
+@import (less) "topTab/appearance/layout.less";
+@import (less) "topTab/appearance/styleOperator.less";
+@import (less) "topTab/appearance/fontOperator.less";
+@import (less) "topTab/appearance/colorPanel.less";
+@import (less) "topTab/view/expand.less";
+@import (less) "topTab/view/select.less";
+@import (less) "topTab/view/search.less";
+@import (less) "topTab/searchBox.less";
+@import (less) "_tool_group.less";
+@import (less) "_navigator.less";
+
+
+

+ 8 - 0
kityminder-editor/less/imageDialog.less

@@ -0,0 +1,8 @@
+.upload-image {
+    width: 0.1px;
+    height: 0.1px;
+    opacity: 0;
+    overflow: hidden;
+    position: absolute;
+    z-index: -1;
+}

+ 77 - 0
kityminder-editor/less/topTab/appearance/colorPanel.less

@@ -0,0 +1,77 @@
+.bg-color-wrap {
+    display: inline-block;
+    width: 30px;
+    height: 22px;
+    margin: 3px 3px 0 0;
+    border: 1px #efefef solid;
+    vertical-align: middle;
+    font-size: 0;
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+
+    &[disabled] {
+        opacity: 0.5;
+    }
+
+    .quick-bg-color {
+        display: inline-block;
+        width: 20px;
+        height: 16px;
+        font-size: 14px;
+        line-height: 16px;
+        vertical-align: top;
+        text-align: center;
+        cursor: default;
+        color: #000;
+        background: url(images/icons.png) no-repeat center -1260px;
+
+        &:hover {
+            background-color: @tool-hover;
+        }
+
+        &:active {
+            background-color: @tool-active;
+        }
+
+        &[disabled] {
+            opacity: 0.5;
+        }
+    }
+
+    .bg-color-preview {
+        display: inline-block;
+        width: 12px;
+        height: 2px;
+        margin: 0 4px 0;
+        background-color: #fff;
+
+        &[disabled] {
+            opacity: 0.5;
+        }
+    }
+}
+
+.bg-color {
+    display: inline-block;
+    width: 8px;
+    height: 16px;
+
+    &:hover {
+        background-color: @tool-hover;
+    }
+
+    &:active {
+        background-color: @tool-active;
+    }
+
+    &[disabled] {
+        opacity: 0.5;
+    }
+
+    .caret {
+        margin-left: -2px;
+        margin-top: 7px;
+    }
+}

+ 160 - 0
kityminder-editor/less/topTab/appearance/fontOperator.less

@@ -0,0 +1,160 @@
+.font-operator {
+    width: 170px;
+    display: inline-block;
+    vertical-align: middle;
+    font-size: 12px;
+    padding: 0 5px;
+
+    .font-size-list {
+        display: inline-block;
+        border: 1px solid #eee;
+        padding: 2px 4px;
+    }
+
+    .font-family-list {
+        display: inline-block;
+        border: 1px solid #eee;
+        padding: 2px 4px;
+    }
+
+}
+
+.current-font-item a {
+    text-decoration: none;
+    display: inline-block;
+}
+
+.current-font-family {
+    width: 75px;
+    height: 18px;
+    overflow: hidden;
+    vertical-align: bottom;
+}
+.current-font-size {
+    width: 32px;
+    height: 18px;
+    overflow: hidden;
+    vertical-align: bottom;
+}
+
+.current-font-item[disabled] {
+    opacity: 0.5;
+}
+
+.font-item {
+    line-height: 1em;
+    text-align: left;
+}
+
+.font-item-selected {
+    background-color: @tool-selected;
+}
+
+.font-bold, .font-italics {
+    display: inline-block;
+    background: url(images/icons.png) no-repeat;
+    cursor: pointer;
+    margin: 0 3px;
+
+
+    &:hover {
+        background-color: @tool-hover;
+    }
+
+    &:active {
+        background-color: @tool-active;
+    }
+
+    &[disabled] {
+        opacity: 0.5;
+    }
+}
+
+.font-bold {
+    background-position: 0 -240px;
+}
+
+.font-italics {
+    background-position: 0 -260px;
+}
+
+.font-bold-selected, .font-italics-selected {
+    background-color: @tool-selected;
+}
+
+.font-color-wrap {
+    display: inline-block;
+    width: 30px;
+    height: 22px;
+    margin: 3px 3px 0 0;
+    border: 1px #efefef solid;
+    vertical-align: middle;
+    font-size: 0;
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+
+    &[disabled] {
+        opacity: 0.5;
+    }
+
+    .quick-font-color {
+        display: inline-block;
+        width: 20px;
+        height: 16px;
+        font-size: 14px;
+        line-height: 16px;
+        vertical-align: top;
+        text-align: center;
+        cursor: default;
+        color: #000;
+
+        &:hover {
+            background-color: @tool-hover;
+        }
+
+        &:active {
+            background-color: @tool-active;
+        }
+
+        &[disabled] {
+            opacity: 0.5;
+        }
+    }
+
+    .font-color-preview {
+        display: inline-block;
+        width: 12px;
+        height: 2px;
+        margin: 0 4px 0;
+        background-color: #000;
+
+        &[disabled] {
+            opacity: 0.5;
+        }
+    }
+}
+
+.font-color {
+    display: inline-block;
+    width: 8px;
+    height: 16px;
+
+    &:hover {
+        background-color: @tool-hover;
+    }
+
+    &:active {
+        background-color: @tool-active;
+    }
+
+    &[disabled] {
+        opacity: 0.5;
+    }
+
+    .caret {
+        margin-left: -2px;
+        margin-top: 7px;
+    }
+}

+ 65 - 0
kityminder-editor/less/topTab/appearance/layout.less

@@ -0,0 +1,65 @@
+.readjust-layout {
+    display: inline-block;
+    vertical-align: middle;
+    padding: 0 10px 0 5px;
+    border-right: 1px dashed #eee;
+}
+
+.btn-icon {
+    width: 25px;
+    height: 25px;
+    margin-left: 12px;
+    display: block;
+}
+
+.btn-label {
+    font-size: 12px;
+}
+
+.btn-wrap {
+    width: 50px;
+    height: 42px;
+    cursor: pointer;
+    display: inline-block;
+    text-decoration: none;
+
+    &[disabled] span {
+        opacity: 0.5;
+    }
+
+    &[disabled] {
+        cursor: default;
+    }
+
+    &[disabled]:hover {
+        background-color: transparent;
+    }
+
+    &[disabled]:active {
+        background-color: transparent;
+    }
+
+    &:link {
+        text-decoration: none;
+    }
+
+    &:visited {
+        text-decoration: none;
+    }
+
+    &:hover {
+        background-color: @tool-hover;
+        text-decoration: none;
+    }
+
+    &:active {
+        background-color: @tool-active;
+    }
+
+}
+
+.reset-layout-icon {
+    background: url(images/icons.png) no-repeat;
+    background-position: 0 -150px;
+}
+

+ 83 - 0
kityminder-editor/less/topTab/appearance/styleOperator.less

@@ -0,0 +1,83 @@
+.style-operator {
+    display: inline-block;
+    vertical-align: middle;
+    padding: 0 5px;
+    border-right: 1px dashed #eee;
+
+    .clear-style {
+        vertical-align: middle;
+    }
+
+}
+
+.clear-style-icon {
+    background: url(images/icons.png) no-repeat;
+    background-position: 0 -175px;;
+}
+
+.s-btn-group-vertical {
+    display: inline-block;
+    vertical-align: middle;
+}
+
+.s-btn-icon {
+    width: 20px;
+    height: 20px;
+    margin-right: 3px;
+    display: inline-block;
+    vertical-align: middle;
+}
+
+.s-btn-label {
+    font-size: 12px;
+    vertical-align: middle;
+    display: inline-block;
+}
+
+.s-btn-wrap {
+//    margin-bottom: 2px;
+    padding: 0 5px 0 3px;
+    display: inline-block;
+    text-decoration: none;
+    font-size: 0;
+
+    &[disabled] span {
+        opacity: 0.5;
+    }
+
+    &[disabled] {
+        cursor: default;
+    }
+
+    &[disabled]:hover {
+        background-color: transparent;
+    }
+
+    &[disabled]:active {
+        background-color: transparent;
+    }
+
+    &:hover {
+        background-color: @tool-hover;
+        text-decoration: none;
+    }
+
+    &:active {
+        background-color: @tool-active;
+    }
+
+}
+
+.copy-style-icon {
+    background: url(images/icons.png) no-repeat;
+    background-position: 0 -200px;
+}
+
+.paste-style-wrap {
+    display: block;
+}
+
+.paste-style-icon {
+    background: url(images/icons.png) no-repeat;
+    background-position: 0 -220px;
+}

+ 71 - 0
kityminder-editor/less/topTab/appearance/templatePanel.less

@@ -0,0 +1,71 @@
+.temp-panel {
+    margin: 5px 5px 5px 10px;
+    border-right: 1px dashed #eee;
+    display: inline-block;
+    vertical-align: middle;
+}
+
+.temp-list {
+    min-width: 124px;
+}
+
+.temp-item-wrap {
+    width: 50px;
+    height: 40px;
+    padding: 0 2px;
+    margin: 5px;
+    display: inline-block;
+}
+
+.temp-item {
+    display: inline-block;
+    width: 50px;
+    height: 40px;
+    background-image: url(images/template.png);
+    background-repeat: no-repeat;
+
+    &.default {
+        background-position: 0 0;
+    }
+
+    &.structure {
+        background-position: -50px 0;
+    }
+
+    &.filetree {
+        background-position: -100px 0;
+    }
+
+    &.right {
+        background-position: -150px 0;
+    }
+
+    &.fish-bone {
+        background-position: -200px 0;
+    }
+
+    &.tianpan {
+        background-position: -250px 0;
+    }
+}
+
+.current-temp-item {
+    width: 74px;
+    padding: 0 0 0 5px;
+    border: 1px solid #fff;
+
+    &:hover {
+        background-color: @tool-hover;
+    }
+
+    &[disabled] {
+        opacity: 0.5;
+    }
+
+    .caret {
+        margin-left: 5px;
+    }
+}
+.temp-item-selected {
+    background-color: @tool-selected;
+}

+ 53 - 0
kityminder-editor/less/topTab/appearance/themePanel.less

@@ -0,0 +1,53 @@
+.theme-panel {
+    height: 42px;
+    margin: 5px;
+    padding: 0 5px 0 0;
+    border-right: 1px dashed #eee;
+    display: inline-block;
+    vertical-align: middle;
+}
+
+.theme-list {
+    min-width: 162px;
+}
+
+div a.theme-item {
+    display: inline-block;
+    width: 70px;
+    height: 30px;
+    text-align: center;
+    line-height: 30px;
+    padding: 0 5px;
+    font-size: 12px;
+    cursor: pointer;
+    text-decoration: none;
+    color: #000;
+}
+
+.theme-item-selected {
+    width: 100px;
+    padding: 6px 7px;
+    border: 1px solid #fff;
+
+    &:hover {
+        background-color: @tool-hover;
+    }
+
+    .caret {
+        margin-left: 5px;
+    }
+
+    &[disabled] {
+        opacity: 0.5;
+    }
+}
+
+.theme-item-wrap {
+    display: inline-block;
+    width: 80px;
+    height: 40px;
+    padding: 5px;
+}
+.theme-item-wrap:hover {
+    background-color: #eff3fa;
+}

+ 21 - 0
kityminder-editor/less/topTab/idea/appendNode.less

@@ -0,0 +1,21 @@
+.append-group {
+    width: 212px;
+}
+
+.append-child-node {
+    .km-btn-icon {
+        background-position: 0 0;
+    }
+}
+
+.append-sibling-node {
+    .km-btn-icon {
+        background-position: 0 -20px;
+    }
+}
+
+.append-parent-node {
+    .km-btn-icon {
+        background-position: 0 -40px;
+    }
+}

+ 15 - 0
kityminder-editor/less/topTab/idea/arrange.less

@@ -0,0 +1,15 @@
+.arrange-group {
+    width: 64px;
+}
+
+.arrange-up {
+    .km-btn-icon {
+        background-position: 0 -280px;
+    }
+}
+
+.arrange-down {
+    .km-btn-icon {
+        background-position: 0 -300px;
+    }
+}

+ 43 - 0
kityminder-editor/less/topTab/idea/hyperlink.less

@@ -0,0 +1,43 @@
+.btn-group-vertical {
+    vertical-align: middle;
+    margin: 5px;
+
+    .hyperlink, .hyperlink-caption {
+        width: 40px;
+        margin: 0;
+        padding: 0;
+        border: none!important;
+        border-radius: 0!important;
+
+        &:hover {
+            background-color: @tool-hover;
+        }
+
+        &:active {
+            background-color: @tool-active;
+        }
+
+        &.active {
+            box-shadow: none;
+            background-color: @tool-hover;
+        }
+    }
+
+    .hyperlink {
+        height: 25px;
+        background: url(images/icons.png) no-repeat center -100px;
+    }
+
+    .hyperlink-caption {
+        height: 20px;
+
+        .caption {
+            font-size: 12px;
+        }
+    }
+}
+
+//override bootstrap
+.open > .dropdown-toggle.btn-default {
+    background-color: @tool-hover;
+}

+ 129 - 0
kityminder-editor/less/topTab/idea/image.less

@@ -0,0 +1,129 @@
+.btn-group-vertical {
+
+    .image-btn, .image-btn-caption {
+        width: 40px;
+        margin: 0;
+        padding: 0;
+        border: none!important;
+        border-radius: 0!important;
+
+        &:hover {
+            background-color: @tool-hover;
+        }
+
+        &:active {
+            background-color: @tool-active;
+        }
+
+        &.active {
+            box-shadow: none;
+            background-color: @tool-hover;
+        }
+    }
+
+    .image-btn {
+        height: 25px;
+        background: url(images/icons.png) no-repeat center -125px;
+    }
+
+    .image-btn-caption {
+        height: 20px;
+
+        .caption {
+            font-size: 12px;
+        }
+    }
+}
+
+.image-preview {
+    display: block;
+    max-width: 50%;
+}
+
+.modal-body {
+    .tab-pane {
+        font-size: inherit;
+        padding-top: 15px;
+    }
+}
+
+.search-result {
+    margin-top: 15px;
+    height: 370px;
+    overflow: hidden;
+
+    ul {
+        margin: 0;
+        padding: 0;
+        list-style: none;
+        clear: both;
+        height: 100%;
+        overflow-x: hidden;
+        overflow-y: auto;
+
+        li {
+            list-style: none;
+            float: left;
+            display: block;
+            width: 130px;
+            height: 130px;
+            line-height: 130px;
+            margin: 6px;
+            padding: 0;
+            font-size: 12px;
+            position: relative;
+            vertical-align: top;
+            text-align: center;
+            overflow: hidden;
+            cursor: pointer;
+            border: 2px solid #fcfcfc;
+
+            &.selected {
+                border: 2px solid #fc8383;
+            }
+
+
+            img {
+                max-width: 126px;
+                max-height: 130px;
+                vertical-align: middle;
+            }
+
+            span {
+                display: block;
+                position: absolute;
+                bottom: 0;
+                height: 20px;
+                background: rgba(0, 0, 0, 0.5);
+                left: 0;
+                right: 0;
+                color: white;
+                line-height: 20px;
+                overflow: hidden;
+                text-overflow: ellipsis;
+                word-break: break-all;
+                white-space: nowrap;
+                opacity: 0;
+                -webkit-transform: translate(0, 20px);
+                -ms-transform: translate(0, 20px);
+                transform: translate(0, 20px);
+                -webkit-transition: all .2s ease;
+                transition: all .2s ease;
+            }
+        }
+
+        li:hover span {
+            opacity: 1;
+            -webkit-transform: translate(0, 0);
+            -ms-transform: translate(0, 0);
+            transform: translate(0, 0);
+        }
+    }
+}
+
+// 覆盖 bootstrap 样式
+@media (min-width: 768px){
+    .form-inline .form-control {
+         width: 422px;
+     }
+}

+ 48 - 0
kityminder-editor/less/topTab/idea/note.less

@@ -0,0 +1,48 @@
+.btn-group-vertical {
+    vertical-align: top;
+    margin: 5px;
+
+    &.note-btn-group {
+        border-right: 1px dashed #eee;
+        padding-right: 5px;
+    }
+
+    .note-btn, .note-btn-caption {
+        width: 40px;
+        margin: 0;
+        padding: 0;
+        border: none!important;
+        border-radius: 0!important;
+
+        &:hover {
+            background-color: @tool-hover;
+        }
+
+        &:active {
+            background-color: @tool-active;
+        }
+
+        &.active {
+            box-shadow: none;
+            background-color: @tool-hover;
+        }
+    }
+
+    .note-btn {
+        height: 25px;
+        background: url(images/icons.png) no-repeat center -1150px;
+    }
+
+    .note-btn-caption {
+        height: 20px;
+
+        .caption {
+            font-size: 12px;
+        }
+    }
+}
+
+//override bootstrap
+.open > .dropdown-toggle.btn-default {
+    background-color: @tool-hover;
+}

+ 168 - 0
kityminder-editor/less/topTab/idea/noteEditor.less

@@ -0,0 +1,168 @@
+.gfm-render {
+
+    font-size: 12px;
+    -webkit-user-select: text;
+    color: #333;
+    line-height: 1.8em;
+
+    blockquote, ul, table, p, pre, hr {
+        margin: 1em 0;
+        cursor: text;
+        &:first-child:last-child {
+            margin: 0;
+        }
+    }
+
+    img {
+        max-width: 100%;
+    }
+
+    a {
+        color: blue;
+        &:hover {
+            color: red;
+        }
+    }
+
+    blockquote {
+        display: block;
+        border-left: 4px solid #E4AD91;
+        color: darken(#E4AD91, 10%);
+        padding-left: 10px;
+        font-style: italic;
+        margin-left: 2em;
+    }
+
+    ul, ol {
+        padding-left: 3em;
+    }
+
+    table {
+        width: 100%;
+        border-collapse: collapse;
+        th, td {
+            border: 1px solid #666;
+            padding: 2px 4px;
+        }
+        th {
+            background: rgba(45, 141, 234, 0.2);
+        }
+        tr:nth-child(even) td {
+            background: rgba(45, 141, 234, 0.03);
+        }
+        margin: 1em 0;
+    }
+
+    em {
+        color: red;
+    }
+
+    del {
+        color: #999;
+    }
+
+    pre {
+        background: rgba(45, 141, 234, 0.1);
+        padding: 5px;
+        border-radius: 5px;
+        word-break: break-all;
+        word-wrap: break-word;
+    }
+
+    code {
+        background: rgba(45, 141, 234, 0.1);
+        /*         display: inline-block; */
+        padding: 0 5px;
+        border-radius: 3px;
+    }
+
+    pre code {
+        background: none;
+    }
+
+    hr {
+        border: none;
+        border-top: 1px solid #CCC;
+    }
+
+    .highlight {
+        background: yellow;
+        color: red;
+    }
+}
+
+.km-note {
+    width: 300px;
+    border-left: 1px solid #babfcd;
+    padding: 5px 10px;
+    background: white;
+    position: absolute;
+    top: 92px;
+    right: 0;
+    bottom: 0;
+    left: auto;
+    z-index: 3;
+
+    &.panel {
+        margin: 0;
+        padding: 0;
+
+        .panel-heading {
+
+            h3 {
+                display: inline-block;
+            }
+
+            .close-note-editor {
+                width: 15px;
+                height: 15px;
+                display: inline-block;
+                float: right;
+
+                &:hover {
+                    cursor: pointer;
+                }
+            }
+        }
+
+        .panel-body {
+            padding: 0;
+        }
+    }
+
+    .CodeMirror {
+        position: absolute;
+        top: 41px;
+        bottom: 0;
+        height: auto;
+        cursor: text;
+        font-size: 14px;
+        line-height: 1.3em;
+        font-family: consolas;
+    }
+}
+.km-note-tips {
+    color: #ccc;
+    padding: 3px 8px;
+}
+#previewer-content {
+    position: absolute;
+    background: #FFD;
+    padding: 5px 15px;
+    border-radius: 5px;
+    max-width: 400px;
+    max-height: 200px;
+    overflow: auto;
+    z-index: 10;
+    box-shadow: 0 0 15px rgba(0, 0, 0, .5);
+    word-break: break-all;
+    .gfm-render;
+}
+#previewer-content.ng-hide {
+    display: block!important;
+    left: -99999px!important;
+    top: -99999px!important;
+}
+.panel-body {
+    padding: 10px;
+}

+ 15 - 0
kityminder-editor/less/topTab/idea/operation.less

@@ -0,0 +1,15 @@
+.operation-group {
+    width: 64px;
+}
+
+.edit-node {
+    .km-btn-icon {
+        background-position: 0 -60px;
+    }
+}
+
+.remove-node {
+    .km-btn-icon {
+        background-position: 0 -80px;
+    }
+}

+ 26 - 0
kityminder-editor/less/topTab/idea/priority.less

@@ -0,0 +1,26 @@
+.priority-sprite(@count) when (@count >= 0) {
+    .priority-sprite(@count - 1);
+    &.priority-@{count} {
+        background-position: 0 (-20px * (@count - 1));
+    }
+}
+
+.tab-content .km-priority {
+    vertical-align: middle;
+    font-size: inherit;
+    display: inline-block;
+    width: 140px;
+    margin: 5px;
+    border-right: 1px dashed #eee;
+
+    .km-priority-item {
+        margin: 0 1px;
+        padding: 1px;
+
+        .km-priority-icon {
+            .priority-sprite(9);
+            background: url(images/iconpriority.png) repeat-y;
+            background-color: transparent;
+        }
+  }
+}

+ 26 - 0
kityminder-editor/less/topTab/idea/progress.less

@@ -0,0 +1,26 @@
+.progress-sprite(@count) when (@count >= 0) {
+    .progress-sprite(@count - 1);
+    &.progress-@{count} {
+        background-position: 0 (-20px * (@count - 1));
+    }
+}
+
+.tab-content .km-progress {
+    vertical-align: middle;
+    font-size: inherit;
+    display: inline-block;
+    width: 140px;
+    margin: 5px;
+    border-right: 1px dashed #eee;
+
+    .km-progress-item {
+        margin: 0 1px;
+        padding: 1px;
+
+        .km-progress-icon {
+            .progress-sprite(9);
+            background: url(images/iconprogress.png) repeat-y;
+            background-color: transparent;
+        }
+    }
+}

+ 83 - 0
kityminder-editor/less/topTab/idea/resource.less

@@ -0,0 +1,83 @@
+.resource-editor {
+    vertical-align: middle;
+    display: inline-block;
+    margin: 5px;
+
+    .input-group, .km-resource {
+        font-size: 12px;
+    }
+
+    .input-group {
+        height: 20px;
+        width: 168px;
+    }
+
+    .resource-dropdown {
+        position: relative;
+        width: 168px;
+        border: 1px solid #ccc;
+        margin-top: -1px;
+        border-bottom-right-radius: 4px;
+        border-bottom-left-radius: 4px;
+
+        .km-resource {
+            position: absolute;
+            width: 154px;
+            margin-bottom: 3px;
+            padding: 0;
+            list-style-type: none;
+            overflow: scroll;
+            max-height: 500px;
+
+            &.open {
+                z-index: 3;
+                background-color: #fff;
+            }
+
+            li {
+                display: inline-block;
+                padding: 1px 2px;
+                border-radius: 4px;
+                margin: 2px 3px;
+
+                &[disabled] {
+                    opacity: 0.5;
+                }
+            }
+        }
+
+        .resource-caret {
+            display: block;
+            float: right;
+            vertical-align: middle;
+            width: 12px;
+            height: 24px;
+            padding: 8px 1px;
+
+            &:hover {background-color: @button-hover;}
+            &:active {background-color: @button-active;}
+        }
+    }
+
+    // 覆盖 bootstrap
+    input.form-control, .btn {
+        font-size: 12px;
+    }
+
+    input.form-control {
+        padding: 2px 4px;
+        height: 24px;
+        border-bottom-left-radius: 0;
+    }
+
+    .input-group-btn {
+        line-height: 24px;
+
+        .btn {
+            padding: 2px 4px;
+            height: 24px;
+            border-bottom-right-radius: 0;
+        }
+    }
+}
+

+ 15 - 0
kityminder-editor/less/topTab/idea/undoRedo.less

@@ -0,0 +1,15 @@
+.do-group {
+    width: 38px;
+}
+
+.undo {
+    .km-btn-icon {
+        background-position: 0 -1240px;
+    }
+}
+
+.redo {
+    .km-btn-icon {
+        background-position: 0 -1220px;
+    }
+}

+ 59 - 0
kityminder-editor/less/topTab/searchBox.less

@@ -0,0 +1,59 @@
+.search-box {
+    float: right;
+    background-color: #fff;
+    border: 1px solid #dbdbdb;
+    position: relative;
+    top: 0;
+    z-index: 3;
+    width: 360px;
+    height: 40px;
+    padding: 3px 6px;
+    opacity: 1;
+
+    .search-input-wrap, .prev-and-next-btn {
+        float: left;
+    }
+
+    .close-search {
+        float: right;
+        height: 16px;
+        width: 16px;
+        padding: 1px;
+        border-radius: 100%;
+        margin-top: 6px;
+        margin-right: 10px;
+
+        .glyphicon {
+            top: -1px
+        }
+
+        &:hover {
+            background-color: #efefef;
+        }
+
+        &:active {
+            background-color: #999;
+        }
+    }
+
+    .search-input-wrap {
+        width: 240px;
+    }
+
+    .prev-and-next-btn {
+        margin-left: 5px;
+
+        .btn:focus {
+            outline: none;
+        }
+    }
+
+    .search-input {
+        //border-right: none;
+    }
+
+    .search-addon {
+        background-color: #fff;
+    }
+
+}

+ 89 - 0
kityminder-editor/less/topTab/topTab.less

@@ -0,0 +1,89 @@
+.top-tab {
+
+    .nav-tabs {
+        background-color: #e1e1e1;
+        border: 0;
+        height: 32px;
+
+        li {
+            margin: 0;
+
+            a {
+                margin: 0;
+                border: 0;
+                padding: 6px 15px;
+                border-radius: 0;
+                vertical-align: middle;
+
+
+                &:hover, &:focus {
+                    background: inherit;
+                    border: 0;
+                }
+            }
+
+
+            &.active a {
+                border: 0;
+                background-color: #fff;
+
+                &:hover, &:focus {
+                    border: 0;
+                }
+            }
+        }
+    }
+
+    .tab-content {
+        height: 60px;
+        background-color: #fff;
+        border-bottom: 1px solid #dbdbdb;
+    }
+
+    .tab-pane {
+        font-size: 0;
+    }
+}
+
+.km-btn-group {
+    display: inline-block;
+    margin: 5px 0;
+    padding: 0 5px;
+    vertical-align: middle;
+    border-right: 1px dashed #eee;
+}
+
+.km-btn-item {
+    display: inline-block;
+    margin: 0 3px;
+    font-size: 0;
+    cursor: default;
+
+    &[disabled] {
+        opacity: 0.5;
+
+        &:hover, &:active {
+            background-color: #fff;
+        }
+    }
+
+    .km-btn-icon {
+        display: inline-block;
+        background: url(images/icons.png) no-repeat;
+        background-position: 0 20px;
+        width: 20px;
+        height: 20px;
+        padding: 2px;
+        margin: 1px;
+        vertical-align: middle;
+    }
+
+    .km-btn-caption {
+        display: inline-block;
+        font-size: 12px;
+        vertical-align: middle;
+    }
+
+    &:hover {background-color: @button-hover;}
+    &:active {background-color: @button-active;}
+}

+ 39 - 0
kityminder-editor/less/topTab/view/expand.less

@@ -0,0 +1,39 @@
+.btn-group-vertical {
+    vertical-align: middle;
+    margin: 5px;
+
+    .expand, .expand-caption {
+        width: 40px;
+        margin: 0;
+        padding: 0;
+        border: none!important;
+        border-radius: 0!important;
+
+        &:hover {
+            background-color: @tool-hover;
+        }
+
+        &:active {
+            background-color: @tool-active;
+        }
+
+        &.active {
+            box-shadow: none;
+            background-color: @tool-hover;
+        }
+    }
+
+    .expand {
+        height: 25px;
+        background: url(images/icons.png) no-repeat 0 -995px;
+        background-position-x: 50%;
+    }
+
+    .expand-caption {
+        height: 20px;
+
+        .caption {
+            font-size: 12px;
+        }
+    }
+}

+ 39 - 0
kityminder-editor/less/topTab/view/search.less

@@ -0,0 +1,39 @@
+.btn-group-vertical {
+    vertical-align: middle;
+    margin: 5px;
+
+    .search, .search-caption {
+        width: 40px;
+        margin: 0;
+        padding: 0;
+        border: none!important;
+        border-radius: 0!important;
+
+        &:hover {
+            background-color: @tool-hover;
+        }
+
+        &:active {
+            background-color: @tool-active;
+        }
+
+        &.active {
+            box-shadow: none;
+            background-color: @tool-hover;
+        }
+    }
+
+    .search {
+        height: 25px;
+        background: url(images/icons.png) no-repeat 0 -345px;
+        background-position-x: 50%;
+    }
+
+    .search-caption {
+        height: 20px;
+
+        .caption {
+            font-size: 12px;
+        }
+    }
+}

+ 38 - 0
kityminder-editor/less/topTab/view/select.less

@@ -0,0 +1,38 @@
+.btn-group-vertical {
+    vertical-align: middle;
+    margin: 5px;
+
+    .select, .select-caption {
+        width: 40px;
+        margin: 0;
+        padding: 0;
+        border: none!important;
+        border-radius: 0!important;
+
+        &:hover {
+            background-color: @tool-hover;
+        }
+
+        &:active {
+            background-color: @tool-active;
+        }
+
+        &.active {
+            box-shadow: none;
+            background-color: @tool-hover;
+        }
+    }
+
+    .select {
+        height: 25px;
+        background: url(images/icons.png) no-repeat 7px -1175px;
+    }
+
+    .select-caption {
+        height: 20px;
+
+        .caption {
+            font-size: 12px;
+        }
+    }
+}

+ 5885 - 0
kityminder-editor/package-lock.json

@@ -0,0 +1,5885 @@
+{
+  "name": "kityminder-editor",
+  "version": "1.0.65",
+  "lockfileVersion": 1,
+  "requires": true,
+  "dependencies": {
+    "abbrev": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+      "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
+      "dev": true
+    },
+    "accepts": {
+      "version": "1.3.5",
+      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
+      "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=",
+      "dev": true,
+      "requires": {
+        "mime-types": "~2.1.18",
+        "negotiator": "0.6.1"
+      }
+    },
+    "acorn": {
+      "version": "0.11.0",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-0.11.0.tgz",
+      "integrity": "sha1-bpXwJTrRYf8BJ9symD5eLlNS1Zo=",
+      "dev": true
+    },
+    "after": {
+      "version": "0.8.2",
+      "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
+      "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=",
+      "dev": true
+    },
+    "ajv": {
+      "version": "4.11.8",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz",
+      "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=",
+      "dev": true,
+      "requires": {
+        "co": "^4.6.0",
+        "json-stable-stringify": "^1.0.1"
+      }
+    },
+    "align-text": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
+      "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=",
+      "dev": true,
+      "requires": {
+        "kind-of": "^3.0.2",
+        "longest": "^1.0.1",
+        "repeat-string": "^1.5.2"
+      }
+    },
+    "alter": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/alter/-/alter-0.2.0.tgz",
+      "integrity": "sha1-x1iICGF1cgNKrmJICvJrHU0cs80=",
+      "dev": true,
+      "requires": {
+        "stable": "~0.1.3"
+      }
+    },
+    "ambi": {
+      "version": "2.5.0",
+      "resolved": "https://registry.npmjs.org/ambi/-/ambi-2.5.0.tgz",
+      "integrity": "sha1-fI43K+SIkRV+fOoBy2+RQ9H3QiA=",
+      "dev": true,
+      "requires": {
+        "editions": "^1.1.1",
+        "typechecker": "^4.3.0"
+      }
+    },
+    "amdefine": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
+      "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
+      "dev": true
+    },
+    "ansi-regex": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz",
+      "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=",
+      "dev": true
+    },
+    "ansi-styles": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz",
+      "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=",
+      "dev": true
+    },
+    "anymatch": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz",
+      "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==",
+      "dev": true,
+      "requires": {
+        "micromatch": "^2.1.5",
+        "normalize-path": "^2.0.0"
+      }
+    },
+    "applause": {
+      "version": "0.3.4",
+      "resolved": "https://registry.npmjs.org/applause/-/applause-0.3.4.tgz",
+      "integrity": "sha1-ewmzqpZagID6XYPaXDVoeKJm0/k=",
+      "dev": true,
+      "requires": {
+        "cson": "^1.6.0",
+        "js-yaml": "^3.0.0",
+        "lodash": "^2.4.0"
+      },
+      "dependencies": {
+        "argparse": {
+          "version": "1.0.10",
+          "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+          "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+          "dev": true,
+          "requires": {
+            "sprintf-js": "~1.0.2"
+          }
+        },
+        "esprima": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz",
+          "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==",
+          "dev": true
+        },
+        "js-yaml": {
+          "version": "3.11.0",
+          "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz",
+          "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==",
+          "dev": true,
+          "requires": {
+            "argparse": "^1.0.7",
+            "esprima": "^4.0.0"
+          }
+        },
+        "lodash": {
+          "version": "2.4.2",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz",
+          "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=",
+          "dev": true
+        }
+      }
+    },
+    "argparse": {
+      "version": "0.1.16",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-0.1.16.tgz",
+      "integrity": "sha1-z9AeD7uj1srtBJ+9dY1A9lGW9Xw=",
+      "dev": true,
+      "requires": {
+        "underscore": "~1.7.0",
+        "underscore.string": "~2.4.0"
+      },
+      "dependencies": {
+        "underscore.string": {
+          "version": "2.4.0",
+          "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.4.0.tgz",
+          "integrity": "sha1-jN2PusTi0uoefi6Al8QvRCKA+Fs=",
+          "dev": true
+        }
+      }
+    },
+    "arr-diff": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
+      "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
+      "dev": true,
+      "requires": {
+        "arr-flatten": "^1.0.1"
+      }
+    },
+    "arr-flatten": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
+      "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
+      "dev": true
+    },
+    "array-differ": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz",
+      "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=",
+      "dev": true
+    },
+    "array-find-index": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
+      "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
+      "dev": true
+    },
+    "array-union": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
+      "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
+      "dev": true,
+      "requires": {
+        "array-uniq": "^1.0.1"
+      }
+    },
+    "array-uniq": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
+      "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
+      "dev": true
+    },
+    "array-unique": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
+      "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
+      "dev": true
+    },
+    "arraybuffer.slice": {
+      "version": "0.0.7",
+      "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz",
+      "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==",
+      "dev": true
+    },
+    "arrify": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+      "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
+      "dev": true
+    },
+    "asap": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+      "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=",
+      "dev": true,
+      "optional": true
+    },
+    "asn1": {
+      "version": "0.2.3",
+      "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
+      "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=",
+      "dev": true
+    },
+    "assert-plus": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz",
+      "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=",
+      "dev": true
+    },
+    "async": {
+      "version": "0.1.22",
+      "resolved": "https://registry.npmjs.org/async/-/async-0.1.22.tgz",
+      "integrity": "sha1-D8GqoIig4+8Ovi2IMbqw3PiEUGE=",
+      "dev": true
+    },
+    "async-each": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz",
+      "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=",
+      "dev": true
+    },
+    "async-each-series": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/async-each-series/-/async-each-series-0.1.1.tgz",
+      "integrity": "sha1-dhfBkXQB/Yykooqtzj266Yr+tDI=",
+      "dev": true
+    },
+    "async-limiter": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
+      "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==",
+      "dev": true
+    },
+    "asynckit": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+      "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
+      "dev": true
+    },
+    "aws-sign2": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz",
+      "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=",
+      "dev": true
+    },
+    "aws4": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz",
+      "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=",
+      "dev": true
+    },
+    "backo2": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
+      "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=",
+      "dev": true
+    },
+    "balanced-match": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+      "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+      "dev": true
+    },
+    "base64-arraybuffer": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz",
+      "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=",
+      "dev": true
+    },
+    "base64id": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz",
+      "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=",
+      "dev": true
+    },
+    "batch": {
+      "version": "0.5.3",
+      "resolved": "https://registry.npmjs.org/batch/-/batch-0.5.3.tgz",
+      "integrity": "sha1-PzQU84AyF0O/wQQvmoP/HVgk1GQ=",
+      "dev": true
+    },
+    "bcrypt-pbkdf": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
+      "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "tweetnacl": "^0.14.3"
+      }
+    },
+    "better-assert": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz",
+      "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=",
+      "dev": true,
+      "requires": {
+        "callsite": "1.0.0"
+      }
+    },
+    "binary-extensions": {
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz",
+      "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=",
+      "dev": true
+    },
+    "blob": {
+      "version": "0.0.4",
+      "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz",
+      "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=",
+      "dev": true
+    },
+    "body-parser": {
+      "version": "1.14.2",
+      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz",
+      "integrity": "sha1-EBXLH+LEQ4WCWVgdtTMy+NDPUPk=",
+      "dev": true,
+      "requires": {
+        "bytes": "2.2.0",
+        "content-type": "~1.0.1",
+        "debug": "~2.2.0",
+        "depd": "~1.1.0",
+        "http-errors": "~1.3.1",
+        "iconv-lite": "0.4.13",
+        "on-finished": "~2.3.0",
+        "qs": "5.2.0",
+        "raw-body": "~2.1.5",
+        "type-is": "~1.6.10"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
+          "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=",
+          "dev": true,
+          "requires": {
+            "ms": "0.7.1"
+          }
+        },
+        "http-errors": {
+          "version": "1.3.1",
+          "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz",
+          "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=",
+          "dev": true,
+          "requires": {
+            "inherits": "~2.0.1",
+            "statuses": "1"
+          }
+        },
+        "iconv-lite": {
+          "version": "0.4.13",
+          "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz",
+          "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=",
+          "dev": true
+        },
+        "ms": {
+          "version": "0.7.1",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz",
+          "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=",
+          "dev": true
+        },
+        "qs": {
+          "version": "5.2.0",
+          "resolved": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz",
+          "integrity": "sha1-qfMRQq9GjLcrJbMBNrokVoNJFr4=",
+          "dev": true
+        }
+      }
+    },
+    "boom": {
+      "version": "2.10.1",
+      "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz",
+      "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=",
+      "dev": true,
+      "requires": {
+        "hoek": "2.x.x"
+      }
+    },
+    "bower-config": {
+      "version": "0.5.3",
+      "resolved": "https://registry.npmjs.org/bower-config/-/bower-config-0.5.3.tgz",
+      "integrity": "sha1-mPxbQah4cO+cu5KXY1z4H1UF/bE=",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "~2.0.0",
+        "mout": "~0.9.0",
+        "optimist": "~0.6.0",
+        "osenv": "0.0.3"
+      },
+      "dependencies": {
+        "graceful-fs": {
+          "version": "2.0.3",
+          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz",
+          "integrity": "sha1-fNLNsiiko/Nule+mzBQt59GhNtA=",
+          "dev": true
+        }
+      }
+    },
+    "brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dev": true,
+      "requires": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "braces": {
+      "version": "1.8.5",
+      "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
+      "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
+      "dev": true,
+      "requires": {
+        "expand-range": "^1.8.1",
+        "preserve": "^0.2.0",
+        "repeat-element": "^1.1.2"
+      }
+    },
+    "browser-sync": {
+      "version": "2.23.6",
+      "resolved": "https://registry.npmjs.org/browser-sync/-/browser-sync-2.23.6.tgz",
+      "integrity": "sha512-loCO5NQKZXfBJrEvmLwF1TPSECCsPopNd29qduoysLmpw8op2lgolGMjz3oI/MjG4duzB9TfDs7k58djRSwPwg==",
+      "dev": true,
+      "requires": {
+        "browser-sync-ui": "v1.0.1",
+        "bs-recipes": "1.3.4",
+        "chokidar": "1.7.0",
+        "connect": "3.5.0",
+        "connect-history-api-fallback": "^1.5.0",
+        "dev-ip": "^1.0.1",
+        "easy-extender": "2.3.2",
+        "eazy-logger": "3.0.2",
+        "emitter-steward": "^1.0.0",
+        "etag": "^1.8.1",
+        "fresh": "^0.5.2",
+        "fs-extra": "3.0.1",
+        "http-proxy": "1.15.2",
+        "immutable": "3.8.2",
+        "localtunnel": "1.8.3",
+        "micromatch": "2.3.11",
+        "opn": "4.0.2",
+        "portscanner": "2.1.1",
+        "qs": "6.2.1",
+        "resp-modifier": "6.0.2",
+        "rx": "4.1.0",
+        "serve-index": "1.8.0",
+        "serve-static": "1.12.2",
+        "server-destroy": "1.0.1",
+        "socket.io": "2.0.4",
+        "ua-parser-js": "0.7.12",
+        "yargs": "6.4.0"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+          "dev": true
+        },
+        "camelcase": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
+          "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
+          "dev": true
+        },
+        "cliui": {
+          "version": "3.2.0",
+          "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
+          "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
+          "dev": true,
+          "requires": {
+            "string-width": "^1.0.1",
+            "strip-ansi": "^3.0.1",
+            "wrap-ansi": "^2.0.0"
+          }
+        },
+        "qs": {
+          "version": "6.2.1",
+          "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.1.tgz",
+          "integrity": "sha1-zgPF/wk1vB2daanxTL0Y5WjWdiU=",
+          "dev": true
+        },
+        "strip-ansi": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+          "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^2.0.0"
+          }
+        },
+        "window-size": {
+          "version": "0.2.0",
+          "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz",
+          "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=",
+          "dev": true
+        },
+        "yargs": {
+          "version": "6.4.0",
+          "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.4.0.tgz",
+          "integrity": "sha1-gW4ahm1VmMzzTlWW3c4i2S2kkNQ=",
+          "dev": true,
+          "requires": {
+            "camelcase": "^3.0.0",
+            "cliui": "^3.2.0",
+            "decamelize": "^1.1.1",
+            "get-caller-file": "^1.0.1",
+            "os-locale": "^1.4.0",
+            "read-pkg-up": "^1.0.1",
+            "require-directory": "^2.1.1",
+            "require-main-filename": "^1.0.1",
+            "set-blocking": "^2.0.0",
+            "string-width": "^1.0.2",
+            "which-module": "^1.0.0",
+            "window-size": "^0.2.0",
+            "y18n": "^3.2.1",
+            "yargs-parser": "^4.1.0"
+          }
+        }
+      }
+    },
+    "browser-sync-ui": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/browser-sync-ui/-/browser-sync-ui-1.0.1.tgz",
+      "integrity": "sha512-RIxmwVVcUFhRd1zxp7m2FfLnXHf59x4Gtj8HFwTA//3VgYI3AKkaQAuDL8KDJnE59XqCshxZa13JYuIWtZlKQg==",
+      "dev": true,
+      "requires": {
+        "async-each-series": "0.1.1",
+        "connect-history-api-fallback": "^1.1.0",
+        "immutable": "^3.7.6",
+        "server-destroy": "1.0.1",
+        "socket.io-client": "2.0.4",
+        "stream-throttle": "^0.1.3"
+      }
+    },
+    "browserify-zlib": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz",
+      "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=",
+      "dev": true,
+      "requires": {
+        "pako": "~0.2.0"
+      }
+    },
+    "bs-recipes": {
+      "version": "1.3.4",
+      "resolved": "https://registry.npmjs.org/bs-recipes/-/bs-recipes-1.3.4.tgz",
+      "integrity": "sha1-DS1NSKcYyMBEdp/cT4lZLci2lYU=",
+      "dev": true
+    },
+    "builtin-modules": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
+      "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
+      "dev": true
+    },
+    "bytes": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz",
+      "integrity": "sha1-/TVGSkA/b5EXwt42Cez/nK4ABYg=",
+      "dev": true
+    },
+    "callsite": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz",
+      "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=",
+      "dev": true
+    },
+    "camel-case": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-1.2.2.tgz",
+      "integrity": "sha1-Gsp8TRlTWaLOmVV5NDPG5VQlEfI=",
+      "dev": true,
+      "requires": {
+        "sentence-case": "^1.1.1",
+        "upper-case": "^1.1.1"
+      }
+    },
+    "camelcase": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
+      "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=",
+      "dev": true
+    },
+    "camelcase-keys": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
+      "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
+      "dev": true,
+      "requires": {
+        "camelcase": "^2.0.0",
+        "map-obj": "^1.0.0"
+      },
+      "dependencies": {
+        "camelcase": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
+          "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=",
+          "dev": true
+        }
+      }
+    },
+    "caseless": {
+      "version": "0.12.0",
+      "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+      "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
+      "dev": true
+    },
+    "center-align": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
+      "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=",
+      "dev": true,
+      "requires": {
+        "align-text": "^0.1.3",
+        "lazy-cache": "^1.0.3"
+      }
+    },
+    "chalk": {
+      "version": "0.5.1",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz",
+      "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=",
+      "dev": true,
+      "requires": {
+        "ansi-styles": "^1.1.0",
+        "escape-string-regexp": "^1.0.0",
+        "has-ansi": "^0.1.0",
+        "strip-ansi": "^0.3.0",
+        "supports-color": "^0.2.0"
+      }
+    },
+    "change-case": {
+      "version": "2.1.6",
+      "resolved": "https://registry.npmjs.org/change-case/-/change-case-2.1.6.tgz",
+      "integrity": "sha1-UUryBRMVimj+fwDf9MMy1sKY0vk=",
+      "dev": true,
+      "requires": {
+        "camel-case": "^1.0.0",
+        "constant-case": "^1.0.0",
+        "dot-case": "^1.0.0",
+        "is-lower-case": "^1.0.0",
+        "is-upper-case": "^1.0.0",
+        "lower-case": "^1.0.0",
+        "param-case": "^1.0.0",
+        "pascal-case": "^1.0.0",
+        "path-case": "^1.0.0",
+        "sentence-case": "^1.0.0",
+        "snake-case": "^1.0.0",
+        "swap-case": "^1.0.0",
+        "title-case": "^1.0.0",
+        "upper-case": "^1.0.0",
+        "upper-case-first": "^1.0.0"
+      }
+    },
+    "chokidar": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz",
+      "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=",
+      "dev": true,
+      "requires": {
+        "anymatch": "^1.3.0",
+        "async-each": "^1.0.0",
+        "fsevents": "^1.0.0",
+        "glob-parent": "^2.0.0",
+        "inherits": "^2.0.1",
+        "is-binary-path": "^1.0.0",
+        "is-glob": "^2.0.0",
+        "path-is-absolute": "^1.0.0",
+        "readdirp": "^2.0.0"
+      }
+    },
+    "clean-css": {
+      "version": "2.2.23",
+      "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-2.2.23.tgz",
+      "integrity": "sha1-BZC1R4tRbEkD7cLYm9P9vdKGMow=",
+      "dev": true,
+      "requires": {
+        "commander": "2.2.x"
+      }
+    },
+    "cli": {
+      "version": "0.6.6",
+      "resolved": "https://registry.npmjs.org/cli/-/cli-0.6.6.tgz",
+      "integrity": "sha1-Aq1Eo4Cr8nraxebwzdewQ9dMU+M=",
+      "dev": true,
+      "requires": {
+        "exit": "0.1.2",
+        "glob": "~ 3.2.1"
+      },
+      "dependencies": {
+        "glob": {
+          "version": "3.2.11",
+          "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz",
+          "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=",
+          "dev": true,
+          "requires": {
+            "inherits": "2",
+            "minimatch": "0.3"
+          }
+        },
+        "minimatch": {
+          "version": "0.3.0",
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz",
+          "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=",
+          "dev": true,
+          "requires": {
+            "lru-cache": "2",
+            "sigmund": "~1.0.0"
+          }
+        }
+      }
+    },
+    "cli-color": {
+      "version": "0.1.7",
+      "resolved": "http://registry.npm.baidu-int.com/cli-color/-/cli-color-0.1.7.tgz",
+      "integrity": "sha1-rcMgD6RxzCEbDaf1ZrcemLnWc0c=",
+      "requires": {
+        "es5-ext": "0.8.x"
+      }
+    },
+    "cliui": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
+      "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
+      "dev": true,
+      "requires": {
+        "center-align": "^0.1.1",
+        "right-align": "^0.1.1",
+        "wordwrap": "0.0.2"
+      }
+    },
+    "co": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+      "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
+      "dev": true
+    },
+    "code-point-at": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+      "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
+      "dev": true
+    },
+    "coffee-script": {
+      "version": "1.3.3",
+      "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.3.3.tgz",
+      "integrity": "sha1-FQ1rTLUiiUNp7+1qIQHCC8f0pPQ=",
+      "dev": true
+    },
+    "colors": {
+      "version": "0.6.2",
+      "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz",
+      "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=",
+      "dev": true
+    },
+    "combined-stream": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
+      "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=",
+      "dev": true,
+      "requires": {
+        "delayed-stream": "~1.0.0"
+      }
+    },
+    "commander": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-2.2.0.tgz",
+      "integrity": "sha1-F1rUuTF/P/YV8gHB5XIk9Vo+kd8=",
+      "dev": true
+    },
+    "component-bind": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz",
+      "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=",
+      "dev": true
+    },
+    "component-emitter": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
+      "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=",
+      "dev": true
+    },
+    "component-inherit": {
+      "version": "0.0.3",
+      "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz",
+      "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=",
+      "dev": true
+    },
+    "concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+      "dev": true
+    },
+    "concat-stream": {
+      "version": "1.6.1",
+      "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.1.tgz",
+      "integrity": "sha512-gslSSJx03QKa59cIKqeJO9HQ/WZMotvYJCuaUULrLpjj8oG40kV2Z+gz82pVxlTkOADi4PJxQPPfhl1ELYrrXw==",
+      "dev": true,
+      "requires": {
+        "inherits": "^2.0.3",
+        "readable-stream": "^2.2.2",
+        "typedarray": "^0.0.6"
+      }
+    },
+    "connect": {
+      "version": "3.5.0",
+      "resolved": "https://registry.npmjs.org/connect/-/connect-3.5.0.tgz",
+      "integrity": "sha1-s1dSWgtMH1BZnNmD4dnv7qlncZg=",
+      "dev": true,
+      "requires": {
+        "debug": "~2.2.0",
+        "finalhandler": "0.5.0",
+        "parseurl": "~1.3.1",
+        "utils-merge": "1.0.0"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
+          "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=",
+          "dev": true,
+          "requires": {
+            "ms": "0.7.1"
+          }
+        },
+        "ms": {
+          "version": "0.7.1",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz",
+          "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=",
+          "dev": true
+        }
+      }
+    },
+    "connect-history-api-fallback": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz",
+      "integrity": "sha1-sGhzk0vF40T+9hGhlqb6rgruAVo=",
+      "dev": true
+    },
+    "constant-case": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-1.1.2.tgz",
+      "integrity": "sha1-jsLKW6ND4Aqjjb9OIA/VrJB+/WM=",
+      "dev": true,
+      "requires": {
+        "snake-case": "^1.1.0",
+        "upper-case": "^1.1.1"
+      }
+    },
+    "content-type": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
+      "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
+      "dev": true
+    },
+    "conventional-commit-types": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/conventional-commit-types/-/conventional-commit-types-2.2.0.tgz",
+      "integrity": "sha1-XblXOdbCEqy+e29lahG5QLqmiUY=",
+      "dev": true
+    },
+    "convert-source-map": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-0.4.1.tgz",
+      "integrity": "sha1-+RmgCZ/jH4D8Wh0OswMWGzlAcMc=",
+      "dev": true
+    },
+    "cookie": {
+      "version": "0.3.1",
+      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
+      "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=",
+      "dev": true
+    },
+    "core-util-is": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+      "dev": true
+    },
+    "cryptiles": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz",
+      "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=",
+      "dev": true,
+      "requires": {
+        "boom": "2.x.x"
+      }
+    },
+    "cson": {
+      "version": "1.6.2",
+      "resolved": "https://registry.npmjs.org/cson/-/cson-1.6.2.tgz",
+      "integrity": "sha1-+uexPaHOsHfeKv26hjDGeQMl9Fk=",
+      "dev": true,
+      "requires": {
+        "ambi": "^2.2.0",
+        "coffee-script": "~1.8.0",
+        "extract-opts": "~2.2.0",
+        "js2coffee": "~0.3.5",
+        "requirefresh": "~1.1.2"
+      },
+      "dependencies": {
+        "coffee-script": {
+          "version": "1.8.0",
+          "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.8.0.tgz",
+          "integrity": "sha1-nJ8dK0pSoADe0Vtll5FwNkgmPB0=",
+          "dev": true,
+          "requires": {
+            "mkdirp": "~0.3.5"
+          }
+        },
+        "mkdirp": {
+          "version": "0.3.5",
+          "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz",
+          "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=",
+          "dev": true
+        }
+      }
+    },
+    "currently-unhandled": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
+      "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
+      "dev": true,
+      "requires": {
+        "array-find-index": "^1.0.1"
+      }
+    },
+    "cz-conventional-changelog": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/cz-conventional-changelog/-/cz-conventional-changelog-1.2.0.tgz",
+      "integrity": "sha1-K8oElkyJGbI/P9aonvXmAIsxs/g=",
+      "dev": true,
+      "requires": {
+        "conventional-commit-types": "^2.0.0",
+        "lodash.map": "^4.5.1",
+        "longest": "^1.0.1",
+        "pad-right": "^0.2.2",
+        "right-pad": "^1.0.1",
+        "word-wrap": "^1.0.3"
+      }
+    },
+    "dashdash": {
+      "version": "1.14.1",
+      "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+      "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+      "dev": true,
+      "requires": {
+        "assert-plus": "^1.0.0"
+      },
+      "dependencies": {
+        "assert-plus": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+          "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+          "dev": true
+        }
+      }
+    },
+    "dateformat": {
+      "version": "1.0.2-1.2.3",
+      "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.2-1.2.3.tgz",
+      "integrity": "sha1-sCIMAt6YYXQztyhRz0fePfLNvuk=",
+      "dev": true
+    },
+    "debug": {
+      "version": "2.6.9",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "dev": true,
+      "requires": {
+        "ms": "2.0.0"
+      }
+    },
+    "decamelize": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+      "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+      "dev": true
+    },
+    "delayed-stream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+      "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+      "dev": true
+    },
+    "depd": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+      "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
+      "dev": true
+    },
+    "destroy": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
+      "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=",
+      "dev": true
+    },
+    "dev-ip": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/dev-ip/-/dev-ip-1.0.1.tgz",
+      "integrity": "sha1-p2o+0YVb56ASu4rBbLgPPADcKPA=",
+      "dev": true
+    },
+    "difflib": {
+      "version": "0.2.4",
+      "resolved": "http://registry.npm.baidu-int.com/difflib/-/difflib-0.2.4.tgz",
+      "integrity": "sha1-teMDYabbAjF21WKJLbhZQKcY9H4=",
+      "requires": {
+        "heap": ">= 0.2.0"
+      }
+    },
+    "dot-case": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-1.1.2.tgz",
+      "integrity": "sha1-HnOCaQDeKNbeVIC8HeMdCEKwa+w=",
+      "dev": true,
+      "requires": {
+        "sentence-case": "^1.1.2"
+      }
+    },
+    "dreamopt": {
+      "version": "0.6.0",
+      "resolved": "http://registry.npm.baidu-int.com/dreamopt/-/dreamopt-0.6.0.tgz",
+      "integrity": "sha1-2BPM2sjTnYrVJndVFKE92mZNa0s=",
+      "requires": {
+        "wordwrap": ">=0.0.2"
+      }
+    },
+    "easy-extender": {
+      "version": "2.3.2",
+      "resolved": "https://registry.npmjs.org/easy-extender/-/easy-extender-2.3.2.tgz",
+      "integrity": "sha1-PTJI/r4rFZYHMW2PnPSRwWZIIh0=",
+      "dev": true,
+      "requires": {
+        "lodash": "^3.10.1"
+      },
+      "dependencies": {
+        "lodash": {
+          "version": "3.10.1",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
+          "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=",
+          "dev": true
+        }
+      }
+    },
+    "eazy-logger": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/eazy-logger/-/eazy-logger-3.0.2.tgz",
+      "integrity": "sha1-oyWqXlPROiIliJsqxBE7K5Y29Pw=",
+      "dev": true,
+      "requires": {
+        "tfunk": "^3.0.1"
+      }
+    },
+    "ecc-jsbn": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
+      "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "jsbn": "~0.1.0"
+      }
+    },
+    "editions": {
+      "version": "1.3.4",
+      "resolved": "https://registry.npmjs.org/editions/-/editions-1.3.4.tgz",
+      "integrity": "sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg==",
+      "dev": true
+    },
+    "ee-first": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+      "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
+      "dev": true
+    },
+    "emitter-steward": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/emitter-steward/-/emitter-steward-1.0.0.tgz",
+      "integrity": "sha1-80Ea3pdYp1Zd+Eiy2gy70bRsvWQ=",
+      "dev": true
+    },
+    "encodeurl": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+      "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
+      "dev": true
+    },
+    "engine.io": {
+      "version": "3.1.5",
+      "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.1.5.tgz",
+      "integrity": "sha512-D06ivJkYxyRrcEe0bTpNnBQNgP9d3xog+qZlLbui8EsMr/DouQpf5o9FzJnWYHEYE0YsFHllUv2R1dkgYZXHcA==",
+      "dev": true,
+      "requires": {
+        "accepts": "~1.3.4",
+        "base64id": "1.0.0",
+        "cookie": "0.3.1",
+        "debug": "~3.1.0",
+        "engine.io-parser": "~2.1.0",
+        "uws": "~9.14.0",
+        "ws": "~3.3.1"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        }
+      }
+    },
+    "engine.io-client": {
+      "version": "3.1.6",
+      "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.1.6.tgz",
+      "integrity": "sha512-hnuHsFluXnsKOndS4Hv6SvUrgdYx1pk2NqfaDMW+GWdgfU3+/V25Cj7I8a0x92idSpa5PIhJRKxPvp9mnoLsfg==",
+      "dev": true,
+      "requires": {
+        "component-emitter": "1.2.1",
+        "component-inherit": "0.0.3",
+        "debug": "~3.1.0",
+        "engine.io-parser": "~2.1.1",
+        "has-cors": "1.1.0",
+        "indexof": "0.0.1",
+        "parseqs": "0.0.5",
+        "parseuri": "0.0.5",
+        "ws": "~3.3.1",
+        "xmlhttprequest-ssl": "~1.5.4",
+        "yeast": "0.1.2"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        }
+      }
+    },
+    "engine.io-parser": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz",
+      "integrity": "sha512-dInLFzr80RijZ1rGpx1+56/uFoH7/7InhH3kZt+Ms6hT8tNx3NGW/WNSA/f8As1WkOfkuyb3tnRyuXGxusclMw==",
+      "dev": true,
+      "requires": {
+        "after": "0.8.2",
+        "arraybuffer.slice": "~0.0.7",
+        "base64-arraybuffer": "0.1.5",
+        "blob": "0.0.4",
+        "has-binary2": "~1.0.2"
+      }
+    },
+    "errno": {
+      "version": "0.1.7",
+      "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
+      "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "prr": "~1.0.1"
+      }
+    },
+    "error-ex": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz",
+      "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=",
+      "dev": true,
+      "requires": {
+        "is-arrayish": "^0.2.1"
+      }
+    },
+    "es5-ext": {
+      "version": "0.8.2",
+      "resolved": "http://registry.npm.baidu-int.com/es5-ext/-/es5-ext-0.8.2.tgz",
+      "integrity": "sha1-q6jZ4ZQ6iVrJaDemKjmz9V7NlKs="
+    },
+    "escape-html": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+      "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=",
+      "dev": true
+    },
+    "escape-string-regexp": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+      "dev": true
+    },
+    "esprima": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz",
+      "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=",
+      "dev": true
+    },
+    "etag": {
+      "version": "1.8.1",
+      "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+      "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
+      "dev": true
+    },
+    "eventemitter2": {
+      "version": "0.4.14",
+      "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz",
+      "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=",
+      "dev": true
+    },
+    "eventemitter3": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz",
+      "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=",
+      "dev": true
+    },
+    "exit": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+      "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=",
+      "dev": true
+    },
+    "expand-brackets": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
+      "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
+      "dev": true,
+      "requires": {
+        "is-posix-bracket": "^0.1.0"
+      }
+    },
+    "expand-range": {
+      "version": "1.8.2",
+      "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
+      "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=",
+      "dev": true,
+      "requires": {
+        "fill-range": "^2.1.0"
+      }
+    },
+    "extend": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
+      "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=",
+      "dev": true
+    },
+    "extglob": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
+      "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
+      "dev": true,
+      "requires": {
+        "is-extglob": "^1.0.0"
+      }
+    },
+    "extract-opts": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/extract-opts/-/extract-opts-2.2.0.tgz",
+      "integrity": "sha1-H6KOunNSxttID4hc63GkaBC+bX0=",
+      "dev": true,
+      "requires": {
+        "typechecker": "~2.0.1"
+      },
+      "dependencies": {
+        "typechecker": {
+          "version": "2.0.8",
+          "resolved": "https://registry.npmjs.org/typechecker/-/typechecker-2.0.8.tgz",
+          "integrity": "sha1-6D2oS7ZMWEzLNFg4V2xAsDN9uC4=",
+          "dev": true
+        }
+      }
+    },
+    "extsprintf": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+      "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
+      "dev": true
+    },
+    "faye-websocket": {
+      "version": "0.10.0",
+      "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz",
+      "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=",
+      "dev": true,
+      "requires": {
+        "websocket-driver": ">=0.5.1"
+      }
+    },
+    "figures": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz",
+      "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=",
+      "dev": true,
+      "requires": {
+        "escape-string-regexp": "^1.0.5",
+        "object-assign": "^4.1.0"
+      }
+    },
+    "file": {
+      "version": "0.2.2",
+      "resolved": "https://registry.npmjs.org/file/-/file-0.2.2.tgz",
+      "integrity": "sha1-w9/Y+M81Na5FXCtCPC5SY112tNM=",
+      "dev": true
+    },
+    "filename-regex": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz",
+      "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=",
+      "dev": true
+    },
+    "fill-range": {
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz",
+      "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=",
+      "dev": true,
+      "requires": {
+        "is-number": "^2.1.0",
+        "isobject": "^2.0.0",
+        "randomatic": "^1.1.3",
+        "repeat-element": "^1.1.2",
+        "repeat-string": "^1.5.2"
+      }
+    },
+    "finalhandler": {
+      "version": "0.5.0",
+      "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.5.0.tgz",
+      "integrity": "sha1-6VCKvs6bbbqHGmlCodeRG5GRGsc=",
+      "dev": true,
+      "requires": {
+        "debug": "~2.2.0",
+        "escape-html": "~1.0.3",
+        "on-finished": "~2.3.0",
+        "statuses": "~1.3.0",
+        "unpipe": "~1.0.0"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
+          "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=",
+          "dev": true,
+          "requires": {
+            "ms": "0.7.1"
+          }
+        },
+        "ms": {
+          "version": "0.7.1",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz",
+          "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=",
+          "dev": true
+        }
+      }
+    },
+    "find-up": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+      "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+      "dev": true,
+      "requires": {
+        "path-exists": "^2.0.0",
+        "pinkie-promise": "^2.0.0"
+      }
+    },
+    "findup-sync": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.1.3.tgz",
+      "integrity": "sha1-fz56l7gjksZTvwZYm9hRkOk8NoM=",
+      "dev": true,
+      "requires": {
+        "glob": "~3.2.9",
+        "lodash": "~2.4.1"
+      },
+      "dependencies": {
+        "glob": {
+          "version": "3.2.11",
+          "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz",
+          "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=",
+          "dev": true,
+          "requires": {
+            "inherits": "2",
+            "minimatch": "0.3"
+          }
+        },
+        "lodash": {
+          "version": "2.4.2",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz",
+          "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=",
+          "dev": true
+        },
+        "minimatch": {
+          "version": "0.3.0",
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz",
+          "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=",
+          "dev": true,
+          "requires": {
+            "lru-cache": "2",
+            "sigmund": "~1.0.0"
+          }
+        }
+      }
+    },
+    "for-in": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+      "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
+      "dev": true
+    },
+    "for-own": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz",
+      "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=",
+      "dev": true,
+      "requires": {
+        "for-in": "^1.0.1"
+      }
+    },
+    "forever-agent": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+      "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
+      "dev": true
+    },
+    "form-data": {
+      "version": "2.1.4",
+      "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz",
+      "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=",
+      "dev": true,
+      "requires": {
+        "asynckit": "^0.4.0",
+        "combined-stream": "^1.0.5",
+        "mime-types": "^2.1.12"
+      }
+    },
+    "fresh": {
+      "version": "0.5.2",
+      "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+      "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
+      "dev": true
+    },
+    "fs-extra": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz",
+      "integrity": "sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE=",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "jsonfile": "^3.0.0",
+        "universalify": "^0.1.0"
+      },
+      "dependencies": {
+        "graceful-fs": {
+          "version": "4.1.11",
+          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
+          "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
+          "dev": true
+        }
+      }
+    },
+    "fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+      "dev": true
+    },
+    "fsevents": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz",
+      "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "nan": "^2.3.0",
+        "node-pre-gyp": "^0.6.39"
+      },
+      "dependencies": {
+        "abbrev": {
+          "version": "1.1.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "ajv": {
+          "version": "4.11.8",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "co": "^4.6.0",
+            "json-stable-stringify": "^1.0.1"
+          }
+        },
+        "ansi-regex": {
+          "version": "2.1.1",
+          "bundled": true,
+          "dev": true
+        },
+        "aproba": {
+          "version": "1.1.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "are-we-there-yet": {
+          "version": "1.1.4",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "delegates": "^1.0.0",
+            "readable-stream": "^2.0.6"
+          }
+        },
+        "asn1": {
+          "version": "0.2.3",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "assert-plus": {
+          "version": "0.2.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "asynckit": {
+          "version": "0.4.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "aws-sign2": {
+          "version": "0.6.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "aws4": {
+          "version": "1.6.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "balanced-match": {
+          "version": "0.4.2",
+          "bundled": true,
+          "dev": true
+        },
+        "bcrypt-pbkdf": {
+          "version": "1.0.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "tweetnacl": "^0.14.3"
+          }
+        },
+        "block-stream": {
+          "version": "0.0.9",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "inherits": "~2.0.0"
+          }
+        },
+        "boom": {
+          "version": "2.10.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "hoek": "2.x.x"
+          }
+        },
+        "brace-expansion": {
+          "version": "1.1.7",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "balanced-match": "^0.4.1",
+            "concat-map": "0.0.1"
+          }
+        },
+        "buffer-shims": {
+          "version": "1.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "caseless": {
+          "version": "0.12.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "co": {
+          "version": "4.6.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "code-point-at": {
+          "version": "1.1.0",
+          "bundled": true,
+          "dev": true
+        },
+        "combined-stream": {
+          "version": "1.0.5",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "delayed-stream": "~1.0.0"
+          }
+        },
+        "concat-map": {
+          "version": "0.0.1",
+          "bundled": true,
+          "dev": true
+        },
+        "console-control-strings": {
+          "version": "1.1.0",
+          "bundled": true,
+          "dev": true
+        },
+        "core-util-is": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true
+        },
+        "cryptiles": {
+          "version": "2.0.5",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "boom": "2.x.x"
+          }
+        },
+        "dashdash": {
+          "version": "1.14.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "assert-plus": "^1.0.0"
+          },
+          "dependencies": {
+            "assert-plus": {
+              "version": "1.0.0",
+              "bundled": true,
+              "dev": true,
+              "optional": true
+            }
+          }
+        },
+        "debug": {
+          "version": "2.6.8",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "deep-extend": {
+          "version": "0.4.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "delayed-stream": {
+          "version": "1.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "delegates": {
+          "version": "1.0.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "detect-libc": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "ecc-jsbn": {
+          "version": "0.1.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "jsbn": "~0.1.0"
+          }
+        },
+        "extend": {
+          "version": "3.0.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "extsprintf": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true
+        },
+        "forever-agent": {
+          "version": "0.6.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "form-data": {
+          "version": "2.1.4",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "asynckit": "^0.4.0",
+            "combined-stream": "^1.0.5",
+            "mime-types": "^2.1.12"
+          }
+        },
+        "fs.realpath": {
+          "version": "1.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "fstream": {
+          "version": "1.0.11",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "graceful-fs": "^4.1.2",
+            "inherits": "~2.0.0",
+            "mkdirp": ">=0.5 0",
+            "rimraf": "2"
+          }
+        },
+        "fstream-ignore": {
+          "version": "1.0.5",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "fstream": "^1.0.0",
+            "inherits": "2",
+            "minimatch": "^3.0.0"
+          }
+        },
+        "gauge": {
+          "version": "2.7.4",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "aproba": "^1.0.3",
+            "console-control-strings": "^1.0.0",
+            "has-unicode": "^2.0.0",
+            "object-assign": "^4.1.0",
+            "signal-exit": "^3.0.0",
+            "string-width": "^1.0.1",
+            "strip-ansi": "^3.0.1",
+            "wide-align": "^1.1.0"
+          }
+        },
+        "getpass": {
+          "version": "0.1.7",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "assert-plus": "^1.0.0"
+          },
+          "dependencies": {
+            "assert-plus": {
+              "version": "1.0.0",
+              "bundled": true,
+              "dev": true,
+              "optional": true
+            }
+          }
+        },
+        "glob": {
+          "version": "7.1.2",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "fs.realpath": "^1.0.0",
+            "inflight": "^1.0.4",
+            "inherits": "2",
+            "minimatch": "^3.0.4",
+            "once": "^1.3.0",
+            "path-is-absolute": "^1.0.0"
+          }
+        },
+        "graceful-fs": {
+          "version": "4.1.11",
+          "bundled": true,
+          "dev": true
+        },
+        "har-schema": {
+          "version": "1.0.5",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "har-validator": {
+          "version": "4.2.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "ajv": "^4.9.1",
+            "har-schema": "^1.0.5"
+          }
+        },
+        "has-unicode": {
+          "version": "2.0.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "hawk": {
+          "version": "3.1.3",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "boom": "2.x.x",
+            "cryptiles": "2.x.x",
+            "hoek": "2.x.x",
+            "sntp": "1.x.x"
+          }
+        },
+        "hoek": {
+          "version": "2.16.3",
+          "bundled": true,
+          "dev": true
+        },
+        "http-signature": {
+          "version": "1.1.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "assert-plus": "^0.2.0",
+            "jsprim": "^1.2.2",
+            "sshpk": "^1.7.0"
+          }
+        },
+        "inflight": {
+          "version": "1.0.6",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "once": "^1.3.0",
+            "wrappy": "1"
+          }
+        },
+        "inherits": {
+          "version": "2.0.3",
+          "bundled": true,
+          "dev": true
+        },
+        "ini": {
+          "version": "1.3.4",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "is-fullwidth-code-point": {
+          "version": "1.0.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "number-is-nan": "^1.0.0"
+          }
+        },
+        "is-typedarray": {
+          "version": "1.0.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "isarray": {
+          "version": "1.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "isstream": {
+          "version": "0.1.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "jodid25519": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "jsbn": "~0.1.0"
+          }
+        },
+        "jsbn": {
+          "version": "0.1.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "json-schema": {
+          "version": "0.2.3",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "json-stable-stringify": {
+          "version": "1.0.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "jsonify": "~0.0.0"
+          }
+        },
+        "json-stringify-safe": {
+          "version": "5.0.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "jsonify": {
+          "version": "0.0.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "jsprim": {
+          "version": "1.4.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "assert-plus": "1.0.0",
+            "extsprintf": "1.0.2",
+            "json-schema": "0.2.3",
+            "verror": "1.3.6"
+          },
+          "dependencies": {
+            "assert-plus": {
+              "version": "1.0.0",
+              "bundled": true,
+              "dev": true,
+              "optional": true
+            }
+          }
+        },
+        "mime-db": {
+          "version": "1.27.0",
+          "bundled": true,
+          "dev": true
+        },
+        "mime-types": {
+          "version": "2.1.15",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "mime-db": "~1.27.0"
+          }
+        },
+        "minimatch": {
+          "version": "3.0.4",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "brace-expansion": "^1.1.7"
+          }
+        },
+        "minimist": {
+          "version": "0.0.8",
+          "bundled": true,
+          "dev": true
+        },
+        "mkdirp": {
+          "version": "0.5.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "minimist": "0.0.8"
+          }
+        },
+        "ms": {
+          "version": "2.0.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "node-pre-gyp": {
+          "version": "0.6.39",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "detect-libc": "^1.0.2",
+            "hawk": "3.1.3",
+            "mkdirp": "^0.5.1",
+            "nopt": "^4.0.1",
+            "npmlog": "^4.0.2",
+            "rc": "^1.1.7",
+            "request": "2.81.0",
+            "rimraf": "^2.6.1",
+            "semver": "^5.3.0",
+            "tar": "^2.2.1",
+            "tar-pack": "^3.4.0"
+          }
+        },
+        "nopt": {
+          "version": "4.0.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "abbrev": "1",
+            "osenv": "^0.1.4"
+          }
+        },
+        "npmlog": {
+          "version": "4.1.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "are-we-there-yet": "~1.1.2",
+            "console-control-strings": "~1.1.0",
+            "gauge": "~2.7.3",
+            "set-blocking": "~2.0.0"
+          }
+        },
+        "number-is-nan": {
+          "version": "1.0.1",
+          "bundled": true,
+          "dev": true
+        },
+        "oauth-sign": {
+          "version": "0.8.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "object-assign": {
+          "version": "4.1.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "once": {
+          "version": "1.4.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "wrappy": "1"
+          }
+        },
+        "os-homedir": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "os-tmpdir": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "osenv": {
+          "version": "0.1.4",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "os-homedir": "^1.0.0",
+            "os-tmpdir": "^1.0.0"
+          }
+        },
+        "path-is-absolute": {
+          "version": "1.0.1",
+          "bundled": true,
+          "dev": true
+        },
+        "performance-now": {
+          "version": "0.2.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "process-nextick-args": {
+          "version": "1.0.7",
+          "bundled": true,
+          "dev": true
+        },
+        "punycode": {
+          "version": "1.4.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "qs": {
+          "version": "6.4.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "rc": {
+          "version": "1.2.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "deep-extend": "~0.4.0",
+            "ini": "~1.3.0",
+            "minimist": "^1.2.0",
+            "strip-json-comments": "~2.0.1"
+          },
+          "dependencies": {
+            "minimist": {
+              "version": "1.2.0",
+              "bundled": true,
+              "dev": true,
+              "optional": true
+            }
+          }
+        },
+        "readable-stream": {
+          "version": "2.2.9",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "buffer-shims": "~1.0.0",
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.1",
+            "isarray": "~1.0.0",
+            "process-nextick-args": "~1.0.6",
+            "string_decoder": "~1.0.0",
+            "util-deprecate": "~1.0.1"
+          }
+        },
+        "request": {
+          "version": "2.81.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "aws-sign2": "~0.6.0",
+            "aws4": "^1.2.1",
+            "caseless": "~0.12.0",
+            "combined-stream": "~1.0.5",
+            "extend": "~3.0.0",
+            "forever-agent": "~0.6.1",
+            "form-data": "~2.1.1",
+            "har-validator": "~4.2.1",
+            "hawk": "~3.1.3",
+            "http-signature": "~1.1.0",
+            "is-typedarray": "~1.0.0",
+            "isstream": "~0.1.2",
+            "json-stringify-safe": "~5.0.1",
+            "mime-types": "~2.1.7",
+            "oauth-sign": "~0.8.1",
+            "performance-now": "^0.2.0",
+            "qs": "~6.4.0",
+            "safe-buffer": "^5.0.1",
+            "stringstream": "~0.0.4",
+            "tough-cookie": "~2.3.0",
+            "tunnel-agent": "^0.6.0",
+            "uuid": "^3.0.0"
+          }
+        },
+        "rimraf": {
+          "version": "2.6.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "glob": "^7.0.5"
+          }
+        },
+        "safe-buffer": {
+          "version": "5.0.1",
+          "bundled": true,
+          "dev": true
+        },
+        "semver": {
+          "version": "5.3.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "set-blocking": {
+          "version": "2.0.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "signal-exit": {
+          "version": "3.0.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "sntp": {
+          "version": "1.0.9",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "hoek": "2.x.x"
+          }
+        },
+        "sshpk": {
+          "version": "1.13.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "asn1": "~0.2.3",
+            "assert-plus": "^1.0.0",
+            "bcrypt-pbkdf": "^1.0.0",
+            "dashdash": "^1.12.0",
+            "ecc-jsbn": "~0.1.1",
+            "getpass": "^0.1.1",
+            "jodid25519": "^1.0.0",
+            "jsbn": "~0.1.0",
+            "tweetnacl": "~0.14.0"
+          },
+          "dependencies": {
+            "assert-plus": {
+              "version": "1.0.0",
+              "bundled": true,
+              "dev": true,
+              "optional": true
+            }
+          }
+        },
+        "string-width": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "code-point-at": "^1.0.0",
+            "is-fullwidth-code-point": "^1.0.0",
+            "strip-ansi": "^3.0.0"
+          }
+        },
+        "string_decoder": {
+          "version": "1.0.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "safe-buffer": "^5.0.1"
+          }
+        },
+        "stringstream": {
+          "version": "0.0.5",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "strip-ansi": {
+          "version": "3.0.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^2.0.0"
+          }
+        },
+        "strip-json-comments": {
+          "version": "2.0.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "tar": {
+          "version": "2.2.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "block-stream": "*",
+            "fstream": "^1.0.2",
+            "inherits": "2"
+          }
+        },
+        "tar-pack": {
+          "version": "3.4.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "debug": "^2.2.0",
+            "fstream": "^1.0.10",
+            "fstream-ignore": "^1.0.5",
+            "once": "^1.3.3",
+            "readable-stream": "^2.1.4",
+            "rimraf": "^2.5.1",
+            "tar": "^2.2.1",
+            "uid-number": "^0.0.6"
+          }
+        },
+        "tough-cookie": {
+          "version": "2.3.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "punycode": "^1.4.1"
+          }
+        },
+        "tunnel-agent": {
+          "version": "0.6.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "safe-buffer": "^5.0.1"
+          }
+        },
+        "tweetnacl": {
+          "version": "0.14.5",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "uid-number": {
+          "version": "0.0.6",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "util-deprecate": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true
+        },
+        "uuid": {
+          "version": "3.0.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "verror": {
+          "version": "1.3.6",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "extsprintf": "1.0.2"
+          }
+        },
+        "wide-align": {
+          "version": "1.1.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "string-width": "^1.0.2"
+          }
+        },
+        "wrappy": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true
+        }
+      }
+    },
+    "gaze": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.2.tgz",
+      "integrity": "sha1-hHIkZ3rbiHDWeSV+0ziP22HkAQU=",
+      "dev": true,
+      "requires": {
+        "globule": "^1.0.0"
+      }
+    },
+    "get-caller-file": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz",
+      "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=",
+      "dev": true
+    },
+    "get-stdin": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
+      "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
+      "dev": true
+    },
+    "getobject": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz",
+      "integrity": "sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=",
+      "dev": true
+    },
+    "getpass": {
+      "version": "0.1.7",
+      "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+      "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+      "dev": true,
+      "requires": {
+        "assert-plus": "^1.0.0"
+      },
+      "dependencies": {
+        "assert-plus": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+          "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+          "dev": true
+        }
+      }
+    },
+    "glob": {
+      "version": "3.1.21",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz",
+      "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "~1.2.0",
+        "inherits": "1",
+        "minimatch": "~0.2.11"
+      },
+      "dependencies": {
+        "inherits": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz",
+          "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=",
+          "dev": true
+        }
+      }
+    },
+    "glob-base": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz",
+      "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=",
+      "dev": true,
+      "requires": {
+        "glob-parent": "^2.0.0",
+        "is-glob": "^2.0.0"
+      }
+    },
+    "glob-parent": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
+      "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
+      "dev": true,
+      "requires": {
+        "is-glob": "^2.0.0"
+      }
+    },
+    "globule": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.0.tgz",
+      "integrity": "sha1-HcScaCLdnoovoAuiopUAboZkvQk=",
+      "dev": true,
+      "requires": {
+        "glob": "~7.1.1",
+        "lodash": "~4.17.4",
+        "minimatch": "~3.0.2"
+      },
+      "dependencies": {
+        "glob": {
+          "version": "7.1.2",
+          "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
+          "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
+          "dev": true,
+          "requires": {
+            "fs.realpath": "^1.0.0",
+            "inflight": "^1.0.4",
+            "inherits": "2",
+            "minimatch": "^3.0.4",
+            "once": "^1.3.0",
+            "path-is-absolute": "^1.0.0"
+          }
+        },
+        "lodash": {
+          "version": "4.17.5",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz",
+          "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==",
+          "dev": true
+        },
+        "minimatch": {
+          "version": "3.0.4",
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+          "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+          "dev": true,
+          "requires": {
+            "brace-expansion": "^1.1.7"
+          }
+        }
+      }
+    },
+    "graceful-fs": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz",
+      "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=",
+      "dev": true
+    },
+    "graceful-readlink": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
+      "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=",
+      "dev": true
+    },
+    "grunt": {
+      "version": "0.4.5",
+      "resolved": "https://registry.npmjs.org/grunt/-/grunt-0.4.5.tgz",
+      "integrity": "sha1-VpN81RlDJK3/bSB2MYMqnWuk5/A=",
+      "dev": true,
+      "requires": {
+        "async": "~0.1.22",
+        "coffee-script": "~1.3.3",
+        "colors": "~0.6.2",
+        "dateformat": "1.0.2-1.2.3",
+        "eventemitter2": "~0.4.13",
+        "exit": "~0.1.1",
+        "findup-sync": "~0.1.2",
+        "getobject": "~0.1.0",
+        "glob": "~3.1.21",
+        "grunt-legacy-log": "~0.1.0",
+        "grunt-legacy-util": "~0.2.0",
+        "hooker": "~0.2.3",
+        "iconv-lite": "~0.2.11",
+        "js-yaml": "~2.0.5",
+        "lodash": "~0.9.2",
+        "minimatch": "~0.2.12",
+        "nopt": "~1.0.10",
+        "rimraf": "~2.2.8",
+        "underscore.string": "~2.2.1",
+        "which": "~1.0.5"
+      }
+    },
+    "grunt-angular-templates": {
+      "version": "0.5.9",
+      "resolved": "https://registry.npmjs.org/grunt-angular-templates/-/grunt-angular-templates-0.5.9.tgz",
+      "integrity": "sha1-KJm+INlDitGbDQqAaqjseiOyWyo=",
+      "dev": true,
+      "requires": {
+        "html-minifier": "~0.6.3"
+      }
+    },
+    "grunt-browser-sync": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/grunt-browser-sync/-/grunt-browser-sync-2.2.0.tgz",
+      "integrity": "sha1-oOnB/RzLXEVMJexRcBE///BqR3I=",
+      "dev": true,
+      "requires": {
+        "browser-sync": "^2.6.4"
+      }
+    },
+    "grunt-contrib-clean": {
+      "version": "0.5.0",
+      "resolved": "https://registry.npmjs.org/grunt-contrib-clean/-/grunt-contrib-clean-0.5.0.tgz",
+      "integrity": "sha1-9T397ghJsce0Dp67umn0jExgecU=",
+      "dev": true,
+      "requires": {
+        "rimraf": "~2.2.1"
+      }
+    },
+    "grunt-contrib-concat": {
+      "version": "0.5.1",
+      "resolved": "https://registry.npmjs.org/grunt-contrib-concat/-/grunt-contrib-concat-0.5.1.tgz",
+      "integrity": "sha1-lTxu/f39LBB6uchQd/LUsk0xzUk=",
+      "dev": true,
+      "requires": {
+        "chalk": "^0.5.1",
+        "source-map": "^0.3.0"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.3.0",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.3.0.tgz",
+          "integrity": "sha1-hYb7mloAXltQHiHNGLbyG0V60fk=",
+          "dev": true,
+          "requires": {
+            "amdefine": ">=0.0.4"
+          }
+        }
+      }
+    },
+    "grunt-contrib-copy": {
+      "version": "0.5.0",
+      "resolved": "https://registry.npmjs.org/grunt-contrib-copy/-/grunt-contrib-copy-0.5.0.tgz",
+      "integrity": "sha1-QQB1rEWlhWuhkbHMclclRQ1KAhU=",
+      "dev": true
+    },
+    "grunt-contrib-cssmin": {
+      "version": "0.12.3",
+      "resolved": "https://registry.npmjs.org/grunt-contrib-cssmin/-/grunt-contrib-cssmin-0.12.3.tgz",
+      "integrity": "sha1-QVdZYJb7dlb8RktMx7B0beHzkBQ=",
+      "dev": true,
+      "requires": {
+        "chalk": "^1.0.0",
+        "clean-css": "^3.1.0",
+        "maxmin": "^1.1.0"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+          "dev": true
+        },
+        "ansi-styles": {
+          "version": "2.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+          "dev": true
+        },
+        "chalk": {
+          "version": "1.1.3",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^2.2.1",
+            "escape-string-regexp": "^1.0.2",
+            "has-ansi": "^2.0.0",
+            "strip-ansi": "^3.0.0",
+            "supports-color": "^2.0.0"
+          }
+        },
+        "clean-css": {
+          "version": "3.4.28",
+          "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz",
+          "integrity": "sha1-vxlF6C/ICPVWlebd6uwBQA79A/8=",
+          "dev": true,
+          "requires": {
+            "commander": "2.8.x",
+            "source-map": "0.4.x"
+          }
+        },
+        "commander": {
+          "version": "2.8.1",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz",
+          "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=",
+          "dev": true,
+          "requires": {
+            "graceful-readlink": ">= 1.0.0"
+          }
+        },
+        "has-ansi": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+          "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^2.0.0"
+          }
+        },
+        "source-map": {
+          "version": "0.4.4",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
+          "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
+          "dev": true,
+          "requires": {
+            "amdefine": ">=0.0.4"
+          }
+        },
+        "strip-ansi": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+          "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^2.0.0"
+          }
+        },
+        "supports-color": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+          "dev": true
+        }
+      }
+    },
+    "grunt-contrib-less": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/grunt-contrib-less/-/grunt-contrib-less-1.4.1.tgz",
+      "integrity": "sha1-O73sC3XRLOqlXWKUNiXAsIYc328=",
+      "dev": true,
+      "requires": {
+        "async": "^2.0.0",
+        "chalk": "^1.0.0",
+        "less": "~2.7.1",
+        "lodash": "^4.8.2"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+          "dev": true
+        },
+        "ansi-styles": {
+          "version": "2.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+          "dev": true
+        },
+        "async": {
+          "version": "2.6.0",
+          "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz",
+          "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==",
+          "dev": true,
+          "requires": {
+            "lodash": "^4.14.0"
+          }
+        },
+        "chalk": {
+          "version": "1.1.3",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^2.2.1",
+            "escape-string-regexp": "^1.0.2",
+            "has-ansi": "^2.0.0",
+            "strip-ansi": "^3.0.0",
+            "supports-color": "^2.0.0"
+          }
+        },
+        "has-ansi": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+          "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^2.0.0"
+          }
+        },
+        "lodash": {
+          "version": "4.17.5",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz",
+          "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==",
+          "dev": true
+        },
+        "strip-ansi": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+          "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^2.0.0"
+          }
+        },
+        "supports-color": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+          "dev": true
+        }
+      }
+    },
+    "grunt-contrib-uglify": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/grunt-contrib-uglify/-/grunt-contrib-uglify-3.3.0.tgz",
+      "integrity": "sha512-W9O7lJE3PlD8VCc5fyaf98QV7f5wEDiU4PBIh0+/6UBbk2LhgzEFS0/p+taH5UD3+PlEn7QPN0o06Z0To6SqXw==",
+      "dev": true,
+      "requires": {
+        "chalk": "^1.0.0",
+        "maxmin": "^1.1.0",
+        "uglify-js": "~3.3.0",
+        "uri-path": "^1.0.0"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+          "dev": true
+        },
+        "ansi-styles": {
+          "version": "2.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+          "dev": true
+        },
+        "chalk": {
+          "version": "1.1.3",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^2.2.1",
+            "escape-string-regexp": "^1.0.2",
+            "has-ansi": "^2.0.0",
+            "strip-ansi": "^3.0.0",
+            "supports-color": "^2.0.0"
+          }
+        },
+        "commander": {
+          "version": "2.15.1",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
+          "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
+          "dev": true
+        },
+        "has-ansi": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+          "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^2.0.0"
+          }
+        },
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
+        },
+        "strip-ansi": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+          "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^2.0.0"
+          }
+        },
+        "supports-color": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+          "dev": true
+        },
+        "uglify-js": {
+          "version": "3.3.16",
+          "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.16.tgz",
+          "integrity": "sha512-FMh5SRqJRGhv9BbaTffENIpDDQIoPDR8DBraunGORGhySArsXlw9++CN+BWzPBLpoI4RcSnpfGPnilTxWL3Vvg==",
+          "dev": true,
+          "requires": {
+            "commander": "~2.15.0",
+            "source-map": "~0.6.1"
+          }
+        }
+      }
+    },
+    "grunt-contrib-watch": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/grunt-contrib-watch/-/grunt-contrib-watch-1.0.0.tgz",
+      "integrity": "sha1-hKGnodar0m7VaEE0lscxM+mQAY8=",
+      "dev": true,
+      "requires": {
+        "async": "^1.5.0",
+        "gaze": "^1.0.0",
+        "lodash": "^3.10.1",
+        "tiny-lr": "^0.2.1"
+      },
+      "dependencies": {
+        "async": {
+          "version": "1.5.2",
+          "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
+          "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
+          "dev": true
+        },
+        "lodash": {
+          "version": "3.10.1",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
+          "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=",
+          "dev": true
+        }
+      }
+    },
+    "grunt-legacy-log": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-0.1.3.tgz",
+      "integrity": "sha1-7ClCboAwIa9ZAp+H0vnNczWgVTE=",
+      "dev": true,
+      "requires": {
+        "colors": "~0.6.2",
+        "grunt-legacy-log-utils": "~0.1.1",
+        "hooker": "~0.2.3",
+        "lodash": "~2.4.1",
+        "underscore.string": "~2.3.3"
+      },
+      "dependencies": {
+        "lodash": {
+          "version": "2.4.2",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz",
+          "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=",
+          "dev": true
+        },
+        "underscore.string": {
+          "version": "2.3.3",
+          "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz",
+          "integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=",
+          "dev": true
+        }
+      }
+    },
+    "grunt-legacy-log-utils": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-0.1.1.tgz",
+      "integrity": "sha1-wHBrndkGThFvNvI/5OawSGcsD34=",
+      "dev": true,
+      "requires": {
+        "colors": "~0.6.2",
+        "lodash": "~2.4.1",
+        "underscore.string": "~2.3.3"
+      },
+      "dependencies": {
+        "lodash": {
+          "version": "2.4.2",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz",
+          "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=",
+          "dev": true
+        },
+        "underscore.string": {
+          "version": "2.3.3",
+          "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz",
+          "integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=",
+          "dev": true
+        }
+      }
+    },
+    "grunt-legacy-util": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-0.2.0.tgz",
+      "integrity": "sha1-kzJIhNv343qf98Am3/RR2UqeVUs=",
+      "dev": true,
+      "requires": {
+        "async": "~0.1.22",
+        "exit": "~0.1.1",
+        "getobject": "~0.1.0",
+        "hooker": "~0.2.3",
+        "lodash": "~0.9.2",
+        "underscore.string": "~2.2.1",
+        "which": "~1.0.5"
+      }
+    },
+    "grunt-module-dependence": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/grunt-module-dependence/-/grunt-module-dependence-0.2.1.tgz",
+      "integrity": "sha512-/3fUiimuVZZM5VAhDD0oxTeh+0jRMavaiP04oHlXs3EzJYHOHVFwsKVbwstGWvZYQhMLk2YY74vIKcU/rmCrUQ==",
+      "dev": true
+    },
+    "grunt-ng-annotate": {
+      "version": "0.9.2",
+      "resolved": "https://registry.npmjs.org/grunt-ng-annotate/-/grunt-ng-annotate-0.9.2.tgz",
+      "integrity": "sha1-cu2ORds4cVrbNbj5YicV9JcV994=",
+      "dev": true,
+      "requires": {
+        "lodash": "~2.4.1",
+        "ng-annotate": "~0.15.1"
+      },
+      "dependencies": {
+        "lodash": {
+          "version": "2.4.2",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz",
+          "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=",
+          "dev": true
+        }
+      }
+    },
+    "grunt-replace": {
+      "version": "0.8.0",
+      "resolved": "https://registry.npmjs.org/grunt-replace/-/grunt-replace-0.8.0.tgz",
+      "integrity": "sha1-InGH8I16M0orKLMqT8AaWTJmCVY=",
+      "dev": true,
+      "requires": {
+        "applause": "0.3.4",
+        "chalk": "^0.5.0"
+      }
+    },
+    "grunt-wiredep": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/grunt-wiredep/-/grunt-wiredep-2.0.0.tgz",
+      "integrity": "sha1-ID9vYT95nW3XLOBE0NzvZNrx8uU=",
+      "dev": true,
+      "requires": {
+        "wiredep": "^2.1.0"
+      }
+    },
+    "gzip-size": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-1.0.0.tgz",
+      "integrity": "sha1-Zs+LEBBHInuVus5uodoMF37Vwi8=",
+      "dev": true,
+      "requires": {
+        "browserify-zlib": "^0.1.4",
+        "concat-stream": "^1.4.1"
+      }
+    },
+    "har-schema": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz",
+      "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=",
+      "dev": true
+    },
+    "har-validator": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz",
+      "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=",
+      "dev": true,
+      "requires": {
+        "ajv": "^4.9.1",
+        "har-schema": "^1.0.5"
+      }
+    },
+    "has-ansi": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz",
+      "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=",
+      "dev": true,
+      "requires": {
+        "ansi-regex": "^0.2.0"
+      }
+    },
+    "has-binary2": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.2.tgz",
+      "integrity": "sha1-6D26SfC5vk0CbSc2U1DZ8D9Uvpg=",
+      "dev": true,
+      "requires": {
+        "isarray": "2.0.1"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
+          "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=",
+          "dev": true
+        }
+      }
+    },
+    "has-cors": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz",
+      "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=",
+      "dev": true
+    },
+    "hawk": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz",
+      "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=",
+      "dev": true,
+      "requires": {
+        "boom": "2.x.x",
+        "cryptiles": "2.x.x",
+        "hoek": "2.x.x",
+        "sntp": "1.x.x"
+      }
+    },
+    "heap": {
+      "version": "0.2.6",
+      "resolved": "http://registry.npm.baidu-int.com/heap/-/heap-0.2.6.tgz",
+      "integrity": "sha1-CH4fELBGky/IWU3Z5tN4r8nR5aw="
+    },
+    "hoek": {
+      "version": "2.16.3",
+      "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
+      "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=",
+      "dev": true
+    },
+    "hooker": {
+      "version": "0.2.3",
+      "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz",
+      "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=",
+      "dev": true
+    },
+    "hosted-git-info": {
+      "version": "2.6.0",
+      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz",
+      "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==",
+      "dev": true
+    },
+    "html-minifier": {
+      "version": "0.6.9",
+      "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-0.6.9.tgz",
+      "integrity": "sha1-UQXcI29efhqLplHUq5gThvx6vlM=",
+      "dev": true,
+      "requires": {
+        "change-case": "2.1.x",
+        "clean-css": "2.2.x",
+        "cli": "0.6.x",
+        "relateurl": "0.2.x",
+        "uglify-js": "2.4.x"
+      },
+      "dependencies": {
+        "async": {
+          "version": "0.2.10",
+          "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
+          "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=",
+          "dev": true
+        },
+        "source-map": {
+          "version": "0.1.34",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.34.tgz",
+          "integrity": "sha1-p8/omux7FoLDsZjQrPtH19CQVms=",
+          "dev": true,
+          "requires": {
+            "amdefine": ">=0.0.4"
+          }
+        },
+        "uglify-js": {
+          "version": "2.4.24",
+          "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.24.tgz",
+          "integrity": "sha1-+tV1XB4Vd2WLsG/5q25UjJW+vW4=",
+          "dev": true,
+          "requires": {
+            "async": "~0.2.6",
+            "source-map": "0.1.34",
+            "uglify-to-browserify": "~1.0.0",
+            "yargs": "~3.5.4"
+          }
+        },
+        "yargs": {
+          "version": "3.5.4",
+          "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.5.4.tgz",
+          "integrity": "sha1-2K/49mXpTDS9JZvevRv68N3TU2E=",
+          "dev": true,
+          "requires": {
+            "camelcase": "^1.0.2",
+            "decamelize": "^1.0.0",
+            "window-size": "0.1.0",
+            "wordwrap": "0.0.2"
+          }
+        }
+      }
+    },
+    "http-errors": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.5.1.tgz",
+      "integrity": "sha1-eIwNLB3iyBuebowBhDtrl+uSB1A=",
+      "dev": true,
+      "requires": {
+        "inherits": "2.0.3",
+        "setprototypeof": "1.0.2",
+        "statuses": ">= 1.3.1 < 2"
+      }
+    },
+    "http-parser-js": {
+      "version": "0.4.11",
+      "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.11.tgz",
+      "integrity": "sha512-QCR5O2AjjMW8Mo4HyI1ctFcv+O99j/0g367V3YoVnrNw5hkDvAWZD0lWGcc+F4yN3V55USPCVix4efb75HxFfA==",
+      "dev": true
+    },
+    "http-proxy": {
+      "version": "1.15.2",
+      "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.15.2.tgz",
+      "integrity": "sha1-ZC/cr/5S00SNK9o7AHnpQJBk2jE=",
+      "dev": true,
+      "requires": {
+        "eventemitter3": "1.x.x",
+        "requires-port": "1.x.x"
+      }
+    },
+    "http-signature": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz",
+      "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=",
+      "dev": true,
+      "requires": {
+        "assert-plus": "^0.2.0",
+        "jsprim": "^1.2.2",
+        "sshpk": "^1.7.0"
+      }
+    },
+    "iconv-lite": {
+      "version": "0.2.11",
+      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.2.11.tgz",
+      "integrity": "sha1-HOYKOleGSiktEyH/RgnKS7llrcg=",
+      "dev": true
+    },
+    "image-size": {
+      "version": "0.5.5",
+      "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz",
+      "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=",
+      "dev": true,
+      "optional": true
+    },
+    "immutable": {
+      "version": "3.8.2",
+      "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz",
+      "integrity": "sha1-wkOZUUVbs5kT2vKBN28VMOEErfM=",
+      "dev": true
+    },
+    "indent-string": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
+      "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
+      "dev": true,
+      "requires": {
+        "repeating": "^2.0.0"
+      }
+    },
+    "indexof": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
+      "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=",
+      "dev": true
+    },
+    "inflight": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+      "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+      "dev": true,
+      "requires": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "inherits": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+      "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+      "dev": true
+    },
+    "invert-kv": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
+      "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=",
+      "dev": true
+    },
+    "is-arrayish": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+      "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+      "dev": true
+    },
+    "is-binary-path": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
+      "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
+      "dev": true,
+      "requires": {
+        "binary-extensions": "^1.0.0"
+      }
+    },
+    "is-buffer": {
+      "version": "1.1.6",
+      "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+      "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+      "dev": true
+    },
+    "is-builtin-module": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
+      "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
+      "dev": true,
+      "requires": {
+        "builtin-modules": "^1.0.0"
+      }
+    },
+    "is-dotfile": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
+      "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=",
+      "dev": true
+    },
+    "is-equal-shallow": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz",
+      "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=",
+      "dev": true,
+      "requires": {
+        "is-primitive": "^2.0.0"
+      }
+    },
+    "is-extendable": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+      "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+      "dev": true
+    },
+    "is-extglob": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+      "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
+      "dev": true
+    },
+    "is-finite": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz",
+      "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=",
+      "dev": true,
+      "requires": {
+        "number-is-nan": "^1.0.0"
+      }
+    },
+    "is-fullwidth-code-point": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+      "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+      "dev": true,
+      "requires": {
+        "number-is-nan": "^1.0.0"
+      }
+    },
+    "is-glob": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+      "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+      "dev": true,
+      "requires": {
+        "is-extglob": "^1.0.0"
+      }
+    },
+    "is-lower-case": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/is-lower-case/-/is-lower-case-1.1.3.tgz",
+      "integrity": "sha1-fhR75HaNxGbbO/shzGCzHmrWk5M=",
+      "dev": true,
+      "requires": {
+        "lower-case": "^1.1.0"
+      }
+    },
+    "is-number": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz",
+      "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=",
+      "dev": true,
+      "requires": {
+        "kind-of": "^3.0.2"
+      }
+    },
+    "is-number-like": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/is-number-like/-/is-number-like-1.0.8.tgz",
+      "integrity": "sha512-6rZi3ezCyFcn5L71ywzz2bS5b2Igl1En3eTlZlvKjpz1n3IZLAYMbKYAIQgFmEu0GENg92ziU/faEOA/aixjbA==",
+      "dev": true,
+      "requires": {
+        "lodash.isfinite": "^3.3.2"
+      }
+    },
+    "is-posix-bracket": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz",
+      "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=",
+      "dev": true
+    },
+    "is-primitive": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz",
+      "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=",
+      "dev": true
+    },
+    "is-typedarray": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+      "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
+      "dev": true
+    },
+    "is-upper-case": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/is-upper-case/-/is-upper-case-1.1.2.tgz",
+      "integrity": "sha1-jQsfp+eTOh5YSDYA7H2WYcuvdW8=",
+      "dev": true,
+      "requires": {
+        "upper-case": "^1.1.0"
+      }
+    },
+    "is-utf8": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
+      "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
+      "dev": true
+    },
+    "isarray": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+      "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+      "dev": true
+    },
+    "isobject": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+      "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+      "dev": true,
+      "requires": {
+        "isarray": "1.0.0"
+      }
+    },
+    "isstream": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+      "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
+      "dev": true
+    },
+    "js-yaml": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-2.0.5.tgz",
+      "integrity": "sha1-olrmUJmZ6X3yeMZxnaEb0Gh3Q6g=",
+      "dev": true,
+      "requires": {
+        "argparse": "~ 0.1.11",
+        "esprima": "~ 1.0.2"
+      }
+    },
+    "js2coffee": {
+      "version": "0.3.5",
+      "resolved": "https://registry.npmjs.org/js2coffee/-/js2coffee-0.3.5.tgz",
+      "integrity": "sha1-Hqv9gjyWakX1p1sxWWgxrYV55go=",
+      "dev": true,
+      "requires": {
+        "coffee-script": "~1.7.1",
+        "file": "~0.2.1",
+        "nopt": "~3.0.1",
+        "underscore": "~1.6.0"
+      },
+      "dependencies": {
+        "coffee-script": {
+          "version": "1.7.1",
+          "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.7.1.tgz",
+          "integrity": "sha1-YplqhheAx15tUGnROCJyO3NAS/w=",
+          "dev": true,
+          "requires": {
+            "mkdirp": "~0.3.5"
+          }
+        },
+        "mkdirp": {
+          "version": "0.3.5",
+          "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz",
+          "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=",
+          "dev": true
+        },
+        "nopt": {
+          "version": "3.0.6",
+          "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
+          "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
+          "dev": true,
+          "requires": {
+            "abbrev": "1"
+          }
+        },
+        "underscore": {
+          "version": "1.6.0",
+          "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz",
+          "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=",
+          "dev": true
+        }
+      }
+    },
+    "jsbn": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+      "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
+      "dev": true,
+      "optional": true
+    },
+    "jshint-stylish": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/jshint-stylish/-/jshint-stylish-1.0.2.tgz",
+      "integrity": "sha1-6Z88w0CvsY4qdwL4eY10AMoxRGo=",
+      "dev": true,
+      "requires": {
+        "chalk": "^1.0.0",
+        "log-symbols": "^1.0.0",
+        "string-length": "^1.0.0",
+        "text-table": "^0.2.0"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+          "dev": true
+        },
+        "ansi-styles": {
+          "version": "2.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+          "dev": true
+        },
+        "chalk": {
+          "version": "1.1.3",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^2.2.1",
+            "escape-string-regexp": "^1.0.2",
+            "has-ansi": "^2.0.0",
+            "strip-ansi": "^3.0.0",
+            "supports-color": "^2.0.0"
+          }
+        },
+        "has-ansi": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+          "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^2.0.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+          "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^2.0.0"
+          }
+        },
+        "supports-color": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+          "dev": true
+        }
+      }
+    },
+    "json-diff": {
+      "version": "0.5.2",
+      "resolved": "http://registry.npm.baidu-int.com/json-diff/-/json-diff-0.5.2.tgz",
+      "integrity": "sha512-N7oapTQdD4rLMUtA7d1HATCPY/BpHuSNL1mhvIuoS0u5NideDvyR+gB/ntXB7ejFz/LM0XzPLNUJQcC68n5sBw==",
+      "requires": {
+        "cli-color": "~0.1.6",
+        "difflib": "~0.2.1",
+        "dreamopt": "~0.6.0"
+      }
+    },
+    "json-schema": {
+      "version": "0.2.3",
+      "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
+      "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
+      "dev": true
+    },
+    "json-stable-stringify": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
+      "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=",
+      "dev": true,
+      "requires": {
+        "jsonify": "~0.0.0"
+      }
+    },
+    "json-stringify-safe": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+      "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
+      "dev": true
+    },
+    "jsonfile": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz",
+      "integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.6"
+      },
+      "dependencies": {
+        "graceful-fs": {
+          "version": "4.1.11",
+          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
+          "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
+          "dev": true,
+          "optional": true
+        }
+      }
+    },
+    "jsonify": {
+      "version": "0.0.0",
+      "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
+      "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
+      "dev": true
+    },
+    "jsprim": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
+      "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
+      "dev": true,
+      "requires": {
+        "assert-plus": "1.0.0",
+        "extsprintf": "1.3.0",
+        "json-schema": "0.2.3",
+        "verror": "1.10.0"
+      },
+      "dependencies": {
+        "assert-plus": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+          "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+          "dev": true
+        }
+      }
+    },
+    "kind-of": {
+      "version": "3.2.2",
+      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+      "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+      "dev": true,
+      "requires": {
+        "is-buffer": "^1.1.5"
+      }
+    },
+    "kity": {
+      "version": "2.0.4",
+      "resolved": "http://registry.npm.baidu-int.com/kity/-/kity-2.0.4.tgz",
+      "integrity": "sha512-u6jPit9N44gPTMzB7EiX3szurI7JB6HPswJESQiS0UnrNiceOeLxGRAm0mgGRuRnkGXwmA3Pzn7hZ1rauINpOA=="
+    },
+    "kityminder-core": {
+      "version": "1.4.50",
+      "resolved": "http://registry.npm.baidu-int.com/kityminder-core/-/kityminder-core-1.4.50.tgz",
+      "integrity": "sha512-HMXTLOqpyvnDVZiRJOt1TghF7hiWWxm2NKc40L9IL31Ev5Rkm4CHyY2m+1RP3YLHW00MWH/IX0KETuYIXnToTw==",
+      "requires": {
+        "json-diff": "^0.5.2",
+        "kity": "^2.0.4",
+        "seajs": "^2.3.0"
+      }
+    },
+    "lazy-cache": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
+      "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=",
+      "dev": true
+    },
+    "lcid": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
+      "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
+      "dev": true,
+      "requires": {
+        "invert-kv": "^1.0.0"
+      }
+    },
+    "less": {
+      "version": "2.7.3",
+      "resolved": "https://registry.npmjs.org/less/-/less-2.7.3.tgz",
+      "integrity": "sha512-KPdIJKWcEAb02TuJtaLrhue0krtRLoRoo7x6BNJIBelO00t/CCdJQUnHW5V34OnHMWzIktSalJxRO+FvytQlCQ==",
+      "dev": true,
+      "requires": {
+        "errno": "^0.1.1",
+        "graceful-fs": "^4.1.2",
+        "image-size": "~0.5.0",
+        "mime": "^1.2.11",
+        "mkdirp": "^0.5.0",
+        "promise": "^7.1.1",
+        "request": "2.81.0",
+        "source-map": "^0.5.3"
+      },
+      "dependencies": {
+        "graceful-fs": {
+          "version": "4.1.11",
+          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
+          "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
+          "dev": true,
+          "optional": true
+        },
+        "source-map": {
+          "version": "0.5.7",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+          "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+          "dev": true,
+          "optional": true
+        }
+      }
+    },
+    "limiter": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.2.tgz",
+      "integrity": "sha512-JIKZ0xb6fZZYa3deZ0BgXCgX6HgV8Nx3mFGeFHmFWW8Fb2c08e0CyE+G3nalpD0xGvGssjGb1UdFr+PprxZEbw==",
+      "dev": true
+    },
+    "livereload-js": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.3.0.tgz",
+      "integrity": "sha512-j1R0/FeGa64Y+NmqfZhyoVRzcFlOZ8sNlKzHjh4VvLULFACZhn68XrX5DFg2FhMvSMJmROuFxRSa560ECWKBMg==",
+      "dev": true
+    },
+    "load-grunt-tasks": {
+      "version": "3.5.2",
+      "resolved": "https://registry.npmjs.org/load-grunt-tasks/-/load-grunt-tasks-3.5.2.tgz",
+      "integrity": "sha1-ByhWEYD9IP+KaSdQWFL8WKrqDIg=",
+      "dev": true,
+      "requires": {
+        "arrify": "^1.0.0",
+        "multimatch": "^2.0.0",
+        "pkg-up": "^1.0.0",
+        "resolve-pkg": "^0.1.0"
+      }
+    },
+    "load-json-file": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+      "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "parse-json": "^2.2.0",
+        "pify": "^2.0.0",
+        "pinkie-promise": "^2.0.0",
+        "strip-bom": "^2.0.0"
+      },
+      "dependencies": {
+        "graceful-fs": {
+          "version": "4.1.11",
+          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
+          "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
+          "dev": true
+        }
+      }
+    },
+    "localtunnel": {
+      "version": "1.8.3",
+      "resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-1.8.3.tgz",
+      "integrity": "sha1-3MWSL9hWUQN9S94k/ZMkjQsk6wU=",
+      "dev": true,
+      "requires": {
+        "debug": "2.6.8",
+        "openurl": "1.1.1",
+        "request": "2.81.0",
+        "yargs": "3.29.0"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+          "dev": true
+        },
+        "cliui": {
+          "version": "3.2.0",
+          "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
+          "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
+          "dev": true,
+          "requires": {
+            "string-width": "^1.0.1",
+            "strip-ansi": "^3.0.1",
+            "wrap-ansi": "^2.0.0"
+          }
+        },
+        "debug": {
+          "version": "2.6.8",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz",
+          "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+          "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^2.0.0"
+          }
+        },
+        "window-size": {
+          "version": "0.1.4",
+          "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz",
+          "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=",
+          "dev": true
+        },
+        "yargs": {
+          "version": "3.29.0",
+          "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.29.0.tgz",
+          "integrity": "sha1-GquWYOrnnYuPZ1vK7qtu40ws9pw=",
+          "dev": true,
+          "requires": {
+            "camelcase": "^1.2.1",
+            "cliui": "^3.0.3",
+            "decamelize": "^1.0.0",
+            "os-locale": "^1.4.0",
+            "window-size": "^0.1.2",
+            "y18n": "^3.2.0"
+          }
+        }
+      }
+    },
+    "lodash": {
+      "version": "0.9.2",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-0.9.2.tgz",
+      "integrity": "sha1-jzSZxSRdNG1oLlsNO0B2fgnxqSw=",
+      "dev": true
+    },
+    "lodash.isfinite": {
+      "version": "3.3.2",
+      "resolved": "https://registry.npmjs.org/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz",
+      "integrity": "sha1-+4m2WpqAKBgz8LdHizpRBPiY67M=",
+      "dev": true
+    },
+    "lodash.map": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz",
+      "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=",
+      "dev": true
+    },
+    "log-symbols": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz",
+      "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=",
+      "dev": true,
+      "requires": {
+        "chalk": "^1.0.0"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+          "dev": true
+        },
+        "ansi-styles": {
+          "version": "2.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+          "dev": true
+        },
+        "chalk": {
+          "version": "1.1.3",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^2.2.1",
+            "escape-string-regexp": "^1.0.2",
+            "has-ansi": "^2.0.0",
+            "strip-ansi": "^3.0.0",
+            "supports-color": "^2.0.0"
+          }
+        },
+        "has-ansi": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+          "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^2.0.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+          "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^2.0.0"
+          }
+        },
+        "supports-color": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+          "dev": true
+        }
+      }
+    },
+    "longest": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
+      "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=",
+      "dev": true
+    },
+    "loud-rejection": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
+      "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
+      "dev": true,
+      "requires": {
+        "currently-unhandled": "^0.4.1",
+        "signal-exit": "^3.0.0"
+      }
+    },
+    "lower-case": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz",
+      "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=",
+      "dev": true
+    },
+    "lru-cache": {
+      "version": "2.7.3",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz",
+      "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=",
+      "dev": true
+    },
+    "map-obj": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
+      "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
+      "dev": true
+    },
+    "maxmin": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/maxmin/-/maxmin-1.1.0.tgz",
+      "integrity": "sha1-cTZehKmd2Piz99X94vANHn9zvmE=",
+      "dev": true,
+      "requires": {
+        "chalk": "^1.0.0",
+        "figures": "^1.0.1",
+        "gzip-size": "^1.0.0",
+        "pretty-bytes": "^1.0.0"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+          "dev": true
+        },
+        "ansi-styles": {
+          "version": "2.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+          "dev": true
+        },
+        "chalk": {
+          "version": "1.1.3",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^2.2.1",
+            "escape-string-regexp": "^1.0.2",
+            "has-ansi": "^2.0.0",
+            "strip-ansi": "^3.0.0",
+            "supports-color": "^2.0.0"
+          }
+        },
+        "has-ansi": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+          "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^2.0.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+          "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^2.0.0"
+          }
+        },
+        "supports-color": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+          "dev": true
+        }
+      }
+    },
+    "media-typer": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+      "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
+      "dev": true
+    },
+    "meow": {
+      "version": "3.7.0",
+      "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
+      "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
+      "dev": true,
+      "requires": {
+        "camelcase-keys": "^2.0.0",
+        "decamelize": "^1.1.2",
+        "loud-rejection": "^1.0.0",
+        "map-obj": "^1.0.1",
+        "minimist": "^1.1.3",
+        "normalize-package-data": "^2.3.4",
+        "object-assign": "^4.0.1",
+        "read-pkg-up": "^1.0.1",
+        "redent": "^1.0.0",
+        "trim-newlines": "^1.0.0"
+      }
+    },
+    "micromatch": {
+      "version": "2.3.11",
+      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
+      "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
+      "dev": true,
+      "requires": {
+        "arr-diff": "^2.0.0",
+        "array-unique": "^0.2.1",
+        "braces": "^1.8.2",
+        "expand-brackets": "^0.1.4",
+        "extglob": "^0.3.1",
+        "filename-regex": "^2.0.0",
+        "is-extglob": "^1.0.0",
+        "is-glob": "^2.0.1",
+        "kind-of": "^3.0.2",
+        "normalize-path": "^2.0.1",
+        "object.omit": "^2.0.0",
+        "parse-glob": "^3.0.4",
+        "regex-cache": "^0.4.2"
+      }
+    },
+    "mime": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+      "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+      "dev": true,
+      "optional": true
+    },
+    "mime-db": {
+      "version": "1.33.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz",
+      "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==",
+      "dev": true
+    },
+    "mime-types": {
+      "version": "2.1.18",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz",
+      "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==",
+      "dev": true,
+      "requires": {
+        "mime-db": "~1.33.0"
+      }
+    },
+    "minimatch": {
+      "version": "0.2.14",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz",
+      "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=",
+      "dev": true,
+      "requires": {
+        "lru-cache": "2",
+        "sigmund": "~1.0.0"
+      }
+    },
+    "minimist": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+      "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+      "dev": true
+    },
+    "mkdirp": {
+      "version": "0.5.1",
+      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+      "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "minimist": "0.0.8"
+      },
+      "dependencies": {
+        "minimist": {
+          "version": "0.0.8",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+          "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
+          "dev": true,
+          "optional": true
+        }
+      }
+    },
+    "mout": {
+      "version": "0.9.1",
+      "resolved": "https://registry.npmjs.org/mout/-/mout-0.9.1.tgz",
+      "integrity": "sha1-hPDz/WrMcxf2PeKv/cwM7gCbBHc=",
+      "dev": true
+    },
+    "ms": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+      "dev": true
+    },
+    "multimatch": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz",
+      "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=",
+      "dev": true,
+      "requires": {
+        "array-differ": "^1.0.0",
+        "array-union": "^1.0.1",
+        "arrify": "^1.0.0",
+        "minimatch": "^3.0.0"
+      },
+      "dependencies": {
+        "minimatch": {
+          "version": "3.0.4",
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+          "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+          "dev": true,
+          "requires": {
+            "brace-expansion": "^1.1.7"
+          }
+        }
+      }
+    },
+    "nan": {
+      "version": "2.10.0",
+      "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz",
+      "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==",
+      "dev": true,
+      "optional": true
+    },
+    "negotiator": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
+      "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=",
+      "dev": true
+    },
+    "ng-annotate": {
+      "version": "0.15.4",
+      "resolved": "https://registry.npmjs.org/ng-annotate/-/ng-annotate-0.15.4.tgz",
+      "integrity": "sha1-ZQdSXI8vKPh4e824mPVtmzEGbpM=",
+      "dev": true,
+      "requires": {
+        "acorn": "~0.11.0",
+        "alter": "~0.2.0",
+        "convert-source-map": "~0.4.1",
+        "optimist": "~0.6.1",
+        "ordered-ast-traverse": "~1.1.1",
+        "simple-fmt": "~0.1.0",
+        "simple-is": "~0.2.0",
+        "source-map": "~0.1.43",
+        "stable": "~0.1.5",
+        "stringmap": "~0.2.2",
+        "stringset": "~0.2.1",
+        "tryor": "~0.1.2"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.1.43",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz",
+          "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=",
+          "dev": true,
+          "requires": {
+            "amdefine": ">=0.0.4"
+          }
+        }
+      }
+    },
+    "nopt": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
+      "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=",
+      "dev": true,
+      "requires": {
+        "abbrev": "1"
+      }
+    },
+    "normalize-package-data": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
+      "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==",
+      "dev": true,
+      "requires": {
+        "hosted-git-info": "^2.1.4",
+        "is-builtin-module": "^1.0.0",
+        "semver": "2 || 3 || 4 || 5",
+        "validate-npm-package-license": "^3.0.1"
+      }
+    },
+    "normalize-path": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+      "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+      "dev": true,
+      "requires": {
+        "remove-trailing-separator": "^1.0.1"
+      }
+    },
+    "number-is-nan": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+      "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
+      "dev": true
+    },
+    "oauth-sign": {
+      "version": "0.8.2",
+      "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
+      "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=",
+      "dev": true
+    },
+    "object-assign": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+      "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+      "dev": true
+    },
+    "object-component": {
+      "version": "0.0.3",
+      "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz",
+      "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=",
+      "dev": true
+    },
+    "object-path": {
+      "version": "0.9.2",
+      "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.9.2.tgz",
+      "integrity": "sha1-D9mnT8X60a45aLWGvaXGMr1sBaU=",
+      "dev": true
+    },
+    "object.omit": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz",
+      "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=",
+      "dev": true,
+      "requires": {
+        "for-own": "^0.1.4",
+        "is-extendable": "^0.1.1"
+      }
+    },
+    "on-finished": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+      "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+      "dev": true,
+      "requires": {
+        "ee-first": "1.1.1"
+      }
+    },
+    "once": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+      "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+      "dev": true,
+      "requires": {
+        "wrappy": "1"
+      }
+    },
+    "openurl": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/openurl/-/openurl-1.1.1.tgz",
+      "integrity": "sha1-OHW0sO96UsFW8NtB1GCduw+Us4c=",
+      "dev": true
+    },
+    "opn": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/opn/-/opn-4.0.2.tgz",
+      "integrity": "sha1-erwi5kTf9jsKltWrfyeQwPAavJU=",
+      "dev": true,
+      "requires": {
+        "object-assign": "^4.0.1",
+        "pinkie-promise": "^2.0.0"
+      }
+    },
+    "optimist": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
+      "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
+      "dev": true,
+      "requires": {
+        "minimist": "~0.0.1",
+        "wordwrap": "~0.0.2"
+      },
+      "dependencies": {
+        "minimist": {
+          "version": "0.0.10",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
+          "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=",
+          "dev": true
+        }
+      }
+    },
+    "ordered-ast-traverse": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/ordered-ast-traverse/-/ordered-ast-traverse-1.1.1.tgz",
+      "integrity": "sha1-aEOhcLwO7otSDMjdwd3TqjD6BXw=",
+      "dev": true,
+      "requires": {
+        "ordered-esprima-props": "~1.1.0"
+      }
+    },
+    "ordered-esprima-props": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/ordered-esprima-props/-/ordered-esprima-props-1.1.0.tgz",
+      "integrity": "sha1-qYJwht9fAQqmDpvQK24DNc6i/8s=",
+      "dev": true
+    },
+    "os-locale": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
+      "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
+      "dev": true,
+      "requires": {
+        "lcid": "^1.0.0"
+      }
+    },
+    "osenv": {
+      "version": "0.0.3",
+      "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.0.3.tgz",
+      "integrity": "sha1-zWrY3bKQkVrZ4idlV2Al1BHynLY=",
+      "dev": true
+    },
+    "pad-right": {
+      "version": "0.2.2",
+      "resolved": "https://registry.npmjs.org/pad-right/-/pad-right-0.2.2.tgz",
+      "integrity": "sha1-b7ySQEXSRPKiokRQMGDTv8YAl3Q=",
+      "dev": true,
+      "requires": {
+        "repeat-string": "^1.5.2"
+      }
+    },
+    "pako": {
+      "version": "0.2.9",
+      "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
+      "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=",
+      "dev": true
+    },
+    "param-case": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/param-case/-/param-case-1.1.2.tgz",
+      "integrity": "sha1-3LCRpDwlm5Io8cNB57akTqC/l0M=",
+      "dev": true,
+      "requires": {
+        "sentence-case": "^1.1.2"
+      }
+    },
+    "parse-glob": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
+      "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=",
+      "dev": true,
+      "requires": {
+        "glob-base": "^0.3.0",
+        "is-dotfile": "^1.0.0",
+        "is-extglob": "^1.0.0",
+        "is-glob": "^2.0.0"
+      }
+    },
+    "parse-json": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+      "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+      "dev": true,
+      "requires": {
+        "error-ex": "^1.2.0"
+      }
+    },
+    "parseqs": {
+      "version": "0.0.5",
+      "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz",
+      "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=",
+      "dev": true,
+      "requires": {
+        "better-assert": "~1.0.0"
+      }
+    },
+    "parseuri": {
+      "version": "0.0.5",
+      "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz",
+      "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=",
+      "dev": true,
+      "requires": {
+        "better-assert": "~1.0.0"
+      }
+    },
+    "parseurl": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
+      "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=",
+      "dev": true
+    },
+    "pascal-case": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-1.1.2.tgz",
+      "integrity": "sha1-Pl1kogBDgwp8STRMLXS0G+DJyZs=",
+      "dev": true,
+      "requires": {
+        "camel-case": "^1.1.1",
+        "upper-case-first": "^1.1.0"
+      }
+    },
+    "path-case": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/path-case/-/path-case-1.1.2.tgz",
+      "integrity": "sha1-UM5roNO+090LXCqcRVNpdDRAlRQ=",
+      "dev": true,
+      "requires": {
+        "sentence-case": "^1.1.2"
+      }
+    },
+    "path-exists": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
+      "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+      "dev": true,
+      "requires": {
+        "pinkie-promise": "^2.0.0"
+      }
+    },
+    "path-is-absolute": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+      "dev": true
+    },
+    "path-type": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
+      "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "pify": "^2.0.0",
+        "pinkie-promise": "^2.0.0"
+      },
+      "dependencies": {
+        "graceful-fs": {
+          "version": "4.1.11",
+          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
+          "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
+          "dev": true
+        }
+      }
+    },
+    "performance-now": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz",
+      "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=",
+      "dev": true
+    },
+    "pify": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+      "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+      "dev": true
+    },
+    "pinkie": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+      "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
+      "dev": true
+    },
+    "pinkie-promise": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+      "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+      "dev": true,
+      "requires": {
+        "pinkie": "^2.0.0"
+      }
+    },
+    "pkg-up": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-1.0.0.tgz",
+      "integrity": "sha1-Pgj7RhUlxEIWJKM7n35tCvWwWiY=",
+      "dev": true,
+      "requires": {
+        "find-up": "^1.0.0"
+      }
+    },
+    "portscanner": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/portscanner/-/portscanner-2.1.1.tgz",
+      "integrity": "sha1-6rtAnk3iSVD1oqUW01rnaTQ/u5Y=",
+      "dev": true,
+      "requires": {
+        "async": "1.5.2",
+        "is-number-like": "^1.0.3"
+      },
+      "dependencies": {
+        "async": {
+          "version": "1.5.2",
+          "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
+          "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
+          "dev": true
+        }
+      }
+    },
+    "preserve": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz",
+      "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=",
+      "dev": true
+    },
+    "pretty-bytes": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz",
+      "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=",
+      "dev": true,
+      "requires": {
+        "get-stdin": "^4.0.1",
+        "meow": "^3.1.0"
+      }
+    },
+    "process-nextick-args": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
+      "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
+      "dev": true
+    },
+    "promise": {
+      "version": "7.3.1",
+      "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
+      "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "asap": "~2.0.3"
+      }
+    },
+    "propprop": {
+      "version": "0.3.1",
+      "resolved": "https://registry.npmjs.org/propprop/-/propprop-0.3.1.tgz",
+      "integrity": "sha1-oEmjVouJZEAGfRXY7J8zc15XAXg=",
+      "dev": true
+    },
+    "prr": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
+      "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
+      "dev": true,
+      "optional": true
+    },
+    "punycode": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+      "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
+      "dev": true
+    },
+    "qs": {
+      "version": "6.4.0",
+      "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz",
+      "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=",
+      "dev": true
+    },
+    "randomatic": {
+      "version": "1.1.7",
+      "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz",
+      "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==",
+      "dev": true,
+      "requires": {
+        "is-number": "^3.0.0",
+        "kind-of": "^4.0.0"
+      },
+      "dependencies": {
+        "is-number": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+          "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+          "dev": true,
+          "requires": {
+            "kind-of": "^3.0.2"
+          },
+          "dependencies": {
+            "kind-of": {
+              "version": "3.2.2",
+              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+              "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+              "dev": true,
+              "requires": {
+                "is-buffer": "^1.1.5"
+              }
+            }
+          }
+        },
+        "kind-of": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
+          "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
+      }
+    },
+    "range-parser": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz",
+      "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=",
+      "dev": true
+    },
+    "raw-body": {
+      "version": "2.1.7",
+      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz",
+      "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=",
+      "dev": true,
+      "requires": {
+        "bytes": "2.4.0",
+        "iconv-lite": "0.4.13",
+        "unpipe": "1.0.0"
+      },
+      "dependencies": {
+        "bytes": {
+          "version": "2.4.0",
+          "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz",
+          "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=",
+          "dev": true
+        },
+        "iconv-lite": {
+          "version": "0.4.13",
+          "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz",
+          "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=",
+          "dev": true
+        }
+      }
+    },
+    "read-pkg": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
+      "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
+      "dev": true,
+      "requires": {
+        "load-json-file": "^1.0.0",
+        "normalize-package-data": "^2.3.2",
+        "path-type": "^1.0.0"
+      }
+    },
+    "read-pkg-up": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
+      "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
+      "dev": true,
+      "requires": {
+        "find-up": "^1.0.0",
+        "read-pkg": "^1.0.0"
+      }
+    },
+    "readable-stream": {
+      "version": "2.3.5",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz",
+      "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==",
+      "dev": true,
+      "requires": {
+        "core-util-is": "~1.0.0",
+        "inherits": "~2.0.3",
+        "isarray": "~1.0.0",
+        "process-nextick-args": "~2.0.0",
+        "safe-buffer": "~5.1.1",
+        "string_decoder": "~1.0.3",
+        "util-deprecate": "~1.0.1"
+      }
+    },
+    "readdirp": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz",
+      "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "minimatch": "^3.0.2",
+        "readable-stream": "^2.0.2",
+        "set-immediate-shim": "^1.0.1"
+      },
+      "dependencies": {
+        "graceful-fs": {
+          "version": "4.1.11",
+          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
+          "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
+          "dev": true
+        },
+        "minimatch": {
+          "version": "3.0.4",
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+          "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+          "dev": true,
+          "requires": {
+            "brace-expansion": "^1.1.7"
+          }
+        }
+      }
+    },
+    "redent": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
+      "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
+      "dev": true,
+      "requires": {
+        "indent-string": "^2.1.0",
+        "strip-indent": "^1.0.1"
+      }
+    },
+    "regex-cache": {
+      "version": "0.4.4",
+      "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz",
+      "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==",
+      "dev": true,
+      "requires": {
+        "is-equal-shallow": "^0.1.3"
+      }
+    },
+    "relateurl": {
+      "version": "0.2.7",
+      "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz",
+      "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=",
+      "dev": true
+    },
+    "remove-trailing-separator": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
+      "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
+      "dev": true
+    },
+    "repeat-element": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz",
+      "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=",
+      "dev": true
+    },
+    "repeat-string": {
+      "version": "1.6.1",
+      "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+      "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
+      "dev": true
+    },
+    "repeating": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
+      "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
+      "dev": true,
+      "requires": {
+        "is-finite": "^1.0.0"
+      }
+    },
+    "request": {
+      "version": "2.81.0",
+      "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz",
+      "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=",
+      "dev": true,
+      "requires": {
+        "aws-sign2": "~0.6.0",
+        "aws4": "^1.2.1",
+        "caseless": "~0.12.0",
+        "combined-stream": "~1.0.5",
+        "extend": "~3.0.0",
+        "forever-agent": "~0.6.1",
+        "form-data": "~2.1.1",
+        "har-validator": "~4.2.1",
+        "hawk": "~3.1.3",
+        "http-signature": "~1.1.0",
+        "is-typedarray": "~1.0.0",
+        "isstream": "~0.1.2",
+        "json-stringify-safe": "~5.0.1",
+        "mime-types": "~2.1.7",
+        "oauth-sign": "~0.8.1",
+        "performance-now": "^0.2.0",
+        "qs": "~6.4.0",
+        "safe-buffer": "^5.0.1",
+        "stringstream": "~0.0.4",
+        "tough-cookie": "~2.3.0",
+        "tunnel-agent": "^0.6.0",
+        "uuid": "^3.0.0"
+      }
+    },
+    "require-directory": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+      "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
+      "dev": true
+    },
+    "require-main-filename": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
+      "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
+      "dev": true
+    },
+    "requirefresh": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/requirefresh/-/requirefresh-1.1.2.tgz",
+      "integrity": "sha1-2Ot0SSfG2RLeNBj5PcurJ7lZ8vM=",
+      "dev": true
+    },
+    "requires-port": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+      "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
+      "dev": true
+    },
+    "resolve-from": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz",
+      "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=",
+      "dev": true
+    },
+    "resolve-pkg": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/resolve-pkg/-/resolve-pkg-0.1.0.tgz",
+      "integrity": "sha1-AsyZNBDik2livZcWahsHfalyVTE=",
+      "dev": true,
+      "requires": {
+        "resolve-from": "^2.0.0"
+      }
+    },
+    "resp-modifier": {
+      "version": "6.0.2",
+      "resolved": "https://registry.npmjs.org/resp-modifier/-/resp-modifier-6.0.2.tgz",
+      "integrity": "sha1-sSTeXE+6/LpUH0j/pzlw9KpFa08=",
+      "dev": true,
+      "requires": {
+        "debug": "^2.2.0",
+        "minimatch": "^3.0.2"
+      },
+      "dependencies": {
+        "minimatch": {
+          "version": "3.0.4",
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+          "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+          "dev": true,
+          "requires": {
+            "brace-expansion": "^1.1.7"
+          }
+        }
+      }
+    },
+    "right-align": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
+      "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=",
+      "dev": true,
+      "requires": {
+        "align-text": "^0.1.1"
+      }
+    },
+    "right-pad": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/right-pad/-/right-pad-1.0.1.tgz",
+      "integrity": "sha1-jKCMLLtbVedNr6lr9/0aJ9VoyNA=",
+      "dev": true
+    },
+    "rimraf": {
+      "version": "2.2.8",
+      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz",
+      "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=",
+      "dev": true
+    },
+    "rx": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz",
+      "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=",
+      "dev": true
+    },
+    "safe-buffer": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
+      "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
+      "dev": true
+    },
+    "seajs": {
+      "version": "2.3.0",
+      "resolved": "http://registry.npm.baidu-int.com/seajs/-/seajs-2.3.0.tgz",
+      "integrity": "sha1-+inQ/h/NQsAYoq61ZwcDVGBZbIs="
+    },
+    "semver": {
+      "version": "5.5.0",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
+      "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
+      "dev": true
+    },
+    "send": {
+      "version": "0.15.2",
+      "resolved": "https://registry.npmjs.org/send/-/send-0.15.2.tgz",
+      "integrity": "sha1-+R+rRAO8+H5xb3DOtdsvV4vcF9Y=",
+      "dev": true,
+      "requires": {
+        "debug": "2.6.4",
+        "depd": "~1.1.0",
+        "destroy": "~1.0.4",
+        "encodeurl": "~1.0.1",
+        "escape-html": "~1.0.3",
+        "etag": "~1.8.0",
+        "fresh": "0.5.0",
+        "http-errors": "~1.6.1",
+        "mime": "1.3.4",
+        "ms": "1.0.0",
+        "on-finished": "~2.3.0",
+        "range-parser": "~1.2.0",
+        "statuses": "~1.3.1"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "2.6.4",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.4.tgz",
+          "integrity": "sha1-dYaps8OXQcAoKuM0RcTorHRzT+A=",
+          "dev": true,
+          "requires": {
+            "ms": "0.7.3"
+          },
+          "dependencies": {
+            "ms": {
+              "version": "0.7.3",
+              "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.3.tgz",
+              "integrity": "sha1-cIFVpeROM/X9D8U+gdDUCpG+H/8=",
+              "dev": true
+            }
+          }
+        },
+        "fresh": {
+          "version": "0.5.0",
+          "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.0.tgz",
+          "integrity": "sha1-9HTKXmqSRtb9jglTz6m5yAWvp44=",
+          "dev": true
+        },
+        "http-errors": {
+          "version": "1.6.2",
+          "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz",
+          "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=",
+          "dev": true,
+          "requires": {
+            "depd": "1.1.1",
+            "inherits": "2.0.3",
+            "setprototypeof": "1.0.3",
+            "statuses": ">= 1.3.1 < 2"
+          },
+          "dependencies": {
+            "depd": {
+              "version": "1.1.1",
+              "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz",
+              "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=",
+              "dev": true
+            }
+          }
+        },
+        "mime": {
+          "version": "1.3.4",
+          "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz",
+          "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=",
+          "dev": true
+        },
+        "ms": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-1.0.0.tgz",
+          "integrity": "sha1-Wa3NIu3FQ/e1OBhi0xOHsfS8lHM=",
+          "dev": true
+        },
+        "setprototypeof": {
+          "version": "1.0.3",
+          "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz",
+          "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=",
+          "dev": true
+        }
+      }
+    },
+    "sentence-case": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-1.1.3.tgz",
+      "integrity": "sha1-gDSq/CFFdy06vhUJqkLJ4QQtwTk=",
+      "dev": true,
+      "requires": {
+        "lower-case": "^1.1.1"
+      }
+    },
+    "serve-index": {
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.8.0.tgz",
+      "integrity": "sha1-fF2WwT+xMRAfk8HFd0+FFqHnjTs=",
+      "dev": true,
+      "requires": {
+        "accepts": "~1.3.3",
+        "batch": "0.5.3",
+        "debug": "~2.2.0",
+        "escape-html": "~1.0.3",
+        "http-errors": "~1.5.0",
+        "mime-types": "~2.1.11",
+        "parseurl": "~1.3.1"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
+          "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=",
+          "dev": true,
+          "requires": {
+            "ms": "0.7.1"
+          }
+        },
+        "ms": {
+          "version": "0.7.1",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz",
+          "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=",
+          "dev": true
+        }
+      }
+    },
+    "serve-static": {
+      "version": "1.12.2",
+      "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.12.2.tgz",
+      "integrity": "sha1-5UbicmCBuBtLzsjpCAjrzdMjr7o=",
+      "dev": true,
+      "requires": {
+        "encodeurl": "~1.0.1",
+        "escape-html": "~1.0.3",
+        "parseurl": "~1.3.1",
+        "send": "0.15.2"
+      }
+    },
+    "server-destroy": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz",
+      "integrity": "sha1-8Tv5KOQrnD55OD5hzDmYtdFObN0=",
+      "dev": true
+    },
+    "set-blocking": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+      "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
+      "dev": true
+    },
+    "set-immediate-shim": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
+      "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=",
+      "dev": true
+    },
+    "setprototypeof": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.2.tgz",
+      "integrity": "sha1-gaVSFB7BBLiOic44MQOtXGZWTQg=",
+      "dev": true
+    },
+    "sigmund": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz",
+      "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=",
+      "dev": true
+    },
+    "signal-exit": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+      "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
+      "dev": true
+    },
+    "simple-fmt": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/simple-fmt/-/simple-fmt-0.1.0.tgz",
+      "integrity": "sha1-GRv1ZqWeZTBILLJatTtKjchcOms=",
+      "dev": true
+    },
+    "simple-is": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/simple-is/-/simple-is-0.2.0.tgz",
+      "integrity": "sha1-Krt1qt453rXMgVzhDmGRFkhQuvA=",
+      "dev": true
+    },
+    "snake-case": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-1.1.2.tgz",
+      "integrity": "sha1-DC8l4wUVjZoY09l3BmGH/vilpmo=",
+      "dev": true,
+      "requires": {
+        "sentence-case": "^1.1.2"
+      }
+    },
+    "sntp": {
+      "version": "1.0.9",
+      "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz",
+      "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=",
+      "dev": true,
+      "requires": {
+        "hoek": "2.x.x"
+      }
+    },
+    "socket.io": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.0.4.tgz",
+      "integrity": "sha1-waRZDO/4fs8TxyZS8Eb3FrKeYBQ=",
+      "dev": true,
+      "requires": {
+        "debug": "~2.6.6",
+        "engine.io": "~3.1.0",
+        "socket.io-adapter": "~1.1.0",
+        "socket.io-client": "2.0.4",
+        "socket.io-parser": "~3.1.1"
+      }
+    },
+    "socket.io-adapter": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz",
+      "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=",
+      "dev": true
+    },
+    "socket.io-client": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.0.4.tgz",
+      "integrity": "sha1-CRilUkBtxeVAs4Dc2Xr8SmQzL44=",
+      "dev": true,
+      "requires": {
+        "backo2": "1.0.2",
+        "base64-arraybuffer": "0.1.5",
+        "component-bind": "1.0.0",
+        "component-emitter": "1.2.1",
+        "debug": "~2.6.4",
+        "engine.io-client": "~3.1.0",
+        "has-cors": "1.1.0",
+        "indexof": "0.0.1",
+        "object-component": "0.0.3",
+        "parseqs": "0.0.5",
+        "parseuri": "0.0.5",
+        "socket.io-parser": "~3.1.1",
+        "to-array": "0.1.4"
+      }
+    },
+    "socket.io-parser": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.1.3.tgz",
+      "integrity": "sha512-g0a2HPqLguqAczs3dMECuA1RgoGFPyvDqcbaDEdCWY9g59kdUAz3YRmaJBNKXflrHNwB7Q12Gkf/0CZXfdHR7g==",
+      "dev": true,
+      "requires": {
+        "component-emitter": "1.2.1",
+        "debug": "~3.1.0",
+        "has-binary2": "~1.0.2",
+        "isarray": "2.0.1"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "isarray": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
+          "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=",
+          "dev": true
+        }
+      }
+    },
+    "source-map": {
+      "version": "0.5.7",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+      "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+      "dev": true
+    },
+    "spdx-correct": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz",
+      "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==",
+      "dev": true,
+      "requires": {
+        "spdx-expression-parse": "^3.0.0",
+        "spdx-license-ids": "^3.0.0"
+      }
+    },
+    "spdx-exceptions": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz",
+      "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==",
+      "dev": true
+    },
+    "spdx-expression-parse": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
+      "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
+      "dev": true,
+      "requires": {
+        "spdx-exceptions": "^2.1.0",
+        "spdx-license-ids": "^3.0.0"
+      }
+    },
+    "spdx-license-ids": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz",
+      "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==",
+      "dev": true
+    },
+    "sprintf-js": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+      "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+      "dev": true
+    },
+    "sshpk": {
+      "version": "1.13.1",
+      "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz",
+      "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=",
+      "dev": true,
+      "requires": {
+        "asn1": "~0.2.3",
+        "assert-plus": "^1.0.0",
+        "bcrypt-pbkdf": "^1.0.0",
+        "dashdash": "^1.12.0",
+        "ecc-jsbn": "~0.1.1",
+        "getpass": "^0.1.1",
+        "jsbn": "~0.1.0",
+        "tweetnacl": "~0.14.0"
+      },
+      "dependencies": {
+        "assert-plus": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+          "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+          "dev": true
+        }
+      }
+    },
+    "stable": {
+      "version": "0.1.6",
+      "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.6.tgz",
+      "integrity": "sha1-kQ9dKu17Ugxud3SZwfMuE5/eyxA=",
+      "dev": true
+    },
+    "statuses": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz",
+      "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=",
+      "dev": true
+    },
+    "stream-throttle": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/stream-throttle/-/stream-throttle-0.1.3.tgz",
+      "integrity": "sha1-rdV8jXzHOoFjDTHNVdOWHPr7qcM=",
+      "dev": true,
+      "requires": {
+        "commander": "^2.2.0",
+        "limiter": "^1.0.5"
+      }
+    },
+    "string-length": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/string-length/-/string-length-1.0.1.tgz",
+      "integrity": "sha1-VpcPscOFWOnnC3KL894mmsRa36w=",
+      "dev": true,
+      "requires": {
+        "strip-ansi": "^3.0.0"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+          "dev": true
+        },
+        "strip-ansi": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+          "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^2.0.0"
+          }
+        }
+      }
+    },
+    "string-width": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+      "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+      "dev": true,
+      "requires": {
+        "code-point-at": "^1.0.0",
+        "is-fullwidth-code-point": "^1.0.0",
+        "strip-ansi": "^3.0.0"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+          "dev": true
+        },
+        "strip-ansi": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+          "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^2.0.0"
+          }
+        }
+      }
+    },
+    "string_decoder": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
+      "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
+      "dev": true,
+      "requires": {
+        "safe-buffer": "~5.1.0"
+      }
+    },
+    "stringmap": {
+      "version": "0.2.2",
+      "resolved": "https://registry.npmjs.org/stringmap/-/stringmap-0.2.2.tgz",
+      "integrity": "sha1-VWwTeyWPlCuHdvWy71gqoGnX0bE=",
+      "dev": true
+    },
+    "stringset": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/stringset/-/stringset-0.2.1.tgz",
+      "integrity": "sha1-7yWcTjSTRDd/zRyRPdLoSMnAQrU=",
+      "dev": true
+    },
+    "stringstream": {
+      "version": "0.0.5",
+      "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
+      "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=",
+      "dev": true
+    },
+    "strip-ansi": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz",
+      "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=",
+      "dev": true,
+      "requires": {
+        "ansi-regex": "^0.2.1"
+      }
+    },
+    "strip-bom": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+      "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+      "dev": true,
+      "requires": {
+        "is-utf8": "^0.2.0"
+      }
+    },
+    "strip-indent": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
+      "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
+      "dev": true,
+      "requires": {
+        "get-stdin": "^4.0.1"
+      }
+    },
+    "supports-color": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz",
+      "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=",
+      "dev": true
+    },
+    "swap-case": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/swap-case/-/swap-case-1.1.2.tgz",
+      "integrity": "sha1-w5IDpFhzhfrTyFCgvRvK+ggZdOM=",
+      "dev": true,
+      "requires": {
+        "lower-case": "^1.1.1",
+        "upper-case": "^1.1.1"
+      }
+    },
+    "text-table": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+      "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
+      "dev": true
+    },
+    "tfunk": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/tfunk/-/tfunk-3.1.0.tgz",
+      "integrity": "sha1-OORBT8ZJd9h6/apy+sttKfgve1s=",
+      "dev": true,
+      "requires": {
+        "chalk": "^1.1.1",
+        "object-path": "^0.9.0"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+          "dev": true
+        },
+        "ansi-styles": {
+          "version": "2.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+          "dev": true
+        },
+        "chalk": {
+          "version": "1.1.3",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^2.2.1",
+            "escape-string-regexp": "^1.0.2",
+            "has-ansi": "^2.0.0",
+            "strip-ansi": "^3.0.0",
+            "supports-color": "^2.0.0"
+          }
+        },
+        "has-ansi": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+          "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^2.0.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+          "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^2.0.0"
+          }
+        },
+        "supports-color": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+          "dev": true
+        }
+      }
+    },
+    "through2": {
+      "version": "0.6.5",
+      "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz",
+      "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=",
+      "dev": true,
+      "requires": {
+        "readable-stream": ">=1.0.33-1 <1.1.0-0",
+        "xtend": ">=4.0.0 <4.1.0-0"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "0.0.1",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+          "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+          "dev": true
+        },
+        "readable-stream": {
+          "version": "1.0.34",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
+          "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
+          "dev": true,
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.1",
+            "isarray": "0.0.1",
+            "string_decoder": "~0.10.x"
+          }
+        },
+        "string_decoder": {
+          "version": "0.10.31",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+          "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
+          "dev": true
+        }
+      }
+    },
+    "tiny-lr": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.2.1.tgz",
+      "integrity": "sha1-s/26gC5dVqM8L28QeUsy5Hescp0=",
+      "dev": true,
+      "requires": {
+        "body-parser": "~1.14.0",
+        "debug": "~2.2.0",
+        "faye-websocket": "~0.10.0",
+        "livereload-js": "^2.2.0",
+        "parseurl": "~1.3.0",
+        "qs": "~5.1.0"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
+          "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=",
+          "dev": true,
+          "requires": {
+            "ms": "0.7.1"
+          }
+        },
+        "ms": {
+          "version": "0.7.1",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz",
+          "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=",
+          "dev": true
+        },
+        "qs": {
+          "version": "5.1.0",
+          "resolved": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz",
+          "integrity": "sha1-TZMuXH6kEcynajEtOaYGIA/VDNk=",
+          "dev": true
+        }
+      }
+    },
+    "title-case": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/title-case/-/title-case-1.1.2.tgz",
+      "integrity": "sha1-+uSmrlRr+iLQg6DuqRCkDRLtT1o=",
+      "dev": true,
+      "requires": {
+        "sentence-case": "^1.1.1",
+        "upper-case": "^1.0.3"
+      }
+    },
+    "to-array": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz",
+      "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=",
+      "dev": true
+    },
+    "tough-cookie": {
+      "version": "2.3.4",
+      "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz",
+      "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==",
+      "dev": true,
+      "requires": {
+        "punycode": "^1.4.1"
+      }
+    },
+    "trim-newlines": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
+      "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=",
+      "dev": true
+    },
+    "tryor": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/tryor/-/tryor-0.1.2.tgz",
+      "integrity": "sha1-gUXkynyv9ArN48z5Rui4u3W0Fys=",
+      "dev": true
+    },
+    "tunnel-agent": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+      "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+      "dev": true,
+      "requires": {
+        "safe-buffer": "^5.0.1"
+      }
+    },
+    "tweetnacl": {
+      "version": "0.14.5",
+      "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+      "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
+      "dev": true,
+      "optional": true
+    },
+    "type-is": {
+      "version": "1.6.16",
+      "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz",
+      "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==",
+      "dev": true,
+      "requires": {
+        "media-typer": "0.3.0",
+        "mime-types": "~2.1.18"
+      }
+    },
+    "typechecker": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/typechecker/-/typechecker-4.5.0.tgz",
+      "integrity": "sha512-bqPE/ck3bVIaXP7gMKTKSHrypT32lpYTpiqzPYeYzdSQnmaGvaGhy7TnN/M/+5R+2rs/kKcp9ZLPRp/Q9Yj+4w==",
+      "dev": true,
+      "requires": {
+        "editions": "^1.3.4"
+      }
+    },
+    "typedarray": {
+      "version": "0.0.6",
+      "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+      "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
+      "dev": true
+    },
+    "ua-parser-js": {
+      "version": "0.7.12",
+      "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.12.tgz",
+      "integrity": "sha1-BMgamb3V3FImPqKdJMa/jUgYpLs=",
+      "dev": true
+    },
+    "uglify-js": {
+      "version": "2.8.29",
+      "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz",
+      "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=",
+      "dev": true,
+      "requires": {
+        "source-map": "~0.5.1",
+        "uglify-to-browserify": "~1.0.0",
+        "yargs": "~3.10.0"
+      }
+    },
+    "uglify-to-browserify": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz",
+      "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=",
+      "dev": true
+    },
+    "ultron": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz",
+      "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==",
+      "dev": true
+    },
+    "underscore": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz",
+      "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=",
+      "dev": true
+    },
+    "underscore.string": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.2.1.tgz",
+      "integrity": "sha1-18D6KvXVoaZ/QlPa7pgTLnM/Dxk=",
+      "dev": true
+    },
+    "universalify": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz",
+      "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=",
+      "dev": true
+    },
+    "unpipe": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+      "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
+      "dev": true
+    },
+    "upper-case": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz",
+      "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=",
+      "dev": true
+    },
+    "upper-case-first": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-1.1.2.tgz",
+      "integrity": "sha1-XXm+3P8UQZUY/S7bCgUHybaFkRU=",
+      "dev": true,
+      "requires": {
+        "upper-case": "^1.1.1"
+      }
+    },
+    "uri-path": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/uri-path/-/uri-path-1.0.0.tgz",
+      "integrity": "sha1-l0fwGDWJM8Md4PzP2C0TjmcmLjI=",
+      "dev": true
+    },
+    "util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+      "dev": true
+    },
+    "utils-merge": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz",
+      "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=",
+      "dev": true
+    },
+    "uuid": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz",
+      "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==",
+      "dev": true
+    },
+    "uws": {
+      "version": "9.14.0",
+      "resolved": "https://registry.npmjs.org/uws/-/uws-9.14.0.tgz",
+      "integrity": "sha512-HNMztPP5A1sKuVFmdZ6BPVpBQd5bUjNC8EFMFiICK+oho/OQsAJy5hnIx4btMHiOk8j04f/DbIlqnEZ9d72dqg==",
+      "dev": true,
+      "optional": true
+    },
+    "validate-npm-package-license": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz",
+      "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==",
+      "dev": true,
+      "requires": {
+        "spdx-correct": "^3.0.0",
+        "spdx-expression-parse": "^3.0.0"
+      }
+    },
+    "verror": {
+      "version": "1.10.0",
+      "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+      "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
+      "dev": true,
+      "requires": {
+        "assert-plus": "^1.0.0",
+        "core-util-is": "1.0.2",
+        "extsprintf": "^1.2.0"
+      },
+      "dependencies": {
+        "assert-plus": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+          "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+          "dev": true
+        }
+      }
+    },
+    "websocket-driver": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz",
+      "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=",
+      "dev": true,
+      "requires": {
+        "http-parser-js": ">=0.4.0",
+        "websocket-extensions": ">=0.1.1"
+      }
+    },
+    "websocket-extensions": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz",
+      "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==",
+      "dev": true
+    },
+    "which": {
+      "version": "1.0.9",
+      "resolved": "https://registry.npmjs.org/which/-/which-1.0.9.tgz",
+      "integrity": "sha1-RgwdoPgQED0DIam2M6+eV15kSG8=",
+      "dev": true
+    },
+    "which-module": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz",
+      "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=",
+      "dev": true
+    },
+    "window-size": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
+      "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=",
+      "dev": true
+    },
+    "wiredep": {
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/wiredep/-/wiredep-2.2.2.tgz",
+      "integrity": "sha1-FETRirLkk3UEEJP+3d3Rto97ZrM=",
+      "dev": true,
+      "requires": {
+        "bower-config": "^0.5.0",
+        "chalk": "^0.5.1",
+        "glob": "^4.0.5",
+        "lodash": "^2.4.1",
+        "minimist": "^1.1.0",
+        "propprop": "^0.3.0",
+        "through2": "^0.6.1"
+      },
+      "dependencies": {
+        "glob": {
+          "version": "4.5.3",
+          "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz",
+          "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=",
+          "dev": true,
+          "requires": {
+            "inflight": "^1.0.4",
+            "inherits": "2",
+            "minimatch": "^2.0.1",
+            "once": "^1.3.0"
+          }
+        },
+        "lodash": {
+          "version": "2.4.2",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz",
+          "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=",
+          "dev": true
+        },
+        "minimatch": {
+          "version": "2.0.10",
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz",
+          "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=",
+          "dev": true,
+          "requires": {
+            "brace-expansion": "^1.0.0"
+          }
+        }
+      }
+    },
+    "word-wrap": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+      "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+      "dev": true
+    },
+    "wordwrap": {
+      "version": "0.0.2",
+      "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
+      "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8="
+    },
+    "wrap-ansi": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+      "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
+      "dev": true,
+      "requires": {
+        "string-width": "^1.0.1",
+        "strip-ansi": "^3.0.1"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+          "dev": true
+        },
+        "strip-ansi": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+          "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^2.0.0"
+          }
+        }
+      }
+    },
+    "wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+      "dev": true
+    },
+    "ws": {
+      "version": "3.3.3",
+      "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz",
+      "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==",
+      "dev": true,
+      "requires": {
+        "async-limiter": "~1.0.0",
+        "safe-buffer": "~5.1.0",
+        "ultron": "~1.1.0"
+      }
+    },
+    "xmlhttprequest-ssl": {
+      "version": "1.5.5",
+      "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz",
+      "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=",
+      "dev": true
+    },
+    "xtend": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
+      "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=",
+      "dev": true
+    },
+    "y18n": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
+      "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=",
+      "dev": true
+    },
+    "yargs": {
+      "version": "3.10.0",
+      "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
+      "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
+      "dev": true,
+      "requires": {
+        "camelcase": "^1.0.2",
+        "cliui": "^2.1.0",
+        "decamelize": "^1.0.0",
+        "window-size": "0.1.0"
+      }
+    },
+    "yargs-parser": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz",
+      "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=",
+      "dev": true,
+      "requires": {
+        "camelcase": "^3.0.0"
+      },
+      "dependencies": {
+        "camelcase": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
+          "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
+          "dev": true
+        }
+      }
+    },
+    "yeast": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
+      "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=",
+      "dev": true
+    }
+  }
+}

+ 59 - 0
kityminder-editor/package.json

@@ -0,0 +1,59 @@
+{
+  "name": "kityminder-editor",
+  "version": "1.0.67",
+  "description": "A powerful mind map editor",
+  "main": "kityminder.editor.js",
+  "scripts": {
+    "init": "npm i -g wr && npm install -g less && npm install -g bower && bower install && npm install",
+    "build": "grunt build",
+    "dev": "grunt dev",
+    "watch": "wr --exec \"lessc --source-map less/editor.less dist/kityminder.editor.css && grunt build\" less ui",
+    "postinstall": "bower install"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/fex-team/kityminder-editor"
+  },
+  "keywords": [
+    "kityminder",
+    "editor",
+    "html5",
+    "js",
+    "mindmap"
+  ],
+  "author": "fex <fex@baidu.com>",
+  "license": "GPL-2.0",
+  "bugs": {
+    "url": "https://github.com/fex-team/kityminder-editor/issues"
+  },
+  "homepage": "https://github.com/fex-team/kityminder-editor",
+  "devDependencies": {
+    "cz-conventional-changelog": "^1.1.5",
+    "grunt": "~0.4.1",
+    "grunt-angular-templates": "~0.5.0",
+    "grunt-browser-sync": "^2.2.0",
+    "grunt-contrib-clean": "^0.5.0",
+    "grunt-contrib-concat": "~0.5.0",
+    "grunt-contrib-copy": "^0.5.0",
+    "grunt-contrib-cssmin": "^0.12.0",
+    "grunt-contrib-less": "^1.0.0",
+    "grunt-contrib-uglify": "^3.3.0",
+    "grunt-contrib-watch": "^1.0.0",
+    "grunt-module-dependence": "~0.2.0",
+    "grunt-ng-annotate": "^0.9.2",
+    "grunt-replace": "~0.8.0",
+    "grunt-wiredep": "^2.0.0",
+    "jshint-stylish": "^1.0.0",
+    "load-grunt-tasks": "^3.1.0",
+    "uglify-js": "^2.8.29"
+  },
+  "dependencies": {
+    "kityminder-core": "^1.4.50"
+  },
+  "config": {
+    "commitizen": {
+      "path": "./node_modules/cz-conventional-changelog"
+    }
+  },
+  "__npminstall_done": false
+}

BIN
kityminder-editor/relations.png


+ 67 - 0
kityminder-editor/server/imageUpload.php

@@ -0,0 +1,67 @@
+<?php
+    /**
+    * @fileOverview: 本文件用于 DEMO 用途,用于提供图片上传后端的接口,接收前端的上传文件请求,返回上传成功后的 URL(绝对地址)
+    *
+    * 原理:
+    *     1. 返回的接口结构为 {errno: <错误号, 无错误则为 0>, msg: <错误信息>, data: {url: <返回的 URL>}};
+    *     2. 由于要兼容两种情况的上传:通过对话框选择本地文件上传和直接 Ctrl + V(多见于截图后),因此本文件分别进行了判断
+    *
+    *
+    * 注意:
+    *     1. 本文件的路径可以进行配置,详见 README.md 中「初始化配置」部分。
+    *     2. 由于使用场景不同,请根据实际场景编写上传文件的处理。
+    *     3. 本文件并没有做任何的安全方面的防护,请勿用于生产环境。
+    *
+    * @author: zhangbobell
+    *
+    * @date: 2016.07.06
+    *
+    */
+
+    // 返回给前端的地址是绝对地址,这里是前缀
+    $HTTP_PREFIX = 'http://localhost/kityminder-editor/';
+
+
+    $errno = 0;
+    $msg = 'ok';
+    $url = '';
+
+
+    if ((($_FILES["upload_file"]["type"] == "image/gif")
+    || ($_FILES["upload_file"]["type"] == "image/jpeg")
+    || ($_FILES["upload_file"]["type"] == "image/jpg")
+    || ($_FILES["upload_file"]["type"] == "image/png"))
+    && ($_FILES["upload_file"]["size"] < 1 * 1000 * 1000)) {
+
+        if ($_FILES["upload_file"]["error"] > 0) {
+            $errno = 414;
+            $msg = $_FILES["upload_file"]["error"];
+        } else {
+
+            // 分为两种情况 `Ctrl + V` 和普通上传
+            if ($_FILES["upload_file"]["name"] === 'blob') {
+                $ext_name =  'png';
+            } else {
+                $ext_name =  array_pop(explode('.', $_FILES["upload_file"]["name"]));
+            }
+
+            $sha1_name =  sha1_file($_FILES["upload_file"]["tmp_name"]) . '.' . $ext_name;
+
+            move_uploaded_file($_FILES["upload_file"]["tmp_name"], "upload/" . $sha1_name);
+            $url = $HTTP_PREFIX . "server/upload/" . $sha1_name;
+        }
+    } else {
+        $errno = 416;
+        $msg = 'File is invalid';
+    }
+
+
+    $result = array(
+        'errno' => $errno,
+        'msg' => $msg,
+        'data' => array(
+            'url' => $url
+        )
+    );
+
+    echo json_encode($result);

+ 40 - 0
kityminder-editor/src/editor.js

@@ -0,0 +1,40 @@
+define(function(require, exports, module) {
+
+    /**
+     * 运行时
+     */
+    var runtimes = [];
+
+    function assemble(runtime) {
+        runtimes.push(runtime);
+    }
+
+    function KMEditor(selector) {
+        this.selector = selector;
+        for (var i = 0; i < runtimes.length; i++) {
+            if (typeof runtimes[i] == 'function') {
+                runtimes[i].call(this, this);
+            }
+        }
+    }
+
+    KMEditor.assemble = assemble;
+
+    assemble(require('./runtime/container'));
+    assemble(require('./runtime/fsm'));
+    assemble(require('./runtime/minder'));
+    assemble(require('./runtime/receiver'));
+    assemble(require('./runtime/hotbox'));
+    assemble(require('./runtime/input'));
+    assemble(require('./runtime/clipboard-mimetype'));
+    assemble(require('./runtime/clipboard'));
+    assemble(require('./runtime/drag'));
+    assemble(require('./runtime/node'));
+    assemble(require('./runtime/history'));
+    assemble(require('./runtime/jumping'));
+    assemble(require('./runtime/priority'));
+    assemble(require('./runtime/progress'));
+
+
+    return module.exports = KMEditor;
+});

+ 11 - 0
kityminder-editor/src/expose-editor.js

@@ -0,0 +1,11 @@
+/**
+ * @fileOverview
+ *
+ * 打包暴露
+ *
+ * @author: techird
+ * @copyright: Baidu FEX, 2014
+ */
+define('expose-editor', function(require, exports, module) {
+    return module.exports = kityminder.Editor = require('./editor');
+});

+ 3 - 0
kityminder-editor/src/hotbox.js

@@ -0,0 +1,3 @@
+define(function(require, exports, module) {
+    return module.exports = window.HotBox;
+});

+ 3 - 0
kityminder-editor/src/lang.js

@@ -0,0 +1,3 @@
+define(function(require, exports, module) {
+
+});

+ 3 - 0
kityminder-editor/src/minder.js

@@ -0,0 +1,3 @@
+define(function(require, exports, module) {
+    return module.exports = window.kityminder.Minder;
+});

+ 123 - 0
kityminder-editor/src/runtime/clipboard-mimetype.js

@@ -0,0 +1,123 @@
+/**
+ * @Desc: 新增一个用于处理系统ctrl+c ctrl+v等方式导入导出节点的MIMETYPE处理,如系统不支持clipboardEvent或者是FF则不初始化改class
+ * @Editor: Naixor
+ * @Date: 2015.9.21
+ */
+define(function(require, exports, module) {
+	function MimeType() {
+		/**
+		 * 私有变量
+		 */
+		var SPLITOR = '\uFEFF';
+		var MIMETYPE = {
+			'application/km': '\uFFFF'
+		};
+		var SIGN = {
+			'\uFEFF': 'SPLITOR',
+			'\uFFFF': 'application/km'
+		};
+
+		/**
+		 * 用于将一段纯文本封装成符合其数据格式的文本
+		 * @method process 			private
+		 * @param  {MIMETYPE} mimetype 数据格式
+		 * @param  {String} text     原始文本
+		 * @return {String}          符合该数据格式下的文本
+		 * @example
+		 * 			var str = "123";
+		 * 			str = process('application/km', str); // 返回的内容再经过MimeType判断会读取出其数据格式为application/km
+		 * 			process('text/plain', str); // 若接受到一个非纯文本信息,则会将其转换为新的数据格式
+		 */
+		function process(mimetype, text) {
+			if (!this.isPureText(text)) {
+				var _mimetype = this.whichMimeType(text);
+				if (!_mimetype) {
+					throw new Error('unknow mimetype!');
+				};
+				text = this.getPureText(text);
+			};
+			if (mimetype === false) {
+				return text;
+			};
+			return mimetype + SPLITOR + text;
+		}
+
+		/**
+		 * 注册数据类型的标识
+		 * @method registMimeTypeProtocol  	public
+		 * @param  {String} type 数据类型
+		 * @param  {String} sign 标识
+		 */
+		this.registMimeTypeProtocol = function(type, sign) {
+			if (sign && SIGN[sign]) {
+				throw new Error('sing has registed!');
+			}
+			if (type && !!MIMETYPE[type]) {
+				throw new Error('mimetype has registed!');
+			};
+			SIGN[sign] = type;
+			MIMETYPE[type] = sign;
+		}
+
+		/**
+		 * 获取已注册数据类型的协议
+		 * @method getMimeTypeProtocol  	public
+		 * @param  {String} type 数据类型
+		 * @param  {String} text|undefiend  文本内容或不传入
+		 * @return {String|Function} 
+		 * @example 
+		 * 			text若不传入则直接返回对应数据格式的处理(process)方法
+		 * 			若传入文本则直接调用对应的process方法进行处理,此时返回处理后的内容
+		 * 			var m = new MimeType();
+		 * 			var kmprocess = m.getMimeTypeProtocol('application/km');
+		 * 			kmprocess("123") === m.getMimeTypeProtocol('application/km', "123");
+		 * 			
+		 */
+		this.getMimeTypeProtocol = function(type, text) {
+			var mimetype = MIMETYPE[type] || false;
+			
+			if (text === undefined) {
+				return process.bind(this, mimetype);
+			};
+			
+			return process(mimetype, text);
+		}
+
+		this.getSpitor = function() {
+			return SPLITOR;
+		}
+
+		this.getMimeType = function(sign) {
+			if (sign !== undefined) {
+				return SIGN[sign] || null;
+			};
+			return MIMETYPE;
+		}
+	}
+
+	MimeType.prototype.isPureText = function(text) {
+		return !(~text.indexOf(this.getSpitor()));
+	}
+
+	MimeType.prototype.getPureText = function(text) {
+		if (this.isPureText(text)) {
+			return text;
+		};
+		return text.split(this.getSpitor())[1];
+	}
+
+	MimeType.prototype.whichMimeType = function(text) {
+		if (this.isPureText(text)) {
+			return null;
+		};
+		return this.getMimeType(text.split(this.getSpitor())[0]);
+	}
+
+	function MimeTypeRuntime() {
+		if (this.minder.supportClipboardEvent && !kity.Browser.gecko) {
+			this.MimeType = new MimeType();
+		};
+	}
+
+	return module.exports = MimeTypeRuntime;
+});

+ 188 - 0
kityminder-editor/src/runtime/clipboard.js

@@ -0,0 +1,188 @@
+/**
+ * @Desc: 处理editor的clipboard事件,只在支持ClipboardEvent并且不是FF的情况下工作
+ * @Editor: Naixor
+ * @Date: 2015.9.21
+ */
+define(function(require, exports, module) {
+
+	function ClipboardRuntime () {
+		var minder = this.minder;
+		var Data = window.kityminder.data;
+
+		if (!minder.supportClipboardEvent || kity.Browser.gecko) {
+			return;
+		};
+
+		var fsm = this.fsm;
+		var receiver = this.receiver;
+		var MimeType = this.MimeType;
+		
+		var kmencode = MimeType.getMimeTypeProtocol('application/km'),
+			decode = Data.getRegisterProtocol('json').decode;
+		var _selectedNodes = [];
+
+		/*
+		 * 增加对多节点赋值粘贴的处理
+		 */
+		function encode (nodes) {
+			var _nodes = [];
+			for (var i = 0, l = nodes.length; i < l; i++) {
+				_nodes.push(minder.exportNode(nodes[i]));
+			}
+			return kmencode(Data.getRegisterProtocol('json').encode(_nodes));
+		}
+
+		var beforeCopy = function (e) {
+			if (document.activeElement == receiver.element) {
+				var clipBoardEvent = e;
+				var state = fsm.state();
+
+				switch (state) {
+					case 'input': {
+						break;
+					}
+					case 'normal': {
+						var nodes = [].concat(minder.getSelectedNodes());
+						if (nodes.length) {
+							// 这里由于被粘贴复制的节点的id信息也都一样,故做此算法
+							// 这里有个疑问,使用node.getParent()或者node.parent会离奇导致出现非选中节点被渲染成选中节点,因此使用isAncestorOf,而没有使用自行回溯的方式
+							if (nodes.length > 1) {
+								var targetLevel;
+								nodes.sort(function(a, b) {
+									return a.getLevel() - b.getLevel();
+								});
+								targetLevel = nodes[0].getLevel();
+								if (targetLevel !== nodes[nodes.length-1].getLevel()) {
+									var plevel, pnode,
+										idx = 0, l = nodes.length, pidx = l-1;
+									
+									pnode = nodes[pidx];
+
+									while (pnode.getLevel() !== targetLevel) {
+										idx = 0;
+										while (idx < l && nodes[idx].getLevel() === targetLevel) {
+											if (nodes[idx].isAncestorOf(pnode)) {
+												nodes.splice(pidx, 1);
+												break;
+											}
+											idx++;
+										}
+										pidx--;
+										pnode = nodes[pidx];
+									}
+								};
+							};
+							var str = encode(nodes);
+				            clipBoardEvent.clipboardData.setData('text/plain', str);
+				        }
+	            		e.preventDefault();			
+						break;
+					}
+				}
+			}
+		}
+
+		var beforeCut = function (e) {
+			if (document.activeElement == receiver.element) {
+				if (minder.getStatus() !== 'normal') {
+	            	e.preventDefault();			
+					return;
+				};
+
+				var clipBoardEvent = e;
+				var state = fsm.state();
+
+				switch (state) {
+					case 'input': {
+						break;
+					}
+					case 'normal': {
+						var nodes = minder.getSelectedNodes();
+						if (nodes.length) {
+				            clipBoardEvent.clipboardData.setData('text/plain', encode(nodes));
+				            minder.execCommand('removenode');
+				        }
+	            		e.preventDefault();			
+						break;
+					}
+				}
+			};
+		}
+
+		var beforePaste = function(e) {
+			if (document.activeElement == receiver.element) {
+				if (minder.getStatus() !== 'normal') {
+	            	e.preventDefault();			
+					return;
+				};
+
+				var clipBoardEvent = e;
+				var state = fsm.state();
+				var textData = clipBoardEvent.clipboardData.getData('text/plain');
+
+				switch (state) {
+					case 'input': {
+						// input状态下如果格式为application/km则不进行paste操作
+						if (!MimeType.isPureText(textData)) {
+							e.preventDefault();
+							return;
+						};
+						break;
+					}
+					case 'normal': {
+						/*
+						 * 针对normal状态下通过对选中节点粘贴导入子节点文本进行单独处理
+						 */
+						var sNodes = minder.getSelectedNodes();
+						
+						if (MimeType.whichMimeType(textData) === 'application/km') {
+							var nodes = decode(MimeType.getPureText(textData));
+							var _node; 
+							sNodes.forEach(function(node) {
+								// 由于粘贴逻辑中为了排除子节点重新排序导致逆序,因此复制的时候倒过来
+								for (var i = nodes.length-1; i >= 0; i--) {
+									_node = minder.createNode(null, node);
+									minder.importNode(_node, nodes[i]);
+									_selectedNodes.push(_node);
+									node.appendChild(_node);
+								}
+							});
+							minder.select(_selectedNodes, true);
+							_selectedNodes = [];
+
+							minder.refresh();
+						}
+                        else if (clipBoardEvent.clipboardData && clipBoardEvent.clipboardData.items[0].type.indexOf('image') > -1) {
+                            var imageFile = clipBoardEvent.clipboardData.items[0].getAsFile();
+                            var serverService = angular.element(document.body).injector().get('server');
+
+                            return serverService.uploadImage(imageFile).then(function (json) {
+                                    var resp = json.data;
+                                    if (resp.errno === 0) {
+                                        minder.execCommand('image', resp.data.url);
+                                    }
+                                });
+                        }
+                        else {
+							sNodes.forEach(function(node) {
+								minder.Text2Children(node, textData);						
+							});
+						}
+	            		e.preventDefault();			
+						break;
+					}
+				}
+			}
+		}
+		/**
+		 * 由editor的receiver统一处理全部事件,包括clipboard事件
+		 * @Editor: Naixor
+		 * @Date: 2015.9.24
+		 */
+		document.addEventListener('copy', beforeCopy);
+        document.addEventListener('cut', beforeCut);
+        document.addEventListener('paste', beforePaste);	
+	}
+
+	return module.exports = ClipboardRuntime;
+});

+ 33 - 0
kityminder-editor/src/runtime/container.js

@@ -0,0 +1,33 @@
+/**
+ * @fileOverview
+ *
+ * 初始化编辑器的容器
+ *
+ * @author: techird
+ * @copyright: Baidu FEX, 2014
+ */
+define(function(require, exports, module) {
+
+    /**
+     * 最先执行的 Runtime,初始化编辑器容器
+     */
+    function ContainerRuntime() {
+        var container;
+
+	    if (typeof(this.selector) == 'string') {
+		    container = document.querySelector(this.selector);
+	    } else {
+		    container = this.selector;
+	    }
+
+        if (!container) throw new Error('Invalid selector: ' + this.selector);
+
+        // 这个类名用于给编辑器添加样式
+        container.classList.add('km-editor');
+
+        // 暴露容器给其他运行时使用
+        this.container = container;
+    }
+
+    return module.exports = ContainerRuntime;
+});

+ 140 - 0
kityminder-editor/src/runtime/drag.js

@@ -0,0 +1,140 @@
+/**
+ * @fileOverview
+ *
+ * 用于拖拽节点时屏蔽键盘事件
+ *
+ * @author: techird
+ * @copyright: Baidu FEX, 2014
+ */
+define(function(require, exports, module) {
+
+    var Hotbox = require('../hotbox');
+    var Debug = require('../tool/debug');
+    var debug = new Debug('drag');
+
+    function DragRuntime() {
+        var fsm = this.fsm;
+        var minder = this.minder;
+        var hotbox = this.hotbox;
+        var receiver = this.receiver;
+        var receiverElement = receiver.element;
+
+        // setup everything to go
+        setupFsm();
+
+        // listen the fsm changes, make action.
+        function setupFsm() {
+
+            // when jumped to drag mode, enter
+            fsm.when('* -> drag', function() {
+                // now is drag mode
+            });
+
+            fsm.when('drag -> *', function(exit, enter, reason) {
+                if (reason == 'drag-finish') {
+                    // now exit drag mode
+                }
+            });
+        }
+
+        var downX, downY;
+        var MOUSE_HAS_DOWN = 0;
+        var MOUSE_HAS_UP = 1;
+        var BOUND_CHECK = 20;
+        var flag = MOUSE_HAS_UP;
+        var maxX, maxY, osx, osy, containerY;
+        var freeHorizen = false, freeVirtical = false;
+        var frame;
+
+        function move(direction, speed) {
+            if (!direction) {
+                freeHorizen = freeVirtical = false;
+                frame && kity.releaseFrame(frame);
+                frame = null;    
+                return;
+            }
+            if (!frame) {
+                frame = kity.requestFrame((function (direction, speed, minder) {
+                    return function (frame) {
+                        switch (direction) {
+                            case 'left':
+                                minder._viewDragger.move({x: -speed, y: 0}, 0);
+                                break;
+                            case 'top':
+                                minder._viewDragger.move({x: 0, y: -speed}, 0);
+                                break;
+                            case 'right':
+                                minder._viewDragger.move({x: speed, y: 0}, 0);
+                                break;
+                            case 'bottom':
+                                minder._viewDragger.move({x: 0, y: speed}, 0);
+                                break;
+                            default:
+                                return;
+                        }
+                        frame.next();
+                    };
+                })(direction, speed, minder));
+            }
+        }
+
+        minder.on('mousedown', function(e) {
+            flag = MOUSE_HAS_DOWN;
+            var rect = minder.getPaper().container.getBoundingClientRect();
+            downX = e.originEvent.clientX;
+            downY = e.originEvent.clientY;
+            containerY = rect.top;
+            maxX = rect.width;
+            maxY = rect.height;
+        });
+
+        minder.on('mousemove', function(e) {
+            if (fsm.state() === 'drag' && flag == MOUSE_HAS_DOWN && minder.getSelectedNode()
+                && (Math.abs(downX - e.originEvent.clientX) > BOUND_CHECK
+                    || Math.abs(downY - e.originEvent.clientY) > BOUND_CHECK)) {
+                osx = e.originEvent.clientX;
+                osy = e.originEvent.clientY - containerY;
+
+                if (osx < BOUND_CHECK) {
+                    move('right', BOUND_CHECK - osx);
+                } else if (osx > maxX - BOUND_CHECK) {
+                    move('left', BOUND_CHECK + osx - maxX);
+                } else {
+                    freeHorizen = true;
+                }
+                if (osy < BOUND_CHECK) {
+                    move('bottom', osy);
+                } else if (osy > maxY - BOUND_CHECK) {
+                    move('top', BOUND_CHECK + osy - maxY);
+                } else {
+                    freeVirtical = true;
+                }
+                if (freeHorizen && freeVirtical) {
+                    move(false);
+                }
+            }
+            if (fsm.state() !== 'drag'
+                && flag === MOUSE_HAS_DOWN
+                && minder.getSelectedNode()
+                && (Math.abs(downX - e.originEvent.clientX) > BOUND_CHECK
+                || Math.abs(downY - e.originEvent.clientY) > BOUND_CHECK)) {
+
+                if (fsm.state() === 'hotbox') {
+                    hotbox.active(Hotbox.STATE_IDLE);
+                }
+
+                return fsm.jump('drag', 'user-drag');
+            }
+        });
+
+        window.addEventListener('mouseup', function () {
+            flag = MOUSE_HAS_UP;
+            if (fsm.state() === 'drag') {
+                move(false);
+                return fsm.jump('normal', 'drag-finish');
+            }
+        }, false);
+    }
+
+    return module.exports = DragRuntime;
+});

+ 121 - 0
kityminder-editor/src/runtime/fsm.js

@@ -0,0 +1,121 @@
+/**
+ * @fileOverview
+ *
+ * 编辑器状态机
+ *
+ * @author: techird
+ * @copyright: Baidu FEX, 2014
+ */
+define(function(require, exports, module) {
+
+    var Debug = require('../tool/debug');
+    var debug = new Debug('fsm');
+
+    function handlerConditionMatch(condition, when, exit, enter) {
+        if (condition.when != when) return false;
+        if (condition.enter != '*' && condition.enter != enter) return false;
+        if (condition.exit != '*' && condition.exit != exit) return;
+        return true;
+    }
+
+    function FSM(defaultState) {
+        var currentState = defaultState;
+        var BEFORE_ARROW = ' - ';
+        var AFTER_ARROW = ' -> ';
+        var handlers = [];
+
+        /**
+         * 状态跳转
+         *
+         * 会通知所有的状态跳转监视器
+         *
+         * @param  {string} newState  新状态名称
+         * @param  {any} reason 跳转的原因,可以作为参数传递给跳转监视器
+         */
+        this.jump = function(newState, reason) {
+            if (!reason) throw new Error('Please tell fsm the reason to jump');
+
+            var oldState = currentState;
+            var notify = [oldState, newState].concat([].slice.call(arguments, 1));
+            var i, handler;
+
+            // 跳转前
+            for (i = 0; i < handlers.length; i++) {
+                handler = handlers[i];
+                if (handlerConditionMatch(handler.condition, 'before', oldState, newState)) {
+                    if (handler.apply(null, notify)) return;
+                }
+            }
+
+            currentState = newState;
+            debug.log('[{0}] {1} -> {2}', reason, oldState, newState);
+
+            // 跳转后
+            for (i = 0; i < handlers.length; i++) {
+                handler = handlers[i];
+                if (handlerConditionMatch(handler.condition, 'after', oldState, newState)) {
+                    handler.apply(null, notify);
+                }
+            }
+            return currentState;
+        };
+
+        /**
+         * 返回当前状态
+         * @return {string}
+         */
+        this.state = function() {
+            return currentState;
+        };
+
+        /**
+         * 添加状态跳转监视器
+         * 
+         * @param {string} condition
+         *     监视的时机
+         *         "* => *" (默认)
+         *
+         * @param  {Function} handler
+         *     监视函数,当状态跳转的时候,会接收三个参数
+         *         * from - 跳转前的状态
+         *         * to - 跳转后的状态
+         *         * reason - 跳转的原因
+         */
+        this.when = function(condition, handler) {
+            if (arguments.length == 1) {
+                handler = condition;
+                condition = '* -> *';
+            }
+
+            var when, resolved, exit, enter;
+
+            resolved = condition.split(BEFORE_ARROW);
+            if (resolved.length == 2) {
+                when = 'before';
+            } else {
+                resolved = condition.split(AFTER_ARROW);
+                if (resolved.length == 2) {
+                    when = 'after';
+                }
+            }
+            if (!when) throw new Error('Illegal fsm condition: ' + condition);
+
+            exit = resolved[0];
+            enter = resolved[1];
+
+            handler.condition = {
+                when: when,
+                exit: exit,
+                enter: enter
+            };
+
+            handlers.push(handler);
+        };
+    }
+
+    function FSMRumtime() {
+        this.fsm = new FSM('normal');
+    }
+
+    return module.exports = FSMRumtime;
+});

+ 133 - 0
kityminder-editor/src/runtime/history.js

@@ -0,0 +1,133 @@
+/**
+ * @fileOverview
+ *
+ * 历史管理
+ *
+ * @author: techird
+ * @copyright: Baidu FEX, 2014
+ */
+
+
+define(function(require, exports, module) {
+    var jsonDiff = require('../tool/jsondiff');
+
+    function HistoryRuntime() {
+        var minder = this.minder;
+        var hotbox = this.hotbox;
+
+        var MAX_HISTORY = 100;
+
+        var lastSnap;
+        var patchLock;
+        var undoDiffs;
+        var redoDiffs;
+
+        function reset() {
+            undoDiffs = [];
+            redoDiffs = [];
+            lastSnap = minder.exportJson();
+        }
+
+        function makeUndoDiff() {
+            var headSnap = minder.exportJson();
+            var diff = jsonDiff(headSnap, lastSnap);
+            if (diff.length) {
+                undoDiffs.push(diff);
+                while (undoDiffs.length > MAX_HISTORY) {
+                    undoDiffs.shift();
+                }
+                lastSnap = headSnap;
+                return true;
+            }
+        }
+
+        function makeRedoDiff() {
+            var revertSnap = minder.exportJson();
+            redoDiffs.push(jsonDiff(revertSnap, lastSnap));
+            lastSnap = revertSnap;
+        }
+
+        function undo() {
+            patchLock = true;
+            var undoDiff = undoDiffs.pop();
+            if (undoDiff) {
+                minder.applyPatches(undoDiff);
+                makeRedoDiff();
+            }
+            patchLock = false;
+        }
+
+        function redo() {
+            patchLock = true;
+            var redoDiff = redoDiffs.pop();
+            if (redoDiff) {
+                minder.applyPatches(redoDiff);
+                makeUndoDiff();
+            }
+            patchLock = false;
+        }
+
+        function changed() {
+            if (patchLock) return;
+            if (makeUndoDiff()) redoDiffs = [];
+        }
+
+        function hasUndo() {
+            return !!undoDiffs.length;
+        }
+
+        function hasRedo() {
+            return !!redoDiffs.length;
+        }
+
+        function updateSelection(e) {
+            if (!patchLock) return;
+            var patch = e.patch;
+            switch (patch.express) {
+                case 'node.add':
+                    minder.select(patch.node.getChild(patch.index), true);
+                    break;
+                case 'node.remove':
+                case 'data.replace':
+                case 'data.remove':
+                case 'data.add':
+                    minder.select(patch.node, true);
+                    break;
+            }
+        }
+
+        this.history = {
+            reset: reset,
+            undo: undo,
+            redo: redo,
+            hasUndo: hasUndo,
+            hasRedo: hasRedo
+        };
+        reset();
+        minder.on('contentchange', changed);
+        minder.on('import', reset);
+        minder.on('patch', updateSelection);
+
+        var main = hotbox.state('main');
+        main.button({
+            position: 'top',
+            label: '撤销',
+            key: 'Ctrl + Z',
+            enable: hasUndo,
+            action: undo,
+            next: 'idle'
+        });
+        main.button({
+            position: 'top',
+            label: '重做',
+            key: 'Ctrl + Y',
+            enable: hasRedo,
+            action: redo,
+            next: 'idle'
+        });
+    }
+
+    window.diff = jsonDiff;
+
+    return module.exports = HistoryRuntime;
+});

+ 56 - 0
kityminder-editor/src/runtime/hotbox.js

@@ -0,0 +1,56 @@
+/**
+ * @fileOverview
+ *
+ * 热盒 Runtime
+ *
+ * @author: techird
+ * @copyright: Baidu FEX, 2014
+ */
+define(function(require, exports, module) {
+    var Hotbox = require('../hotbox');
+
+    function HotboxRuntime() {
+        var fsm = this.fsm;
+        var minder = this.minder;
+        var receiver = this.receiver;
+        var container = this.container;
+
+        var hotbox = new Hotbox(container);
+
+        hotbox.setParentFSM(fsm);
+
+        fsm.when('normal -> hotbox', function(exit, enter, reason) {
+            var node = minder.getSelectedNode();
+            var position;
+            if (node) {
+                var box = node.getRenderBox();
+                position = {
+                    x: box.cx,
+                    y: box.cy
+                };
+            }
+            hotbox.active('main', position);
+        });
+
+        fsm.when('normal -> normal', function(exit, enter, reason, e) {
+            if (reason == 'shortcut-handle') {
+                var handleResult = hotbox.dispatch(e);
+                if (handleResult) {
+                    e.preventDefault();
+                } else {
+                    minder.dispatchKeyEvent(e);
+                }
+            }
+        });
+
+        fsm.when('modal -> normal', function(exit, enter, reason, e) {
+            if (reason == 'import-text-finish') {
+                receiver.element.focus();
+            }
+        });
+
+        this.hotbox = hotbox;
+    }
+
+    return module.exports = HotboxRuntime;
+});

+ 395 - 0
kityminder-editor/src/runtime/input.js

@@ -0,0 +1,395 @@
+/**
+ * @fileOverview
+ *
+ * 文本输入支持
+ *
+ * @author: techird
+ * @copyright: Baidu FEX, 2014
+ */
+define(function(require, exports, module) {
+
+    require('../tool/innertext');
+
+    var Debug = require('../tool/debug');
+    var debug = new Debug('input');
+
+    function InputRuntime() {
+        var fsm = this.fsm;
+        var minder = this.minder;
+        var hotbox = this.hotbox;
+        var receiver = this.receiver;
+        var receiverElement = receiver.element;
+        var isGecko = window.kity.Browser.gecko;
+
+        // setup everything to go
+        setupReciverElement();
+        setupFsm();
+        setupHotbox();
+
+        // expose editText()
+        this.editText = editText;
+
+
+        // listen the fsm changes, make action.
+        function setupFsm() {
+
+            // when jumped to input mode, enter
+            fsm.when('* -> input', enterInputMode);
+
+            // when exited, commit or exit depends on the exit reason
+            fsm.when('input -> *', function(exit, enter, reason) {
+                switch (reason) {
+                    case 'input-cancel':
+                        return exitInputMode();
+                    case 'input-commit':
+                    default:
+                        return commitInputResult();
+                }
+            });
+
+            // lost focus to commit
+            receiver.onblur(function (e) {
+                if (fsm.state() == 'input') {
+                    fsm.jump('normal', 'input-commit');
+                }
+            });
+
+            minder.on('beforemousedown', function () {
+                if (fsm.state() == 'input') {
+                    fsm.jump('normal', 'input-commit');
+                }
+            });
+
+            minder.on('dblclick', function() {
+                if (minder.getSelectedNode() && minder._status !== 'readonly') {
+                    editText();
+                }
+            });
+        }
+
+
+        // let the receiver follow the current selected node position
+        function setupReciverElement() {
+            if (debug.flaged) {
+                receiverElement.classList.add('debug');
+            }
+
+            receiverElement.onmousedown = function(e) {
+                e.stopPropagation();
+            };
+
+            minder.on('layoutallfinish viewchange viewchanged selectionchange', function(e) {
+
+                // viewchange event is too frequenced, lazy it
+                if (e.type == 'viewchange' && fsm.state() != 'input') return;
+
+                updatePosition();
+            });
+
+            updatePosition();
+        }
+
+
+        // edit entrance in hotbox
+        function setupHotbox() {
+            hotbox.state('main').button({
+                position: 'center',
+                label: '编辑',
+                key: 'F2',
+                enable: function() {
+                    return minder.queryCommandState('text') != -1;
+                },
+                action: editText
+            });
+        }
+
+
+        /**
+         * 增加对字体的鉴别,以保证用户在编辑状态ctrl/cmd + b/i所触发的加粗斜体与显示一致
+         * @editor Naixor
+         * @Date 2015-12-2
+         */
+         // edit for the selected node
+        function editText() {
+            var node = minder.getSelectedNode();
+            if (!node) {
+                return;
+            }
+            var textContainer = receiverElement;
+            receiverElement.innerText = "";
+            if (node.getData('font-weight') === 'bold') {
+                var b = document.createElement('b');
+                textContainer.appendChild(b);
+                textContainer = b;
+            }
+            if (node.getData('font-style') === 'italic') {
+                var i = document.createElement('i');
+                textContainer.appendChild(i);
+                textContainer = i;
+            }
+            textContainer.innerText = minder.queryCommandValue('text');
+
+            if (isGecko) {
+                receiver.fixFFCaretDisappeared();
+            };
+            fsm.jump('input', 'input-request');
+            receiver.selectAll();
+        }
+
+        /**
+         * 增加对字体的鉴别,以保证用户在编辑状态ctrl/cmd + b/i所触发的加粗斜体与显示一致
+         * @editor Naixor
+         * @Date 2015-12-2
+         */
+        function enterInputMode() {
+            var node = minder.getSelectedNode();
+            if (node) {
+                var fontSize = node.getData('font-size') || node.getStyle('font-size');
+                receiverElement.style.fontSize = fontSize + 'px';
+                receiverElement.style.minWidth = 0;
+                receiverElement.style.minWidth = receiverElement.clientWidth + 'px';
+                receiverElement.style.fontWeight = node.getData('font-weight') || '';
+                receiverElement.style.fontStyle = node.getData('font-style') || '';
+                receiverElement.classList.add('input');
+                receiverElement.focus();
+            }
+        }
+
+        /**
+         * 按照文本提交操作处理
+         * @Desc: 从其他节点复制文字到另一个节点时部分浏览器(chrome)会自动包裹一个span标签,这样试用一下逻辑出来的就不是text节点二是span节点因此导致undefined的情况发生
+         * @Warning: 下方代码使用[].slice.call来将HTMLDomCollection处理成为Array,ie8及以下会有问题
+         * @Editor: Naixor
+         * @Date: 2015.9.16
+         */
+        function commitInputText (textNodes) {
+            var text = '';
+            var TAB_CHAR = '\t',
+                ENTER_CHAR = '\n',
+                STR_CHECK = /\S/,
+                SPACE_CHAR = '\u0020',
+                // 针对FF,SG,BD,LB,IE等浏览器下SPACE的charCode存在为32和160的情况做处理
+                SPACE_CHAR_REGEXP = new RegExp('(\u0020|' + String.fromCharCode(160) + ')'),
+                BR = document.createElement('br');
+            var isBold = false,
+                isItalic = false;
+
+            for (var str,
+                    _divChildNodes,
+                    space_l, space_num, tab_num,
+                    i = 0, l = textNodes.length; i < l; i++) {
+                str = textNodes[i];
+
+                switch (Object.prototype.toString.call(str)) {
+                    // 正常情况处理
+                    case '[object HTMLBRElement]': {
+                        text += ENTER_CHAR;
+                        break;
+                    }
+                    case '[object Text]': {
+                        // SG下会莫名其妙的加上&nbsp;影响后续判断,干掉!
+                        /**
+                         * FF下的wholeText会导致如下问题:
+                         *     |123| -> 在一个节点中输入一段字符,此时TextNode为[#Text 123]
+                         *     提交并重新编辑,在后面追加几个字符
+                         *     |123abc| -> 此时123为一个TextNode为[#Text 123, #Text abc],但是对这两个任意取值wholeText均为全部内容123abc
+                         * 上述BUG仅存在在FF中,故将wholeText更改为textContent
+                         */
+                        str = str.textContent.replace("&nbsp;", " ");
+
+                        if (!STR_CHECK.test(str)) {
+                            space_l = str.length;
+                            while (space_l--) {
+                                if (SPACE_CHAR_REGEXP.test(str[space_l])) {
+                                    text += SPACE_CHAR;
+                                } else if (str[space_l] === TAB_CHAR) {
+                                    text += TAB_CHAR;
+                                }
+                            }
+                        } else {
+                            text += str;
+                        }
+                        break;
+                    }
+                    // ctrl + b/i 会给字体加上<b>/<i>标签来实现黑体和斜体
+                    case '[object HTMLElement]': {
+                        switch (str.nodeName) {
+                            case "B": {
+                                isBold = true;
+                                break;
+                            }
+                            case "I": {
+                                isItalic = true;
+                                break;
+                            }
+                            default: {}
+                        }
+                        [].splice.apply(textNodes, [i, 1].concat([].slice.call(str.childNodes)));
+                        l = textNodes.length;
+                        i--;
+                        break;
+                    }
+                    // 被增加span标签的情况会被处理成正常情况并会推交给上面处理
+                    case '[object HTMLSpanElement]': {
+                        [].splice.apply(textNodes, [i, 1].concat([].slice.call(str.childNodes)));
+                        l = textNodes.length;
+                        i--;
+                        break;
+                    }
+                    // 若标签为image标签,则判断是否为合法url,是将其加载进来
+                    case '[object HTMLImageElement]': {
+                        if (str.src) {
+                            if (/http(|s):\/\//.test(str.src)) {
+                                minder.execCommand("Image", str.src, str.alt);
+                            } else {
+                                // data:image协议情况
+                            }
+                        };
+                        break;
+                    }
+                    // 被增加div标签的情况会被处理成正常情况并会推交给上面处理
+                    case '[object HTMLDivElement]': {
+                        _divChildNodes = [];
+                        for (var di = 0, l = str.childNodes.length; di < l; di++) {
+                            _divChildNodes.push(str.childNodes[di]);
+                        }
+                        _divChildNodes.push(BR);
+                        [].splice.apply(textNodes, [i, 1].concat(_divChildNodes));
+                        l = textNodes.length;
+                        i--;
+                        break;
+                    }
+                    default: {
+                        if (str && str.childNodes.length) {
+                            _divChildNodes = [];
+                            for (var di = 0, l = str.childNodes.length; di < l; di++) {
+                                _divChildNodes.push(str.childNodes[di]);
+                            }
+                            _divChildNodes.push(BR);
+                            [].splice.apply(textNodes, [i, 1].concat(_divChildNodes));
+                            l = textNodes.length;
+                            i--;
+                        } else {
+                            if (str && str.textContent !== undefined) {
+                                text += str.textContent;
+                            } else {
+                                text += "";
+                            }
+                        }
+                        // // 其他带有样式的节点被粘贴进来,则直接取textContent,若取不出来则置空
+                    }
+                }
+            };
+
+            text = text.replace(/^\n*|\n*$/g, '');
+            text = text.replace(new RegExp('(\n|\r|\n\r)(\u0020|' + String.fromCharCode(160) + '){4}', 'g'), '$1\t');
+            minder.getSelectedNode().setText(text);
+            if (isBold) {
+                minder.queryCommandState('bold') || minder.execCommand('bold');
+            } else {
+                minder.queryCommandState('bold') && minder.execCommand('bold');
+            }
+
+            if (isItalic) {
+                minder.queryCommandState('italic') || minder.execCommand('italic');
+            } else {
+                minder.queryCommandState('italic') && minder.execCommand('italic');
+            }
+            exitInputMode();
+            return text;
+        }
+
+        /**
+         * 判断节点的文本信息是否是
+         * @Desc: 从其他节点复制文字到另一个节点时部分浏览器(chrome)会自动包裹一个span标签,这样使用以下逻辑出来的就不是text节点二是span节点因此导致undefined的情况发生
+         * @Notice: 此处逻辑应该拆分到 kityminder-core/core/data中去,单独增加一个对某个节点importJson的事件
+         * @Editor: Naixor
+         * @Date: 2015.9.16
+         */
+        function commitInputNode(node, text) {
+            try {
+                minder.decodeData('text', text).then(function(json) {
+                    function importText(node, json, minder) {
+                        var data = json.data;
+
+                        node.setText(data.text || '');
+
+                        var childrenTreeData = json.children || [];
+                        for (var i = 0; i < childrenTreeData.length; i++) {
+                            var childNode = minder.createNode(null, node);
+                            importText(childNode, childrenTreeData[i], minder);
+                        }
+                        return node;
+                    }
+                    importText(node, json, minder);
+                    minder.fire("contentchange");
+                    minder.getRoot().renderTree();
+                    minder.layout(300);
+                });
+            } catch (e) {
+                minder.fire("contentchange");
+                minder.getRoot().renderTree();
+
+                // 无法被转换成脑图节点则不处理
+                if (e.toString() !== 'Error: Invalid local format') {
+                    throw e;
+                }
+            }
+        }
+
+        function commitInputResult() {
+            /**
+             * @Desc: 进行如下处理:
+             *             根据用户的输入判断是否生成新的节点
+             *        fix #83 https://github.com/fex-team/kityminder-editor/issues/83
+             * @Editor: Naixor
+             * @Date: 2015.9.16
+             */
+            var textNodes = [].slice.call(receiverElement.childNodes);
+
+            /**
+             * @Desc: 增加setTimeout的原因:ie下receiverElement.innerHTML=""会导致后
+             * 		  面commitInputText中使用textContent报错,不要问我什么原因!
+             * @Editor: Naixor
+             * @Date: 2015.12.14
+             */
+            setTimeout(function () {
+                // 解决过大内容导致SVG窜位问题
+                receiverElement.innerHTML = "";
+            }, 0);
+            var node = minder.getSelectedNode();
+
+            textNodes = commitInputText(textNodes);
+            commitInputNode(node, textNodes);
+
+            if (node.type == 'root') {
+                var rootText = minder.getRoot().getText();
+                minder.fire('initChangeRoot', {text: rootText});
+            }
+        }
+
+        function exitInputMode() {
+            receiverElement.classList.remove('input');
+            receiver.selectAll();
+        }
+
+        function updatePosition() {
+            var planed = updatePosition;
+
+            var focusNode = minder.getSelectedNode();
+            if (!focusNode) return;
+
+            if (!planed.timer) {
+                planed.timer = setTimeout(function() {
+                    var box = focusNode.getRenderBox('TextRenderer');
+                    receiverElement.style.left = Math.round(box.x) + 'px';
+                    receiverElement.style.top = (debug.flaged ? Math.round(box.bottom + 30) : Math.round(box.y)) + 'px';
+                    //receiverElement.focus();
+                    planed.timer = 0;
+                });
+            }
+        }
+    }
+
+    return module.exports = InputRuntime;
+});

+ 184 - 0
kityminder-editor/src/runtime/jumping.js

@@ -0,0 +1,184 @@
+/**
+ * @fileOverview
+ *
+ * 根据按键控制状态机的跳转
+ *
+ * @author: techird
+ * @copyright: Baidu FEX, 2014
+ */
+define(function(require, exports, module) {
+
+    var Hotbox = require('../hotbox');
+
+
+    // Nice: http://unixpapa.com/js/key.html
+    function isIntendToInput(e) {
+        if (e.ctrlKey || e.metaKey || e.altKey) return false;
+
+        // a-zA-Z
+        if (e.keyCode >= 65 && e.keyCode <= 90) return true;
+
+        // 0-9 以及其上面的符号
+        if (e.keyCode >= 48 && e.keyCode <= 57) return true;
+        
+        // 小键盘区域 (除回车外)
+        if (e.keyCode != 108 && e.keyCode >= 96 && e.keyCode <= 111) return true;
+
+        // 小键盘区域 (除回车外)
+        // @yinheli from pull request
+        if (e.keyCode != 108 && e.keyCode >= 96 && e.keyCode <= 111) return true;
+
+        // 输入法
+        if (e.keyCode == 229 || e.keyCode === 0) return true;
+
+        return false;
+    }
+    /**
+     * @Desc: 下方使用receiver.enable()和receiver.disable()通过
+     *        修改div contenteditable属性的hack来解决开启热核后依然无法屏蔽浏览器输入的bug;
+     *        特别: win下FF对于此种情况必须要先blur在focus才能解决,但是由于这样做会导致用户
+     *             输入法状态丢失,因此对FF暂不做处理
+     * @Editor: Naixor
+     * @Date: 2015.09.14
+     */
+    function JumpingRuntime() {
+        var fsm = this.fsm;
+        var minder = this.minder;
+        var receiver = this.receiver;
+        var container = this.container;
+        var receiverElement = receiver.element;
+        var hotbox = this.hotbox;
+        var compositionLock = false;
+
+        // normal -> *
+        receiver.listen('normal', function(e) {
+            // 为了防止处理进入edit模式而丢失处理的首字母,此时receiver必须为enable
+            receiver.enable();
+            // normal -> hotbox
+            if (e.is('Space')) {
+                e.preventDefault();
+                // safari下Space触发hotbox,然而这时Space已在receiver上留下作案痕迹,因此抹掉
+                if (kity.Browser.safari) {
+                    receiverElement.innerHTML = '';
+                }
+                return fsm.jump('hotbox', 'space-trigger');
+            }
+
+            /**
+             * check
+             * @editor Naixor
+             * @Date 2015-12-2
+             */
+            switch (e.type) {
+                case 'keydown': {
+                    if (minder.getSelectedNode()) {
+                        if (isIntendToInput(e)) {
+                            return fsm.jump('input', 'user-input');
+                        };
+                    } else {
+                        receiverElement.innerHTML = '';
+                    }
+                    // normal -> normal shortcut
+                    fsm.jump('normal', 'shortcut-handle', e);
+                    break;
+                }
+                case 'keyup': {
+                    break;
+                }
+                default: {}
+            }
+        });
+
+        // hotbox -> normal
+        receiver.listen('hotbox', function(e) {
+            receiver.disable();
+            e.preventDefault();
+            var handleResult = hotbox.dispatch(e);
+            if (hotbox.state() == Hotbox.STATE_IDLE && fsm.state() == 'hotbox') {
+                return fsm.jump('normal', 'hotbox-idle');
+            }
+        });
+
+        // input => normal
+        receiver.listen('input', function(e) {
+            receiver.enable();
+            if (e.type == 'keydown') {
+                if (e.is('Enter')) {
+                    e.preventDefault();
+                    return fsm.jump('normal', 'input-commit');
+                }
+                if (e.is('Esc')) {
+                    e.preventDefault();
+                    return fsm.jump('normal', 'input-cancel');
+                }
+                if (e.is('Tab') || e.is('Shift + Tab')) {
+                    e.preventDefault();
+                }
+            } else if (e.type == 'keyup' && e.is('Esc')) {
+                e.preventDefault();
+                if (!compositionLock) {
+                    return fsm.jump('normal', 'input-cancel');
+                }
+            }
+            else if (e.type == 'compositionstart') {
+                compositionLock = true;
+            }
+            else if (e.type == 'compositionend') {
+                setTimeout(function () {
+                    compositionLock = false;
+                });
+            }
+        });
+
+        //////////////////////////////////////////////
+        /// 右键呼出热盒
+        /// 判断的标准是:按下的位置和结束的位置一致
+        //////////////////////////////////////////////
+        var downX, downY;
+        var MOUSE_RB = 2; // 右键
+
+        container.addEventListener('mousedown', function(e) {
+            if (e.button == MOUSE_RB) {
+                e.preventDefault();
+            }
+            if (fsm.state() == 'hotbox') {
+                hotbox.active(Hotbox.STATE_IDLE);
+                fsm.jump('normal', 'blur');
+            } else if (fsm.state() == 'normal' && e.button == MOUSE_RB) {
+                downX = e.clientX;
+                downY = e.clientY;
+            }
+        }, false);
+
+        container.addEventListener('mousewheel', function(e) {
+            if (fsm.state() == 'hotbox') {
+                hotbox.active(Hotbox.STATE_IDLE);
+                fsm.jump('normal', 'mousemove-blur');
+            }
+        }, false);
+
+        container.addEventListener('contextmenu', function(e) {
+            e.preventDefault();
+        });
+
+        container.addEventListener('mouseup', function(e) {
+            if (fsm.state() != 'normal') {
+                return;
+            }
+            if (e.button != MOUSE_RB || e.clientX != downX || e.clientY != downY) {
+                return;
+            }
+            if (!minder.getSelectedNode()) {
+                return;
+            }
+            fsm.jump('hotbox', 'content-menu');
+        }, false);
+
+        // 阻止热盒事件冒泡,在热盒正确执行前导致热盒关闭
+        hotbox.$element.addEventListener('mousedown', function(e) {
+            e.stopPropagation();
+        });
+    }
+
+    return module.exports = JumpingRuntime;
+});

+ 31 - 0
kityminder-editor/src/runtime/minder.js

@@ -0,0 +1,31 @@
+/**
+ * @fileOverview
+ *
+ * 脑图示例运行时
+ *
+ * @author: techird
+ * @copyright: Baidu FEX, 2014
+ */
+define(function(require, exports, module) {
+    var Minder = require('../minder');
+
+    function MinderRuntime() {
+
+        // 不使用 kityminder 的按键处理,由 ReceiverRuntime 统一处理
+        var minder = new Minder({
+            enableKeyReceiver: false,
+            enableAnimation: true
+        });
+
+        // 渲染,初始化
+        minder.renderTo(this.selector);
+        minder.setTheme(null);
+        minder.select(minder.getRoot(), true);
+        minder.execCommand('text', '中心主题');
+
+        // 导出给其它 Runtime 使用
+        this.minder = minder;
+    }
+
+    return module.exports = MinderRuntime;
+});

+ 112 - 0
kityminder-editor/src/runtime/node.js

@@ -0,0 +1,112 @@
+define(function(require, exports, module) {
+
+    function NodeRuntime() {
+        var runtime = this;
+        var minder = this.minder;
+        var hotbox = this.hotbox;
+        var fsm = this.fsm;
+
+        var main = hotbox.state('main');
+
+        var buttons = [
+            '前移:Alt+Up:ArrangeUp',
+            '下级:Tab|Insert:AppendChildNode',
+            '同级:Enter:AppendSiblingNode',
+            '后移:Alt+Down:ArrangeDown',
+            '删除:Delete|Backspace:RemoveNode',
+            '上级:Shift+Tab|Shift+Insert:AppendParentNode'
+            //'全选:Ctrl+A:SelectAll'
+        ];
+
+        var AppendLock = 0;
+
+        buttons.forEach(function(button) {
+            var parts = button.split(':');
+            var label = parts.shift();
+            var key = parts.shift();
+            var command = parts.shift();
+            main.button({
+                position: 'ring',
+                label: label,
+                key: key,
+                action: function() {
+                    if (command.indexOf('Append') === 0) {
+                        AppendLock++;
+                        minder.execCommand(command, '分支主题');
+
+                        // provide in input runtime
+                        function afterAppend () {
+                            if (!--AppendLock) {
+                                runtime.editText();
+                            }
+                            minder.off('layoutallfinish', afterAppend);
+                        }
+                        minder.on('layoutallfinish', afterAppend);
+                    } else {
+                        minder.execCommand(command);
+                        fsm.jump('normal', 'command-executed');
+                    }
+                },
+                enable: function() {
+                    return minder.queryCommandState(command) != -1;
+                }
+            });
+        });
+
+        main.button({
+            position: 'bottom',
+            label: '导入节点',
+            key: 'Alt + V',
+            enable: function() {
+                var selectedNodes = minder.getSelectedNodes();
+                return selectedNodes.length == 1;
+            },
+            action: importNodeData,
+            next: 'idle'
+        });
+
+        main.button({
+            position: 'bottom',
+            label: '导出节点',
+            key: 'Alt + C',
+            enable: function() {
+                var selectedNodes = minder.getSelectedNodes();
+                return selectedNodes.length == 1;
+            },
+            action: exportNodeData,
+            next: 'idle'
+        });
+
+        function importNodeData() {
+            minder.fire('importNodeData');
+        }
+
+        function exportNodeData() {
+            minder.fire('exportNodeData');
+        }
+
+        //main.button({
+        //    position: 'ring',
+        //    key: '/',
+        //    action: function(){
+        //        if (!minder.queryCommandState('expand')) {
+        //            minder.execCommand('expand');
+        //        } else if (!minder.queryCommandState('collapse')) {
+        //            minder.execCommand('collapse');
+        //        }
+        //    },
+        //    enable: function() {
+        //        return minder.queryCommandState('expand') != -1 || minder.queryCommandState('collapse') != -1;
+        //    },
+        //    beforeShow: function() {
+        //        if (!minder.queryCommandState('expand')) {
+        //            this.$button.children[0].innerHTML = '展开';
+        //        } else {
+        //            this.$button.children[0].innerHTML = '收起';
+        //        }
+        //    }
+        //})
+    }
+
+    return module.exports = NodeRuntime;
+});

+ 51 - 0
kityminder-editor/src/runtime/priority.js

@@ -0,0 +1,51 @@
+define(function(require, exports, module){
+
+    function PriorityRuntime() {
+        var minder = this.minder;
+        var hotbox = this.hotbox;
+
+        var main = hotbox.state('main');
+
+        main.button({
+            position: 'top',
+            label: '优先级',
+            key: 'P',
+            next: 'priority',
+            enable: function() {
+                return minder.queryCommandState('priority') != -1;
+            }
+        });
+
+        var priority = hotbox.state('priority');
+        '123456789'.replace(/./g, function(p) {
+            priority.button({
+                position: 'ring',
+                label: 'P' + p,
+                key: p,
+                action: function() {
+                    minder.execCommand('Priority', p);
+                }
+            });
+        });
+
+        priority.button({
+            position: 'center',
+            label: '移除',
+            key: 'Del',
+            action: function() {
+                minder.execCommand('Priority', 0);
+            }
+        });
+
+        priority.button({
+            position: 'top',
+            label: '返回',
+            key: 'esc',
+            next: 'back'
+        });
+
+    }
+
+    return module.exports = PriorityRuntime;
+
+});

+ 52 - 0
kityminder-editor/src/runtime/progress.js

@@ -0,0 +1,52 @@
+define(function(require, exports, module){
+
+    function ProgressRuntime() {
+        var minder = this.minder;
+        var hotbox = this.hotbox;
+
+        var main = hotbox.state('main');
+
+        main.button({
+            position: 'top',
+            label: '进度',
+            key: 'G',
+            next: 'progress',
+            enable: function() {
+                return minder.queryCommandState('progress') != -1;
+            }
+        });
+
+        var progress = hotbox.state('progress');
+        '012345678'.replace(/./g, function(p) {
+            progress.button({
+                position: 'ring',
+                label: 'G' + p,
+                key: p,
+                action: function() {
+                    minder.execCommand('Progress', parseInt(p) + 1);
+                }
+            });
+        });
+
+        progress.button({
+            position: 'center',
+            label: '移除',
+            key: 'Del',
+            action: function() {
+                minder.execCommand('Progress', 0);
+            }
+        });
+
+        progress.button({
+            position: 'top',
+            label: '返回',
+            key: 'esc',
+            next: 'back'
+        });
+
+
+    }
+
+    return module.exports = ProgressRuntime;
+
+});

+ 146 - 0
kityminder-editor/src/runtime/receiver.js

@@ -0,0 +1,146 @@
+/**
+ * @fileOverview
+ *
+ * 键盘事件接收/分发器
+ *
+ * @author: techird
+ * @copyright: Baidu FEX, 2014
+ */
+
+define(function(require, exports, module) {
+    var key = require('../tool/key');
+    var hotbox = require('hotbox');
+
+    function ReceiverRuntime() {
+        var fsm = this.fsm;
+        var minder = this.minder;
+        var me = this;
+
+        // 接收事件的 div
+        var element = document.createElement('div');
+        element.contentEditable = true;
+        /**
+         * @Desc: 增加tabindex属性使得element的contenteditable不管是trur还是false都能有focus和blur事件
+         * @Editor: Naixor
+         * @Date: 2015.09.14
+         */
+        element.setAttribute('tabindex', -1);
+        element.classList.add('receiver');
+        element.onkeydown = element.onkeypress = element.onkeyup = dispatchKeyEvent;
+        element.addEventListener('compositionstart', dispatchKeyEvent);
+        // element.addEventListener('compositionend', dispatchKeyEvent);
+        this.container.appendChild(element);
+
+        // receiver 对象
+        var receiver = {
+            element: element,
+            selectAll: function() {
+                // 保证有被选中的
+                if (!element.innerHTML) element.innerHTML = '&nbsp;';
+                var range = document.createRange();
+                var selection = window.getSelection();
+                range.selectNodeContents(element);
+                selection.removeAllRanges();
+                selection.addRange(range);
+                element.focus();
+            },
+            /**
+             * @Desc: 增加enable和disable方法用于解决热核态的输入法屏蔽问题
+             * @Editor: Naixor
+             * @Date: 2015.09.14
+             */
+            enable: function() {
+                element.setAttribute("contenteditable", true);
+            },
+            disable: function() {
+                element.setAttribute("contenteditable", false);
+            },
+            /**
+             * @Desc: hack FF下div contenteditable的光标丢失BUG
+             * @Editor: Naixor
+             * @Date: 2015.10.15
+             */
+            fixFFCaretDisappeared: function() {
+                element.removeAttribute("contenteditable");
+                element.setAttribute("contenteditable", "true");
+                element.blur();
+                element.focus();
+            },
+            /**
+             * 以此事件代替通过mouse事件来判断receiver丢失焦点的事件
+             * @editor Naixor
+             * @Date 2015-12-2
+             */
+            onblur: function (handler) {
+                element.onblur = handler;
+            }
+        };
+        receiver.selectAll();
+
+        minder.on('beforemousedown', receiver.selectAll);
+        minder.on('receiverfocus', receiver.selectAll);
+        minder.on('readonly', function() {
+            // 屏蔽minder的事件接受,删除receiver和hotbox
+            minder.disable();
+            editor.receiver.element.parentElement.removeChild(editor.receiver.element);
+            editor.hotbox.$container.removeChild(editor.hotbox.$element);
+        });
+
+        // 侦听器,接收到的事件会派发给所有侦听器
+        var listeners = [];
+
+        // 侦听指定状态下的事件,如果不传 state,侦听所有状态
+        receiver.listen = function(state, listener) {
+            if (arguments.length == 1) {
+                listener = state;
+                state = '*';
+            }
+            listener.notifyState = state;
+            listeners.push(listener);
+        };
+
+        function dispatchKeyEvent(e) {
+            e.is = function(keyExpression) {
+                var subs = keyExpression.split('|');
+                for (var i = 0; i < subs.length; i++) {
+                    if (key.is(this, subs[i])) return true;
+                }
+                return false;
+            };
+            var listener, jumpState;
+            for (var i = 0; i < listeners.length; i++) {
+
+                listener = listeners[i];
+                // 忽略不在侦听状态的侦听器
+                if (listener.notifyState != '*' && listener.notifyState != fsm.state()) {
+                    continue;
+                }
+
+                /**
+                 *
+                 * 对于所有的侦听器,只允许一种处理方式:跳转状态。
+                 * 如果侦听器确定要跳转,则返回要跳转的状态。
+                 * 每个事件只允许一个侦听器进行状态跳转
+                 * 跳转动作由侦听器自行完成(因为可能需要在跳转时传递 reason),返回跳转结果即可。
+                 * 比如:
+                 *
+                 * ```js
+                 *  receiver.listen('normal', function(e) {
+                 *      if (isSomeReasonForJumpState(e)) {
+                 *          return fsm.jump('newstate', e);
+                 *      }
+                 *  });
+                 * ```
+                 */
+                if (listener.call(null, e)) {
+                    return;
+                }
+            }
+        }
+
+        this.receiver = receiver;
+    }
+
+    return module.exports = ReceiverRuntime;
+
+});

+ 47 - 0
kityminder-editor/src/tool/debug.js

@@ -0,0 +1,47 @@
+/**
+ * @fileOverview
+ *
+ * 支持各种调试后门
+ *
+ * @author: techird
+ * @copyright: Baidu FEX, 2014
+ */
+define(function(require, exports, module) {
+    var format = require('./format');
+
+    function noop() {}
+
+    function stringHash(str) {
+        var hash = 0;
+        for (var i = 0; i < str.length; i++) {
+            hash += str.charCodeAt(i);
+        }
+        return hash;
+    }
+
+    /* global console */
+    function Debug(flag) {
+        var debugMode = this.flaged = window.location.search.indexOf(flag) != -1;
+
+        if (debugMode) {
+            var h = stringHash(flag) % 360;
+
+            var flagStyle = format(
+                'background: hsl({0}, 50%, 80%); ' +
+                'color: hsl({0}, 100%, 30%); ' +
+                'padding: 2px 3px; ' +
+                'margin: 1px 3px 0 0;' +
+                'border-radius: 2px;', h);
+
+            var textStyle = 'background: none; color: black;';
+            this.log = function() {
+                var output = format.apply(null, arguments);
+                console.log(format('%c{0}%c{1}', flag, output), flagStyle, textStyle);
+            };
+        } else {
+            this.log = noop;
+        }
+    }
+
+    return module.exports = Debug;
+});

+ 11 - 0
kityminder-editor/src/tool/format.js

@@ -0,0 +1,11 @@
+define(function(require, exports, module) {
+    function format(template, args) {
+        if (typeof(args) != 'object') {
+            args = [].slice.call(arguments, 1);
+        }
+        return String(template).replace(/\{(\w+)\}/ig, function(match, $key) {
+            return args[$key] || $key;
+        });
+    }
+    return module.exports = format;
+});

+ 54 - 0
kityminder-editor/src/tool/innertext.js

@@ -0,0 +1,54 @@
+/**
+ * @fileOverview
+ *
+ * innerText polyfill
+ *
+ * @author: techird
+ * @copyright: Baidu FEX, 2014
+ */
+
+
+define(function(require, exports, module) {
+    if ((!('innerText' in document.createElement('a'))) && ('getSelection' in window)) {
+        HTMLElement.prototype.__defineGetter__('innerText', function() {
+            var selection = window.getSelection(),
+                ranges    = [],
+                str, i;
+
+            // Save existing selections.
+            for (i = 0; i < selection.rangeCount; i++) {
+                ranges[i] = selection.getRangeAt(i);
+            }
+
+            // Deselect everything.
+            selection.removeAllRanges();
+
+            // Select `el` and all child nodes.
+            // 'this' is the element .innerText got called on
+            selection.selectAllChildren(this);
+
+            // Get the string representation of the selected nodes.
+            str = selection.toString();
+
+            // Deselect everything. Again.
+            selection.removeAllRanges();
+
+            // Restore all formerly existing selections.
+            for (i = 0; i < ranges.length; i++) {
+                selection.addRange(ranges[i]);
+            }
+
+            // Oh look, this is what we wanted.
+            // String representation of the element, close to as rendered.
+            return str;
+        });
+        HTMLElement.prototype.__defineSetter__('innerText', function(text) {
+            /**
+             * @Desc: 解决FireFox节点内容删除后text为null,出现报错的问题
+             * @Editor: Naixor
+             * @Date: 2015.9.16
+             */
+            this.innerHTML = (text || '').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\n/g, '<br>');
+        });
+    }
+});

+ 91 - 0
kityminder-editor/src/tool/jsondiff.js

@@ -0,0 +1,91 @@
+/**
+ * @fileOverview
+ *
+ *
+ *
+ * @author: techird
+ * @copyright: Baidu FEX, 2014
+ */
+
+
+define(function(require, exports, module) {
+    /*!
+    * https://github.com/Starcounter-Jack/Fast-JSON-Patch
+    * json-patch-duplex.js 0.5.0
+    * (c) 2013 Joachim Wester
+    * MIT license
+    */
+
+    var _objectKeys = (function () {
+        if (Object.keys)
+            return Object.keys;
+
+        return function (o) {
+            var keys = [];
+            for (var i in o) {
+                if (o.hasOwnProperty(i)) {
+                    keys.push(i);
+                }
+            }
+            return keys;
+        };
+    })();
+    function escapePathComponent(str) {
+        if (str.indexOf('/') === -1 && str.indexOf('~') === -1)
+            return str;
+        return str.replace(/~/g, '~0').replace(/\//g, '~1');
+    }
+    function deepClone(obj) {
+        if (typeof obj === "object") {
+            return JSON.parse(JSON.stringify(obj));
+        } else {
+            return obj;
+        }
+    }
+
+    // Dirty check if obj is different from mirror, generate patches and update mirror
+    function _generate(mirror, obj, patches, path) {
+        var newKeys = _objectKeys(obj);
+        var oldKeys = _objectKeys(mirror);
+        var changed = false;
+        var deleted = false;
+
+        for (var t = oldKeys.length - 1; t >= 0; t--) {
+            var key = oldKeys[t];
+            var oldVal = mirror[key];
+            if (obj.hasOwnProperty(key)) {
+                var newVal = obj[key];
+                if (typeof oldVal == "object" && oldVal != null && typeof newVal == "object" && newVal != null) {
+                    _generate(oldVal, newVal, patches, path + "/" + escapePathComponent(key));
+                } else {
+                    if (oldVal != newVal) {
+                        changed = true;
+                        patches.push({ op: "replace", path: path + "/" + escapePathComponent(key), value: deepClone(newVal) });
+                    }
+                }
+            } else {
+                patches.push({ op: "remove", path: path + "/" + escapePathComponent(key) });
+                deleted = true; // property has been deleted
+            }
+        }
+
+        if (!deleted && newKeys.length == oldKeys.length) {
+            return;
+        }
+
+        for (var t = 0; t < newKeys.length; t++) {
+            var key = newKeys[t];
+            if (!mirror.hasOwnProperty(key)) {
+                patches.push({ op: "add", path: path + "/" + escapePathComponent(key), value: deepClone(obj[key]) });
+            }
+        }
+    }
+
+    function compare(tree1, tree2) {
+        var patches = [];
+        _generate(tree1, tree2, patches, '');
+        return patches;
+    }
+
+    return module.exports = compare;
+});

+ 69 - 0
kityminder-editor/src/tool/key.js

@@ -0,0 +1,69 @@
+define(function(require, exports, module) {
+    var keymap = require('./keymap');
+
+    var CTRL_MASK = 0x1000;
+    var ALT_MASK = 0x2000;
+    var SHIFT_MASK = 0x4000;
+
+    function hash(unknown) {
+        if (typeof(unknown) == 'string') {
+            return hashKeyExpression(unknown);
+        }
+        return hashKeyEvent(unknown);
+    }
+    function is(a, b) {
+        return a && b && hash(a) == hash(b);
+    }
+    exports.hash = hash;
+    exports.is = is;
+
+
+    function hashKeyEvent(keyEvent) {
+        var hashCode = 0;
+        if (keyEvent.ctrlKey || keyEvent.metaKey) {
+            hashCode |= CTRL_MASK;
+        }
+        if (keyEvent.altKey) {
+            hashCode |= ALT_MASK;
+        }
+        if (keyEvent.shiftKey) {
+            hashCode |= SHIFT_MASK;
+        }
+        // Shift, Control, Alt KeyCode ignored.
+        if ([16, 17, 18, 91].indexOf(keyEvent.keyCode) === -1) {
+            /**
+             * 解决浏览器输入法状态下对keyDown的keyCode判断不准确的问题,使用keyIdentifier,
+             * 可以解决chrome和safari下的各种问题,其他浏览器依旧有问题,然而那并不影响我们对特
+             * 需判断的按键进行判断(比如Space在safari输入法态下就是229,其他的就不是)
+             * @editor Naixor
+             * @Date 2015-12-2
+             */
+            if (keyEvent.keyCode === 229 && keyEvent.keyIdentifier) {
+                return hashCode |= parseInt(keyEvent.keyIdentifier.substr(2), 16);
+            }
+            hashCode |= keyEvent.keyCode;
+        }
+        return hashCode;
+    }
+
+    function hashKeyExpression(keyExpression) {
+        var hashCode = 0;
+        keyExpression.toLowerCase().split(/\s*\+\s*/).forEach(function(name) {
+            switch(name) {
+                case 'ctrl':
+                case 'cmd':
+                    hashCode |= CTRL_MASK;
+                    break;
+                case 'alt':
+                    hashCode |= ALT_MASK;
+                    break;
+                case 'shift':
+                    hashCode |= SHIFT_MASK;
+                    break;
+                default:
+                    hashCode |= keymap[name];
+            }
+        });
+        return hashCode;
+    }
+});

+ 82 - 0
kityminder-editor/src/tool/keymap.js

@@ -0,0 +1,82 @@
+define(function(require, exports, module) {
+    var keymap = {
+
+        'Shift': 16,
+        'Control': 17,
+        'Alt': 18,
+        'CapsLock': 20,
+
+        'BackSpace': 8,
+        'Tab': 9,
+        'Enter': 13,
+        'Esc': 27,
+        'Space': 32,
+
+        'PageUp': 33,
+        'PageDown': 34,
+        'End': 35,
+        'Home': 36,
+
+        'Insert': 45,
+
+        'Left': 37,
+        'Up': 38,
+        'Right': 39,
+        'Down': 40,
+
+        'Direction': {
+            37: 1,
+            38: 1,
+            39: 1,
+            40: 1
+        },
+
+        'Del': 46,
+
+        'NumLock': 144,
+
+        'Cmd': 91,
+        'CmdFF': 224,
+        'F1': 112,
+        'F2': 113,
+        'F3': 114,
+        'F4': 115,
+        'F5': 116,
+        'F6': 117,
+        'F7': 118,
+        'F8': 119,
+        'F9': 120,
+        'F10': 121,
+        'F11': 122,
+        'F12': 123,
+
+        '`': 192,
+        '=': 187,
+        '-': 189,
+
+        '/': 191,
+        '.': 190
+    };
+
+    // 小写适配
+    for (var key in keymap) {
+        if (keymap.hasOwnProperty(key)) {
+            keymap[key.toLowerCase()] = keymap[key];
+        }
+    }
+    var aKeyCode = 65;
+    var aCharCode = 'a'.charCodeAt(0);
+
+    // letters
+    'abcdefghijklmnopqrstuvwxyz'.split('').forEach(function(letter) {
+        keymap[letter] = aKeyCode + (letter.charCodeAt(0) - aCharCode);
+    });
+
+    // numbers
+    var n = 9;
+    do {
+        keymap[n.toString()] = n + 48;
+    } while (--n);
+
+    module.exports = keymap;
+});

+ 47 - 0
kityminder-editor/ui/dialog/hyperlink/hyperlink.ctrl.js

@@ -0,0 +1,47 @@
+angular.module('kityminderEditor')
+    .controller('hyperlink.ctrl', function ($scope, $modalInstance, link) {
+
+        var urlRegex = '^(?!mailto:)(?:(?:http|https|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$';
+        $scope.R_URL = new RegExp(urlRegex, 'i');
+
+        $scope.url = link.url || '';
+        $scope.title = link.title || '';
+
+        setTimeout(function() {
+            var $linkUrl = $('#link-url');
+            $linkUrl.focus();
+            $linkUrl[0].setSelectionRange(0, $scope.url.length);
+        }, 30);
+
+        $scope.shortCut = function(e) {
+            e.stopPropagation();
+
+            if (e.keyCode == 13) {
+                $scope.ok();
+            } else if (e.keyCode == 27) {
+                $scope.cancel();
+            }
+        };
+
+        $scope.ok = function () {
+            if($scope.R_URL.test($scope.url)) {
+                $modalInstance.close({
+                    url: $scope.url,
+                    title: $scope.title
+                });
+            } else {
+                $scope.urlPassed = false;
+
+                var $linkUrl = $('#link-url');
+                $linkUrl.focus();
+                $linkUrl[0].setSelectionRange(0, $scope.url.length);
+            }
+            editor.receiver.selectAll();
+        };
+
+        $scope.cancel = function () {
+            $modalInstance.dismiss('cancel');
+            editor.receiver.selectAll();
+        };
+
+    });

+ 26 - 0
kityminder-editor/ui/dialog/hyperlink/hyperlink.tpl.html

@@ -0,0 +1,26 @@
+<div class="modal-header">
+    <h3 class="modal-title">链接</h3>
+</div>
+<div class="modal-body">
+    <form>
+        <div class="form-group" id="link-url-wrap" ng-class="{true: 'has-success', false: 'has-error'}[urlPassed]">
+            <label for="link-url">链接地址:</label>
+            <input type="text"
+                   class="form-control"
+                   ng-model="url"
+                   ng-blur="urlPassed = R_URL.test(url)"
+                   ng-focus="this.value = url"
+                   ng-keydown="shortCut($event)"
+                   id="link-url"
+                   placeholder="必填:以 http(s):// 或 ftp:// 开头">
+        </div>
+        <div class="form-group" ng-class="{'has-success' : titlePassed}">
+            <label for="link-title">提示文本:</label>
+            <input type="text" class="form-control" ng-model="title" ng-blur="titlePassed = true" id="link-title" placeholder="选填:鼠标在链接上悬停时提示的文本">
+        </div>
+    </form>
+</div>
+<div class="modal-footer">
+    <button class="btn btn-primary" ng-click="ok()">确定</button>
+    <button class="btn btn-warning" ng-click="cancel()">取消</button>
+</div>

+ 95 - 0
kityminder-editor/ui/dialog/imExportNode/imExportNode.ctrl.js

@@ -0,0 +1,95 @@
+angular.module('kityminderEditor')
+    .controller('imExportNode.ctrl', function ($scope, $modalInstance, title, defaultValue, type) {
+
+        $scope.title = title;
+
+        $scope.value = defaultValue;
+
+        $scope.type = type;
+
+        $scope.ok = function () {
+            if ($scope.value == '') {
+                return;
+            }
+            $modalInstance.close($scope.value);
+            editor.receiver.selectAll();
+        };
+
+        $scope.cancel = function () {
+            $modalInstance.dismiss('cancel');
+            editor.receiver.selectAll();
+        };
+
+        setTimeout(function() {
+            $('.single-input').focus();
+
+            $('.single-input')[0].setSelectionRange(0, defaultValue.length);
+
+        }, 30);
+
+        $scope.shortCut = function(e) {
+            e.stopPropagation();
+
+            //if (e.keyCode == 13 && e.shiftKey == false) {
+            //    $scope.ok();
+            //}
+
+            if (e.keyCode == 27) {
+                $scope.cancel();
+            }
+
+            // tab 键屏蔽默认事件 和 backspace 键屏蔽默认事件
+            if (e.keyCode == 8 && type == 'export') {
+                e.preventDefault();
+            }
+
+            if (e.keyCode == 9) {
+                e.preventDefault();
+                var $textarea = e.target;
+                var pos = getCursortPosition($textarea);
+                var str = $textarea.value;
+                $textarea.value = str.substr(0, pos) + '\t' + str.substr(pos);
+                setCaretPosition($textarea, pos + 1);
+            }
+
+        };
+
+        /*
+        * 获取 textarea 的光标位置
+        * @Author: Naixor
+        * @date: 2015.09.23
+        * */
+        function getCursortPosition (ctrl) {
+            var CaretPos = 0;	// IE Support
+            if (document.selection) {
+                ctrl.focus ();
+                var Sel = document.selection.createRange ();
+                Sel.moveStart ('character', -ctrl.value.length);
+                CaretPos = Sel.text.length;
+            }
+            // Firefox support
+            else if (ctrl.selectionStart || ctrl.selectionStart == '0') {
+                CaretPos = ctrl.selectionStart;
+            }
+            return (CaretPos);
+        }
+
+        /*
+         * 设置 textarea 的光标位置
+         * @Author: Naixor
+         * @date: 2015.09.23
+         * */
+        function setCaretPosition(ctrl, pos){
+            if(ctrl.setSelectionRange) {
+                ctrl.focus();
+                ctrl.setSelectionRange(pos,pos);
+            } else if (ctrl.createTextRange) {
+                var range = ctrl.createTextRange();
+                range.collapse(true);
+                range.moveEnd('character', pos);
+                range.moveStart('character', pos);
+                range.select();
+            }
+        }
+
+    });

+ 16 - 0
kityminder-editor/ui/dialog/imExportNode/imExportNode.tpl.html

@@ -0,0 +1,16 @@
+<div class="modal-header">
+    <h3 class="modal-title">{{ title }}</h3>
+</div>
+<div class="modal-body">
+    <textarea type="text"
+              class="form-control single-input"
+              rows="8"
+              ng-keydown="shortCut($event);"
+              ng-model="value"
+              ng-readonly="type === 'export'">
+    </textarea>
+</div>
+<div class="modal-footer">
+    <button class="btn btn-primary" ng-click="ok()" ng-disabled="type === 'import' && value == ''">OK</button>
+    <button class="btn btn-warning" ng-click="cancel()">Cancel</button>
+</div>

+ 114 - 0
kityminder-editor/ui/dialog/image/image.ctrl.js

@@ -0,0 +1,114 @@
+angular.module('kityminderEditor')
+    .controller('image.ctrl', ['$http', '$scope', '$modalInstance', 'image', 'server', function($http, $scope, $modalInstance, image, server) {
+
+        $scope.data = {
+            list: [],
+            url: image.url || '',
+            title: image.title || '',
+            R_URL: /^https?\:\/\/\w+/
+        };
+
+        setTimeout(function() {
+            var $imageUrl = $('#image-url');
+            $imageUrl.focus();
+            $imageUrl[0].setSelectionRange(0, $scope.data.url.length);
+        }, 300);
+
+
+        // 搜索图片按钮点击事件
+        $scope.searchImage = function() {
+            $scope.list = [];
+
+            getImageData()
+                .success(function(json) {
+                    if(json && json.data) {
+                        for(var i = 0; i < json.data.length; i++) {
+                            if(json.data[i].objURL) {
+                                $scope.list.push({
+                                    title: json.data[i].fromPageTitleEnc,
+                                    src: json.data[i].middleURL,
+                                    url: json.data[i].middleURL
+                                });
+                            }
+                        }
+                    }
+                })
+                .error(function() {
+
+                });
+        };
+
+        // 选择图片的鼠标点击事件
+        $scope.selectImage = function($event) {
+            var targetItem = $('#img-item'+ (this.$index));
+            var targetImg = $('#img-'+ (this.$index));
+
+            targetItem.siblings('.selected').removeClass('selected');
+            targetItem.addClass('selected');
+
+            $scope.data.url = targetImg.attr('src');
+            $scope.data.title = targetImg.attr('alt');
+        };
+
+        // 自动上传图片,后端需要直接返回图片 URL
+        $scope.uploadImage = function() {
+            var fileInput = $('#upload-image');
+            if (!fileInput.val()) {
+                return;
+            }
+            if (/^.*\.(jpg|JPG|jpeg|JPEG|gif|GIF|png|PNG)$/.test(fileInput.val())) {
+                var file = fileInput[0].files[0];
+                return server.uploadImage(file).then(function (json) {
+                    var resp = json.data;
+                    if (resp.errno === 0) {
+                        $scope.data.url = resp.data.url;
+                    }
+                });
+            } else {
+                alert("后缀只能是 jpg、gif 及 png");
+            }
+        };
+
+        $scope.shortCut = function(e) {
+            e.stopPropagation();
+
+            if (e.keyCode == 13) {
+                $scope.ok();
+            } else if (e.keyCode == 27) {
+                $scope.cancel();
+            }
+        };
+
+        $scope.ok = function () {
+            if($scope.data.R_URL.test($scope.data.url)) {
+                $modalInstance.close({
+                    url: $scope.data.url,
+                    title: $scope.data.title
+                });
+            } else {
+                $scope.urlPassed = false;
+
+                var $imageUrl = $('#image-url');
+                if ($imageUrl) {
+                    $imageUrl.focus();
+                    $imageUrl[0].setSelectionRange(0, $scope.data.url.length);
+                }
+
+            }
+
+            editor.receiver.selectAll();
+        };
+
+        $scope.cancel = function () {
+            $modalInstance.dismiss('cancel');
+            editor.receiver.selectAll();
+        };
+
+        function getImageData() {
+            var key = $scope.data.searchKeyword2;
+            var currentTime = new Date();
+            var url = 'http://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&ct=201326592&fp=result&queryWord='+ key +'&cl=2&lm=-1&ie=utf-8&oe=utf-8&st=-1&ic=0&word='+ key +'&face=0&istype=2&nc=1&pn=60&rn=60&gsm=3c&'+ currentTime.getTime() +'=&callback=JSON_CALLBACK';
+
+            return $http.jsonp(url);
+        }
+    }]);

+ 69 - 0
kityminder-editor/ui/dialog/image/image.tpl.html

@@ -0,0 +1,69 @@
+<div class="modal-header">
+    <h3 class="modal-title">图片</h3>
+</div>
+<div class="modal-body">
+    <tabset>
+        <tab heading="图片搜索">
+            <form class="form-inline">
+                <div class="form-group">
+                    <label for="search-keyword">关键词:</label>
+                    <input type="text" class="form-control" ng-model="data.searchKeyword2" id="search-keyword" placeholder="请输入搜索的关键词">
+                </div>
+                <button class="btn btn-primary" ng-click="searchImage()">百度一下</button>
+            </form>
+            <div class="search-result" id="search-result">
+                <ul>
+                    <li ng-repeat="image in list" id="{{ 'img-item' + $index }}" ng-class="{'selected' : isSelected}" ng-click="selectImage($event)">
+                        <img id="{{ 'img-' + $index }}" ng-src="{{ image.src || '' }}" alt="{{ image.title }}" onerror="this.parentNode.removeChild(this)" />
+                        <span>{{ image.title }}</span>
+                    </li>
+                </ul>
+            </div>
+        </tab>
+        <tab heading="外链图片">
+            <form>
+                <div class="form-group" ng-class="{true: 'has-success', false: 'has-error'}[urlPassed]">
+                    <label for="image-url">链接地址:</label>
+                    <input type="text"
+                           class="form-control"
+                           ng-model="data.url"
+                           ng-blur="urlPassed = data.R_URL.test(data.url)"
+                           ng-focus="this.value = data.url"
+                           ng-keydown="shortCut($event)"
+                           id="image-url"
+                           placeholder="必填:以 http(s):// 开头">
+                </div>
+                <div class="form-group" ng-class="{'has-success' : titlePassed}">
+                    <label for="image-title">提示文本:</label>
+                    <input type="text" class="form-control" ng-model="data.title" ng-blur="titlePassed = true" id="image-title" placeholder="选填:鼠标在图片上悬停时提示的文本">
+                </div>
+                <div class="form-group">
+                    <label for="image-preview">图片预览:</label>
+                    <img class="image-preview" id="image-preview" ng-src="{{ data.url }}" alt="{{ data.title }}"/>
+                </div>
+            </form>
+        </tab>
+        <tab heading="上传图片" active="true">
+            <form>
+                <div class="form-group">
+                    <!-- 这里不能用 ng-change -->
+                    <input type="file" name="upload-image" id="upload-image" class="upload-image" accept=".jpg,.JPG,jpeg,JPEG,.png,.PNG,.gif,.GIF" onchange="angular.element(this).scope().uploadImage()"/>
+                    <label for="upload-image" class="btn btn-primary"><span>选择文件&hellip;</span></label>
+                </div>
+                <div class="form-group" ng-class="{'has-success' : titlePassed}">
+                    <label for="image-title">提示文本:</label>
+                    <input type="text" class="form-control" ng-model="data.title" ng-blur="titlePassed = true" id="image-title" placeholder="选填:鼠标在图片上悬停时提示的文本">
+                </div>
+                <div class="form-group">
+                    <label for="image-preview">图片预览:</label>
+                    <img class="image-preview" id="image-preview" ng-src="{{ data.url }}" title="{{ data.title }}" alt="{{ data.title }}"/>
+                </div>
+            </form>
+        </tab>
+    </tabset>
+
+</div>
+<div class="modal-footer">
+    <button class="btn btn-primary" ng-click="ok()">确定</button>
+    <button class="btn btn-warning" ng-click="cancel()">取消</button>
+</div>

+ 31 - 0
kityminder-editor/ui/directive/appendNode/appendNode.directive.js

@@ -0,0 +1,31 @@
+angular.module('kityminderEditor')
+    .directive('appendNode', ['commandBinder', function(commandBinder) {
+        return {
+            restrict: 'E',
+            templateUrl: 'ui/directive/appendNode/appendNode.html',
+            scope: {
+                minder: '='
+            },
+            replace: true,
+            link: function($scope) {
+                var minder = $scope.minder;
+
+                commandBinder.bind(minder, 'appendchildnode', $scope)
+
+                $scope.execCommand = function(command) {
+                    minder.execCommand(command, '分支主题');
+                    editText();
+                };
+
+                function editText() {
+                    var receiverElement = editor.receiver.element;
+                    var fsm = editor.fsm;
+                    var receiver = editor.receiver;
+
+                    receiverElement.innerText = minder.queryCommandValue('text');
+                    fsm.jump('input', 'input-request');
+                    receiver.selectAll();
+                }
+            }
+        }
+    }]);

+ 23 - 0
kityminder-editor/ui/directive/appendNode/appendNode.html

@@ -0,0 +1,23 @@
+<div class="km-btn-group append-group">
+    <div class="km-btn-item append-child-node"
+         ng-disabled="minder.queryCommandState('AppendChildNode') === -1"
+         ng-click="minder.queryCommandState('AppendChildNode') === -1 || execCommand('AppendChildNode')"
+         title="{{ 'appendchildnode' | lang:'ui/command' }}">
+        <i class="km-btn-icon"></i>
+        <span class="km-btn-caption">{{ 'appendchildnode' | lang:'ui/command' }}</span>
+    </div>
+    <div class="km-btn-item append-parent-node"
+         ng-disabled="minder.queryCommandState('AppendParentNode') === -1"
+         ng-click="minder.queryCommandState('AppendParentNode') === -1 || execCommand('AppendParentNode')"
+         title="{{ 'appendparentnode' | lang:'ui/command' }}">
+        <i class="km-btn-icon"></i>
+        <span class="km-btn-caption">{{ 'appendparentnode' | lang:'ui/command' }}</span>
+    </div>
+    <div class="km-btn-item append-sibling-node"
+         ng-disabled="minder.queryCommandState('AppendSiblingNode') === -1"
+         ng-click="minder.queryCommandState('AppendSiblingNode') === -1 ||execCommand('AppendSiblingNode')"
+         title="{{ 'appendsiblingnode' | lang:'ui/command' }}">
+        <i class="km-btn-icon"></i>
+        <span class="km-btn-caption">{{ 'appendsiblingnode' | lang:'ui/command' }}</span>
+    </div>
+</div>

+ 16 - 0
kityminder-editor/ui/directive/arrange/arrange.directive.js

@@ -0,0 +1,16 @@
+angular.module('kityminderEditor')
+    .directive('arrange', ['commandBinder', function(commandBinder) {
+        return {
+            restrict: 'E',
+            templateUrl: 'ui/directive/arrange/arrange.html',
+            scope: {
+                minder: '='
+            },
+            replace: true,
+            link: function($scope) {
+                var minder = $scope.minder;
+
+                //commandBinder.bind(minder, 'priority', $scope);
+            }
+        }
+    }]);

+ 16 - 0
kityminder-editor/ui/directive/arrange/arrange.html

@@ -0,0 +1,16 @@
+<div class="km-btn-group arrange-group">
+    <div class="km-btn-item arrange-up"
+         ng-disabled="minder.queryCommandState('ArrangeUp') === -1"
+         ng-click="minder.queryCommandState('ArrangeUp') === -1 || minder.execCommand('ArrangeUp')"
+         title="{{ 'arrangeup' | lang:'ui/command' }}">
+        <i class="km-btn-icon"></i>
+        <span class="km-btn-caption">{{ 'arrangeup' | lang:'ui/command' }}</span>
+    </div>
+    <div class="km-btn-item arrange-down"
+         ng-disabled="minder.queryCommandState('ArrangeDown') === -1"
+         ng-click="minder.queryCommandState('ArrangeDown') === -1 || minder.execCommand('ArrangeDown');"
+         title="{{ 'arrangedown' | lang:'ui/command' }}">
+        <i class="km-btn-icon"></i>
+        <span class="km-btn-caption">{{ 'arrangedown' | lang:'ui/command' }}</span>
+    </div>
+</div>

+ 33 - 0
kityminder-editor/ui/directive/colorPanel/colorPanel.directive.js

@@ -0,0 +1,33 @@
+angular.module('kityminderEditor')
+	.directive('colorPanel', function() {
+		return {
+			restrict: 'E',
+			templateUrl: 'ui/directive/colorPanel/colorPanel.html',
+			scope: {
+				minder: '='
+			},
+            replace: true,
+			link: function(scope) {
+
+				var minder = scope.minder;
+				var currentTheme = minder.getThemeItems();
+
+				scope.$on('colorPicked', function(event, color) {
+                    event.stopPropagation();
+					scope.bgColor = color;
+					minder.execCommand('background', color);
+				});
+
+				scope.setDefaultBg = function() {
+                    var currentNode = minder.getSelectedNode();
+                    var bgColor = minder.getNodeStyle(currentNode, 'background');
+
+                    // 有可能是 kity 的颜色类
+                    return typeof bgColor === 'object' ? bgColor.toHEX() : bgColor;
+                };
+
+                scope.bgColor = scope.setDefaultBg() || '#fff';
+
+			}
+		}
+	});

+ 16 - 0
kityminder-editor/ui/directive/colorPanel/colorPanel.html

@@ -0,0 +1,16 @@
+<div class="bg-color-wrap">
+        <span class="quick-bg-color"
+              ng-click="minder.queryCommandState('background') === -1 || minder.execCommand('background', bgColor)"
+              ng-disabled="minder.queryCommandState('background') === -1"></span>
+		<span color-picker
+              class="bg-color"
+              set-color="setDefaultBg()"
+              ng-disabled="minder.queryCommandState('background') === -1">
+            <span class="caret"></span>
+        </span>
+        <span class="bg-color-preview"
+              ng-style="{ 'background-color': bgColor }"
+              ng-click="minder.queryCommandState('background') === -1 || minder.execCommand('background', bgColor)"
+              ng-disabled="minder.queryCommandState('background') === -1"></span>
+
+</div>

+ 15 - 0
kityminder-editor/ui/directive/expandLevel/expandLevel.directive.js

@@ -0,0 +1,15 @@
+angular.module('kityminderEditor')
+    .directive('expandLevel', function() {
+        return {
+            restrict: 'E',
+            templateUrl: 'ui/directive/expandLevel/expandLevel.html',
+            scope: {
+                minder: '='
+            },
+            replace: true,
+            link: function($scope) {
+
+                $scope.levels = [1, 2, 3, 4, 5, 6];
+            }
+        }
+    });

+ 21 - 0
kityminder-editor/ui/directive/expandLevel/expandLevel.html

@@ -0,0 +1,21 @@
+<div class="btn-group-vertical" dropdown is-open="isopen">
+    <button type="button"
+            class="btn btn-default expand"
+            title="{{ 'expandtoleaf' | lang:'ui' }}"
+            ng-class="{'active': isopen}"
+            ng-click="minder.execCommand('ExpandToLevel', 9999)"></button>
+    <button type="button"
+            class="btn btn-default expand-caption dropdown-toggle"
+            title="{{ 'expandtoleaf' | lang:'ui' }}"
+            dropdown-toggle>
+        <span class="caption">{{ 'expandtoleaf' | lang:'ui' }}</span>
+        <span class="caret"></span>
+        <span class="sr-only">{{ 'expandtoleaf' | lang:'ui' }}</span>
+    </button>
+    <ul class="dropdown-menu" role="menu">
+        <li ng-repeat="level in levels">
+            <a href
+               ng-click="minder.execCommand('ExpandToLevel', level)">{{ 'expandtolevel' + level  | lang:'ui/command' }}</a>
+        </li>
+    </ul>
+</div>

+ 83 - 0
kityminder-editor/ui/directive/fontOperator/fontOperator.directive.js

@@ -0,0 +1,83 @@
+angular.module('kityminderEditor')
+	.directive('fontOperator', function() {
+		return {
+			restrict: 'E',
+			templateUrl: 'ui/directive/fontOperator/fontOperator.html',
+			scope: {
+				minder: '='
+			},
+            replace: true,
+			link: function(scope) {
+				var minder = scope.minder;
+				var currentTheme = minder.getThemeItems();
+
+				scope.fontSizeList = [10, 12, 16, 18, 24, 32, 48];
+                scope.fontFamilyList = [{
+                    name: '宋体',
+                    val: '宋体,SimSun'
+                }, {
+                    name: '微软雅黑',
+                    val: '微软雅黑,Microsoft YaHei'
+                }, {
+                    name: '楷体',
+                    val: '楷体,楷体_GB2312,SimKai'
+                }, {
+                    name: '黑体',
+                    val: '黑体, SimHei'
+                }, {
+                    name: '隶书',
+                    val: '隶书, SimLi'
+                }, {
+                    name: 'Andale Mono',
+                    val: 'andale mono'
+                }, {
+                    name: 'Arial',
+                    val: 'arial,helvetica,sans-serif'
+                }, {
+                    name: 'arialBlack',
+                    val: 'arial black,avant garde'
+                }, {
+                    name: 'Comic Sans Ms',
+                    val: 'comic sans ms'
+                }, {
+                    name: 'Impact',
+                    val: 'impact,chicago'
+                }, {
+                    name: 'Times New Roman',
+                    val: 'times new roman'
+                }, {
+                    name: 'Sans-Serif',
+                    val: 'sans-serif'
+                }];
+
+                scope.$on('colorPicked', function(event, color) {
+                    event.stopPropagation();
+
+                    scope.foreColor = color;
+                    minder.execCommand('forecolor', color);
+                });
+
+                scope.setDefaultColor = function() {
+                    var currentNode = minder.getSelectedNode();
+                    var fontColor = minder.getNodeStyle(currentNode, 'color');
+
+                    // 有可能是 kity 的颜色类
+                    return typeof fontColor === 'object' ? fontColor.toHEX() : fontColor;
+                };
+
+                scope.foreColor = scope.setDefaultColor() || '#000';
+
+                scope.getFontfamilyName = function(val) {
+                    var fontName = '';
+                    scope.fontFamilyList.forEach(function(ele, idx, arr) {
+                        if (ele.val === val) {
+                            fontName = ele.name;
+                            return '';
+                        }
+                    });
+
+                    return fontName;
+                }
+			}
+		}
+	});

+ 51 - 0
kityminder-editor/ui/directive/fontOperator/fontOperator.html

@@ -0,0 +1,51 @@
+<div class="font-operator">
+    <div class="dropdown font-family-list" dropdown>
+        <div class="dropdown-toggle current-font-item" dropdown-toggle ng-disabled="minder.queryCommandState('fontfamily') === -1">
+            <a href class="current-font-family"  title="{{ 'fontfamily' | lang: 'ui' }}">{{ getFontfamilyName(minder.queryCommandValue('fontfamily')) || '字体' }}</a>
+            <span class="caret"></span>
+        </div>
+        <ul class="dropdown-menu font-list">
+            <li ng-repeat="f in fontFamilyList" class="font-item-wrap">
+                <a ng-click="minder.execCommand('fontfamily', f.val)" class="font-item" ng-class="{ 'font-item-selected' : f == minder.queryCommandValue('fontfamily') }" ng-style="{'font-family': f.val }">{{ f.name }}</a>
+            </li>
+        </ul>
+    </div>
+    <div class="dropdown font-size-list" dropdown>
+        <div class="dropdown-toggle current-font-item" dropdown-toggle ng-disabled="minder.queryCommandState('fontsize') === -1">
+            <a href class="current-font-size"  title="{{ 'fontsize' | lang: 'ui' }}">{{ minder.queryCommandValue('fontsize') || '字号' }}</a>
+            <span class="caret"></span>
+        </div>
+        <ul class="dropdown-menu font-list">
+            <li ng-repeat="f in fontSizeList" class="font-item-wrap">
+                <a ng-click="minder.execCommand('fontsize', f)" class="font-item" ng-class="{ 'font-item-selected' : f == minder.queryCommandValue('fontsize') }" ng-style="{'font-size': f + 'px'}">{{ f }}</a>
+            </li>
+        </ul>
+    </div>
+    <span class="s-btn-icon font-bold"
+          ng-click="minder.queryCommandState('bold') === -1 || minder.execCommand('bold')"
+          ng-class="{'font-bold-selected' : minder.queryCommandState('bold') == 1}"
+          ng-disabled="minder.queryCommandState('bold') === -1"></span>
+    <span class="s-btn-icon font-italics"
+          ng-click="minder.queryCommandState('italic') === -1 || minder.execCommand('italic')"
+          ng-class="{'font-italics-selected' : minder.queryCommandState('italic') == 1}"
+          ng-disabled="minder.queryCommandState('italic') === -1">
+    </span>
+    <div class="font-color-wrap">
+        <span class="quick-font-color"
+              ng-click="minder.queryCommandState('forecolor') === -1 || minder.execCommand('forecolor', foreColor)"
+              ng-disabled="minder.queryCommandState('forecolor') === -1">A</span>
+		<span color-picker
+              class="font-color"
+              set-color="setDefaultColor()"
+              ng-disabled="minder.queryCommandState('forecolor') === -1">
+            <span class="caret"></span>
+        </span>
+        <span class="font-color-preview"
+              ng-style="{ 'background-color': foreColor }"
+              ng-click="minder.queryCommandState('forecolor') === -1 || minder.execCommand('forecolor', foreColor)"
+              ng-disabled="minder.queryCommandState('forecolor') === -1"></span>
+
+    </div>
+    <color-panel minder="minder" class="inline-directive"></color-panel>
+
+</div>

+ 35 - 0
kityminder-editor/ui/directive/hyperLink/hyperLink.directive.js

@@ -0,0 +1,35 @@
+angular.module('kityminderEditor')
+    .directive('hyperLink', ['$modal', function($modal) {
+        return {
+            restrict: 'E',
+            templateUrl: 'ui/directive/hyperLink/hyperLink.html',
+            scope: {
+                minder: '='
+            },
+            replace: true,
+            link: function($scope) {
+                var minder = $scope.minder;
+
+                $scope.addHyperlink = function() {
+
+                    var link = minder.queryCommandValue('HyperLink');
+
+                    var hyperlinkModal = $modal.open({
+                        animation: true,
+                        templateUrl: 'ui/dialog/hyperlink/hyperlink.tpl.html',
+                        controller: 'hyperlink.ctrl',
+                        size: 'md',
+                        resolve: {
+                            link: function() {
+                                return link;
+                            }
+                        }
+                    });
+
+                    hyperlinkModal.result.then(function(result) {
+                        minder.execCommand('HyperLink', result.url, result.title || '');
+                    });
+                }
+            }
+        }
+    }]);

+ 27 - 0
kityminder-editor/ui/directive/hyperLink/hyperLink.html

@@ -0,0 +1,27 @@
+<div class="btn-group-vertical" dropdown is-open="isopen">
+    <button type="button"
+            class="btn btn-default hyperlink"
+            title="{{ 'link' | lang:'ui' }}"
+            ng-class="{'active': isopen}"
+            ng-click="addHyperlink()"
+            ng-disabled="minder.queryCommandState('HyperLink') === -1"></button>
+    <button type="button"
+            class="btn btn-default hyperlink-caption dropdown-toggle"
+            ng-disabled="minder.queryCommandState('HyperLink') === -1"
+            title="{{ 'link' | lang:'ui' }}"
+            dropdown-toggle>
+        <span class="caption">{{ 'link' | lang:'ui' }}</span>
+        <span class="caret"></span>
+        <span class="sr-only">{{ 'link' | lang:'ui' }}</span>
+    </button>
+    <ul class="dropdown-menu" role="menu">
+        <li>
+            <a href
+               ng-click="addHyperlink()">{{ 'insertlink' | lang:'ui' }}</a>
+        </li>
+        <li>
+            <a href
+               ng-click="minder.execCommand('HyperLink', null)">{{ 'removelink' | lang:'ui' }}</a>
+        </li>
+    </ul>
+</div>

+ 35 - 0
kityminder-editor/ui/directive/imageBtn/imageBtn.directive.js

@@ -0,0 +1,35 @@
+angular.module('kityminderEditor')
+    .directive('imageBtn', ['$modal', function($modal) {
+        return {
+            restrict: 'E',
+            templateUrl: 'ui/directive/imageBtn/imageBtn.html',
+            scope: {
+                minder: '='
+            },
+            replace: true,
+            link: function($scope) {
+                var minder = $scope.minder;
+
+                $scope.addImage = function() {
+
+                    var image = minder.queryCommandValue('image');
+
+                    var imageModal = $modal.open({
+                        animation: true,
+                        templateUrl: 'ui/dialog/image/image.tpl.html',
+                        controller: 'image.ctrl',
+                        size: 'md',
+                        resolve: {
+                            image: function() {
+                                return image;
+                            }
+                        }
+                    });
+
+                    imageModal.result.then(function(result) {
+                        minder.execCommand('image', result.url, result.title || '');
+                    });
+                }
+            }
+        }
+    }]);

+ 27 - 0
kityminder-editor/ui/directive/imageBtn/imageBtn.html

@@ -0,0 +1,27 @@
+<div class="btn-group-vertical" dropdown is-open="isopen">
+    <button type="button"
+            class="btn btn-default image-btn"
+            title="{{ 'image' | lang:'ui' }}"
+            ng-class="{'active': isopen}"
+            ng-click="addImage()"
+            ng-disabled="minder.queryCommandState('Image') === -1"></button>
+    <button type="button"
+            class="btn btn-default image-btn-caption dropdown-toggle"
+            ng-disabled="minder.queryCommandState('Image') === -1"
+            title="{{ 'image' | lang:'ui' }}"
+            dropdown-toggle>
+        <span class="caption">{{ 'image' | lang:'ui' }}</span>
+        <span class="caret"></span>
+        <span class="sr-only">{{ 'image' | lang:'ui' }}</span>
+    </button>
+    <ul class="dropdown-menu" role="menu">
+        <li>
+            <a href
+               ng-click="addImage()">{{ 'insertimage' | lang:'ui' }}</a>
+        </li>
+        <li>
+            <a href
+               ng-click="minder.execCommand('Image', '')">{{ 'removeimage' | lang:'ui' }}</a>
+        </li>
+    </ul>
+</div>

+ 71 - 0
kityminder-editor/ui/directive/kityminderEditor/kityminderEditor.directive.js

@@ -0,0 +1,71 @@
+angular.module('kityminderEditor')
+	.directive('kityminderEditor', ['config', 'minder.service', 'revokeDialog', function(config, minderService, revokeDialog) {
+		return {
+			restrict: 'EA',
+			templateUrl: 'ui/directive/kityminderEditor/kityminderEditor.html',
+			replace: true,
+			scope: {
+				onInit: '&'
+			},
+			link: function(scope, element, attributes) {
+
+				var $minderEditor = element.children('.minder-editor')[0];
+
+				function onInit(editor, minder) {
+					scope.onInit({
+						editor: editor,
+						minder: minder
+					});
+
+					minderService.executeCallback();
+				}
+
+				if (typeof(seajs) != 'undefined') {
+					/* global seajs */
+					seajs.config({
+						base: './src'
+					});
+
+					define('demo', function(require) {
+						var Editor = require('editor');
+
+						var editor = window.editor = new Editor($minderEditor);
+
+						if (window.localStorage.__dev_minder_content) {
+							editor.minder.importJson(JSON.parse(window.localStorage.__dev_minder_content));
+						}
+
+						editor.minder.on('contentchange', function() {
+							window.localStorage.__dev_minder_content = JSON.stringify(editor.minder.exportJson());
+						});
+
+						window.minder = window.km = editor.minder;
+
+						scope.editor = editor;
+						scope.minder = minder;
+                        scope.config = config.get();
+
+                        //scope.minder.setDefaultOptions(scope.config);
+						scope.$apply();
+
+						onInit(editor, minder);
+					});
+
+					seajs.use('demo');
+
+				} else if (window.kityminder && window.kityminder.Editor) {
+					var editor = new kityminder.Editor($minderEditor);
+
+					window.editor = scope.editor = editor;
+					window.minder = scope.minder = editor.minder;
+
+                    scope.config = config.get();
+
+                    //scope.minder.setDefaultOptions(config.getConfig());
+
+                    onInit(editor, editor.minder);
+                }
+
+			}
+		}
+	}]);

+ 8 - 0
kityminder-editor/ui/directive/kityminderEditor/kityminderEditor.html

@@ -0,0 +1,8 @@
+<div class="minder-editor-container">
+    <div class="top-tab" top-tab="minder" editor="editor" ng-if="minder" ></div>
+    <div search-box minder="minder" ng-if="minder"></div>
+	<div class="minder-editor"></div>
+    <div class="km-note" note-editor minder="minder" ng-if="minder"></div>
+    <div class="note-previewer" note-previewer ng-if="minder"></div>
+    <div class="navigator" navigator minder="minder" ng-if="minder"></div>
+</div>

+ 34 - 0
kityminder-editor/ui/directive/kityminderViewer/kityminderViewer.directive.js

@@ -0,0 +1,34 @@
+angular.module('kityminderEditor')
+    .directive('kityminderViewer', ['config', 'minder.service', function(config, minderService) {
+        return {
+            restrict: 'EA',
+            templateUrl: 'ui/directive/kityminderViewer/kityminderViewer.html',
+            replace: true,
+            scope: {
+                onInit: '&'
+            },
+            link: function(scope, element, attributes) {
+
+                var $minderEditor = element.children('.minder-viewer')[0];
+
+                function onInit(editor, minder) {
+                    scope.onInit({
+                        editor: editor,
+                        minder: minder
+                    });
+
+                    minderService.executeCallback();
+                }
+
+                if (window.kityminder && window.kityminder.Editor) {
+                    var editor = new kityminder.Editor($minderEditor);
+
+                    window.editor = scope.editor = editor;
+                    window.minder = scope.minder = editor.minder;
+
+                    onInit(editor, editor.minder);
+                }
+
+            }
+        }
+    }]);

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott