diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7176f4b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+**.DS_Store
diff --git a/CNAME b/CNAME
new file mode 100644
index 0000000..e6fbf56
--- /dev/null
+++ b/CNAME
@@ -0,0 +1 @@
+term.syui.ai
diff --git a/css/terminal-nyan.css b/css/terminal-nyan.css
new file mode 100644
index 0000000..c63f825
--- /dev/null
+++ b/css/terminal-nyan.css
@@ -0,0 +1,8 @@
+#window {
+ -moz-box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.75);
+ -webkit-box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.75);
+ background: #333;
+ height: 100%;
+ overflow: hidden;
+ width: 100%;
+}
diff --git a/css/terminal.css b/css/terminal.css
new file mode 100644
index 0000000..1b9950b
--- /dev/null
+++ b/css/terminal.css
@@ -0,0 +1,486 @@
+html {
+ -webkit-font-smoothing: antialiased;
+ -moz-font-smoothing: antialiased;
+ -ms-font-smoothing: antialiased;
+ -o-font-smoothing: antialiased;
+}
+body {
+ background-attachment: fixed;
+ -webkit-background-size: cover;
+ background-size: cover;
+ color: #444;
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
+
+#window {
+ margin-left: auto;
+ margin-right: auto;
+ background: #333;
+ border-radius: 4px;
+ overflow: hidden;
+ width: 100%;
+ height: 100%;
+ margin:5px;
+}
+
+#topbar {
+ width: 100%;
+ height: 21px;
+ font-size: 16px;
+ font-family: "Myriad Pro", sans-serif;
+ text-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25);
+}
+#topbar ul li {
+ float: left;
+ padding: 0 10px;
+ height: 21px;
+ line-height: 24px;
+}
+#topbar ul li:first-child {
+ font-size: 20px;
+ line-height: 26px;
+ margin-left: 5px;
+}
+#topbar ul li:nth-child(2) {
+ font-family: "Myriad-Semi", sans-serif;
+}
+#topbar ul li:active {
+ background-image: -webkit-gradient(linear, left bottom, left top, color-stop(1, #4a82ff), color-stop(0, #0052fc));
+ color: #fff;
+ text-shadow: none;
+}
+#toolbar {
+ width: 100%;
+ height: 25px;
+ background: #ccc;
+}
+#toolbar .top {
+ float: left;
+ width: 100%;
+ height: 23px;
+}
+#toolbar .bottom {
+ float: left;
+ width: 100%;
+ height: 30px;
+}
+#toolbar #lights {
+ float: left;
+ position: relative;
+ top: 6px;
+ left: 7px;
+}
+.light {
+ float: left;
+ width: 14px;
+ height: 14px;
+ border-radius: 14px;
+ -webkit-box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.5), 0px 0px 3px #000 inset;
+ -moz-box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.5), 0px 0px 3px #000 inset;
+ box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.5), 0px 0px 3px #000 inset;
+ overflow: hidden;
+}
+#lights:hover .glyph {
+ opacity: 1;
+ cursor: default;
+}
+.light .shine {
+ width: 4px;
+ height: 3px;
+ border-radius: 10px;
+ background: -moz-radial-gradient(center, ellipse cover, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
+ background-image: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, rgba(255, 255, 255, 1)), color-stop(100%, rgba(255, 255, 255, 0)));
+ background: -webkit-radial-gradient(center, ellipse cover, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
+ background: -o-radial-gradient(center, ellipse cover, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
+ background: -ms-radial-gradient(center, ellipse cover, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
+ background: radial-gradient(center, ellipse cover, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
+}
+.light .glow {
+ width: 14px;
+ height: 8px;
+ background-image: -webkit-gradient(radial, center bottom, 0, center center, 5, from(rgba(255, 255, 255, 0.75)), to(rgba(255, 255, 255, 0)));
+ background: 0px 0px -moz-radial-gradient(bottom, cover, rgba(255, 255, 255, 0.70) 0%, rgba(255, 255, 255, 0) 80%);
+}
+.red {
+ background: #f41b16;
+ background: -moz-linear-gradient(top, #f41b16 0%, #fc7471 100%);
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f41b16), color-stop(100%, #fc7471));
+ background: -webkit-linear-gradient(top, #f41b16 0%, #fc7471 100%);
+ background: -o-linear-gradient(top, #f41b16 0%, #fc7471 100%);
+ background: -ms-linear-gradient(top, #f41b16 0%, #fc7471 100%);
+ background: linear-gradient(top, #f41b16 0%, #fc7471 100%);
+}
+.red:active {
+ background: #972f2e;
+ background: -moz-linear-gradient(top, #972f2e 0%, #fc7471 100%);
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #972f2e), color-stop(100%, #fc7471));
+ background: -webkit-linear-gradient(top, #972f2e 0%, #fc7471 100%);
+ background: -o-linear-gradient(top, #972f2e 0%, #fc7471 100%);
+ background: -ms-linear-gradient(top, #972f2e 0%, #fc7471 100%);
+ background: linear-gradient(top, #972f2e 0%, #fc7471 100%);
+}
+.red .shine {
+ position: relative;
+ top: -21px;
+ left: 5px;
+}
+.red .glow {
+ position: relative;
+ top: -20px;
+}
+.red .glyph {
+ position: relative;
+ top: -5px;
+ left: 3px;
+ font-size: 14px;
+ font-weight: 400;
+ color: #9b3a36;
+ z-index: 50;
+ opacity: 0;
+}
+.yellow {
+ background: #f4a316;
+ background: -moz-linear-gradient(left, #f4a316 0%, #fcc371 100%);
+ background: -webkit-gradient(linear, left top, right top, color-stop(0%, #f4a316), color-stop(100%, #fcc371));
+ background: -webkit-linear-gradient(left, #f4a316 0%, #fcc371 100%);
+ background: -o-linear-gradient(left, #f4a316 0%, #fcc371 100%);
+ background: -ms-linear-gradient(left, #f4a316 0%, #fcc371 100%);
+ background: linear-gradient(left, #f4a316 0%, #fcc371 100%);
+ margin: 0px 7px;
+}
+.yellow:active {
+ background: #ae4f1e;
+ background: -moz-linear-gradient(top, #ae4f1e 0%, #fcc371 100%);
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ae4f1e), color-stop(100%, #fcc371));
+ background: -webkit-linear-gradient(top, #ae4f1e 0%, #fcc371 100%);
+ background: -o-linear-gradient(top, #ae4f1e 0%, #fcc371 100%);
+ background: -ms-linear-gradient(top, #ae4f1e 0%, #fcc371 100%);
+ background: linear-gradient(top, #ae4f1e 0%, #fcc371 100%);
+}
+.yellow .shine {
+ position: relative;
+ top: -21px;
+ left: 5px;
+}
+.yellow .glow {
+ position: relative;
+ top: -20px;
+}
+.yellow .glyph {
+ position: relative;
+ top: -5px;
+ left: 3px;
+ font-size: 24px;
+ color: #854322;
+ z-index: 50;
+ opacity: 0;
+ -webkit-transform: scaleY(1.5) scaleX(1.3);
+}
+.green {
+ background: #4cae2e;
+ background: -moz-linear-gradient(top, #4cae2e 0%, #dafc71 100%);
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #4cae2e), color-stop(100%, #dafc71));
+ background: -webkit-linear-gradient(top, #4cae2e 0%, #dafc71 100%);
+ background: -o-linear-gradient(top, #4cae2e 0%, #dafc71 100%);
+ background: -ms-linear-gradient(top, #4cae2e 0%, #dafc71 100%);
+ background: linear-gradient(top, #4cae2e 0%, #dafc71 100%);
+}
+.green:active {
+ background: #48752b;
+ background: -moz-linear-gradient(top, #48752b 0%, #dafc71 100%);
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #48752b), color-stop(100%, #dafc71));
+ background: -webkit-linear-gradient(top, #48752b 0%, #dafc71 100%);
+ background: -o-linear-gradient(top, #48752b 0%, #dafc71 100%);
+ background: -ms-linear-gradient(top, #48752b 0%, #dafc71 100%);
+ background: linear-gradient(top, #48752b 0%, #dafc71 100%);
+}
+.green .shine {
+ position: relative;
+ top: -20px;
+ left: 5px;
+}
+.green .glow {
+ position: relative;
+ top: -20px;
+}
+.green .glyph {
+ position: relative;
+ top: -5px;
+ left: 3px;
+ font-size: 14px;
+ font-weight: bold;
+ color: #25571d;
+ z-index: 50;
+ opacity: 0;
+}
+@-moz-document url-prefix() {
+ .red .glyph {
+ position: relative;
+ top: -5px;
+ }
+ .yellow .glyph {
+ top: -4px;
+ left: 3px;
+ }
+ .green .glyph {
+ position: relative;
+ top: -4px;
+ }
+}
+#title {
+ float: left;
+ position: relative;
+ top: 6px;
+ width: 40%;
+ left: 45%;
+ font-family: "Myriad Pro", sans-serif;
+ font-size: 16px;
+ line-height: 14px;
+ font-weight: bold;
+}
+.folder {
+ float: left;
+ margin-right: 5px;
+}
+.folder .tab {
+ width: 4px;
+ height: 2px;
+ background: #a4c5da;
+ border: 1px solid #728ea3;
+ border-bottom: none;
+ border-radius: 2px 2px 0px 0px;
+ -webkit-box-shadow: 0px -1px 0px #99b5c7 inset;
+ margin-left: 1px;
+ z-index: 5000;
+ margin-bottom: -1px;
+}
+.folder .body {
+ width: 14px;
+ height: 10px;
+ border: 1px solid #6e8ba1;
+ background: #b8cfe0;
+ background: -moz-linear-gradient(top, #b8cfe0 0%, #86adc8 100%);
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #b8cfe0), color-stop(100%, #86adc8));
+ background: -webkit-linear-gradient(top, #b8cfe0 0%, #86adc8 100%);
+ background: -o-linear-gradient(top, #b8cfe0 0%, #86adc8 100%);
+ background: -ms-linear-gradient(top, #b8cfe0 0%, #86adc8 100%);
+ background: linear-gradient(top, #b8cfe0 0%, #86adc8 100%);
+ z-index: -50;
+ -webkit-box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25) inset, 0px 1px 0px rgba(0, 0, 0, 0.2);
+ -moz-box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25) inset, 0px 1px 0px rgba(0, 0, 0, 0.2);
+}
+#nav {
+ margin: 1px 8px;
+ float: left;
+}
+#view {
+ margin: 2px 0 0 110px;
+ display: inline-block;
+}
+.control_box {
+ height: 20px;
+ border-radius: 3px;
+ border: 1px solid #555;
+ background-image: -webkit-gradient(linear, left bottom, left top, color-stop(1, #fefefe), color-stop(0, #b8b8b8));
+ box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25);
+}
+.control_box .control {
+ height: 20px;
+ border-right: 1px solid #2e2e2e;
+ float: left;
+ text-align: center;
+ width: 27px;
+}
+.control:last-child {
+ border-right: 0px solid !important;
+}
+.control:active {
+ background: #b0afb0;
+ -webkit-box-shadow: 0px 0px 4px #000 inset;
+}
+.active {
+ background: #707070 !important;
+ -webkit-box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.6) inset !important;
+}
+#body {
+ font-family: Andale Mono, monospace;
+ line-height: 1em;
+ font-size: 13px;
+ float: left;
+ width: 100%;
+ background: #002b36;
+ padding: 10px;
+ line-height: 1.5em;
+}
+#body p {
+ color: #63de00!important;
+}
+@keyframes blink {
+ 0% {
+ background: rgba(99, 222, 0, 100);
+ }
+ 100% {
+ background: rgba(99, 222, 0, 0);
+ }
+}
+@-webkit-keyframes blink {
+ 0% {
+ background: rgba(99, 222, 0, 100);
+ }
+ 100% {
+ background: rgba(99, 222, 0, 0);
+ }
+}
+@-moz-keyframes blink {
+ 0% {
+ background: rgba(99, 222, 0, 100);
+ }
+ 100% {
+ background: rgba(99, 222, 0, 0);
+ }
+}
+.cursor {
+ width: 10px;
+ margin-left: 0px;
+ color: #fff;
+}
+#body p::-webkit-selection {
+ background: #0b209e;
+}
+#body p::selection {
+ background: #0b209e;
+}
+#body p::-moz-selection {
+ background: #0b209e;
+}
+#body p {
+ margin-top: 5px;
+ margin-bottom: 5px;
+ font-size: 13px;
+}
+#content {
+ float: left;
+ margin-top: 1px;
+}
+#foot {
+ height: 23px;
+ width: 100%;
+ float: left;
+ background-image: -webkit-gradient(linear, left bottom, left top, color-stop(1, #cbcbcb), color-stop(0, #a7a7a7));
+ border-top: 1px solid #515151;
+ border-radius: 0 0 5px 5px;
+}
+#foot .handle {
+ width: 11px;
+ height: 11px;
+ float: right;
+ margin: 6px;
+ overflow: hidden;
+}
+.handle .grip {
+ -webkit-transform: rotate(45deg) scaley(3);
+ margin: 2px 0 0 2px;
+ color: #646464;
+ text-shadow: 1px 1px 0 #c6c6c6;
+ font-size: 14px;
+}
+.icon .frame {
+ width: 82px;
+ height: 82px;
+ border-radius: 5px;
+ border: 2px solid transparent;
+}
+.icon .name {
+ color: #000;
+ padding-top: 3px;
+ border-radius: 15px;
+ width: 55px;
+ margin: 5px 0 0 15px;
+}
+.icon .folder {
+ margin: 15px 0 0 6px;
+}
+#icon-github {
+ text-align: -999px;
+ font-size: 1px;
+ display: block;
+ width: 156px;
+ height: 133px;
+ background-image: url(../img/sprite.png);
+ background-position: 0 133px;
+}
+#icon-github:hover {
+ background-position: 0 0px;
+}
+#icon-rubygems {
+ text-align: -999px;
+ font-size: 1px;
+ display: block;
+ width: 156px;
+ height: 133px;
+ background-image: url(../img/sprite.png);
+ background-position: 158px 133px;
+}
+#icon-rubygems:hover {
+ background-position: 158px 0px;
+}
+.source-urls {
+ margin-top: 40px;
+ margin-bottom: 40px;
+}
+.no-margin-bot {
+ color: #337AB7;
+}
+span {
+ font-size: 15px;
+}
+#particles-js {
+ position: absolute;
+ width: 98%;
+}
+#particles-js-no {
+ position: absolute;
+ width: 98%;
+}
+
+#icon-github:hover,
+i.icon.ion-close-circled:hover,
+i.icon.ion-minus-circled:hover,
+i.icon.ion-plus-circled:hover {
+ color: rgba(0, 0, 0, .5);
+}
+i.icon.ion-close-circled {
+ color: rgba(212, 42, 38, 0.83);
+ text-shadow: 0 0 1px rgba(187, 187, 187, 0.56);
+ padding-top: 3px;
+}
+i.icon.ion-minus-circled {
+ color: rgb(160, 165, 34);
+ text-shadow: 0 0 1px rgba(187, 187, 187, 0.56);
+ padding-top: 3px;
+}
+i.icon.ion-plus-circled {
+ color: rgb(82, 183, 51);
+ text-shadow: 0 0 1px rgba(187, 187, 187, 0.56);
+ padding-top: 3px;
+}
+.icon {
+ margin: 7px;
+ float: left;
+ font-size: 20px;
+}
+#title-left {
+ position: relative;
+ top: -8px;
+ font-family: "Myriad Pro", sans-serif;
+ font-size: 14px;
+ left: 49%;
+}
+#terminal-origin {
+ font-family: monospace;
+}
+@media all and (-webkit-min-device-pixel-ratio: 0) and (min-resolution: .001dpcm) {
+ #title-left {
+ top: -13px;
+ }
+}
diff --git a/css/terminal.mobile.css b/css/terminal.mobile.css
new file mode 100644
index 0000000..fbf2afc
--- /dev/null
+++ b/css/terminal.mobile.css
@@ -0,0 +1,22 @@
+@media screen and (max-width:1000px){i.icon.ion-minus-circled{display:none}
+#window{width:100%;}
+}
+@media screen and (max-width:800px){body{padding-top:0px;}
+#title-left{left:50%;}
+#window{width:100%;}
+.container{padding:0px;}
+/*article{padding:10px 20px;}*/
+i.icon.ion-minus-circled{display:none}
+}
+@media screen and (max-width:800px){#title-left{left:48%;}
+}
+@media screen and (max-width:500px){#title-left{left:40%;}
+}
+@media screen and (max-width:400px){body{padding-top:0px;width:auto;}
+#title-left{left:50%;}
+/*article{padding:10px 10px;}*/
+#particles-js{width:auto;}
+#particles-js-no{width:auto;}
+i.icon.ion-minus-circled{display:none}
+i.icon.ion-plus-circled{display:none}
+}
diff --git a/icon/ai.png b/icon/ai.png
new file mode 100644
index 0000000..d21dabe
Binary files /dev/null and b/icon/ai.png differ
diff --git a/icon/ai.svg b/icon/ai.svg
new file mode 100644
index 0000000..8926e2a
--- /dev/null
+++ b/icon/ai.svg
@@ -0,0 +1,1882 @@
+
+
diff --git a/icon/apple-touch-icon.png b/icon/apple-touch-icon.png
new file mode 100644
index 0000000..d21dabe
Binary files /dev/null and b/icon/apple-touch-icon.png differ
diff --git a/icon/avatar.png b/icon/avatar.png
new file mode 100644
index 0000000..f091ef1
Binary files /dev/null and b/icon/avatar.png differ
diff --git a/icon/term.png b/icon/term.png
new file mode 100644
index 0000000..dcff3bc
Binary files /dev/null and b/icon/term.png differ
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..5e0a606
--- /dev/null
+++ b/index.html
@@ -0,0 +1,25 @@
+
+
+
+ ai/term
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/js/bundle.js b/js/bundle.js
new file mode 100644
index 0000000..21c283e
--- /dev/null
+++ b/js/bundle.js
@@ -0,0 +1,5241 @@
+/******/ (function(modules) { // webpackBootstrap
+/******/ var parentHotUpdateCallback = this["webpackHotUpdate"];
+/******/ this["webpackHotUpdate"] =
+/******/ function webpackHotUpdateCallback(chunkId, moreModules) { // eslint-disable-line no-unused-vars
+/******/ hotAddUpdateChunk(chunkId, moreModules);
+/******/ if(parentHotUpdateCallback) parentHotUpdateCallback(chunkId, moreModules);
+/******/ }
+/******/
+/******/ function hotDownloadUpdateChunk(chunkId) { // eslint-disable-line no-unused-vars
+/******/ var head = document.getElementsByTagName("head")[0];
+/******/ var script = document.createElement("script");
+/******/ script.type = "text/javascript";
+/******/ script.charset = "utf-8";
+/******/ script.src = __webpack_require__.p + "" + chunkId + "." + hotCurrentHash + ".hot-update.js";
+/******/ head.appendChild(script);
+/******/ }
+/******/
+/******/ function hotDownloadManifest(callback) { // eslint-disable-line no-unused-vars
+/******/ if(typeof XMLHttpRequest === "undefined")
+/******/ return callback(new Error("No browser support"));
+/******/ try {
+/******/ var request = new XMLHttpRequest();
+/******/ var requestPath = __webpack_require__.p + "" + hotCurrentHash + ".hot-update.json";
+/******/ request.open("GET", requestPath, true);
+/******/ request.timeout = 10000;
+/******/ request.send(null);
+/******/ } catch(err) {
+/******/ return callback(err);
+/******/ }
+/******/ request.onreadystatechange = function() {
+/******/ if(request.readyState !== 4) return;
+/******/ if(request.status === 0) {
+/******/ // timeout
+/******/ callback(new Error("Manifest request to " + requestPath + " timed out."));
+/******/ } else if(request.status === 404) {
+/******/ // no update available
+/******/ callback();
+/******/ } else if(request.status !== 200 && request.status !== 304) {
+/******/ // other failure
+/******/ callback(new Error("Manifest request to " + requestPath + " failed."));
+/******/ } else {
+/******/ // success
+/******/ try {
+/******/ var update = JSON.parse(request.responseText);
+/******/ } catch(e) {
+/******/ callback(e);
+/******/ return;
+/******/ }
+/******/ callback(null, update);
+/******/ }
+/******/ };
+/******/ }
+
+/******/
+/******/
+/******/ // Copied from https://github.com/facebook/react/blob/bef45b0/src/shared/utils/canDefineProperty.js
+/******/ var canDefineProperty = false;
+/******/ try {
+/******/ Object.defineProperty({}, "x", {
+/******/ get: function() {}
+/******/ });
+/******/ canDefineProperty = true;
+/******/ } catch(x) {
+/******/ // IE will fail on defineProperty
+/******/ }
+/******/
+/******/ var hotApplyOnUpdate = true;
+/******/ var hotCurrentHash = "df5ff963eab1d8f408b8"; // eslint-disable-line no-unused-vars
+/******/ var hotCurrentModuleData = {};
+/******/ var hotCurrentParents = []; // eslint-disable-line no-unused-vars
+/******/
+/******/ function hotCreateRequire(moduleId) { // eslint-disable-line no-unused-vars
+/******/ var me = installedModules[moduleId];
+/******/ if(!me) return __webpack_require__;
+/******/ var fn = function(request) {
+/******/ if(me.hot.active) {
+/******/ if(installedModules[request]) {
+/******/ if(installedModules[request].parents.indexOf(moduleId) < 0)
+/******/ installedModules[request].parents.push(moduleId);
+/******/ if(me.children.indexOf(request) < 0)
+/******/ me.children.push(request);
+/******/ } else hotCurrentParents = [moduleId];
+/******/ } else {
+/******/ console.warn("[HMR] unexpected require(" + request + ") from disposed module " + moduleId);
+/******/ hotCurrentParents = [];
+/******/ }
+/******/ return __webpack_require__(request);
+/******/ };
+/******/ for(var name in __webpack_require__) {
+/******/ if(Object.prototype.hasOwnProperty.call(__webpack_require__, name)) {
+/******/ if(canDefineProperty) {
+/******/ Object.defineProperty(fn, name, (function(name) {
+/******/ return {
+/******/ configurable: true,
+/******/ enumerable: true,
+/******/ get: function() {
+/******/ return __webpack_require__[name];
+/******/ },
+/******/ set: function(value) {
+/******/ __webpack_require__[name] = value;
+/******/ }
+/******/ };
+/******/ }(name)));
+/******/ } else {
+/******/ fn[name] = __webpack_require__[name];
+/******/ }
+/******/ }
+/******/ }
+/******/
+/******/ function ensure(chunkId, callback) {
+/******/ if(hotStatus === "ready")
+/******/ hotSetStatus("prepare");
+/******/ hotChunksLoading++;
+/******/ __webpack_require__.e(chunkId, function() {
+/******/ try {
+/******/ callback.call(null, fn);
+/******/ } finally {
+/******/ finishChunkLoading();
+/******/ }
+/******/
+/******/ function finishChunkLoading() {
+/******/ hotChunksLoading--;
+/******/ if(hotStatus === "prepare") {
+/******/ if(!hotWaitingFilesMap[chunkId]) {
+/******/ hotEnsureUpdateChunk(chunkId);
+/******/ }
+/******/ if(hotChunksLoading === 0 && hotWaitingFiles === 0) {
+/******/ hotUpdateDownloaded();
+/******/ }
+/******/ }
+/******/ }
+/******/ });
+/******/ }
+/******/ if(canDefineProperty) {
+/******/ Object.defineProperty(fn, "e", {
+/******/ enumerable: true,
+/******/ value: ensure
+/******/ });
+/******/ } else {
+/******/ fn.e = ensure;
+/******/ }
+/******/ return fn;
+/******/ }
+/******/
+/******/ function hotCreateModule(moduleId) { // eslint-disable-line no-unused-vars
+/******/ var hot = {
+/******/ // private stuff
+/******/ _acceptedDependencies: {},
+/******/ _declinedDependencies: {},
+/******/ _selfAccepted: false,
+/******/ _selfDeclined: false,
+/******/ _disposeHandlers: [],
+/******/
+/******/ // Module API
+/******/ active: true,
+/******/ accept: function(dep, callback) {
+/******/ if(typeof dep === "undefined")
+/******/ hot._selfAccepted = true;
+/******/ else if(typeof dep === "function")
+/******/ hot._selfAccepted = dep;
+/******/ else if(typeof dep === "object")
+/******/ for(var i = 0; i < dep.length; i++)
+/******/ hot._acceptedDependencies[dep[i]] = callback;
+/******/ else
+/******/ hot._acceptedDependencies[dep] = callback;
+/******/ },
+/******/ decline: function(dep) {
+/******/ if(typeof dep === "undefined")
+/******/ hot._selfDeclined = true;
+/******/ else if(typeof dep === "number")
+/******/ hot._declinedDependencies[dep] = true;
+/******/ else
+/******/ for(var i = 0; i < dep.length; i++)
+/******/ hot._declinedDependencies[dep[i]] = true;
+/******/ },
+/******/ dispose: function(callback) {
+/******/ hot._disposeHandlers.push(callback);
+/******/ },
+/******/ addDisposeHandler: function(callback) {
+/******/ hot._disposeHandlers.push(callback);
+/******/ },
+/******/ removeDisposeHandler: function(callback) {
+/******/ var idx = hot._disposeHandlers.indexOf(callback);
+/******/ if(idx >= 0) hot._disposeHandlers.splice(idx, 1);
+/******/ },
+/******/
+/******/ // Management API
+/******/ check: hotCheck,
+/******/ apply: hotApply,
+/******/ status: function(l) {
+/******/ if(!l) return hotStatus;
+/******/ hotStatusHandlers.push(l);
+/******/ },
+/******/ addStatusHandler: function(l) {
+/******/ hotStatusHandlers.push(l);
+/******/ },
+/******/ removeStatusHandler: function(l) {
+/******/ var idx = hotStatusHandlers.indexOf(l);
+/******/ if(idx >= 0) hotStatusHandlers.splice(idx, 1);
+/******/ },
+/******/
+/******/ //inherit from previous dispose call
+/******/ data: hotCurrentModuleData[moduleId]
+/******/ };
+/******/ return hot;
+/******/ }
+/******/
+/******/ var hotStatusHandlers = [];
+/******/ var hotStatus = "idle";
+/******/
+/******/ function hotSetStatus(newStatus) {
+/******/ hotStatus = newStatus;
+/******/ for(var i = 0; i < hotStatusHandlers.length; i++)
+/******/ hotStatusHandlers[i].call(null, newStatus);
+/******/ }
+/******/
+/******/ // while downloading
+/******/ var hotWaitingFiles = 0;
+/******/ var hotChunksLoading = 0;
+/******/ var hotWaitingFilesMap = {};
+/******/ var hotRequestedFilesMap = {};
+/******/ var hotAvailibleFilesMap = {};
+/******/ var hotCallback;
+/******/
+/******/ // The update info
+/******/ var hotUpdate, hotUpdateNewHash;
+/******/
+/******/ function toModuleId(id) {
+/******/ var isNumber = (+id) + "" === id;
+/******/ return isNumber ? +id : id;
+/******/ }
+/******/
+/******/ function hotCheck(apply, callback) {
+/******/ if(hotStatus !== "idle") throw new Error("check() is only allowed in idle status");
+/******/ if(typeof apply === "function") {
+/******/ hotApplyOnUpdate = false;
+/******/ callback = apply;
+/******/ } else {
+/******/ hotApplyOnUpdate = apply;
+/******/ callback = callback || function(err) {
+/******/ if(err) throw err;
+/******/ };
+/******/ }
+/******/ hotSetStatus("check");
+/******/ hotDownloadManifest(function(err, update) {
+/******/ if(err) return callback(err);
+/******/ if(!update) {
+/******/ hotSetStatus("idle");
+/******/ callback(null, null);
+/******/ return;
+/******/ }
+/******/
+/******/ hotRequestedFilesMap = {};
+/******/ hotAvailibleFilesMap = {};
+/******/ hotWaitingFilesMap = {};
+/******/ for(var i = 0; i < update.c.length; i++)
+/******/ hotAvailibleFilesMap[update.c[i]] = true;
+/******/ hotUpdateNewHash = update.h;
+/******/
+/******/ hotSetStatus("prepare");
+/******/ hotCallback = callback;
+/******/ hotUpdate = {};
+/******/ var chunkId = 0;
+/******/ { // eslint-disable-line no-lone-blocks
+/******/ /*globals chunkId */
+/******/ hotEnsureUpdateChunk(chunkId);
+/******/ }
+/******/ if(hotStatus === "prepare" && hotChunksLoading === 0 && hotWaitingFiles === 0) {
+/******/ hotUpdateDownloaded();
+/******/ }
+/******/ });
+/******/ }
+/******/
+/******/ function hotAddUpdateChunk(chunkId, moreModules) { // eslint-disable-line no-unused-vars
+/******/ if(!hotAvailibleFilesMap[chunkId] || !hotRequestedFilesMap[chunkId])
+/******/ return;
+/******/ hotRequestedFilesMap[chunkId] = false;
+/******/ for(var moduleId in moreModules) {
+/******/ if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
+/******/ hotUpdate[moduleId] = moreModules[moduleId];
+/******/ }
+/******/ }
+/******/ if(--hotWaitingFiles === 0 && hotChunksLoading === 0) {
+/******/ hotUpdateDownloaded();
+/******/ }
+/******/ }
+/******/
+/******/ function hotEnsureUpdateChunk(chunkId) {
+/******/ if(!hotAvailibleFilesMap[chunkId]) {
+/******/ hotWaitingFilesMap[chunkId] = true;
+/******/ } else {
+/******/ hotRequestedFilesMap[chunkId] = true;
+/******/ hotWaitingFiles++;
+/******/ hotDownloadUpdateChunk(chunkId);
+/******/ }
+/******/ }
+/******/
+/******/ function hotUpdateDownloaded() {
+/******/ hotSetStatus("ready");
+/******/ var callback = hotCallback;
+/******/ hotCallback = null;
+/******/ if(!callback) return;
+/******/ if(hotApplyOnUpdate) {
+/******/ hotApply(hotApplyOnUpdate, callback);
+/******/ } else {
+/******/ var outdatedModules = [];
+/******/ for(var id in hotUpdate) {
+/******/ if(Object.prototype.hasOwnProperty.call(hotUpdate, id)) {
+/******/ outdatedModules.push(toModuleId(id));
+/******/ }
+/******/ }
+/******/ callback(null, outdatedModules);
+/******/ }
+/******/ }
+/******/
+/******/ function hotApply(options, callback) {
+/******/ if(hotStatus !== "ready") throw new Error("apply() is only allowed in ready status");
+/******/ if(typeof options === "function") {
+/******/ callback = options;
+/******/ options = {};
+/******/ } else if(options && typeof options === "object") {
+/******/ callback = callback || function(err) {
+/******/ if(err) throw err;
+/******/ };
+/******/ } else {
+/******/ options = {};
+/******/ callback = callback || function(err) {
+/******/ if(err) throw err;
+/******/ };
+/******/ }
+/******/
+/******/ function getAffectedStuff(module) {
+/******/ var outdatedModules = [module];
+/******/ var outdatedDependencies = {};
+/******/
+/******/ var queue = outdatedModules.slice();
+/******/ while(queue.length > 0) {
+/******/ var moduleId = queue.pop();
+/******/ var module = installedModules[moduleId];
+/******/ if(!module || module.hot._selfAccepted)
+/******/ continue;
+/******/ if(module.hot._selfDeclined) {
+/******/ return new Error("Aborted because of self decline: " + moduleId);
+/******/ }
+/******/ if(moduleId === 0) {
+/******/ return;
+/******/ }
+/******/ for(var i = 0; i < module.parents.length; i++) {
+/******/ var parentId = module.parents[i];
+/******/ var parent = installedModules[parentId];
+/******/ if(parent.hot._declinedDependencies[moduleId]) {
+/******/ return new Error("Aborted because of declined dependency: " + moduleId + " in " + parentId);
+/******/ }
+/******/ if(outdatedModules.indexOf(parentId) >= 0) continue;
+/******/ if(parent.hot._acceptedDependencies[moduleId]) {
+/******/ if(!outdatedDependencies[parentId])
+/******/ outdatedDependencies[parentId] = [];
+/******/ addAllToSet(outdatedDependencies[parentId], [moduleId]);
+/******/ continue;
+/******/ }
+/******/ delete outdatedDependencies[parentId];
+/******/ outdatedModules.push(parentId);
+/******/ queue.push(parentId);
+/******/ }
+/******/ }
+/******/
+/******/ return [outdatedModules, outdatedDependencies];
+/******/ }
+/******/
+/******/ function addAllToSet(a, b) {
+/******/ for(var i = 0; i < b.length; i++) {
+/******/ var item = b[i];
+/******/ if(a.indexOf(item) < 0)
+/******/ a.push(item);
+/******/ }
+/******/ }
+/******/
+/******/ // at begin all updates modules are outdated
+/******/ // the "outdated" status can propagate to parents if they don't accept the children
+/******/ var outdatedDependencies = {};
+/******/ var outdatedModules = [];
+/******/ var appliedUpdate = {};
+/******/ for(var id in hotUpdate) {
+/******/ if(Object.prototype.hasOwnProperty.call(hotUpdate, id)) {
+/******/ var moduleId = toModuleId(id);
+/******/ var result = getAffectedStuff(moduleId);
+/******/ if(!result) {
+/******/ if(options.ignoreUnaccepted)
+/******/ continue;
+/******/ hotSetStatus("abort");
+/******/ return callback(new Error("Aborted because " + moduleId + " is not accepted"));
+/******/ }
+/******/ if(result instanceof Error) {
+/******/ hotSetStatus("abort");
+/******/ return callback(result);
+/******/ }
+/******/ appliedUpdate[moduleId] = hotUpdate[moduleId];
+/******/ addAllToSet(outdatedModules, result[0]);
+/******/ for(var moduleId in result[1]) {
+/******/ if(Object.prototype.hasOwnProperty.call(result[1], moduleId)) {
+/******/ if(!outdatedDependencies[moduleId])
+/******/ outdatedDependencies[moduleId] = [];
+/******/ addAllToSet(outdatedDependencies[moduleId], result[1][moduleId]);
+/******/ }
+/******/ }
+/******/ }
+/******/ }
+/******/
+/******/ // Store self accepted outdated modules to require them later by the module system
+/******/ var outdatedSelfAcceptedModules = [];
+/******/ for(var i = 0; i < outdatedModules.length; i++) {
+/******/ var moduleId = outdatedModules[i];
+/******/ if(installedModules[moduleId] && installedModules[moduleId].hot._selfAccepted)
+/******/ outdatedSelfAcceptedModules.push({
+/******/ module: moduleId,
+/******/ errorHandler: installedModules[moduleId].hot._selfAccepted
+/******/ });
+/******/ }
+/******/
+/******/ // Now in "dispose" phase
+/******/ hotSetStatus("dispose");
+/******/ var queue = outdatedModules.slice();
+/******/ while(queue.length > 0) {
+/******/ var moduleId = queue.pop();
+/******/ var module = installedModules[moduleId];
+/******/ if(!module) continue;
+/******/
+/******/ var data = {};
+/******/
+/******/ // Call dispose handlers
+/******/ var disposeHandlers = module.hot._disposeHandlers;
+/******/ for(var j = 0; j < disposeHandlers.length; j++) {
+/******/ var cb = disposeHandlers[j];
+/******/ cb(data);
+/******/ }
+/******/ hotCurrentModuleData[moduleId] = data;
+/******/
+/******/ // disable module (this disables requires from this module)
+/******/ module.hot.active = false;
+/******/
+/******/ // remove module from cache
+/******/ delete installedModules[moduleId];
+/******/
+/******/ // remove "parents" references from all children
+/******/ for(var j = 0; j < module.children.length; j++) {
+/******/ var child = installedModules[module.children[j]];
+/******/ if(!child) continue;
+/******/ var idx = child.parents.indexOf(moduleId);
+/******/ if(idx >= 0) {
+/******/ child.parents.splice(idx, 1);
+/******/ }
+/******/ }
+/******/ }
+/******/
+/******/ // remove outdated dependency from module children
+/******/ for(var moduleId in outdatedDependencies) {
+/******/ if(Object.prototype.hasOwnProperty.call(outdatedDependencies, moduleId)) {
+/******/ var module = installedModules[moduleId];
+/******/ var moduleOutdatedDependencies = outdatedDependencies[moduleId];
+/******/ for(var j = 0; j < moduleOutdatedDependencies.length; j++) {
+/******/ var dependency = moduleOutdatedDependencies[j];
+/******/ var idx = module.children.indexOf(dependency);
+/******/ if(idx >= 0) module.children.splice(idx, 1);
+/******/ }
+/******/ }
+/******/ }
+/******/
+/******/ // Not in "apply" phase
+/******/ hotSetStatus("apply");
+/******/
+/******/ hotCurrentHash = hotUpdateNewHash;
+/******/
+/******/ // insert new code
+/******/ for(var moduleId in appliedUpdate) {
+/******/ if(Object.prototype.hasOwnProperty.call(appliedUpdate, moduleId)) {
+/******/ modules[moduleId] = appliedUpdate[moduleId];
+/******/ }
+/******/ }
+/******/
+/******/ // call accept handlers
+/******/ var error = null;
+/******/ for(var moduleId in outdatedDependencies) {
+/******/ if(Object.prototype.hasOwnProperty.call(outdatedDependencies, moduleId)) {
+/******/ var module = installedModules[moduleId];
+/******/ var moduleOutdatedDependencies = outdatedDependencies[moduleId];
+/******/ var callbacks = [];
+/******/ for(var i = 0; i < moduleOutdatedDependencies.length; i++) {
+/******/ var dependency = moduleOutdatedDependencies[i];
+/******/ var cb = module.hot._acceptedDependencies[dependency];
+/******/ if(callbacks.indexOf(cb) >= 0) continue;
+/******/ callbacks.push(cb);
+/******/ }
+/******/ for(var i = 0; i < callbacks.length; i++) {
+/******/ var cb = callbacks[i];
+/******/ try {
+/******/ cb(outdatedDependencies);
+/******/ } catch(err) {
+/******/ if(!error)
+/******/ error = err;
+/******/ }
+/******/ }
+/******/ }
+/******/ }
+/******/
+/******/ // Load self accepted modules
+/******/ for(var i = 0; i < outdatedSelfAcceptedModules.length; i++) {
+/******/ var item = outdatedSelfAcceptedModules[i];
+/******/ var moduleId = item.module;
+/******/ hotCurrentParents = [moduleId];
+/******/ try {
+/******/ __webpack_require__(moduleId);
+/******/ } catch(err) {
+/******/ if(typeof item.errorHandler === "function") {
+/******/ try {
+/******/ item.errorHandler(err);
+/******/ } catch(err) {
+/******/ if(!error)
+/******/ error = err;
+/******/ }
+/******/ } else if(!error)
+/******/ error = err;
+/******/ }
+/******/ }
+/******/
+/******/ // handle errors in accept handlers and self accepted module load
+/******/ if(error) {
+/******/ hotSetStatus("fail");
+/******/ return callback(error);
+/******/ }
+/******/
+/******/ hotSetStatus("idle");
+/******/ callback(null, outdatedModules);
+/******/ }
+
+/******/ // The module cache
+/******/ var installedModules = {};
+
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+
+/******/ // Check if module is in cache
+/******/ if(installedModules[moduleId])
+/******/ return installedModules[moduleId].exports;
+
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = installedModules[moduleId] = {
+/******/ exports: {},
+/******/ id: moduleId,
+/******/ loaded: false,
+/******/ hot: hotCreateModule(moduleId),
+/******/ parents: hotCurrentParents,
+/******/ children: []
+/******/ };
+
+/******/ // Execute the module function
+/******/ modules[moduleId].call(module.exports, module, module.exports, hotCreateRequire(moduleId));
+
+/******/ // Flag the module as loaded
+/******/ module.loaded = true;
+
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
+
+
+/******/ // expose the modules object (__webpack_modules__)
+/******/ __webpack_require__.m = modules;
+
+/******/ // expose the module cache
+/******/ __webpack_require__.c = installedModules;
+
+/******/ // __webpack_public_path__
+/******/ __webpack_require__.p = "";
+
+/******/ // __webpack_hash__
+/******/ __webpack_require__.h = function() { return hotCurrentHash; };
+
+/******/ // Load entry module and return exports
+/******/ return hotCreateRequire(0)(0);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ (function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+ var riot = __webpack_require__(1);
+ // Provide some settings
+ riot.settings.brackets = '{{ }}';
+ // Get application tag and mount it! Yeah baby!
+ __webpack_require__(3);
+ riot.mount('app');
+ // Router
+ __webpack_require__(33);
+ // SASS
+ __webpack_require__(52);
+ __webpack_require__(54);
+ __webpack_require__(56);
+
+/***/ }),
+/* 1 */
+/***/ (function(module, exports, __webpack_require__) {
+
+ var __WEBPACK_AMD_DEFINE_RESULT__;/* Riot v2.6.8, @license MIT */
+
+ ;(function(window, undefined) {
+ 'use strict';
+ var riot = { version: 'v2.6.8', settings: {} },
+ // be aware, internal usage
+ // ATTENTION: prefix the global dynamic variables with `__`
+
+ // counter to give a unique id to all the Tag instances
+ __uid = 0,
+ // tags instances cache
+ __virtualDom = [],
+ // tags implementation cache
+ __tagImpl = {},
+
+ /**
+ * Const
+ */
+ GLOBAL_MIXIN = '__global_mixin',
+
+ // riot specific prefixes
+ RIOT_PREFIX = 'riot-',
+ RIOT_TAG = RIOT_PREFIX + 'tag',
+ RIOT_TAG_IS = 'data-is',
+
+ // for typeof == '' comparisons
+ T_STRING = 'string',
+ T_OBJECT = 'object',
+ T_UNDEF = 'undefined',
+ T_FUNCTION = 'function',
+ XLINK_NS = 'http://www.w3.org/1999/xlink',
+ XLINK_REGEX = /^xlink:(\w+)/,
+ // special native tags that cannot be treated like the others
+ SPECIAL_TAGS_REGEX = /^(?:t(?:body|head|foot|[rhd])|caption|col(?:group)?|opt(?:ion|group))$/,
+ RESERVED_WORDS_BLACKLIST = /^(?:_(?:item|id|parent)|update|root|(?:un)?mount|mixin|is(?:Mounted|Loop)|tags|parent|opts|trigger|o(?:n|ff|ne))$/,
+ // SVG tags list https://www.w3.org/TR/SVG/attindex.html#PresentationAttributes
+ SVG_TAGS_LIST = ['altGlyph', 'animate', 'animateColor', 'circle', 'clipPath', 'defs', 'ellipse', 'feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feFlood', 'feGaussianBlur', 'feImage', 'feMerge', 'feMorphology', 'feOffset', 'feSpecularLighting', 'feTile', 'feTurbulence', 'filter', 'font', 'foreignObject', 'g', 'glyph', 'glyphRef', 'image', 'line', 'linearGradient', 'marker', 'mask', 'missing-glyph', 'path', 'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'stop', 'svg', 'switch', 'symbol', 'text', 'textPath', 'tref', 'tspan', 'use'],
+
+ // version# for IE 8-11, 0 for others
+ IE_VERSION = (window && window.document || {}).documentMode | 0,
+
+ // detect firefox to fix #1374
+ FIREFOX = window && !!window.InstallTrigger
+ /* istanbul ignore next */
+ riot.observable = function(el) {
+
+ /**
+ * Extend the original object or create a new empty one
+ * @type { Object }
+ */
+
+ el = el || {}
+
+ /**
+ * Private variables
+ */
+ var callbacks = {},
+ slice = Array.prototype.slice
+
+ /**
+ * Private Methods
+ */
+
+ /**
+ * Helper function needed to get and loop all the events in a string
+ * @param { String } e - event string
+ * @param {Function} fn - callback
+ */
+ function onEachEvent(e, fn) {
+ var es = e.split(' '), l = es.length, i = 0
+ for (; i < l; i++) {
+ var name = es[i]
+ if (name) fn(name, i)
+ }
+ }
+
+ /**
+ * Public Api
+ */
+
+ // extend the el object adding the observable methods
+ Object.defineProperties(el, {
+ /**
+ * Listen to the given space separated list of `events` and
+ * execute the `callback` each time an event is triggered.
+ * @param { String } events - events ids
+ * @param { Function } fn - callback function
+ * @returns { Object } el
+ */
+ on: {
+ value: function(events, fn) {
+ if (typeof fn != 'function') return el
+
+ onEachEvent(events, function(name, pos) {
+ (callbacks[name] = callbacks[name] || []).push(fn)
+ fn.typed = pos > 0
+ })
+
+ return el
+ },
+ enumerable: false,
+ writable: false,
+ configurable: false
+ },
+
+ /**
+ * Removes the given space separated list of `events` listeners
+ * @param { String } events - events ids
+ * @param { Function } fn - callback function
+ * @returns { Object } el
+ */
+ off: {
+ value: function(events, fn) {
+ if (events == '*' && !fn) callbacks = {}
+ else {
+ onEachEvent(events, function(name, pos) {
+ if (fn) {
+ var arr = callbacks[name]
+ for (var i = 0, cb; cb = arr && arr[i]; ++i) {
+ if (cb == fn) arr.splice(i--, 1)
+ }
+ } else delete callbacks[name]
+ })
+ }
+ return el
+ },
+ enumerable: false,
+ writable: false,
+ configurable: false
+ },
+
+ /**
+ * Listen to the given space separated list of `events` and
+ * execute the `callback` at most once
+ * @param { String } events - events ids
+ * @param { Function } fn - callback function
+ * @returns { Object } el
+ */
+ one: {
+ value: function(events, fn) {
+ function on() {
+ el.off(events, on)
+ fn.apply(el, arguments)
+ }
+ return el.on(events, on)
+ },
+ enumerable: false,
+ writable: false,
+ configurable: false
+ },
+
+ /**
+ * Execute all callback functions that listen to
+ * the given space separated list of `events`
+ * @param { String } events - events ids
+ * @returns { Object } el
+ */
+ trigger: {
+ value: function(events) {
+
+ // getting the arguments
+ var arglen = arguments.length - 1,
+ args = new Array(arglen),
+ fns
+
+ for (var i = 0; i < arglen; i++) {
+ args[i] = arguments[i + 1] // skip first argument
+ }
+
+ onEachEvent(events, function(name, pos) {
+
+ fns = slice.call(callbacks[name] || [], 0)
+
+ for (var i = 0, fn; fn = fns[i]; ++i) {
+ if (fn.busy) continue
+ fn.busy = 1
+ fn.apply(el, fn.typed ? [name].concat(args) : args)
+ if (fns[i] !== fn) { i-- }
+ fn.busy = 0
+ }
+
+ if (callbacks['*'] && name != '*')
+ el.trigger.apply(el, ['*', name].concat(args))
+
+ })
+
+ return el
+ },
+ enumerable: false,
+ writable: false,
+ configurable: false
+ }
+ })
+
+ return el
+
+ }
+ /* istanbul ignore next */
+ ;(function(riot) {
+
+ /**
+ * Simple client-side router
+ * @module riot-route
+ */
+
+
+ var RE_ORIGIN = /^.+?\/\/+[^\/]+/,
+ EVENT_LISTENER = 'EventListener',
+ REMOVE_EVENT_LISTENER = 'remove' + EVENT_LISTENER,
+ ADD_EVENT_LISTENER = 'add' + EVENT_LISTENER,
+ HAS_ATTRIBUTE = 'hasAttribute',
+ REPLACE = 'replace',
+ POPSTATE = 'popstate',
+ HASHCHANGE = 'hashchange',
+ TRIGGER = 'trigger',
+ MAX_EMIT_STACK_LEVEL = 3,
+ win = typeof window != 'undefined' && window,
+ doc = typeof document != 'undefined' && document,
+ hist = win && history,
+ loc = win && (hist.location || win.location), // see html5-history-api
+ prot = Router.prototype, // to minify more
+ clickEvent = doc && doc.ontouchstart ? 'touchstart' : 'click',
+ started = false,
+ central = riot.observable(),
+ routeFound = false,
+ debouncedEmit,
+ base, current, parser, secondParser, emitStack = [], emitStackLevel = 0
+
+ /**
+ * Default parser. You can replace it via router.parser method.
+ * @param {string} path - current path (normalized)
+ * @returns {array} array
+ */
+ function DEFAULT_PARSER(path) {
+ return path.split(/[/?#]/)
+ }
+
+ /**
+ * Default parser (second). You can replace it via router.parser method.
+ * @param {string} path - current path (normalized)
+ * @param {string} filter - filter string (normalized)
+ * @returns {array} array
+ */
+ function DEFAULT_SECOND_PARSER(path, filter) {
+ var re = new RegExp('^' + filter[REPLACE](/\*/g, '([^/?#]+?)')[REPLACE](/\.\./, '.*') + '$'),
+ args = path.match(re)
+
+ if (args) return args.slice(1)
+ }
+
+ /**
+ * Simple/cheap debounce implementation
+ * @param {function} fn - callback
+ * @param {number} delay - delay in seconds
+ * @returns {function} debounced function
+ */
+ function debounce(fn, delay) {
+ var t
+ return function () {
+ clearTimeout(t)
+ t = setTimeout(fn, delay)
+ }
+ }
+
+ /**
+ * Set the window listeners to trigger the routes
+ * @param {boolean} autoExec - see route.start
+ */
+ function start(autoExec) {
+ debouncedEmit = debounce(emit, 1)
+ win[ADD_EVENT_LISTENER](POPSTATE, debouncedEmit)
+ win[ADD_EVENT_LISTENER](HASHCHANGE, debouncedEmit)
+ doc[ADD_EVENT_LISTENER](clickEvent, click)
+ if (autoExec) emit(true)
+ }
+
+ /**
+ * Router class
+ */
+ function Router() {
+ this.$ = []
+ riot.observable(this) // make it observable
+ central.on('stop', this.s.bind(this))
+ central.on('emit', this.e.bind(this))
+ }
+
+ function normalize(path) {
+ return path[REPLACE](/^\/|\/$/, '')
+ }
+
+ function isString(str) {
+ return typeof str == 'string'
+ }
+
+ /**
+ * Get the part after domain name
+ * @param {string} href - fullpath
+ * @returns {string} path from root
+ */
+ function getPathFromRoot(href) {
+ return (href || loc.href)[REPLACE](RE_ORIGIN, '')
+ }
+
+ /**
+ * Get the part after base
+ * @param {string} href - fullpath
+ * @returns {string} path from base
+ */
+ function getPathFromBase(href) {
+ return base[0] == '#'
+ ? (href || loc.href || '').split(base)[1] || ''
+ : (loc ? getPathFromRoot(href) : href || '')[REPLACE](base, '')
+ }
+
+ function emit(force) {
+ // the stack is needed for redirections
+ var isRoot = emitStackLevel == 0, first
+ if (MAX_EMIT_STACK_LEVEL <= emitStackLevel) return
+
+ emitStackLevel++
+ emitStack.push(function() {
+ var path = getPathFromBase()
+ if (force || path != current) {
+ central[TRIGGER]('emit', path)
+ current = path
+ }
+ })
+ if (isRoot) {
+ while (first = emitStack.shift()) first() // stack increses within this call
+ emitStackLevel = 0
+ }
+ }
+
+ function click(e) {
+ if (
+ e.which != 1 // not left click
+ || e.metaKey || e.ctrlKey || e.shiftKey // or meta keys
+ || e.defaultPrevented // or default prevented
+ ) return
+
+ var el = e.target
+ while (el && el.nodeName != 'A') el = el.parentNode
+
+ if (
+ !el || el.nodeName != 'A' // not A tag
+ || el[HAS_ATTRIBUTE]('download') // has download attr
+ || !el[HAS_ATTRIBUTE]('href') // has no href attr
+ || el.target && el.target != '_self' // another window or frame
+ || el.href.indexOf(loc.href.match(RE_ORIGIN)[0]) == -1 // cross origin
+ ) return
+
+ if (el.href != loc.href
+ && (
+ el.href.split('#')[0] == loc.href.split('#')[0] // internal jump
+ || base[0] != '#' && getPathFromRoot(el.href).indexOf(base) !== 0 // outside of base
+ || base[0] == '#' && el.href.split(base)[0] != loc.href.split(base)[0] // outside of #base
+ || !go(getPathFromBase(el.href), el.title || doc.title) // route not found
+ )) return
+
+ e.preventDefault()
+ }
+
+ /**
+ * Go to the path
+ * @param {string} path - destination path
+ * @param {string} title - page title
+ * @param {boolean} shouldReplace - use replaceState or pushState
+ * @returns {boolean} - route not found flag
+ */
+ function go(path, title, shouldReplace) {
+ // Server-side usage: directly execute handlers for the path
+ if (!hist) return central[TRIGGER]('emit', getPathFromBase(path))
+
+ path = base + normalize(path)
+ title = title || doc.title
+ // browsers ignores the second parameter `title`
+ shouldReplace
+ ? hist.replaceState(null, title, path)
+ : hist.pushState(null, title, path)
+ // so we need to set it manually
+ doc.title = title
+ routeFound = false
+ emit()
+ return routeFound
+ }
+
+ /**
+ * Go to path or set action
+ * a single string: go there
+ * two strings: go there with setting a title
+ * two strings and boolean: replace history with setting a title
+ * a single function: set an action on the default route
+ * a string/RegExp and a function: set an action on the route
+ * @param {(string|function)} first - path / action / filter
+ * @param {(string|RegExp|function)} second - title / action
+ * @param {boolean} third - replace flag
+ */
+ prot.m = function(first, second, third) {
+ if (isString(first) && (!second || isString(second))) go(first, second, third || false)
+ else if (second) this.r(first, second)
+ else this.r('@', first)
+ }
+
+ /**
+ * Stop routing
+ */
+ prot.s = function() {
+ this.off('*')
+ this.$ = []
+ }
+
+ /**
+ * Emit
+ * @param {string} path - path
+ */
+ prot.e = function(path) {
+ this.$.concat('@').some(function(filter) {
+ var args = (filter == '@' ? parser : secondParser)(normalize(path), normalize(filter))
+ if (typeof args != 'undefined') {
+ this[TRIGGER].apply(null, [filter].concat(args))
+ return routeFound = true // exit from loop
+ }
+ }, this)
+ }
+
+ /**
+ * Register route
+ * @param {string} filter - filter for matching to url
+ * @param {function} action - action to register
+ */
+ prot.r = function(filter, action) {
+ if (filter != '@') {
+ filter = '/' + normalize(filter)
+ this.$.push(filter)
+ }
+ this.on(filter, action)
+ }
+
+ var mainRouter = new Router()
+ var route = mainRouter.m.bind(mainRouter)
+
+ /**
+ * Create a sub router
+ * @returns {function} the method of a new Router object
+ */
+ route.create = function() {
+ var newSubRouter = new Router()
+ // assign sub-router's main method
+ var router = newSubRouter.m.bind(newSubRouter)
+ // stop only this sub-router
+ router.stop = newSubRouter.s.bind(newSubRouter)
+ return router
+ }
+
+ /**
+ * Set the base of url
+ * @param {(str|RegExp)} arg - a new base or '#' or '#!'
+ */
+ route.base = function(arg) {
+ base = arg || '#'
+ current = getPathFromBase() // recalculate current path
+ }
+
+ /** Exec routing right now **/
+ route.exec = function() {
+ emit(true)
+ }
+
+ /**
+ * Replace the default router to yours
+ * @param {function} fn - your parser function
+ * @param {function} fn2 - your secondParser function
+ */
+ route.parser = function(fn, fn2) {
+ if (!fn && !fn2) {
+ // reset parser for testing...
+ parser = DEFAULT_PARSER
+ secondParser = DEFAULT_SECOND_PARSER
+ }
+ if (fn) parser = fn
+ if (fn2) secondParser = fn2
+ }
+
+ /**
+ * Helper function to get url query as an object
+ * @returns {object} parsed query
+ */
+ route.query = function() {
+ var q = {}
+ var href = loc.href || current
+ href[REPLACE](/[?&](.+?)=([^&]*)/g, function(_, k, v) { q[k] = v })
+ return q
+ }
+
+ /** Stop routing **/
+ route.stop = function () {
+ if (started) {
+ if (win) {
+ win[REMOVE_EVENT_LISTENER](POPSTATE, debouncedEmit)
+ win[REMOVE_EVENT_LISTENER](HASHCHANGE, debouncedEmit)
+ doc[REMOVE_EVENT_LISTENER](clickEvent, click)
+ }
+ central[TRIGGER]('stop')
+ started = false
+ }
+ }
+
+ /**
+ * Start routing
+ * @param {boolean} autoExec - automatically exec after starting if true
+ */
+ route.start = function (autoExec) {
+ if (!started) {
+ if (win) {
+ if (document.readyState == 'complete') start(autoExec)
+ // the timeout is needed to solve
+ // a weird safari bug https://github.com/riot/route/issues/33
+ else win[ADD_EVENT_LISTENER]('load', function() {
+ setTimeout(function() { start(autoExec) }, 1)
+ })
+ }
+ started = true
+ }
+ }
+
+ /** Prepare the router **/
+ route.base()
+ route.parser()
+
+ riot.route = route
+ })(riot)
+ /* istanbul ignore next */
+
+ /**
+ * The riot template engine
+ * @version v2.4.2
+ */
+ /**
+ * riot.util.brackets
+ *
+ * - `brackets ` - Returns a string or regex based on its parameter
+ * - `brackets.set` - Change the current riot brackets
+ *
+ * @module
+ */
+
+ var brackets = (function (UNDEF) {
+
+ var
+ REGLOB = 'g',
+
+ R_MLCOMMS = /\/\*[^*]*\*+(?:[^*\/][^*]*\*+)*\//g,
+
+ R_STRINGS = /"[^"\\]*(?:\\[\S\s][^"\\]*)*"|'[^'\\]*(?:\\[\S\s][^'\\]*)*'/g,
+
+ S_QBLOCKS = R_STRINGS.source + '|' +
+ /(?:\breturn\s+|(?:[$\w\)\]]|\+\+|--)\s*(\/)(?![*\/]))/.source + '|' +
+ /\/(?=[^*\/])[^[\/\\]*(?:(?:\[(?:\\.|[^\]\\]*)*\]|\\.)[^[\/\\]*)*?(\/)[gim]*/.source,
+
+ UNSUPPORTED = RegExp('[\\' + 'x00-\\x1F<>a-zA-Z0-9\'",;\\\\]'),
+
+ NEED_ESCAPE = /(?=[[\]()*+?.^$|])/g,
+
+ FINDBRACES = {
+ '(': RegExp('([()])|' + S_QBLOCKS, REGLOB),
+ '[': RegExp('([[\\]])|' + S_QBLOCKS, REGLOB),
+ '{': RegExp('([{}])|' + S_QBLOCKS, REGLOB)
+ },
+
+ DEFAULT = '{ }'
+
+ var _pairs = [
+ '{', '}',
+ '{', '}',
+ /{[^}]*}/,
+ /\\([{}])/g,
+ /\\({)|{/g,
+ RegExp('\\\\(})|([[({])|(})|' + S_QBLOCKS, REGLOB),
+ DEFAULT,
+ /^\s*{\^?\s*([$\w]+)(?:\s*,\s*(\S+))?\s+in\s+(\S.*)\s*}/,
+ /(^|[^\\]){=[\S\s]*?}/
+ ]
+
+ var
+ cachedBrackets = UNDEF,
+ _regex,
+ _cache = [],
+ _settings
+
+ function _loopback (re) { return re }
+
+ function _rewrite (re, bp) {
+ if (!bp) bp = _cache
+ return new RegExp(
+ re.source.replace(/{/g, bp[2]).replace(/}/g, bp[3]), re.global ? REGLOB : ''
+ )
+ }
+
+ function _create (pair) {
+ if (pair === DEFAULT) return _pairs
+
+ var arr = pair.split(' ')
+
+ if (arr.length !== 2 || UNSUPPORTED.test(pair)) {
+ throw new Error('Unsupported brackets "' + pair + '"')
+ }
+ arr = arr.concat(pair.replace(NEED_ESCAPE, '\\').split(' '))
+
+ arr[4] = _rewrite(arr[1].length > 1 ? /{[\S\s]*?}/ : _pairs[4], arr)
+ arr[5] = _rewrite(pair.length > 3 ? /\\({|})/g : _pairs[5], arr)
+ arr[6] = _rewrite(_pairs[6], arr)
+ arr[7] = RegExp('\\\\(' + arr[3] + ')|([[({])|(' + arr[3] + ')|' + S_QBLOCKS, REGLOB)
+ arr[8] = pair
+ return arr
+ }
+
+ function _brackets (reOrIdx) {
+ return reOrIdx instanceof RegExp ? _regex(reOrIdx) : _cache[reOrIdx]
+ }
+
+ _brackets.split = function split (str, tmpl, _bp) {
+ // istanbul ignore next: _bp is for the compiler
+ if (!_bp) _bp = _cache
+
+ var
+ parts = [],
+ match,
+ isexpr,
+ start,
+ pos,
+ re = _bp[6]
+
+ isexpr = start = re.lastIndex = 0
+
+ while ((match = re.exec(str))) {
+
+ pos = match.index
+
+ if (isexpr) {
+
+ if (match[2]) {
+ re.lastIndex = skipBraces(str, match[2], re.lastIndex)
+ continue
+ }
+ if (!match[3]) {
+ continue
+ }
+ }
+
+ if (!match[1]) {
+ unescapeStr(str.slice(start, pos))
+ start = re.lastIndex
+ re = _bp[6 + (isexpr ^= 1)]
+ re.lastIndex = start
+ }
+ }
+
+ if (str && start < str.length) {
+ unescapeStr(str.slice(start))
+ }
+
+ return parts
+
+ function unescapeStr (s) {
+ if (tmpl || isexpr) {
+ parts.push(s && s.replace(_bp[5], '$1'))
+ } else {
+ parts.push(s)
+ }
+ }
+
+ function skipBraces (s, ch, ix) {
+ var
+ match,
+ recch = FINDBRACES[ch]
+
+ recch.lastIndex = ix
+ ix = 1
+ while ((match = recch.exec(s))) {
+ if (match[1] &&
+ !(match[1] === ch ? ++ix : --ix)) break
+ }
+ return ix ? s.length : recch.lastIndex
+ }
+ }
+
+ _brackets.hasExpr = function hasExpr (str) {
+ return _cache[4].test(str)
+ }
+
+ _brackets.loopKeys = function loopKeys (expr) {
+ var m = expr.match(_cache[9])
+
+ return m
+ ? { key: m[1], pos: m[2], val: _cache[0] + m[3].trim() + _cache[1] }
+ : { val: expr.trim() }
+ }
+
+ _brackets.array = function array (pair) {
+ return pair ? _create(pair) : _cache
+ }
+
+ function _reset (pair) {
+ if ((pair || (pair = DEFAULT)) !== _cache[8]) {
+ _cache = _create(pair)
+ _regex = pair === DEFAULT ? _loopback : _rewrite
+ _cache[9] = _regex(_pairs[9])
+ }
+ cachedBrackets = pair
+ }
+
+ function _setSettings (o) {
+ var b
+
+ o = o || {}
+ b = o.brackets
+ Object.defineProperty(o, 'brackets', {
+ set: _reset,
+ get: function () { return cachedBrackets },
+ enumerable: true
+ })
+ _settings = o
+ _reset(b)
+ }
+
+ Object.defineProperty(_brackets, 'settings', {
+ set: _setSettings,
+ get: function () { return _settings }
+ })
+
+ /* istanbul ignore next: in the browser riot is always in the scope */
+ _brackets.settings = typeof riot !== 'undefined' && riot.settings || {}
+ _brackets.set = _reset
+
+ _brackets.R_STRINGS = R_STRINGS
+ _brackets.R_MLCOMMS = R_MLCOMMS
+ _brackets.S_QBLOCKS = S_QBLOCKS
+
+ return _brackets
+
+ })()
+
+ /**
+ * @module tmpl
+ *
+ * tmpl - Root function, returns the template value, render with data
+ * tmpl.hasExpr - Test the existence of a expression inside a string
+ * tmpl.loopKeys - Get the keys for an 'each' loop (used by `_each`)
+ */
+
+ var tmpl = (function () {
+
+ var _cache = {}
+
+ function _tmpl (str, data) {
+ if (!str) return str
+
+ return (_cache[str] || (_cache[str] = _create(str))).call(data, _logErr)
+ }
+
+ _tmpl.haveRaw = brackets.hasRaw
+
+ _tmpl.hasExpr = brackets.hasExpr
+
+ _tmpl.loopKeys = brackets.loopKeys
+
+ // istanbul ignore next
+ _tmpl.clearCache = function () { _cache = {} }
+
+ _tmpl.errorHandler = null
+
+ function _logErr (err, ctx) {
+
+ if (_tmpl.errorHandler) {
+
+ err.riotData = {
+ tagName: ctx && ctx.root && ctx.root.tagName,
+ _riot_id: ctx && ctx._riot_id //eslint-disable-line camelcase
+ }
+ _tmpl.errorHandler(err)
+ }
+ }
+
+ function _create (str) {
+ var expr = _getTmpl(str)
+
+ if (expr.slice(0, 11) !== 'try{return ') expr = 'return ' + expr
+
+ return new Function('E', expr + ';') // eslint-disable-line no-new-func
+ }
+
+ var
+ CH_IDEXPR = String.fromCharCode(0x2057),
+ RE_CSNAME = /^(?:(-?[_A-Za-z\xA0-\xFF][-\w\xA0-\xFF]*)|\u2057(\d+)~):/,
+ RE_QBLOCK = RegExp(brackets.S_QBLOCKS, 'g'),
+ RE_DQUOTE = /\u2057/g,
+ RE_QBMARK = /\u2057(\d+)~/g
+
+ function _getTmpl (str) {
+ var
+ qstr = [],
+ expr,
+ parts = brackets.split(str.replace(RE_DQUOTE, '"'), 1)
+
+ if (parts.length > 2 || parts[0]) {
+ var i, j, list = []
+
+ for (i = j = 0; i < parts.length; ++i) {
+
+ expr = parts[i]
+
+ if (expr && (expr = i & 1
+
+ ? _parseExpr(expr, 1, qstr)
+
+ : '"' + expr
+ .replace(/\\/g, '\\\\')
+ .replace(/\r\n?|\n/g, '\\n')
+ .replace(/"/g, '\\"') +
+ '"'
+
+ )) list[j++] = expr
+
+ }
+
+ expr = j < 2 ? list[0]
+ : '[' + list.join(',') + '].join("")'
+
+ } else {
+
+ expr = _parseExpr(parts[1], 0, qstr)
+ }
+
+ if (qstr[0]) {
+ expr = expr.replace(RE_QBMARK, function (_, pos) {
+ return qstr[pos]
+ .replace(/\r/g, '\\r')
+ .replace(/\n/g, '\\n')
+ })
+ }
+ return expr
+ }
+
+ var
+ RE_BREND = {
+ '(': /[()]/g,
+ '[': /[[\]]/g,
+ '{': /[{}]/g
+ }
+
+ function _parseExpr (expr, asText, qstr) {
+
+ expr = expr
+ .replace(RE_QBLOCK, function (s, div) {
+ return s.length > 2 && !div ? CH_IDEXPR + (qstr.push(s) - 1) + '~' : s
+ })
+ .replace(/\s+/g, ' ').trim()
+ .replace(/\ ?([[\({},?\.:])\ ?/g, '$1')
+
+ if (expr) {
+ var
+ list = [],
+ cnt = 0,
+ match
+
+ while (expr &&
+ (match = expr.match(RE_CSNAME)) &&
+ !match.index
+ ) {
+ var
+ key,
+ jsb,
+ re = /,|([[{(])|$/g
+
+ expr = RegExp.rightContext
+ key = match[2] ? qstr[match[2]].slice(1, -1).trim().replace(/\s+/g, ' ') : match[1]
+
+ while (jsb = (match = re.exec(expr))[1]) skipBraces(jsb, re)
+
+ jsb = expr.slice(0, match.index)
+ expr = RegExp.rightContext
+
+ list[cnt++] = _wrapExpr(jsb, 1, key)
+ }
+
+ expr = !cnt ? _wrapExpr(expr, asText)
+ : cnt > 1 ? '[' + list.join(',') + '].join(" ").trim()' : list[0]
+ }
+ return expr
+
+ function skipBraces (ch, re) {
+ var
+ mm,
+ lv = 1,
+ ir = RE_BREND[ch]
+
+ ir.lastIndex = re.lastIndex
+ while (mm = ir.exec(expr)) {
+ if (mm[0] === ch) ++lv
+ else if (!--lv) break
+ }
+ re.lastIndex = lv ? expr.length : ir.lastIndex
+ }
+ }
+
+ // istanbul ignore next: not both
+ var // eslint-disable-next-line max-len
+ JS_CONTEXT = '"in this?this:' + (typeof window !== 'object' ? 'global' : 'window') + ').',
+ JS_VARNAME = /[,{][\$\w]+(?=:)|(^ *|[^$\w\.{])(?!(?:typeof|true|false|null|undefined|in|instanceof|is(?:Finite|NaN)|void|NaN|new|Date|RegExp|Math)(?![$\w]))([$_A-Za-z][$\w]*)/g,
+ JS_NOPROPS = /^(?=(\.[$\w]+))\1(?:[^.[(]|$)/
+
+ function _wrapExpr (expr, asText, key) {
+ var tb
+
+ expr = expr.replace(JS_VARNAME, function (match, p, mvar, pos, s) {
+ if (mvar) {
+ pos = tb ? 0 : pos + match.length
+
+ if (mvar !== 'this' && mvar !== 'global' && mvar !== 'window') {
+ match = p + '("' + mvar + JS_CONTEXT + mvar
+ if (pos) tb = (s = s[pos]) === '.' || s === '(' || s === '['
+ } else if (pos) {
+ tb = !JS_NOPROPS.test(s.slice(pos))
+ }
+ }
+ return match
+ })
+
+ if (tb) {
+ expr = 'try{return ' + expr + '}catch(e){E(e,this)}'
+ }
+
+ if (key) {
+
+ expr = (tb
+ ? 'function(){' + expr + '}.call(this)' : '(' + expr + ')'
+ ) + '?"' + key + '":""'
+
+ } else if (asText) {
+
+ expr = 'function(v){' + (tb
+ ? expr.replace('return ', 'v=') : 'v=(' + expr + ')'
+ ) + ';return v||v===0?v:""}.call(this)'
+ }
+
+ return expr
+ }
+
+ _tmpl.version = brackets.version = 'v2.4.2'
+
+ return _tmpl
+
+ })()
+
+ /*
+ lib/browser/tag/mkdom.js
+
+ Includes hacks needed for the Internet Explorer version 9 and below
+ See: http://kangax.github.io/compat-table/es5/#ie8
+ http://codeplanet.io/dropping-ie8/
+ */
+ var mkdom = (function _mkdom() {
+ var
+ reHasYield = /|>([\S\s]*?)<\/yield\s*>|>)/ig,
+ reYieldSrc = /]*)['"]\s*>([\S\s]*?)<\/yield\s*>/ig,
+ reYieldDest = /|>([\S\s]*?)<\/yield\s*>)/ig
+ var
+ rootEls = { tr: 'tbody', th: 'tr', td: 'tr', col: 'colgroup' },
+ tblTags = IE_VERSION && IE_VERSION < 10
+ ? SPECIAL_TAGS_REGEX : /^(?:t(?:body|head|foot|[rhd])|caption|col(?:group)?)$/
+
+ /**
+ * Creates a DOM element to wrap the given content. Normally an `DIV`, but can be
+ * also a `TABLE`, `SELECT`, `TBODY`, `TR`, or `COLGROUP` element.
+ *
+ * @param { String } templ - The template coming from the custom tag definition
+ * @param { String } [html] - HTML content that comes from the DOM element where you
+ * will mount the tag, mostly the original tag in the page
+ * @param { Boolean } checkSvg - flag needed to know if we need to force the svg rendering in case of loop nodes
+ * @returns {HTMLElement} DOM element with _templ_ merged through `YIELD` with the _html_.
+ */
+ function _mkdom(templ, html, checkSvg) {
+ var
+ match = templ && templ.match(/^\s*<([-\w]+)/),
+ tagName = match && match[1].toLowerCase(),
+ el = mkEl('div', checkSvg && isSVGTag(tagName))
+
+ // replace all the yield tags with the tag inner html
+ templ = replaceYield(templ, html)
+
+ /* istanbul ignore next */
+ if (tblTags.test(tagName))
+ el = specialTags(el, templ, tagName)
+ else
+ setInnerHTML(el, templ)
+
+ el.stub = true
+
+ return el
+ }
+
+ /*
+ Creates the root element for table or select child elements:
+ tr/th/td/thead/tfoot/tbody/caption/col/colgroup/option/optgroup
+ */
+ function specialTags(el, templ, tagName) {
+ var
+ select = tagName[0] === 'o',
+ parent = select ? 'select>' : 'table>'
+
+ // trim() is important here, this ensures we don't have artifacts,
+ // so we can check if we have only one element inside the parent
+ el.innerHTML = '<' + parent + templ.trim() + '' + parent
+ parent = el.firstChild
+
+ // returns the immediate parent if tr/th/td/col is the only element, if not
+ // returns the whole tree, as this can include additional elements
+ if (select) {
+ parent.selectedIndex = -1 // for IE9, compatible w/current riot behavior
+ } else {
+ // avoids insertion of cointainer inside container (ex: tbody inside tbody)
+ var tname = rootEls[tagName]
+ if (tname && parent.childElementCount === 1) parent = $(tname, parent)
+ }
+ return parent
+ }
+
+ /*
+ Replace the yield tag from any tag template with the innerHTML of the
+ original tag in the page
+ */
+ function replaceYield(templ, html) {
+ // do nothing if no yield
+ if (!reHasYield.test(templ)) return templ
+
+ // be careful with #1343 - string on the source having `$1`
+ var src = {}
+
+ html = html && html.replace(reYieldSrc, function (_, ref, text) {
+ src[ref] = src[ref] || text // preserve first definition
+ return ''
+ }).trim()
+
+ return templ
+ .replace(reYieldDest, function (_, ref, def) { // yield with from - to attrs
+ return src[ref] || def || ''
+ })
+ .replace(reYieldAll, function (_, def) { // yield without any "from"
+ return html || def || ''
+ })
+ }
+
+ return _mkdom
+
+ })()
+
+ /**
+ * Convert the item looped into an object used to extend the child tag properties
+ * @param { Object } expr - object containing the keys used to extend the children tags
+ * @param { * } key - value to assign to the new object returned
+ * @param { * } val - value containing the position of the item in the array
+ * @returns { Object } - new object containing the values of the original item
+ *
+ * The variables 'key' and 'val' are arbitrary.
+ * They depend on the collection type looped (Array, Object)
+ * and on the expression used on the each tag
+ *
+ */
+ function mkitem(expr, key, val) {
+ var item = {}
+ item[expr.key] = key
+ if (expr.pos) item[expr.pos] = val
+ return item
+ }
+
+ /**
+ * Unmount the redundant tags
+ * @param { Array } items - array containing the current items to loop
+ * @param { Array } tags - array containing all the children tags
+ */
+ function unmountRedundant(items, tags) {
+
+ var i = tags.length,
+ j = items.length,
+ t
+
+ while (i > j) {
+ t = tags[--i]
+ tags.splice(i, 1)
+ t.unmount()
+ }
+ }
+
+ /**
+ * Move the nested custom tags in non custom loop tags
+ * @param { Object } child - non custom loop tag
+ * @param { Number } i - current position of the loop tag
+ */
+ function moveNestedTags(child, i) {
+ Object.keys(child.tags).forEach(function(tagName) {
+ var tag = child.tags[tagName]
+ if (isArray(tag))
+ each(tag, function (t) {
+ moveChildTag(t, tagName, i)
+ })
+ else
+ moveChildTag(tag, tagName, i)
+ })
+ }
+
+ /**
+ * Adds the elements for a virtual tag
+ * @param { Tag } tag - the tag whose root's children will be inserted or appended
+ * @param { Node } src - the node that will do the inserting or appending
+ * @param { Tag } target - only if inserting, insert before this tag's first child
+ */
+ function addVirtual(tag, src, target) {
+ var el = tag._root, sib
+ tag._virts = []
+ while (el) {
+ sib = el.nextSibling
+ if (target)
+ src.insertBefore(el, target._root)
+ else
+ src.appendChild(el)
+
+ tag._virts.push(el) // hold for unmounting
+ el = sib
+ }
+ }
+
+ /**
+ * Move virtual tag and all child nodes
+ * @param { Tag } tag - first child reference used to start move
+ * @param { Node } src - the node that will do the inserting
+ * @param { Tag } target - insert before this tag's first child
+ * @param { Number } len - how many child nodes to move
+ */
+ function moveVirtual(tag, src, target, len) {
+ var el = tag._root, sib, i = 0
+ for (; i < len; i++) {
+ sib = el.nextSibling
+ src.insertBefore(el, target._root)
+ el = sib
+ }
+ }
+
+ /**
+ * Insert a new tag avoiding the insert for the conditional tags
+ * @param {Boolean} isVirtual [description]
+ * @param { Tag } prevTag - tag instance used as reference to prepend our new tag
+ * @param { Tag } newTag - new tag to be inserted
+ * @param { HTMLElement } root - loop parent node
+ * @param { Array } tags - array containing the current tags list
+ * @param { Function } virtualFn - callback needed to move or insert virtual DOM
+ * @param { Object } dom - DOM node we need to loop
+ */
+ function insertTag(isVirtual, prevTag, newTag, root, tags, virtualFn, dom) {
+ if (isInStub(prevTag.root)) return
+ if (isVirtual) virtualFn(prevTag, root, newTag, dom.childNodes.length)
+ else root.insertBefore(prevTag.root, newTag.root) // #1374 some browsers reset selected here
+ }
+
+
+ /**
+ * Manage tags having the 'each'
+ * @param { Object } dom - DOM node we need to loop
+ * @param { Tag } parent - parent tag instance where the dom node is contained
+ * @param { String } expr - string contained in the 'each' attribute
+ */
+ function _each(dom, parent, expr) {
+
+ // remove the each property from the original tag
+ remAttr(dom, 'each')
+
+ var mustReorder = typeof getAttr(dom, 'no-reorder') !== T_STRING || remAttr(dom, 'no-reorder'),
+ tagName = getTagName(dom),
+ impl = __tagImpl[tagName] || { tmpl: getOuterHTML(dom) },
+ useRoot = SPECIAL_TAGS_REGEX.test(tagName),
+ root = dom.parentNode,
+ ref = document.createTextNode(''),
+ child = getTag(dom),
+ isOption = tagName.toLowerCase() === 'option', // the option tags must be treated differently
+ tags = [],
+ oldItems = [],
+ hasKeys,
+ isVirtual = dom.tagName == 'VIRTUAL'
+
+ // parse the each expression
+ expr = tmpl.loopKeys(expr)
+
+ // insert a marked where the loop tags will be injected
+ root.insertBefore(ref, dom)
+
+ // clean template code
+ parent.one('before-mount', function () {
+
+ // remove the original DOM node
+ dom.parentNode.removeChild(dom)
+ if (root.stub) root = parent.root
+
+ }).on('update', function () {
+ // get the new items collection
+ var items = tmpl(expr.val, parent),
+ // create a fragment to hold the new DOM nodes to inject in the parent tag
+ frag = document.createDocumentFragment()
+
+ // object loop. any changes cause full redraw
+ if (!isArray(items)) {
+ hasKeys = items || false
+ items = hasKeys ?
+ Object.keys(items).map(function (key) {
+ return mkitem(expr, key, items[key])
+ }) : []
+ }
+
+ // loop all the new items
+ var i = 0,
+ itemsLength = items.length
+
+ for (; i < itemsLength; i++) {
+ // reorder only if the items are objects
+ var
+ item = items[i],
+ _mustReorder = mustReorder && typeof item == T_OBJECT && !hasKeys,
+ oldPos = oldItems.indexOf(item),
+ pos = ~oldPos && _mustReorder ? oldPos : i,
+ // does a tag exist in this position?
+ tag = tags[pos]
+
+ item = !hasKeys && expr.key ? mkitem(expr, item, i) : item
+
+ // new tag
+ if (
+ !_mustReorder && !tag // with no-reorder we just update the old tags
+ ||
+ _mustReorder && !~oldPos || !tag // by default we always try to reorder the DOM elements
+ ) {
+
+ tag = new Tag(impl, {
+ parent: parent,
+ isLoop: true,
+ hasImpl: !!__tagImpl[tagName],
+ root: useRoot ? root : dom.cloneNode(),
+ item: item
+ }, dom.innerHTML)
+
+ tag.mount()
+
+ if (isVirtual) tag._root = tag.root.firstChild // save reference for further moves or inserts
+ // this tag must be appended
+ if (i == tags.length || !tags[i]) { // fix 1581
+ if (isVirtual)
+ addVirtual(tag, frag)
+ else frag.appendChild(tag.root)
+ }
+ // this tag must be insert
+ else {
+ insertTag(isVirtual, tag, tags[i], root, tags, addVirtual, dom)
+ oldItems.splice(i, 0, item)
+ }
+
+ tags.splice(i, 0, tag)
+ pos = i // handled here so no move
+ } else tag.update(item, true)
+
+ // reorder the tag if it's not located in its previous position
+ if (
+ pos !== i && _mustReorder &&
+ tags[i] // fix 1581 unable to reproduce it in a test!
+ ) {
+ // #closes 2040 PLEASE DON'T REMOVE IT!
+ // there are no tests for this feature
+ if (contains(items, oldItems[i]))
+ insertTag(isVirtual, tag, tags[i], root, tags, moveVirtual, dom)
+
+ // update the position attribute if it exists
+ if (expr.pos)
+ tag[expr.pos] = i
+ // move the old tag instance
+ tags.splice(i, 0, tags.splice(pos, 1)[0])
+ // move the old item
+ oldItems.splice(i, 0, oldItems.splice(pos, 1)[0])
+ // if the loop tags are not custom
+ // we need to move all their custom tags into the right position
+ if (!child && tag.tags) moveNestedTags(tag, i)
+ }
+
+ // cache the original item to use it in the events bound to this node
+ // and its children
+ tag._item = item
+ // cache the real parent tag internally
+ defineProperty(tag, '_parent', parent)
+ }
+
+ // remove the redundant tags
+ unmountRedundant(items, tags)
+
+ // insert the new nodes
+ root.insertBefore(frag, ref)
+ if (isOption) {
+
+ // #1374 FireFox bug in