Run js-beautify and fixjsstyle on code

Found this pointer on stackoverflow:
https://stackoverflow.com/a/31660434/5508494

End goal is to get the code formatted well enough that
clang format will run correctly against it.

Change-Id: I80053e78d253d8eee49233e42d55e5807ae8fdc8
Signed-off-by: Andrew Geissler <geissonator@yahoo.com>
diff --git a/app/common/directives/app-header.js b/app/common/directives/app-header.js
index 93d8fa8..31f683c 100644
--- a/app/common/directives/app-header.js
+++ b/app/common/directives/app-header.js
@@ -1,94 +1,98 @@
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.common.directives')
-        .directive('appHeader', ['APIUtils', function (APIUtils) {
-            return {
-                'restrict': 'E',
-                'template': require('./app-header.html'),
-                'scope': {
-                   'path': '='
-                },
-                'controller': ['$rootScope', '$scope','dataService', 'userModel', '$location', '$route',
-                function($rootScope, $scope, dataService, userModel, $location, $route){
-                    $scope.dataService = dataService;
+  angular
+    .module('app.common.directives')
+    .directive('appHeader', ['APIUtils', function(APIUtils) {
+      return {
+        'restrict': 'E',
+        'template': require('./app-header.html'),
+        'scope': {
+          'path': '='
+        },
+        'controller': ['$rootScope', '$scope', 'dataService', 'userModel', '$location', '$route',
+          function($rootScope, $scope, dataService, userModel, $location, $route) {
+            $scope.dataService = dataService;
 
-                    $scope.loadServerHealth = function(){
-                        APIUtils.getLogs().then(function(result){
-                            dataService.updateServerHealth(result.data);
-                        });
-                    }
-
-                    $scope.loadServerStatus = function(){
-                        if(!userModel.isLoggedIn()){
-                            return;
-                        }
-                        APIUtils.getHostState().then(function(status){
-                            if(status == 'xyz.openbmc_project.State.Host.HostState.Off'){
-                                dataService.setPowerOffState();
-                            }else if(status == 'xyz.openbmc_project.State.Host.HostState.Running'){
-                                dataService.setPowerOnState();
-                            }else{
-                                dataService.setErrorState();
-                            }
-                        }, function(error){
-                            dataService.activateErrorModal();
-                        });
-                    }
-
-                    $scope.loadNetworkInfo = function(){
-                        if(!userModel.isLoggedIn()){
-                            return;
-                        }
-                        APIUtils.getNetworkInfo().then(function(data){
-                            dataService.setNetworkInfo(data);
-                        });
-                    }
-
-                    function loadData(){
-                       $scope.loadServerStatus();
-                       $scope.loadNetworkInfo();
-                       $scope.loadServerHealth();
-                    }
-
-                    loadData();
-
-                    $scope.logout = function(){
-                        userModel.logout(function(status, error){
-                            if(status){
-                               $location.path('/logout');
-                            }else{
-                                console.log(error);
-                            }
-                        });
-                    }
-
-                    $scope.refresh = function(){
-                        //reload current page controllers and header
-                        loadData();
-                        $route.reload();
-                        //Add flash class to header timestamp on click of refresh
-                        var myEl = angular.element( document.querySelector( '.header__refresh' ) );
-                        myEl.addClass('flash');
-                        setTimeout(function () {
-                            myEl.removeClass("flash");
-                        },2000);
-
-                    }
-
-                    var loginListener = $rootScope.$on('user-logged-in', function(event, arg){
-                        loadData();
-                    });
-
-                    $scope.$on('$destroy', function(){
-                        loginListener();
-                    });
-
-                    $scope.multiRecent = function(){
-                        $scope.multi_server_recent = !$scope.multi_server_recent;
-                    };
-                }]
+            $scope.loadServerHealth = function() {
+              APIUtils.getLogs().then(function(result) {
+                dataService.updateServerHealth(result.data);
+              });
             };
-        }]);
+
+            $scope.loadServerStatus = function() {
+              if (!userModel.isLoggedIn()) {
+                return;
+              }
+              APIUtils.getHostState().then(function(status) {
+                if (status == 'xyz.openbmc_project.State.Host.HostState.Off') {
+                  dataService.setPowerOffState();
+                }
+                else if (status == 'xyz.openbmc_project.State.Host.HostState.Running') {
+                  dataService.setPowerOnState();
+                }
+                else {
+                  dataService.setErrorState();
+                }
+              }, function(error) {
+                dataService.activateErrorModal();
+              });
+            };
+
+            $scope.loadNetworkInfo = function() {
+              if (!userModel.isLoggedIn()) {
+                return;
+              }
+              APIUtils.getNetworkInfo().then(function(data) {
+                dataService.setNetworkInfo(data);
+              });
+            };
+
+            function loadData() {
+              $scope.loadServerStatus();
+              $scope.loadNetworkInfo();
+              $scope.loadServerHealth();
+            }
+
+            loadData();
+
+            $scope.logout = function() {
+              userModel.logout(function(status, error) {
+                if (status) {
+                  $location.path('/logout');
+                }
+                else {
+                  console.log(error);
+                }
+              });
+            };
+
+            $scope.refresh = function() {
+              //reload current page controllers and header
+              loadData();
+              $route.reload();
+              //Add flash class to header timestamp on click of refresh
+              var myEl = angular.element(document.querySelector('.header__refresh'));
+              myEl.addClass('flash');
+              setTimeout(function() {
+                myEl.removeClass('flash');
+              }, 2000);
+
+            };
+
+            var loginListener = $rootScope.$on('user-logged-in', function(event, arg) {
+              loadData();
+            });
+
+            $scope.$on('$destroy', function() {
+              loginListener();
+            });
+
+            $scope.multiRecent = function() {
+              $scope.multi_server_recent = !$scope.multi_server_recent;
+            };
+          }
+        ]
+      };
+    }]);
 })(window.angular);
diff --git a/app/common/directives/app-navigation.js b/app/common/directives/app-navigation.js
index 02d3f2d..80d09ec 100644
--- a/app/common/directives/app-navigation.js
+++ b/app/common/directives/app-navigation.js
@@ -1,68 +1,75 @@
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.common.directives')
-        .directive('appNavigation', function () {
-            return {
-                'restrict': 'E',
-                'template': require('./app-navigation.html'),
-                'scope': {
-                    'path': '=',
-                    'showNavigation': '='
-                },
-                'controller': ['$scope', '$location', 'dataService', function($scope, $location, dataService){
-                    $scope.dataService = dataService;
-                    $scope.showSubMenu = false;
-                    $scope.change = function(firstLevel){
-                        if(firstLevel != $scope.firstLevel) {
-                            $scope.firstLevel = firstLevel;
-                            $scope.showSubMenu = true;
-                        }else{
-                           $scope.showSubMenu = !$scope.showSubMenu;
-                        }
-                    };
-                    $scope.closeSubnav = function(){
-                        $scope.showSubMenu = false;
-                    };
-                    $scope.$watch('path', function(){
-                        var urlRoot = $location.path().split("/")[1];
-                        if(urlRoot != ""){
-                            $scope.firstLevel = urlRoot;
-                        }else{
-                            $scope.firstLevel = 'overview';
-                        }
-                        $scope.showSubMenu = false;
-                    });
-                    $scope.$watch('showNavigation', function(){
-                        var paddingTop = 0;
-                        var urlRoot = $location.path().split("/")[1];
-                        if(urlRoot != ""){
-                            $scope.firstLevel = urlRoot;
-                        }else{
-                            $scope.firstLevel = 'overview';
-                        }
+  angular
+    .module('app.common.directives')
+    .directive('appNavigation', function() {
+      return {
+        'restrict': 'E',
+        'template': require('./app-navigation.html'),
+        'scope': {
+          'path': '=',
+          'showNavigation': '='
+        },
+        'controller': ['$scope', '$location', 'dataService', function($scope, $location, dataService) {
+          $scope.dataService = dataService;
+          $scope.showSubMenu = false;
+          $scope.change = function(firstLevel) {
+            if (firstLevel != $scope.firstLevel) {
+              $scope.firstLevel = firstLevel;
+              $scope.showSubMenu = true;
+            }
+            else {
+              $scope.showSubMenu = !$scope.showSubMenu;
+            }
+          };
+          $scope.closeSubnav = function() {
+            $scope.showSubMenu = false;
+          };
+          $scope.$watch('path', function() {
+            var urlRoot = $location.path().split('/')[1];
+            if (urlRoot != '') {
+              $scope.firstLevel = urlRoot;
+            }
+            else {
+              $scope.firstLevel = 'overview';
+            }
+            $scope.showSubMenu = false;
+          });
+          $scope.$watch('showNavigation', function() {
+            var paddingTop = 0;
+            var urlRoot = $location.path().split('/')[1];
+            if (urlRoot != '') {
+              $scope.firstLevel = urlRoot;
+            }
+            else {
+              $scope.firstLevel = 'overview';
+            }
 
-                        if($scope.showNavigation){
-                            paddingTop = document.getElementById('header__wrapper').offsetHeight;
-                        }
-                        dataService.bodyStyle = {'padding-top': paddingTop + 'px'};
-                        $scope.navStyle = {'top': paddingTop + 'px'};
-                    });
-                }],
-                link: function(scope, element, attributes) {
-                    var rawNavElement = angular.element(element)[0];
-                    angular.element(window.document).bind('click', function(event){
-                       if (rawNavElement.contains(event.target))
-                           return;
-
-                       if(scope.showSubMenu){
-                           scope.$apply(function(){
-                              scope.showSubMenu = false;
-                           });
-                       }
-                   });
-                }
+            if ($scope.showNavigation) {
+              paddingTop = document.getElementById('header__wrapper').offsetHeight;
+            }
+            dataService.bodyStyle = {
+              'padding-top': paddingTop + 'px'
             };
-        });
+            $scope.navStyle = {
+              'top': paddingTop + 'px'
+            };
+          });
+        }],
+        link: function(scope, element, attributes) {
+          var rawNavElement = angular.element(element)[0];
+          angular.element(window.document).bind('click', function(event) {
+            if (rawNavElement.contains(event.target))
+              return;
+
+            if (scope.showSubMenu) {
+              scope.$apply(function() {
+                scope.showSubMenu = false;
+              });
+            }
+          });
+        }
+      };
+    });
 })(window.angular);
diff --git a/app/common/directives/confirm.js b/app/common/directives/confirm.js
index 5bb699a..a542783 100644
--- a/app/common/directives/confirm.js
+++ b/app/common/directives/confirm.js
@@ -1,39 +1,44 @@
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.common.directives')
-        .directive('confirm', ['$timeout', function($timeout){
-            return {
-                'restrict': 'E',
-                'template': require('./confirm.html'),
-                'scope': {
-                   'title': '@',
-                   'message': '@',
-                   'confirm': '=',
-                   'callback': '='
-                },
-                'controller': ['$scope',function($scope){
-                    $scope.cancel = function(){
-                        $scope.confirm = false;
-                        $scope.$parent.confirm = false;
-                    };
-                    $scope.accept = function(){
-                        $scope.callback();
-                        $scope.cancel();
-                    }
-                }],
-                link: function(scope, e) {
-                    scope.$watch('confirm', function(){
-                        if(scope.confirm){
-                            $timeout(function(){
-                                angular.element(e[0].parentNode).css({'min-height': e[0].querySelector('.inline__confirm').offsetHeight + 'px'});
-                            }, 0);
-                        }else{
-                            angular.element(e[0].parentNode).css({'min-height': 0+ 'px'});
-                        }
-                    });
-                }
-            };
-        }]);
+  angular
+    .module('app.common.directives')
+    .directive('confirm', ['$timeout', function($timeout) {
+      return {
+        'restrict': 'E',
+        'template': require('./confirm.html'),
+        'scope': {
+          'title': '@',
+          'message': '@',
+          'confirm': '=',
+          'callback': '='
+        },
+        'controller': ['$scope', function($scope) {
+          $scope.cancel = function() {
+            $scope.confirm = false;
+            $scope.$parent.confirm = false;
+          };
+          $scope.accept = function() {
+            $scope.callback();
+            $scope.cancel();
+          };
+        }],
+        link: function(scope, e) {
+          scope.$watch('confirm', function() {
+            if (scope.confirm) {
+              $timeout(function() {
+                angular.element(e[0].parentNode).css({
+                  'min-height': e[0].querySelector('.inline__confirm').offsetHeight + 'px'
+                });
+              }, 0);
+            }
+            else {
+              angular.element(e[0].parentNode).css({
+                'min-height': 0 + 'px'
+              });
+            }
+          });
+        }
+      };
+    }]);
 })(window.angular);
diff --git a/app/common/directives/errors.js b/app/common/directives/errors.js
index 2c9b109..8123694 100644
--- a/app/common/directives/errors.js
+++ b/app/common/directives/errors.js
@@ -1,18 +1,18 @@
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.common.directives')
-        .directive('errors', ['APIUtils', function (APIUtils) {
-            return {
-                'restrict': 'E',
-                'template': require('./errors.html'),
-                'scope': {
-                   'path': '='
-                },
-                'controller': ['$scope','dataService', function($scope, dataService){
-                    $scope.dataService = dataService;
-                }]
-            };
-        }]);
+  angular
+    .module('app.common.directives')
+    .directive('errors', ['APIUtils', function(APIUtils) {
+      return {
+        'restrict': 'E',
+        'template': require('./errors.html'),
+        'scope': {
+          'path': '='
+        },
+        'controller': ['$scope', 'dataService', function($scope, dataService) {
+          $scope.dataService = dataService;
+        }]
+      };
+    }]);
 })(window.angular);
diff --git a/app/common/directives/file.js b/app/common/directives/file.js
index 11adf8a..8ed6c2e 100644
--- a/app/common/directives/file.js
+++ b/app/common/directives/file.js
@@ -1,21 +1,21 @@
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.common.directives')
-        .directive('file', function () {
-            return {
-                scope: {
-                    file: '='
-                },
-                link: function (scope, el, attrs) {
-                    el.bind('change', function (event) {
-                        var file = event.target.files[0];
-                        scope.file = file ? file : undefined;
-                        scope.$apply();
-                    });
-                }
-            };
-        });
+  angular
+    .module('app.common.directives')
+    .directive('file', function() {
+      return {
+        scope: {
+          file: '='
+        },
+        link: function(scope, el, attrs) {
+          el.bind('change', function(event) {
+            var file = event.target.files[0];
+            scope.file = file ? file : undefined;
+            scope.$apply();
+          });
+        }
+      };
+    });
 
-})(window.angular);
\ No newline at end of file
+})(window.angular);
diff --git a/app/common/directives/firmware-list.js b/app/common/directives/firmware-list.js
index 4cdf6d7..163df82 100644
--- a/app/common/directives/firmware-list.js
+++ b/app/common/directives/firmware-list.js
@@ -1,32 +1,32 @@
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.common.directives')
-        .directive('firmwareList', ['APIUtils', function (APIUtils) {
-            return {
-                'restrict': 'E',
-                'template': require('./firmware-list.html'),
-                'scope': {
-                   'title': '@',
-                   'firmwares': '=',
-                   'filterBy': '=',
-                   'version': '='
-                },
-                'controller': ['$rootScope', '$scope','dataService', '$location', '$timeout', function($rootScope, $scope, dataService, $location, $timeout){
-                    $scope.dataService = dataService;
-                    $scope.activate = function(imageId, imageVersion, imageType){
-                        $scope.$parent.activateImage(imageId, imageVersion, imageType);
-                    }
+  angular
+    .module('app.common.directives')
+    .directive('firmwareList', ['APIUtils', function(APIUtils) {
+      return {
+        'restrict': 'E',
+        'template': require('./firmware-list.html'),
+        'scope': {
+          'title': '@',
+          'firmwares': '=',
+          'filterBy': '=',
+          'version': '='
+        },
+        'controller': ['$rootScope', '$scope', 'dataService', '$location', '$timeout', function($rootScope, $scope, dataService, $location, $timeout) {
+          $scope.dataService = dataService;
+          $scope.activate = function(imageId, imageVersion, imageType) {
+            $scope.$parent.activateImage(imageId, imageVersion, imageType);
+          };
 
-                    $scope.delete = function(imageId, imageVersion){
-                        $scope.$parent.deleteImage(imageId, imageVersion);
-                    }
+          $scope.delete = function(imageId, imageVersion) {
+            $scope.$parent.deleteImage(imageId, imageVersion);
+          };
 
-                    $scope.changePriority = function(imageId, imageVersion, from, to){
-                        $scope.$parent.changePriority(imageId, imageVersion, from, to);
-                    }
-                }]
-            };
-        }]);
+          $scope.changePriority = function(imageId, imageVersion, from, to) {
+            $scope.$parent.changePriority(imageId, imageVersion, from, to);
+          };
+        }]
+      };
+    }]);
 })(window.angular);
diff --git a/app/common/directives/index.js b/app/common/directives/index.js
index 1fed678..33155f4 100644
--- a/app/common/directives/index.js
+++ b/app/common/directives/index.js
@@ -1,9 +1,9 @@
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.common.directives', [
-            'app.common.services'
-        ]);
+  angular
+    .module('app.common.directives', [
+      'app.common.services'
+    ]);
 
 })(window.angular);
diff --git a/app/common/directives/loader.js b/app/common/directives/loader.js
index b37a898..8edc128 100644
--- a/app/common/directives/loader.js
+++ b/app/common/directives/loader.js
@@ -1,16 +1,16 @@
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.common.directives')
-        .directive('loader', function () {
-            return {
-                'restrict': 'E',
-                'template': require('./loader.html'),
-                scope: {
-                    loading: '='
-                }
-            };
-        });
+  angular
+    .module('app.common.directives')
+    .directive('loader', function() {
+      return {
+        'restrict': 'E',
+        'template': require('./loader.html'),
+        scope: {
+          loading: '='
+        }
+      };
+    });
 
 })(window.angular);
diff --git a/app/common/directives/log-event.js b/app/common/directives/log-event.js
index e858239..c48a3ee 100644
--- a/app/common/directives/log-event.js
+++ b/app/common/directives/log-event.js
@@ -1,41 +1,43 @@
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.common.directives')
-        .directive('logEvent', ['APIUtils', function (APIUtils) {
-            return {
-                'restrict': 'E',
-                'template': require('./log-event.html'),
-                'scope': {
-                   'event': '=',
-                   'tmz': '=',
-                   'multiSelected': '='
-                },
-                'controller': ['$rootScope', '$scope','dataService', '$location', '$timeout', function($rootScope, $scope, dataService, $location, $timeout){
-                    $scope.dataService = dataService;
-                    $scope.copySuccess = function (event) {
-                        event.copied = true;
-                        $timeout(function(){
-                            event.copied = false;
-                        }, 5000);
-                    };
-                    $scope.copyFailed = function (err) {
-                        console.error('Error!', err);
-                    };
-                    $scope.resolveEvent = function(event){
-                        APIUtils.resolveLogs([{Id: event.Id}]).then(function(){
-                            event.Resolved = 1;
-                        });
-                    }
+  angular
+    .module('app.common.directives')
+    .directive('logEvent', ['APIUtils', function(APIUtils) {
+      return {
+        'restrict': 'E',
+        'template': require('./log-event.html'),
+        'scope': {
+          'event': '=',
+          'tmz': '=',
+          'multiSelected': '='
+        },
+        'controller': ['$rootScope', '$scope', 'dataService', '$location', '$timeout', function($rootScope, $scope, dataService, $location, $timeout) {
+          $scope.dataService = dataService;
+          $scope.copySuccess = function(event) {
+            event.copied = true;
+            $timeout(function() {
+              event.copied = false;
+            }, 5000);
+          };
+          $scope.copyFailed = function(err) {
+            console.error('Error!', err);
+          };
+          $scope.resolveEvent = function(event) {
+            APIUtils.resolveLogs([{
+              Id: event.Id
+            }]).then(function() {
+              event.Resolved = 1;
+            });
+          };
 
-                    $scope.accept = function(){
-                        $scope.event.selected = true;
-                        $timeout(function(){
-                            $scope.$parent.accept();
-                        }, 10);
-                    }
-                }]
-            };
-        }]);
+          $scope.accept = function() {
+            $scope.event.selected = true;
+            $timeout(function() {
+              $scope.$parent.accept();
+            }, 10);
+          };
+        }]
+      };
+    }]);
 })(window.angular);
diff --git a/app/common/directives/log-filter.js b/app/common/directives/log-filter.js
index 370e666..69bb8e3 100644
--- a/app/common/directives/log-filter.js
+++ b/app/common/directives/log-filter.js
@@ -1,50 +1,51 @@
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.common.directives')
-        .directive('logFilter', ['APIUtils', function (APIUtils) {
-            return {
-                'restrict': 'E',
-                'template': require('./log-filter.html'),
-                'controller': ['$rootScope', '$scope','dataService', '$location', function($rootScope, $scope, dataService, $location){
-                    $scope.dataService = dataService;
-                    $scope.toggleSeverityAll = function(){
-                        $scope.selectedSeverity.all = !$scope.selectedSeverity.all;
+  angular
+    .module('app.common.directives')
+    .directive('logFilter', ['APIUtils', function(APIUtils) {
+      return {
+        'restrict': 'E',
+        'template': require('./log-filter.html'),
+        'controller': ['$rootScope', '$scope', 'dataService', '$location', function($rootScope, $scope, dataService, $location) {
+          $scope.dataService = dataService;
+          $scope.toggleSeverityAll = function() {
+            $scope.selectedSeverity.all = !$scope.selectedSeverity.all;
 
-                        if($scope.selectedSeverity.all){
-                            $scope.selectedSeverity.low = false;
-                            $scope.selectedSeverity.medium = false;
-                            $scope.selectedSeverity.high = false;
-                        }
-                    }
+            if ($scope.selectedSeverity.all) {
+              $scope.selectedSeverity.low = false;
+              $scope.selectedSeverity.medium = false;
+              $scope.selectedSeverity.high = false;
+            }
+          };
 
-                    $scope.toggleSeverity = function(severity){
-                        $scope.selectedSeverity[severity] = !$scope.selectedSeverity[severity];
+          $scope.toggleSeverity = function(severity) {
+            $scope.selectedSeverity[severity] = !$scope.selectedSeverity[severity];
 
-                        if(['high', 'medium', 'low'].indexOf(severity) > -1){
-                            if($scope.selectedSeverity[severity] == false &&
-                               (!$scope.selectedSeverity.low &&
-                                !$scope.selectedSeverity.medium &&
-                                !$scope.selectedSeverity.high
-                               )){
-                                $scope.selectedSeverity.all = true;
-                                return;
-                            }
-                        }
+            if (['high', 'medium', 'low'].indexOf(severity) > -1) {
+              if ($scope.selectedSeverity[severity] == false &&
+                (!$scope.selectedSeverity.low &&
+                  !$scope.selectedSeverity.medium &&
+                  !$scope.selectedSeverity.high
+                )) {
+                $scope.selectedSeverity.all = true;
+                return;
+              }
+            }
 
-                        if($scope.selectedSeverity.low &&
-                           $scope.selectedSeverity.medium &&
-                           $scope.selectedSeverity.high){
-                            $scope.selectedSeverity.all = true;
-                            $scope.selectedSeverity.low = false;
-                            $scope.selectedSeverity.medium = false;
-                            $scope.selectedSeverity.high = false;
-                        }else{
-                            $scope.selectedSeverity.all = false;
-                        }
-                    }
-                }]
-            };
-        }]);
+            if ($scope.selectedSeverity.low &&
+              $scope.selectedSeverity.medium &&
+              $scope.selectedSeverity.high) {
+              $scope.selectedSeverity.all = true;
+              $scope.selectedSeverity.low = false;
+              $scope.selectedSeverity.medium = false;
+              $scope.selectedSeverity.high = false;
+            }
+            else {
+              $scope.selectedSeverity.all = false;
+            }
+          };
+        }]
+      };
+    }]);
 })(window.angular);
diff --git a/app/common/directives/log-search-control.js b/app/common/directives/log-search-control.js
index c610c18..f262f5f 100644
--- a/app/common/directives/log-search-control.js
+++ b/app/common/directives/log-search-control.js
@@ -1,44 +1,46 @@
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.common.directives')
-        .directive('logSearchControl', ['APIUtils', function (APIUtils) {
-            return {
-                'restrict': 'E',
-                'template': require('./log-search-control.html'),
-                'controller': ['$rootScope', '$scope','dataService', '$location', function($rootScope, $scope, dataService, $location){
-                    $scope.dataService = dataService;
-                    $scope.doSearchOnEnter = function (event) {
-                        var search = $scope.customSearch.replace(/^\s+/g,'').replace(/\s+$/g,'');
-                        if (event.keyCode === 13 &&
-                            search.length >= 2) {
-                            $scope.clearSearchItem();
-                            $scope.addSearchItem(search);
-                        }else{
-                            if(search.length == 0){
-                                $scope.clearSearchItem();
-                            }
-                        }
-                    };
+  angular
+    .module('app.common.directives')
+    .directive('logSearchControl', ['APIUtils', function(APIUtils) {
+      return {
+        'restrict': 'E',
+        'template': require('./log-search-control.html'),
+        'controller': ['$rootScope', '$scope', 'dataService', '$location', function($rootScope, $scope, dataService, $location) {
+          $scope.dataService = dataService;
+          $scope.doSearchOnEnter = function(event) {
+            var search = $scope.customSearch.replace(/^\s+/g, '').replace(/\s+$/g, '');
+            if (event.keyCode === 13 &&
+              search.length >= 2) {
+              $scope.clearSearchItem();
+              $scope.addSearchItem(search);
+            }
+            else {
+              if (search.length == 0) {
+                $scope.clearSearchItem();
+              }
+            }
+          };
 
-                    $scope.clear = function(){
-                        $scope.customSearch = "";
-                        $scope.clearSearchItem();
-                    }
+          $scope.clear = function() {
+            $scope.customSearch = '';
+            $scope.clearSearchItem();
+          };
 
-                    $scope.doSearchOnClick = function() {
-                        var search = $scope.customSearch.replace(/^\s+/g,'').replace(/\s+$/g,'');
-                        if (search.length >= 2) {
-                            $scope.clearSearchItem();
-                            $scope.addSearchItem(search);
-                        }else{
-                            if(search.length == 0){
-                                $scope.clearSearchItem();
-                            }
-                        }
-                    }
-                }]
-            };
-        }]);
+          $scope.doSearchOnClick = function() {
+            var search = $scope.customSearch.replace(/^\s+/g, '').replace(/\s+$/g, '');
+            if (search.length >= 2) {
+              $scope.clearSearchItem();
+              $scope.addSearchItem(search);
+            }
+            else {
+              if (search.length == 0) {
+                $scope.clearSearchItem();
+              }
+            }
+          };
+        }]
+      };
+    }]);
 })(window.angular);
diff --git a/app/common/directives/paginate.js b/app/common/directives/paginate.js
index e69de29..8b13789 100644
--- a/app/common/directives/paginate.js
+++ b/app/common/directives/paginate.js
@@ -0,0 +1 @@
+
diff --git a/app/common/directives/toggle-flag.js b/app/common/directives/toggle-flag.js
index 9c342b0..4a4e454 100644
--- a/app/common/directives/toggle-flag.js
+++ b/app/common/directives/toggle-flag.js
@@ -1,31 +1,31 @@
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.common.directives')
-        .directive('toggleFlag', function ($document) {
-            return {
-                restrict: 'A',
-                link: function (scope, element, attrs) {
+  angular
+    .module('app.common.directives')
+    .directive('toggleFlag', function($document) {
+      return {
+        restrict: 'A',
+        link: function(scope, element, attrs) {
 
-                    function elementClick(e) {
-                        e.stopPropagation();
-                    }
+          function elementClick(e) {
+            e.stopPropagation();
+          }
 
-                    function documentClick(e) {
-                        scope[attrs.toggleFlag] = false;
-                        scope.$apply();
-                    }
+          function documentClick(e) {
+            scope[attrs.toggleFlag] = false;
+            scope.$apply();
+          }
 
-                    element.on('click', elementClick);
-                    $document.on('click', documentClick);
+          element.on('click', elementClick);
+          $document.on('click', documentClick);
 
-                    // remove event handlers when directive is destroyed
-                    scope.$on('$destroy', function () {
-                        element.off('click', elementClick);
-                        $document.off('click', documentClick);
-                    });
-                }
-            };
-        });
-})(window.angular);
\ No newline at end of file
+          // remove event handlers when directive is destroyed
+          scope.$on('$destroy', function() {
+            element.off('click', elementClick);
+            $document.off('click', documentClick);
+          });
+        }
+      };
+    });
+})(window.angular);
diff --git a/app/common/filters/index.js b/app/common/filters/index.js
index 5c719fa..f3de907 100644
--- a/app/common/filters/index.js
+++ b/app/common/filters/index.js
@@ -1,25 +1,25 @@
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.common.filters', [])
-        .filter('unResolvedCount', function () {
-            return function (data) {
-               data = data.filter(function(item){
-                  return item.Resolved == 0;
-               });
-               return data.length;
-            }
-        })
-        .filter('quiescedToError', function () {
-            return function (state) {
-               if(state.toLowerCase() == 'quiesced'){
-                  return 'Error';
-               }else{
-                return state;
-               }
-            }
-        })
-        ;
+  angular
+    .module('app.common.filters', [])
+    .filter('unResolvedCount', function() {
+      return function(data) {
+        data = data.filter(function(item) {
+          return item.Resolved == 0;
+        });
+        return data.length;
+      }
+    })
+    .filter('quiescedToError', function() {
+      return function(state) {
+        if (state.toLowerCase() == 'quiesced') {
+          return 'Error';
+        }
+        else {
+          return state;
+        }
+      }
+    });
 
 })(window.angular);
diff --git a/app/common/services/api-utils.js b/app/common/services/api-utils.js
index 13f1406..a024142 100644
--- a/app/common/services/api-utils.js
+++ b/app/common/services/api-utils.js
@@ -6,1134 +6,1233 @@
  * @name APIUtils
  */
 
-window.angular && (function (angular) {
-    'use strict';
-    angular
-        .module('app.common.services')
-        .factory('APIUtils', ['$http', 'Constants', '$q', 'dataService',function($http, Constants, $q, DataService){
-          var getScaledValue = function(value, scale){
-            scale = scale + "";
-            scale = parseInt(scale, 10);
-            var power = Math.abs(parseInt(scale,10));
+window.angular && (function(angular) {
+  'use strict';
+  angular
+    .module('app.common.services')
+    .factory('APIUtils', ['$http', 'Constants', '$q', 'dataService', function($http, Constants, $q, DataService) {
+      var getScaledValue = function(value, scale) {
+        scale = scale + '';
+        scale = parseInt(scale, 10);
+        var power = Math.abs(parseInt(scale, 10));
 
-            if(scale > 0){
-              value = value * Math.pow(10, power);
-            }else if(scale < 0){
-              value = value / Math.pow(10, power);
+        if (scale > 0) {
+          value = value * Math.pow(10, power);
+        }
+        else if (scale < 0) {
+          value = value / Math.pow(10, power);
+        }
+        return value;
+      };
+      var SERVICE = {
+        API_CREDENTIALS: Constants.API_CREDENTIALS,
+        API_RESPONSE: Constants.API_RESPONSE,
+        CHASSIS_POWER_STATE: Constants.CHASSIS_POWER_STATE,
+        HOST_STATE_TEXT: Constants.HOST_STATE,
+        HOST_STATE: Constants.HOST_STATE,
+        LED_STATE: Constants.LED_STATE,
+        LED_STATE_TEXT: Constants.LED_STATE_TEXT,
+        HOST_SESSION_STORAGE_KEY: Constants.API_CREDENTIALS.host_storage_key,
+        getChassisState: function() {
+          var deferred = $q.defer();
+          $http({
+            method: 'GET',
+            url: DataService.getHost() + '/xyz/openbmc_project/state/chassis0/attr/CurrentPowerState',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: true
+          }).then(function(response) {
+            var json = JSON.stringify(response.data);
+            var content = JSON.parse(json);
+            deferred.resolve(content.data);
+          }, function(error) {
+            console.log(error);
+            deferred.reject(error);
+          });
+          return deferred.promise;
+        },
+        getHostState: function() {
+          var deferred = $q.defer();
+          $http({
+            method: 'GET',
+            url: DataService.getHost() + '/xyz/openbmc_project/state/host0/attr/CurrentHostState',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: true
+          }).then(function(response) {
+            var json = JSON.stringify(response.data);
+            var content = JSON.parse(json);
+            deferred.resolve(content.data);
+          }, function(error) {
+            console.log(error);
+            deferred.reject(error);
+          });
+          return deferred.promise;
+        },
+        getNetworkInfo: function() {
+          var deferred = $q.defer();
+          $http({
+            method: 'GET',
+            url: DataService.getHost() + '/xyz/openbmc_project/network/enumerate',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: true
+          }).then(function(response) {
+            var json = JSON.stringify(response.data);
+            var content = JSON.parse(json);
+            var hostname = '';
+            var macAddress = '';
+
+            function parseNetworkData(content) {
+              var data = {
+                interface_ids: [],
+                interfaces: {},
+                ip_addresses: {
+                  ipv4: [],
+                  ipv6: []
+                },
+              };
+              var interfaceId = '',
+                keyParts = [],
+                interfaceHash = '',
+                interfaceType = '';
+              for (var key in content.data) {
+                if (key.match(/network\/eth\d+$/ig)) {
+                  interfaceId = key.split('/').pop();
+                  if (data.interface_ids.indexOf(interfaceId) == -1) {
+                    data.interface_ids.push(interfaceId);
+                    data.interfaces[interfaceId] = {
+                      interfaceIname: '',
+                      DomainName: '',
+                      MACAddress: '',
+                      Nameservers: [],
+                      DHCPEnabled: 0,
+                      ipv4: {
+                        ids: [],
+                        values: []
+                      },
+                      ipv6: {
+                        ids: [],
+                        values: []
+                      }
+                    };
+                    data.interfaces[interfaceId].MACAddress = content.data[key].MACAddress;
+                    data.interfaces[interfaceId].DomainName = content.data[key].DomainName.join(' ');
+                    data.interfaces[interfaceId].Nameservers = content.data[key].Nameservers;
+                    data.interfaces[interfaceId].DHCPEnabled = content.data[key].DHCPEnabled;
+                  }
+                }
+                else if (key.match(/network\/eth\d+\/ipv[4|6]\/[a-z0-9]+$/ig)) {
+                  keyParts = key.split('/');
+                  interfaceHash = keyParts.pop();
+                  interfaceType = keyParts.pop();
+                  interfaceId = keyParts.pop();
+
+                  if (data.interfaces[interfaceId][interfaceType].ids.indexOf(interfaceHash) == -1) {
+                    data.interfaces[interfaceId][interfaceType].ids.push(interfaceHash);
+                    data.interfaces[interfaceId][interfaceType].values.push(content.data[key]);
+                    data.ip_addresses[interfaceType].push(content.data[key]['Address']);
+                  }
+                }
+              }
+              return data;
             }
-            return value;
-          };
-          var SERVICE = {
-              API_CREDENTIALS: Constants.API_CREDENTIALS,
-              API_RESPONSE: Constants.API_RESPONSE,
-              CHASSIS_POWER_STATE: Constants.CHASSIS_POWER_STATE,
-              HOST_STATE_TEXT: Constants.HOST_STATE,
-              HOST_STATE: Constants.HOST_STATE,
-              LED_STATE: Constants.LED_STATE,
-              LED_STATE_TEXT: Constants.LED_STATE_TEXT,
-              HOST_SESSION_STORAGE_KEY: Constants.API_CREDENTIALS.host_storage_key,
-              getChassisState: function(){
-                var deferred = $q.defer();
-                $http({
-                  method: 'GET',
-                  url: DataService.getHost() + "/xyz/openbmc_project/state/chassis0/attr/CurrentPowerState",
-                  headers: {
-                      'Accept': 'application/json',
-                      'Content-Type': 'application/json'
-                  },
-                  withCredentials: true
-                }).then(function(response){
-                      var json = JSON.stringify(response.data);
-                      var content = JSON.parse(json);
-                      deferred.resolve(content.data);
-                }, function(error){
-                  console.log(error);
-                  deferred.reject(error);
+
+            if (content.data.hasOwnProperty('/xyz/openbmc_project/network/config') &&
+              content.data['/xyz/openbmc_project/network/config'].hasOwnProperty('HostName')
+            ) {
+              hostname = content.data['/xyz/openbmc_project/network/config'].HostName;
+            }
+
+            if (content.data.hasOwnProperty('/xyz/openbmc_project/network/eth0') &&
+              content.data['/xyz/openbmc_project/network/eth0'].hasOwnProperty('MACAddress')
+            ) {
+              macAddress = content.data['/xyz/openbmc_project/network/eth0'].MACAddress;
+            }
+
+            deferred.resolve({
+              data: content.data,
+              hostname: hostname,
+              mac_address: macAddress,
+              formatted_data: parseNetworkData(content)
+            });
+          }, function(error) {
+            console.log(error);
+            deferred.reject(error);
+          });
+          return deferred.promise;
+        },
+        getLEDState: function() {
+          var deferred = $q.defer();
+          $http({
+            method: 'GET',
+            url: DataService.getHost() + '/xyz/openbmc_project/led/groups/enclosure_identify',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: true
+          }).then(function(response) {
+            var json = JSON.stringify(response.data);
+            var content = JSON.parse(json);
+            deferred.resolve(content.data.Asserted);
+          }, function(error) {
+            console.log(error);
+            deferred.reject(error);
+          });
+          return deferred.promise;
+        },
+        login: function(username, password, callback) {
+          $http({
+            method: 'POST',
+            url: DataService.getHost() + '/login',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: true,
+            data: JSON.stringify({
+              'data': [username, password]
+            })
+          }).then(function(response) {
+            if (callback) {
+              callback(response.data);
+            }
+          }, function(error) {
+            if (callback) {
+              if (error && error.status && error.status == 'error') {
+                callback(error);
+              }
+              else {
+                callback(error, true);
+              }
+            }
+            console.log(error);
+          });
+        },
+        testPassword: function(username, password) {
+          // Calls /login without the current session to verify the given password is correct
+          // ignore the interceptor logout on a bad password
+          DataService.ignoreHttpError = true;
+          return $http({
+            method: 'POST',
+            url: DataService.getHost() + '/login',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: false,
+            data: JSON.stringify({
+              'data': [username, password]
+            })
+          }).then(function(response) {
+            return response.data;
+          });
+        },
+        logout: function(callback) {
+          $http({
+            method: 'POST',
+            url: DataService.getHost() + '/logout',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: true,
+            data: JSON.stringify({
+              'data': []
+            })
+          }).then(function(response) {
+            if (callback) {
+              callback(response.data);
+            }
+          }, function(error) {
+            if (callback) {
+              callback(null, error);
+            }
+            console.log(error);
+          });
+        },
+        changePassword: function(user, newPassword) {
+          var deferred = $q.defer();
+          $http({
+            method: 'POST',
+            url: DataService.getHost() + '/xyz/openbmc_project/user/' + user + '/action/SetPassword',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: true,
+            data: JSON.stringify({
+              'data': [newPassword]
+            }),
+            responseType: 'arraybuffer'
+          }).then(function(response, status, headers) {
+            deferred.resolve({
+              data: response,
+              status: status,
+              headers: headers
+            });
+          }, function(error) {
+            console.log(error);
+            deferred.reject(error);
+          });
+          return deferred.promise;
+        },
+        chassisPowerOn: function(callback) {
+          $http({
+            method: 'POST',
+            url: DataService.getHost() + '/xyz/openbmc_project/state/host0',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: true,
+            data: JSON.stringify({
+              'data': []
+            })
+          }).then(function(response) {
+            var json = JSON.stringify(response.data);
+            var content = JSON.parse(json);
+            if (callback) {
+              return callback(content.data.CurrentPowerState);
+            }
+          }, function(error) {
+            if (callback) {
+              callback(error);
+            }
+            else {
+              console.log(error);
+            }
+          });
+        },
+        chassisPowerOff: function() {
+          var deferred = $q.defer();
+          $http({
+            method: 'PUT',
+            url: DataService.getHost() + '/xyz/openbmc_project/state/chassis0/attr/RequestedPowerTransition',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: true,
+            data: JSON.stringify({
+              'data': 'xyz.openbmc_project.State.Chassis.Transition.Off'
+            })
+          }).then(function(response) {
+            var json = JSON.stringify(response.data);
+            var content = JSON.parse(json);
+            deferred.resolve(content.status);
+          }, function(error) {
+            console.log(error);
+            deferred.reject(error);
+          });
+          return deferred.promise;
+        },
+        setLEDState: function(state, callback) {
+          $http({
+            method: 'PUT',
+            url: DataService.getHost() + '/xyz/openbmc_project/led/groups/enclosure_identify/attr/Asserted',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: true,
+            data: JSON.stringify({
+              'data': state
+            })
+          }).then(function(response) {
+            var json = JSON.stringify(response.data);
+            var content = JSON.parse(json);
+            if (callback) {
+              return callback(content.status);
+            }
+          }, function(error) {
+            if (callback) {
+              callback(error);
+            }
+            else {
+              console.log(error);
+            }
+          });
+        },
+        bmcReboot: function(callback) {
+          $http({
+            method: 'PUT',
+            url: DataService.getHost() + '/xyz/openbmc_project/state/bmc0/attr/RequestedBmcTransition',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: true,
+            data: JSON.stringify({
+              'data': 'xyz.openbmc_project.State.BMC.Transition.Reboot'
+            })
+          }).then(function(response) {
+            var json = JSON.stringify(response.data);
+            var content = JSON.parse(json);
+            if (callback) {
+              return callback(content.status);
+            }
+          }, function(error) {
+            if (callback) {
+              callback(error);
+            }
+            else {
+              console.log(error);
+            }
+          });
+        },
+        hostPowerOn: function() {
+          var deferred = $q.defer();
+          $http({
+            method: 'PUT',
+            url: DataService.getHost() + '/xyz/openbmc_project/state/host0/attr/RequestedHostTransition',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: true,
+            data: JSON.stringify({
+              'data': 'xyz.openbmc_project.State.Host.Transition.On'
+            })
+          }).then(function(response) {
+            var json = JSON.stringify(response.data);
+            var content = JSON.parse(json);
+            deferred.resolve(content.status);
+          }, function(error) {
+            console.log(error);
+            deferred.reject(error);
+          });
+          return deferred.promise;
+        },
+        hostPowerOff: function() {
+          var deferred = $q.defer();
+          $http({
+            method: 'PUT',
+            url: DataService.getHost() + '/xyz/openbmc_project/state/host0/attr/RequestedHostTransition',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: true,
+            data: JSON.stringify({
+              'data': 'xyz.openbmc_project.State.Host.Transition.Off'
+            })
+          }).then(function(response) {
+            var json = JSON.stringify(response.data);
+            var content = JSON.parse(json);
+            deferred.resolve(content.status);
+          }, function(error) {
+            console.log(error);
+            deferred.reject(error);
+          });
+          return deferred.promise;
+        },
+        hostReboot: function() {
+          var deferred = $q.defer();
+          $http({
+            method: 'PUT',
+            url: DataService.getHost() + '/xyz/openbmc_project/state/host0/attr/RequestedHostTransition',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: true,
+            data: JSON.stringify({
+              'data': 'xyz.openbmc_project.State.Host.Transition.Reboot'
+            })
+          }).then(function(response) {
+            var json = JSON.stringify(response.data);
+            var content = JSON.parse(json);
+            deferred.resolve(content.status);
+          }, function(error) {
+            console.log(error);
+            deferred.reject(error);
+          });
+
+          return deferred.promise;
+        },
+        hostShutdown: function(callback) {
+          $http({
+            method: 'POST',
+            url: DataService.getHost() + '/xyz/openbmc_project/state/host0',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: true,
+            data: JSON.stringify({
+              'data': []
+            })
+          }).then(function(response) {
+            var json = JSON.stringify(response.data);
+            var content = JSON.parse(json);
+            if (callback) {
+              return callback(content);
+            }
+          }, function(error) {
+            if (callback) {
+              callback(error);
+            }
+            else {
+              console.log(error);
+            }
+          });
+        },
+        getLogs: function() {
+          var deferred = $q.defer();
+          $http({
+            method: 'GET',
+            url: DataService.getHost() + '/xyz/openbmc_project/logging/enumerate',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: true
+          }).then(function(response) {
+            var json = JSON.stringify(response.data);
+            var content = JSON.parse(json);
+            var dataClone = JSON.parse(JSON.stringify(content.data));
+            var data = [];
+            var severityCode = '';
+            var priority = '';
+            var health = '';
+            var relatedItems = [];
+
+            for (var key in content.data) {
+              if (content.data.hasOwnProperty(key) && content.data[key].hasOwnProperty('Id')) {
+                var severityFlags = {
+                  low: false,
+                  medium: false,
+                  high: false
+                };
+                var healthFlags = {
+                  critical: false,
+                  warning: false,
+                  good: false
+                };
+                severityCode = content.data[key].Severity.split('.').pop();
+                priority = Constants.SEVERITY_TO_PRIORITY_MAP[severityCode];
+                severityFlags[priority.toLowerCase()] = true;
+                health = Constants.SEVERITY_TO_HEALTH_MAP[severityCode];
+                healthFlags[health.toLowerCase()] = true;
+                relatedItems = [];
+                content.data[key].associations.forEach(function(item) {
+                  relatedItems.push(item[2]);
                 });
-                return deferred.promise;
-              },
-              getHostState: function(){
-                var deferred = $q.defer();
-                $http({
-                  method: 'GET',
-                  url: DataService.getHost() + "/xyz/openbmc_project/state/host0/attr/CurrentHostState",
-                  headers: {
-                      'Accept': 'application/json',
-                      'Content-Type': 'application/json'
-                  },
-                  withCredentials: true
-                }).then(function(response){
-                      var json = JSON.stringify(response.data);
-                      var content = JSON.parse(json);
-                      deferred.resolve(content.data);
-                }, function(error){
-                  console.log(error);
-                  deferred.reject(error);
+
+                data.push(Object.assign({
+                  path: key,
+                  copied: false,
+                  priority: priority,
+                  severity_code: severityCode,
+                  severity_flags: severityFlags,
+                  health_flags: healthFlags,
+                  additional_data: content.data[key].AdditionalData.join('\n'),
+                  type: content.data[key].Message,
+                  selected: false,
+                  search_text: ('#' + content.data[key].Id + ' ' + severityCode + ' ' + content.data[key].Severity + ' ' + content.data[key].AdditionalData.join(' ')).toLowerCase(),
+                  meta: false,
+                  confirm: false,
+                  related_items: relatedItems,
+                  data: {
+                    key: key,
+                    value: content.data[key]
+                  }
+                }, content.data[key]));
+              }
+            }
+            deferred.resolve({
+              data: data,
+              original: dataClone
+            });
+          }, function(error) {
+            console.log(error);
+            deferred.reject(error);
+          });
+
+          return deferred.promise;
+        },
+        getAllSensorStatus: function(callback) {
+          $http({
+            method: 'GET',
+            url: DataService.getHost() + '/xyz/openbmc_project/sensors/enumerate',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: true
+          }).then(function(response) {
+            var json = JSON.stringify(response.data);
+            var content = JSON.parse(json);
+            var dataClone = JSON.parse(JSON.stringify(content.data));
+            var sensorData = [];
+            var severity = {};
+            var title = '';
+            var tempKeyParts = [];
+            var order = 0;
+            var customOrder = 0;
+
+            function getSensorStatus(reading) {
+              var severityFlags = {
+                  critical: false,
+                  warning: false,
+                  normal: false
+                },
+                severityText = '',
+                order = 0;
+
+              if (reading.hasOwnProperty('CriticalLow') &&
+                reading.Value < reading.CriticalLow
+              ) {
+                severityFlags.critical = true;
+                severityText = 'critical';
+                order = 2;
+              }
+              else if (reading.hasOwnProperty('CriticalHigh') &&
+                reading.Value > reading.CriticalHigh
+              ) {
+                severityFlags.critical = true;
+                severityText = 'critical';
+                order = 2;
+              }
+              else if (reading.hasOwnProperty('CriticalLow') &&
+                reading.hasOwnProperty('WarningLow') &&
+                reading.Value >= reading.CriticalLow && reading.Value <= reading.WarningLow) {
+                severityFlags.warning = true;
+                severityText = 'warning';
+                order = 1;
+              }
+              else if (reading.hasOwnProperty('WarningHigh') &&
+                reading.hasOwnProperty('CriticalHigh') &&
+                reading.Value >= reading.WarningHigh && reading.Value <= reading.CriticalHigh) {
+                severityFlags.warning = true;
+                severityText = 'warning';
+                order = 1;
+              }
+              else {
+                severityFlags.normal = true;
+                severityText = 'normal';
+              }
+              return {
+                flags: severityFlags,
+                severityText: severityText,
+                order: order
+              };
+            }
+
+            for (var key in content.data) {
+              if (content.data.hasOwnProperty(key) && content.data[key].hasOwnProperty('Unit')) {
+
+                severity = getSensorStatus(content.data[key]);
+
+                if (!content.data[key].hasOwnProperty('CriticalLow')) {
+                  content.data[key].CriticalLow = '--';
+                  content.data[key].CriticalHigh = '--';
+                }
+
+                if (!content.data[key].hasOwnProperty('WarningLow')) {
+                  content.data[key].WarningLow = '--';
+                  content.data[key].WarningHigh = '--';
+                }
+
+                tempKeyParts = key.split('/');
+                title = tempKeyParts.pop();
+                title = tempKeyParts.pop() + '_' + title;
+                title = title.split('_').map(function(item) {
+                  return item.toLowerCase().charAt(0).toUpperCase() + item.slice(1);
+                }).reduce(function(prev, el) {
+                  return prev + ' ' + el;
                 });
-                return deferred.promise;
-              },
-              getNetworkInfo: function(){
-                var deferred = $q.defer();
-                $http({
-                  method: 'GET',
-                  url: DataService.getHost() + "/xyz/openbmc_project/network/enumerate",
-                  headers: {
-                      'Accept': 'application/json',
-                      'Content-Type': 'application/json'
+
+                content.data[key].Value = getScaledValue(content.data[key].Value, content.data[key].Scale);
+                content.data[key].CriticalLow = getScaledValue(content.data[key].CriticalLow, content.data[key].Scale);
+                content.data[key].CriticalHigh = getScaledValue(content.data[key].CriticalHigh, content.data[key].Scale);
+                content.data[key].WarningLow = getScaledValue(content.data[key].WarningLow, content.data[key].Scale);
+                content.data[key].WarningHigh = getScaledValue(content.data[key].WarningHigh, content.data[key].Scale);
+                if (Constants.SENSOR_SORT_ORDER.indexOf(content.data[key].Unit) > -1) {
+                  customOrder = Constants.SENSOR_SORT_ORDER.indexOf(content.data[key].Unit);
+                }
+                else {
+                  customOrder = Constants.SENSOR_SORT_ORDER_DEFAULT;
+                }
+
+                sensorData.push(Object.assign({
+                  path: key,
+                  selected: false,
+                  confirm: false,
+                  copied: false,
+                  title: title,
+                  unit: Constants.SENSOR_UNIT_MAP[content.data[key].Unit],
+                  severity_flags: severity.flags,
+                  status: severity.severityText,
+                  order: severity.order,
+                  custom_order: customOrder,
+                  search_text: (title + ' ' + content.data[key].Value + ' ' +
+                    Constants.SENSOR_UNIT_MAP[content.data[key].Unit] + ' ' +
+                    severity.severityText + ' ' +
+                    content.data[key].CriticalLow + ' ' +
+                    content.data[key].CriticalHigh + ' ' +
+                    content.data[key].WarningLow + ' ' +
+                    content.data[key].WarningHigh + ' '
+                  ).toLowerCase(),
+                  original_data: {
+                    key: key,
+                    value: content.data[key]
+                  }
+                }, content.data[key]));
+              }
+            }
+
+            callback(sensorData, dataClone);
+          }, function(error) {
+            console.log(error);
+          });
+        },
+        getActivation: function(imageId) {
+          return $http({
+            method: 'GET',
+            url: DataService.getHost() + '/xyz/openbmc_project/software/' + imageId + '/attr/Activation',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: true
+          }).then(function(response) {
+            return response.data;
+          });
+        },
+        getFirmwares: function() {
+          var deferred = $q.defer();
+          $http({
+            method: 'GET',
+            url: DataService.getHost() + '/xyz/openbmc_project/software/enumerate',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: true
+          }).then(function(response) {
+            var json = JSON.stringify(response.data);
+            var content = JSON.parse(json);
+            var data = [];
+            var activationStatus = '';
+            var isExtended = false;
+            var bmcActiveVersion = '';
+            var hostActiveVersion = '';
+            var imageType = '';
+            var extendedVersions = [];
+            var functionalImages = [];
+
+            function getFormatedExtendedVersions(extendedVersion) {
+              var versions = [];
+              extendedVersion = extendedVersion.split(',');
+
+              extendedVersion.forEach(function(item) {
+                var parts = item.split('-');
+                var numberIndex = 0;
+                for (var i = 0; i < parts.length; i++) {
+                  if (/[0-9]/.test(parts[i])) {
+                    numberIndex = i;
+                    break;
+                  }
+                }
+                var titlePart = parts.splice(0, numberIndex);
+                titlePart = titlePart.join('');
+                titlePart = titlePart[0].toUpperCase() + titlePart.substr(1, titlePart.length);
+                var versionPart = parts.join('-');
+                versions.push({
+                  title: titlePart,
+                  version: versionPart
+                });
+              });
+
+              return versions;
+            }
+
+            // Get the list of functional images so we can compare
+            // later if an image is functional
+            if (content.data[Constants.FIRMWARE.FUNCTIONAL_OBJPATH]) {
+              functionalImages = content.data[Constants.FIRMWARE.FUNCTIONAL_OBJPATH].endpoints;
+            }
+            for (var key in content.data) {
+              if (content.data.hasOwnProperty(key) && content.data[key].hasOwnProperty('Version')) {
+                // If the image is "Functional" use that for the
+                // activation status, else use the value of "Activation"
+                // github.com/openbmc/phosphor-dbus-interfaces/blob/master/xyz/openbmc_project/Software/Activation.interface.yaml
+                activationStatus = content.data[key].Activation.split('.').pop();
+                if (functionalImages.includes(key)) {
+                  activationStatus = 'Functional';
+                }
+
+                imageType = content.data[key].Purpose.split('.').pop();
+                isExtended = content.data[key].hasOwnProperty('ExtendedVersion') && content.data[key].ExtendedVersion != '';
+                if (isExtended) {
+                  extendedVersions = getFormatedExtendedVersions(content.data[key].ExtendedVersion);
+                }
+                data.push(Object.assign({
+                  path: key,
+                  activationStatus: activationStatus,
+                  imageId: key.split('/').pop(),
+                  imageType: imageType,
+                  isExtended: isExtended,
+                  extended: {
+                    show: false,
+                    versions: extendedVersions
                   },
-                  withCredentials: true
-                }).then(function(response){
-                    var json = JSON.stringify(response.data);
-                    var content = JSON.parse(json);
-                    var hostname = "";
-                    var macAddress = "";
+                  data: {
+                    key: key,
+                    value: content.data[key]
+                  }
+                }, content.data[key]));
 
-                    function parseNetworkData(content){
-                      var data = {
-                        interface_ids: [],
-                        interfaces: {},
-                        ip_addresses: {ipv4 : [],
-                                       ipv6 : []},
-                      };
-                      var interfaceId = '', keyParts = [], interfaceHash = '', interfaceType = '';
-                      for(var key in content.data){
-                        if(key.match(/network\/eth\d+$/ig)){
-                          interfaceId = key.split("/").pop();
-                          if(data.interface_ids.indexOf(interfaceId) == -1){
-                            data.interface_ids.push(interfaceId);
-                            data.interfaces[interfaceId] = {
-                              interfaceIname: '',
-                              DomainName:'',
-                              MACAddress:'',
-                              Nameservers: [],
-                              DHCPEnabled: 0,
-                              ipv4:
-                                {
-                                 ids: [],
-                                 values: []
-                                },
-                              ipv6:
-                                {
-                                 ids: [],
-                                 values: []
-                                }
-                            };
-                            data.interfaces[interfaceId].MACAddress = content.data[key].MACAddress;
-                            data.interfaces[interfaceId].DomainName = content.data[key].DomainName.join(" ");
-                            data.interfaces[interfaceId].Nameservers = content.data[key].Nameservers;
-                            data.interfaces[interfaceId].DHCPEnabled = content.data[key].DHCPEnabled;
-                          }
-                        }else if(key.match(/network\/eth\d+\/ipv[4|6]\/[a-z0-9]+$/ig)){
-                          keyParts = key.split("/");
-                          interfaceHash = keyParts.pop();
-                          interfaceType = keyParts.pop();
-                          interfaceId = keyParts.pop();
+                if (activationStatus == 'Functional' && imageType == 'BMC') {
+                  bmcActiveVersion = content.data[key].Version;
+                }
 
-                          if(data.interfaces[interfaceId][interfaceType].ids.indexOf(interfaceHash) == -1){
-                            data.interfaces[interfaceId][interfaceType].ids.push(interfaceHash);
-                            data.interfaces[interfaceId][interfaceType].values.push(content.data[key]);
-                            data.ip_addresses[interfaceType].push(content.data[key]['Address']);
-                          }
-                        }
-                      }
-                      return data;
+                if (activationStatus == 'Functional' && imageType == 'Host') {
+                  hostActiveVersion = content.data[key].Version;
+                }
+              }
+            }
+
+            deferred.resolve({
+              data: data,
+              bmcActiveVersion: bmcActiveVersion,
+              hostActiveVersion: hostActiveVersion
+            });
+          }, function(error) {
+            console.log(error);
+            deferred.reject(error);
+          });
+
+          return deferred.promise;
+        },
+        changePriority: function(imageId, priority) {
+          var deferred = $q.defer();
+          $http({
+            method: 'PUT',
+            url: DataService.getHost() + '/xyz/openbmc_project/software/' + imageId + '/attr/Priority',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: true,
+            data: JSON.stringify({
+              'data': priority
+            })
+          }).then(function(response) {
+            var json = JSON.stringify(response.data);
+            var content = JSON.parse(json);
+            deferred.resolve(content);
+          }, function(error) {
+            console.log(error);
+            deferred.reject(error);
+          });
+
+          return deferred.promise;
+        },
+        deleteImage: function(imageId) {
+          var deferred = $q.defer();
+          $http({
+            method: 'POST',
+            url: DataService.getHost() + '/xyz/openbmc_project/software/' + imageId + '/action/Delete',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: true,
+            data: JSON.stringify({
+              'data': []
+            })
+          }).then(function(response) {
+            var json = JSON.stringify(response.data);
+            var content = JSON.parse(json);
+            deferred.resolve(content);
+          }, function(error) {
+            console.log(error);
+            deferred.reject(error);
+          });
+
+          return deferred.promise;
+        },
+        activateImage: function(imageId) {
+          var deferred = $q.defer();
+          $http({
+            method: 'PUT',
+            url: DataService.getHost() + '/xyz/openbmc_project/software/' + imageId + '/attr/RequestedActivation',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: true,
+            data: JSON.stringify({
+              'data': Constants.FIRMWARE.ACTIVATE_FIRMWARE
+            })
+          }).then(function(response) {
+            var json = JSON.stringify(response.data);
+            var content = JSON.parse(json);
+            deferred.resolve(content);
+          }, function(error) {
+            console.log(error);
+            deferred.reject(error);
+          });
+
+          return deferred.promise;
+        },
+        uploadImage: function(file) {
+          return $http({
+            method: 'POST',
+            timeout: 5 * 60 * 1000,
+            url: DataService.getHost() + '/upload/image',
+            headers: {
+              'Content-Type': 'application/octet-stream'
+            },
+            withCredentials: true,
+            data: file
+          }).then(function(response) {
+            return response.data;
+          });
+        },
+        downloadImage: function(host, filename) {
+          return $http({
+            method: 'POST',
+            url: DataService.getHost() + '/xyz/openbmc_project/software/action/DownloadViaTFTP',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: true,
+            data: JSON.stringify({
+              'data': [filename, host]
+            }),
+            responseType: 'arraybuffer'
+          }).then(function(response) {
+            return response.data;
+          });
+        },
+        getBMCEthernetInfo: function() {
+          var deferred = $q.defer();
+          $http({
+            method: 'GET',
+            url: DataService.getHost() + '/xyz/openbmc_project/inventory/system/chassis/motherboard/boxelder/bmc/ethernet',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: true
+          }).then(function(response) {
+            var json = JSON.stringify(response.data);
+            var content = JSON.parse(json);
+            deferred.resolve(content.data);
+          }, function(error) {
+            console.log(error);
+            deferred.reject(error);
+          });
+
+          return deferred.promise;
+        },
+        getBMCInfo: function(callback) {
+          var deferred = $q.defer();
+          $http({
+            method: 'GET',
+            url: DataService.getHost() + '/xyz/openbmc_project/inventory/system/chassis/motherboard/boxelder/bmc',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: true
+          }).then(function(response) {
+            var json = JSON.stringify(response.data);
+            var content = JSON.parse(json);
+            deferred.resolve(content.data);
+          }, function(error) {
+            console.log(error);
+            deferred.reject(error);
+          });
+          return deferred.promise;
+        },
+        getServerInfo: function() {
+          // TODO: openbmc/openbmc#3117 Need a way via REST to get
+          // interfaces so we can get the system object(s) by the looking
+          // for the system interface.
+          return $http({
+            method: 'GET',
+            url: DataService.getHost() + '/xyz/openbmc_project/inventory/system',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: true
+          }).then(function(response) {
+            return response.data;
+          });
+        },
+        getBMCTime: function() {
+          return $http({
+            method: 'GET',
+            url: DataService.getHost() + '/xyz/openbmc_project/time/bmc',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: true
+          }).then(function(response) {
+            return response.data;
+          });
+        },
+        getHardwares: function(callback) {
+          $http({
+            method: 'GET',
+            url: DataService.getHost() + '/xyz/openbmc_project/inventory/enumerate',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: true
+          }).then(function(response) {
+            var json = JSON.stringify(response.data);
+            var content = JSON.parse(json);
+            var hardwareData = [];
+            var keyIndexMap = {};
+            var title = '';
+            var data = [];
+            var searchText = '';
+            var componentIndex = -1;
+            var tempParts = [];
+
+
+            function isSubComponent(key) {
+
+              for (var i = 0; i < Constants.HARDWARE.parent_components.length; i++) {
+                if (key.split(Constants.HARDWARE.parent_components[i]).length == 2) return true;
+              }
+
+              return false;
+            }
+
+            function titlelize(title) {
+              title = title.replace(/([A-Z0-9]+)/g, ' $1').replace(/^\s+/, '');
+              for (var i = 0; i < Constants.HARDWARE.uppercase_titles.length; i++) {
+                if (title.toLowerCase().indexOf((Constants.HARDWARE.uppercase_titles[i] + ' ')) > -1) {
+                  return title.toUpperCase();
+                }
+              }
+
+              return title;
+            }
+
+            function camelcaseToLabel(obj) {
+              var transformed = [],
+                label = '',
+                value = '';
+              for (var key in obj) {
+                label = key.replace(/([A-Z0-9]+)/g, ' $1').replace(/^\s+/, '');
+                if (obj[key] !== '') {
+                  value = obj[key];
+                  if (value == 1 || value == 0) {
+                    value = (value == 1) ? 'Yes' : 'No';
+                  }
+                  transformed.push({
+                    key: label,
+                    value: value
+                  });
+                }
+              }
+
+              return transformed;
+            }
+
+            function getSearchText(data) {
+              var searchText = '';
+              for (var i = 0; i < data.length; i++) {
+                searchText += ' ' + data[i].key + ' ' + data[i].value;
+              }
+
+              return searchText;
+            }
+
+            for (var key in content.data) {
+              if (content.data.hasOwnProperty(key) &&
+                key.indexOf(Constants.HARDWARE.component_key_filter) == 0) {
+
+                data = camelcaseToLabel(content.data[key]);
+                searchText = getSearchText(data);
+                title = key.split('/').pop();
+
+                title = titlelize(title);
+
+                if (!isSubComponent(key)) {
+                  hardwareData.push(Object.assign({
+                    path: key,
+                    title: title,
+                    selected: false,
+                    expanded: false,
+                    search_text: title.toLowerCase() + ' ' + searchText.toLowerCase(),
+                    sub_components: [],
+                    original_data: {
+                      key: key,
+                      value: content.data[key]
                     }
+                  }, {
+                    items: data
+                  }));
 
-                    if(content.data.hasOwnProperty('/xyz/openbmc_project/network/config') &&
-                      content.data['/xyz/openbmc_project/network/config'].hasOwnProperty('HostName')
-                      ){
-                      hostname = content.data['/xyz/openbmc_project/network/config'].HostName;
-                    }
+                  keyIndexMap[key] = hardwareData.length - 1;
+                }
+                else {
+                  var tempParts = key.split('/');
+                  tempParts.pop();
+                  tempParts = tempParts.join('/');
+                  componentIndex = keyIndexMap[tempParts];
+                  data = content.data[key];
+                  data.title = title;
+                  hardwareData[componentIndex].sub_components.push(data);
+                  hardwareData[componentIndex].search_text += ' ' + title.toLowerCase();
 
-                    if(content.data.hasOwnProperty('/xyz/openbmc_project/network/eth0') &&
-                      content.data['/xyz/openbmc_project/network/eth0'].hasOwnProperty('MACAddress')
-                      ){
-                      macAddress = content.data['/xyz/openbmc_project/network/eth0'].MACAddress;
-                    }
-
-                    deferred.resolve({
-                      data: content.data,
-                      hostname: hostname,
-                      mac_address: macAddress,
-                      formatted_data: parseNetworkData(content)
+                  // Sort the subcomponents alphanumeric so they are displayed on the
+                  // inventory page in order (e.g. core 0, core 1, core 2, ... core 12, core 13)
+                  hardwareData[componentIndex].sub_components.sort(function(a, b) {
+                    return a.title.localeCompare(b.title, 'en', {
+                      numeric: true
                     });
-                }, function(error){
-                  console.log(error);
-                  deferred.reject(error);
-                });
-                return deferred.promise;
-              },
-              getLEDState: function(){
-                var deferred = $q.defer();
-                $http({
-                  method: 'GET',
-                  url: DataService.getHost() + "/xyz/openbmc_project/led/groups/enclosure_identify",
-                  headers: {
-                      'Accept': 'application/json',
-                      'Content-Type': 'application/json'
-                  },
-                  withCredentials: true
-                }).then(function(response){
-                    var json = JSON.stringify(response.data);
-                    var content = JSON.parse(json);
-                    deferred.resolve(content.data.Asserted);
-                }, function(error){
-                  console.log(error);
-                  deferred.reject(error);
-                });
-                return deferred.promise;
-              },
-              login: function(username, password, callback){
-                $http({
-                  method: 'POST',
-                  url: DataService.getHost() + "/login",
-                  headers: {
-                      'Accept': 'application/json',
-                      'Content-Type': 'application/json'
-                  },
-                  withCredentials: true,
-                  data: JSON.stringify({"data": [username, password]})
-                }).then(function(response){
-                  if(callback){
-                      callback(response.data);
-                  }
-                }, function(error){
-                  if(callback){
-                      if(error && error.status && error.status == 'error'){
-                        callback(error);
-                      }else{
-                        callback(error, true);
-                      }
-                  }
-                  console.log(error);
-                });
-              },
-              testPassword: function(username, password){
-                // Calls /login without the current session to verify the given password is correct
-                // ignore the interceptor logout on a bad password
-                DataService.ignoreHttpError = true;
-                return $http({
-                  method: 'POST',
-                  url: DataService.getHost() + "/login",
-                  headers: {
-                    'Accept': 'application/json',
-                    'Content-Type': 'application/json'
-                  },
-                  withCredentials: false,
-                  data: JSON.stringify({"data": [username, password]})
-                }).then(function(response){
-                  return response.data;
-                });
-              },
-              logout: function(callback){
-                $http({
-                  method: 'POST',
-                  url: DataService.getHost() + "/logout",
-                  headers: {
-                      'Accept': 'application/json',
-                      'Content-Type': 'application/json'
-                  },
-                  withCredentials: true,
-                  data: JSON.stringify({"data": []})
-                }).then(function(response){
-                  if(callback){
-                      callback(response.data);
-                  }
-                }, function(error){
-                  if(callback){
-                      callback(null, error);
-                  }
-                  console.log(error);
-                });
-              },
-              changePassword: function(user, newPassword){
-                var deferred = $q.defer();
-                $http({
-                  method: 'POST',
-                  url: DataService.getHost() + "/xyz/openbmc_project/user/" + user + "/action/SetPassword",
-                  headers: {
-                    'Accept': 'application/json',
-                    'Content-Type': 'application/json'
-                  },
-                  withCredentials: true,
-                  data: JSON.stringify({"data": [newPassword]}),
-                  responseType: 'arraybuffer'
-                }).then(function(response, status, headers){
-                  deferred.resolve({
-                    data: response,
-                    status: status,
-                    headers: headers
                   });
-                }, function(error){
-                  console.log(error);
-                  deferred.reject(error);
-                });
-                return deferred.promise;
+                }
+              }
+            }
+
+            if (callback) {
+              callback(hardwareData, content.data);
+            }
+            else {
+              return {
+                data: hardwareData,
+                original_data: content.data
+              };
+            }
+          });
+        },
+        deleteLogs: function(logs) {
+          var defer = $q.defer();
+          var promises = [];
+
+          function finished() {
+            defer.resolve();
+          }
+
+          logs.forEach(function(item) {
+            promises.push($http({
+              method: 'POST',
+              url: DataService.getHost() + '/xyz/openbmc_project/logging/entry/' + item.Id + '/action/Delete',
+              headers: {
+                'Accept': 'application/json',
+                'Content-Type': 'application/json'
               },
-              chassisPowerOn: function(callback){
-                $http({
-                  method: 'POST',
-                  url: DataService.getHost() + "/xyz/openbmc_project/state/host0",
-                  headers: {
-                      'Accept': 'application/json',
-                      'Content-Type': 'application/json'
-                  },
-                  withCredentials: true,
-                  data: JSON.stringify({"data": []})
-                }).then(function(response){
-                      var json = JSON.stringify(response.data);
-                      var content = JSON.parse(json);
-                      if(callback){
-                          return callback(content.data.CurrentPowerState);
-                      }
-                }, function(error){
-                  if(callback){
-                      callback(error);
-                  }else{
-                      console.log(error);
-                  }
-                });
+              withCredentials: true,
+              data: JSON.stringify({
+                'data': []
+              })
+            }));
+          });
+
+          $q.all(promises).then(finished);
+
+          return defer.promise;
+        },
+        resolveLogs: function(logs) {
+          var defer = $q.defer();
+          var promises = [];
+
+          function finished() {
+            defer.resolve();
+          }
+
+          logs.forEach(function(item) {
+            promises.push($http({
+              method: 'PUT',
+              url: DataService.getHost() + '/xyz/openbmc_project/logging/entry/' + item.Id + '/attr/Resolved',
+              headers: {
+                'Accept': 'application/json',
+                'Content-Type': 'application/json'
               },
-              chassisPowerOff: function(){
-                var deferred = $q.defer();
-                $http({
-                  method: 'PUT',
-                  url: DataService.getHost() + "/xyz/openbmc_project/state/chassis0/attr/RequestedPowerTransition",
-                  headers: {
-                      'Accept': 'application/json',
-                      'Content-Type': 'application/json'
-                  },
-                  withCredentials: true,
-                  data: JSON.stringify({"data": "xyz.openbmc_project.State.Chassis.Transition.Off"})
-                }).then(function(response){
-                      var json = JSON.stringify(response.data);
-                      var content = JSON.parse(json);
-                      deferred.resolve(content.status);
-                }, function(error){
-                  console.log(error);
-                  deferred.reject(error);
-                });
-                return deferred.promise;
-              },
-              setLEDState: function(state, callback){
-                $http({
-                  method: 'PUT',
-                  url: DataService.getHost() + "/xyz/openbmc_project/led/groups/enclosure_identify/attr/Asserted",
-                  headers: {
-                      'Accept': 'application/json',
-                      'Content-Type': 'application/json'
-                  },
-                  withCredentials: true,
-                  data: JSON.stringify({"data": state})
-                }).then(function(response){
-                      var json = JSON.stringify(response.data);
-                      var content = JSON.parse(json);
-                      if(callback){
-                          return callback(content.status);
-                      }
-                }, function(error){
-                  if(callback){
-                      callback(error);
-                  }else{
-                      console.log(error);
-                  }
-                });
-              },
-              bmcReboot: function(callback){
-                $http({
-                  method: 'PUT',
-                  url: DataService.getHost() + "/xyz/openbmc_project/state/bmc0/attr/RequestedBmcTransition",
-                  headers: {
-                      'Accept': 'application/json',
-                      'Content-Type': 'application/json'
-                  },
-                  withCredentials: true,
-                  data: JSON.stringify({"data": "xyz.openbmc_project.State.BMC.Transition.Reboot"})
-                }).then(function(response){
-                      var json = JSON.stringify(response.data);
-                      var content = JSON.parse(json);
-                      if(callback){
-                          return callback(content.status);
-                      }
-                }, function(error){
-                  if(callback){
-                      callback(error);
-                  }else{
-                      console.log(error);
-                  }
-                });
-              },
-              hostPowerOn: function(){
-                var deferred = $q.defer();
-                $http({
-                  method: 'PUT',
-                  url: DataService.getHost() + "/xyz/openbmc_project/state/host0/attr/RequestedHostTransition",
-                  headers: {
-                      'Accept': 'application/json',
-                      'Content-Type': 'application/json'
-                  },
-                  withCredentials: true,
-                  data: JSON.stringify({"data": "xyz.openbmc_project.State.Host.Transition.On"})
-                }).then(function(response){
-                      var json = JSON.stringify(response.data);
-                      var content = JSON.parse(json);
-                      deferred.resolve(content.status);
-                }, function(error){
-                  console.log(error);
-                  deferred.reject(error);
-                });
-                return deferred.promise;
-              },
-              hostPowerOff: function(){
-                var deferred = $q.defer();
-                $http({
-                  method: 'PUT',
-                  url: DataService.getHost() + "/xyz/openbmc_project/state/host0/attr/RequestedHostTransition",
-                  headers: {
-                      'Accept': 'application/json',
-                      'Content-Type': 'application/json'
-                  },
-                  withCredentials: true,
-                  data: JSON.stringify({"data": "xyz.openbmc_project.State.Host.Transition.Off"})
-                }).then(function(response){
-                      var json = JSON.stringify(response.data);
-                      var content = JSON.parse(json);
-                      deferred.resolve(content.status);
-                }, function(error){
-                  console.log(error);
-                  deferred.reject(error);
-                });
-                return deferred.promise;
-              },
-              hostReboot: function(){
-                var deferred = $q.defer();
-                $http({
-                  method: 'PUT',
-                  url: DataService.getHost() + "/xyz/openbmc_project/state/host0/attr/RequestedHostTransition",
-                  headers: {
-                      'Accept': 'application/json',
-                      'Content-Type': 'application/json'
-                  },
-                  withCredentials: true,
-                  data: JSON.stringify({"data": "xyz.openbmc_project.State.Host.Transition.Reboot"})
-                }).then(function(response){
-                      var json = JSON.stringify(response.data);
-                      var content = JSON.parse(json);
-                      deferred.resolve(content.status);
-                }, function(error){
-                  console.log(error);
-                  deferred.reject(error);
-                });
+              withCredentials: true,
+              data: JSON.stringify({
+                'data': '1'
+              })
+            }));
+          });
 
-                return deferred.promise;
-              },
-              hostShutdown: function(callback){
-                $http({
-                  method: 'POST',
-                  url: DataService.getHost() + "/xyz/openbmc_project/state/host0",
-                  headers: {
-                      'Accept': 'application/json',
-                      'Content-Type': 'application/json'
-                  },
-                  withCredentials: true,
-                  data: JSON.stringify({"data": []})
-                }).then(function(response){
-                      var json = JSON.stringify(response.data);
-                      var content = JSON.parse(json);
-                      if(callback){
-                          return callback(content);
-                      }
-                }, function(error){
-                  if(callback){
-                      callback(error);
-                  }else{
-                      console.log(error);
-                  }
-                });
-              },
-              getLogs: function(){
-                var deferred = $q.defer();
-                $http({
-                  method: 'GET',
-                  url: DataService.getHost() + "/xyz/openbmc_project/logging/enumerate",
-                  headers: {
-                      'Accept': 'application/json',
-                      'Content-Type': 'application/json'
-                  },
-                  withCredentials: true
-                }).then(function(response){
-                      var json = JSON.stringify(response.data);
-                      var content = JSON.parse(json);
-                      var dataClone = JSON.parse(JSON.stringify(content.data));
-                      var data = [];
-                      var severityCode = '';
-                      var priority = '';
-                      var health = '';
-                      var relatedItems = [];
+          $q.all(promises).then(finished);
 
-                      for(var key in content.data){
-                        if(content.data.hasOwnProperty(key) && content.data[key].hasOwnProperty('Id')){
-                          var severityFlags = {low: false, medium: false, high: false};
-                          var healthFlags = {critical: false, warning: false, good: false};
-                          severityCode = content.data[key].Severity.split(".").pop();
-                          priority = Constants.SEVERITY_TO_PRIORITY_MAP[severityCode];
-                          severityFlags[priority.toLowerCase()] = true;
-                          health = Constants.SEVERITY_TO_HEALTH_MAP[severityCode];
-                          healthFlags[health.toLowerCase()] = true;
-                          relatedItems = [];
-                          content.data[key].associations.forEach(function(item){
-                            relatedItems.push(item[2]);
-                          });
+          return defer.promise;
+        },
+        getPowerConsumption: function() {
+          return $http({
+            method: 'GET',
+            url: DataService.getHost() + '/xyz/openbmc_project/sensors/power/total_power',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: true
+          }).then(function(response) {
+            var json = JSON.stringify(response.data);
+            var content = JSON.parse(json);
 
-                          data.push(Object.assign({
-                            path: key,
-                            copied: false,
-                            priority: priority,
-                            severity_code: severityCode,
-                            severity_flags: severityFlags,
-                            health_flags: healthFlags,
-                            additional_data: content.data[key].AdditionalData.join("\n"),
-                            type: content.data[key].Message,
-                            selected: false,
-                            search_text: ("#" + content.data[key].Id + " " + severityCode + " " + content.data[key].Severity + " " + content.data[key].AdditionalData.join(" ")).toLowerCase(),
-                            meta: false,
-                            confirm: false,
-                            related_items: relatedItems,
-                            data: {key: key, value: content.data[key]}
-                          }, content.data[key]));
-                        }
-                      }
-                      deferred.resolve({data: data, original: dataClone});
-                }, function(error){
-                  console.log(error);
-                  deferred.reject(error);
-                });
+            return getScaledValue(content.data.Value,
+                content.data.Scale) + ' ' +
+              Constants.POWER_CONSUMPTION_TEXT[content.data.Unit];
+          }, function(error) {
+            if ('Not Found' == error.statusText) {
+              return Constants.POWER_CONSUMPTION_TEXT.notavailable;
+            }
+            else {
+              throw error;
+            }
+          });
+        },
+        getPowerCap: function() {
+          return $http({
+            method: 'GET',
+            url: DataService.getHost() + '/xyz/openbmc_project/control/host0/power_cap',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: true
+          }).then(function(response) {
+            var json = JSON.stringify(response.data);
+            var content = JSON.parse(json);
 
-                return deferred.promise;
-              },
-              getAllSensorStatus: function(callback){
-                $http({
-                  method: 'GET',
-                  url: DataService.getHost() + "/xyz/openbmc_project/sensors/enumerate",
-                  headers: {
-                      'Accept': 'application/json',
-                      'Content-Type': 'application/json'
-                  },
-                  withCredentials: true
-                }).then(function(response){
-                      var json = JSON.stringify(response.data);
-                      var content = JSON.parse(json);
-                      var dataClone = JSON.parse(JSON.stringify(content.data));
-                      var sensorData = [];
-                      var severity = {};
-                      var title = "";
-                      var tempKeyParts = [];
-                      var order = 0;
-                      var customOrder = 0;
+            return (false == content.data.PowerCapEnable) ?
+              Constants.POWER_CAP_TEXT.disabled :
+              content.data.PowerCap + ' ' + Constants.POWER_CAP_TEXT.unit;
+          });
+        },
+        setHostname: function(hostname) {
+          return $http({
+            method: 'PUT',
+            url: DataService.getHost() + '/xyz/openbmc_project/network/config/attr/HostName',
+            headers: {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+            },
+            withCredentials: true,
+            data: JSON.stringify({
+              'data': hostname
+            })
+          }).then(function(response) {
+            return response.data;
+          });
+        },
+      };
+      return SERVICE;
+    }]);
 
-                      function getSensorStatus(reading){
-                        var severityFlags = {critical: false, warning: false, normal: false}, severityText = '', order = 0;
-
-                        if(reading.hasOwnProperty('CriticalLow') &&
-                          reading.Value < reading.CriticalLow
-                          ){
-                          severityFlags.critical = true;
-                          severityText = 'critical';
-                          order = 2;
-                        }else if(reading.hasOwnProperty('CriticalHigh') &&
-                          reading.Value > reading.CriticalHigh
-                          ){
-                          severityFlags.critical = true;
-                          severityText = 'critical';
-                          order = 2;
-                        }else if(reading.hasOwnProperty('CriticalLow') &&
-                          reading.hasOwnProperty('WarningLow') &&
-                          reading.Value >= reading.CriticalLow && reading.Value <= reading.WarningLow){
-                          severityFlags.warning = true;
-                          severityText = 'warning';
-                          order = 1;
-                        }else if(reading.hasOwnProperty('WarningHigh') &&
-                          reading.hasOwnProperty('CriticalHigh') &&
-                          reading.Value >= reading.WarningHigh && reading.Value <= reading.CriticalHigh){
-                          severityFlags.warning = true;
-                          severityText = 'warning';
-                          order = 1;
-                        }else{
-                          severityFlags.normal = true;
-                          severityText = 'normal';
-                        }
-                        return { flags: severityFlags, severityText: severityText, order: order};
-                      }
-
-                      for(var key in content.data){
-                        if(content.data.hasOwnProperty(key) && content.data[key].hasOwnProperty('Unit')){
-
-                          severity = getSensorStatus(content.data[key]);
-
-                          if(!content.data[key].hasOwnProperty('CriticalLow')){
-                            content.data[key].CriticalLow = "--";
-                            content.data[key].CriticalHigh = "--";
-                          }
-
-                          if(!content.data[key].hasOwnProperty('WarningLow')){
-                            content.data[key].WarningLow = "--";
-                            content.data[key].WarningHigh = "--";
-                          }
-
-                          tempKeyParts = key.split("/");
-                          title = tempKeyParts.pop();
-                          title = tempKeyParts.pop() + '_' + title;
-                          title = title.split("_").map(function(item){
-                             return item.toLowerCase().charAt(0).toUpperCase() + item.slice(1);
-                          }).reduce(function(prev, el){
-                            return prev + " " + el;
-                          });
-
-                          content.data[key].Value = getScaledValue(content.data[key].Value, content.data[key].Scale);
-                          content.data[key].CriticalLow = getScaledValue(content.data[key].CriticalLow, content.data[key].Scale);
-                          content.data[key].CriticalHigh = getScaledValue(content.data[key].CriticalHigh, content.data[key].Scale);
-                          content.data[key].WarningLow = getScaledValue(content.data[key].WarningLow, content.data[key].Scale);
-                          content.data[key].WarningHigh = getScaledValue(content.data[key].WarningHigh, content.data[key].Scale);
-                          if(Constants.SENSOR_SORT_ORDER.indexOf(content.data[key].Unit) > -1){
-                            customOrder = Constants.SENSOR_SORT_ORDER.indexOf(content.data[key].Unit);
-                          }else{
-                            customOrder = Constants.SENSOR_SORT_ORDER_DEFAULT;
-                          }
-
-                          sensorData.push(Object.assign({
-                            path: key,
-                            selected: false,
-                            confirm: false,
-                            copied: false,
-                            title: title,
-                            unit: Constants.SENSOR_UNIT_MAP[content.data[key].Unit],
-                            severity_flags: severity.flags,
-                            status: severity.severityText,
-                            order: severity.order,
-                            custom_order: customOrder,
-                            search_text: (title + " " + content.data[key].Value + " " +
-                               Constants.SENSOR_UNIT_MAP[content.data[key].Unit] + " " +
-                               severity.severityText + " " +
-                               content.data[key].CriticalLow + " " +
-                               content.data[key].CriticalHigh + " " +
-                               content.data[key].WarningLow + " " +
-                               content.data[key].WarningHigh + " "
-                               ).toLowerCase(),
-                            original_data: {key: key, value: content.data[key]}
-                          }, content.data[key]));
-                        }
-                      }
-
-                      callback(sensorData, dataClone);
-                }, function(error){
-                  console.log(error);
-                });
-              },
-              getActivation: function(imageId){
-                return $http({
-                  method: 'GET',
-                  url: DataService.getHost() + "/xyz/openbmc_project/software/" + imageId + "/attr/Activation",
-                  headers: {
-                    'Accept': 'application/json',
-                    'Content-Type': 'application/json'
-                  },
-                  withCredentials: true
-                }).then(function(response){
-                  return response.data;
-                });
-              },
-              getFirmwares: function(){
-                var deferred = $q.defer();
-                $http({
-                  method: 'GET',
-                  url: DataService.getHost() + "/xyz/openbmc_project/software/enumerate",
-                  headers: {
-                      'Accept': 'application/json',
-                      'Content-Type': 'application/json'
-                  },
-                  withCredentials: true
-                }).then(function(response){
-                      var json = JSON.stringify(response.data);
-                      var content = JSON.parse(json);
-                      var data = [];
-                      var activationStatus = "";
-                      var isExtended = false;
-                      var bmcActiveVersion = "";
-                      var hostActiveVersion = "";
-                      var imageType = "";
-                      var extendedVersions = [];
-                      var functionalImages = [];
-
-                      function getFormatedExtendedVersions(extendedVersion){
-                        var versions = [];
-                        extendedVersion = extendedVersion.split(",");
-
-                        extendedVersion.forEach(function(item){
-                          var parts = item.split("-");
-                          var numberIndex = 0;
-                          for(var i = 0; i < parts.length; i++){
-                            if(/[0-9]/.test(parts[i])){
-                              numberIndex = i;
-                              break;
-                            }
-                          }
-                          var titlePart = parts.splice(0, numberIndex);
-                          titlePart = titlePart.join("");
-                          titlePart = titlePart[0].toUpperCase() + titlePart.substr(1, titlePart.length);
-                          var versionPart = parts.join("-");
-                          versions.push({
-                            title: titlePart,
-                            version: versionPart
-                          });
-                        });
-
-                        return versions;
-                      }
-
-                      // Get the list of functional images so we can compare
-                      // later if an image is functional
-                      if (content.data[Constants.FIRMWARE.FUNCTIONAL_OBJPATH])
-                      {
-                        functionalImages = content.data[Constants.FIRMWARE.FUNCTIONAL_OBJPATH].endpoints;
-                      }
-                      for(var key in content.data){
-                        if(content.data.hasOwnProperty(key) && content.data[key].hasOwnProperty('Version')){
-                          // If the image is "Functional" use that for the
-                          // activation status, else use the value of "Activation"
-                          // github.com/openbmc/phosphor-dbus-interfaces/blob/master/xyz/openbmc_project/Software/Activation.interface.yaml
-                          activationStatus = content.data[key].Activation.split(".").pop();
-                          if (functionalImages.includes(key))
-                          {
-                            activationStatus = "Functional";
-                          }
-
-                          imageType = content.data[key].Purpose.split(".").pop();
-                          isExtended = content.data[key].hasOwnProperty('ExtendedVersion') && content.data[key].ExtendedVersion != "";
-                          if(isExtended){
-                            extendedVersions = getFormatedExtendedVersions(content.data[key].ExtendedVersion);
-                          }
-                          data.push(Object.assign({
-                            path: key,
-                            activationStatus: activationStatus,
-                            imageId: key.split("/").pop(),
-                            imageType: imageType,
-                            isExtended: isExtended,
-                            extended: {
-                              show: false,
-                              versions: extendedVersions
-                            },
-                            data: {key: key, value: content.data[key]}
-                          }, content.data[key]));
-
-                          if(activationStatus == 'Functional' && imageType == 'BMC'){
-                            bmcActiveVersion = content.data[key].Version;
-                          }
-
-                          if(activationStatus == 'Functional' && imageType == 'Host'){
-                            hostActiveVersion = content.data[key].Version;
-                          }
-                        }
-                      }
-
-                      deferred.resolve({
-                          data: data,
-                          bmcActiveVersion: bmcActiveVersion,
-                          hostActiveVersion: hostActiveVersion
-                      });
-                }, function(error){
-                  console.log(error);
-                  deferred.reject(error);
-                });
-
-                return deferred.promise;
-              },
-              changePriority: function(imageId, priority){
-                var deferred = $q.defer();
-                $http({
-                  method: 'PUT',
-                  url: DataService.getHost() + "/xyz/openbmc_project/software/" + imageId + "/attr/Priority",
-                  headers: {
-                      'Accept': 'application/json',
-                      'Content-Type': 'application/json'
-                  },
-                  withCredentials: true,
-                  data: JSON.stringify({"data": priority})
-                }).then(function(response){
-                      var json = JSON.stringify(response.data);
-                      var content = JSON.parse(json);
-                      deferred.resolve(content);
-                }, function(error){
-                  console.log(error);
-                  deferred.reject(error);
-                });
-
-                return deferred.promise;
-              },
-              deleteImage: function(imageId){
-                var deferred = $q.defer();
-                $http({
-                  method: 'POST',
-                  url: DataService.getHost() + "/xyz/openbmc_project/software/" + imageId + "/action/Delete",
-                  headers: {
-                      'Accept': 'application/json',
-                      'Content-Type': 'application/json'
-                  },
-                  withCredentials: true,
-                  data: JSON.stringify({"data": []})
-                }).then(function(response){
-                      var json = JSON.stringify(response.data);
-                      var content = JSON.parse(json);
-                      deferred.resolve(content);
-                }, function(error){
-                  console.log(error);
-                  deferred.reject(error);
-                });
-
-                return deferred.promise;
-              },
-              activateImage: function(imageId){
-                var deferred = $q.defer();
-                $http({
-                  method: 'PUT',
-                  url: DataService.getHost() + "/xyz/openbmc_project/software/" + imageId + "/attr/RequestedActivation",
-                  headers: {
-                      'Accept': 'application/json',
-                      'Content-Type': 'application/json'
-                  },
-                  withCredentials: true,
-                  data: JSON.stringify({"data": Constants.FIRMWARE.ACTIVATE_FIRMWARE})
-                }).then(function(response){
-                      var json = JSON.stringify(response.data);
-                      var content = JSON.parse(json);
-                      deferred.resolve(content);
-                }, function(error){
-                  console.log(error);
-                  deferred.reject(error);
-                });
-
-                return deferred.promise;
-              },
-              uploadImage: function(file){
-                return $http({
-                  method: 'POST',
-                  timeout: 5 * 60 * 1000,
-                  url: DataService.getHost() + "/upload/image",
-                  headers: {
-                    'Content-Type': 'application/octet-stream'
-                  },
-                  withCredentials: true,
-                  data: file
-                }).then(function(response){
-                  return response.data;
-                });
-              },
-              downloadImage: function(host, filename){
-                return $http({
-                  method: 'POST',
-                  url: DataService.getHost() + "/xyz/openbmc_project/software/action/DownloadViaTFTP",
-                  headers: {
-                    'Accept': 'application/json',
-                    'Content-Type': 'application/json'
-                  },
-                  withCredentials: true,
-                  data: JSON.stringify({"data": [filename, host]}),
-                  responseType: 'arraybuffer'
-                }).then(function(response){
-                  return response.data;
-                });
-              },
-              getBMCEthernetInfo: function(){
-                var deferred = $q.defer();
-                $http({
-                  method: 'GET',
-                  url: DataService.getHost() + "/xyz/openbmc_project/inventory/system/chassis/motherboard/boxelder/bmc/ethernet",
-                  headers: {
-                      'Accept': 'application/json',
-                      'Content-Type': 'application/json'
-                  },
-                  withCredentials: true
-                }).then(function(response){
-                    var json = JSON.stringify(response.data);
-                    var content = JSON.parse(json);
-                    deferred.resolve(content.data);
-                }, function(error){
-                  console.log(error);
-                  deferred.reject(error);
-                });
-
-                return deferred.promise;
-              },
-              getBMCInfo: function(callback){
-                var deferred = $q.defer();
-                $http({
-                  method: 'GET',
-                  url: DataService.getHost() + "/xyz/openbmc_project/inventory/system/chassis/motherboard/boxelder/bmc",
-                  headers: {
-                      'Accept': 'application/json',
-                      'Content-Type': 'application/json'
-                  },
-                  withCredentials: true
-                }).then(function(response){
-                    var json = JSON.stringify(response.data);
-                    var content = JSON.parse(json);
-                    deferred.resolve(content.data);
-                }, function(error){
-                  console.log(error);
-                  deferred.reject(error);
-                });
-                return deferred.promise;
-              },
-              getServerInfo: function(){
-                // TODO: openbmc/openbmc#3117 Need a way via REST to get
-                // interfaces so we can get the system object(s) by the looking
-                // for the system interface.
-                return $http({
-                  method: 'GET',
-                  url: DataService.getHost() + "/xyz/openbmc_project/inventory/system",
-                  headers: {
-                    'Accept': 'application/json',
-                    'Content-Type': 'application/json'
-                  },
-                  withCredentials: true
-                }).then(function(response){
-                  return response.data;
-                });
-              },
-              getBMCTime: function(){
-                return $http({
-                  method: 'GET',
-                  url: DataService.getHost() + "/xyz/openbmc_project/time/bmc",
-                  headers: {
-                    'Accept': 'application/json',
-                    'Content-Type': 'application/json'
-                  },
-                  withCredentials: true
-                }).then(function(response){
-                  return response.data;
-                });
-              },
-              getHardwares: function(callback){
-                $http({
-                  method: 'GET',
-                  url: DataService.getHost() + "/xyz/openbmc_project/inventory/enumerate",
-                  headers: {
-                      'Accept': 'application/json',
-                      'Content-Type': 'application/json'
-                  },
-                  withCredentials: true
-                }).then(function(response){
-                      var json = JSON.stringify(response.data);
-                      var content = JSON.parse(json);
-                      var hardwareData = [];
-                      var keyIndexMap = {};
-                      var title = "";
-                      var data = [];
-                      var searchText = "";
-                      var componentIndex = -1;
-                      var tempParts = [];
-
-
-                      function isSubComponent(key){
-
-                        for(var i = 0; i < Constants.HARDWARE.parent_components.length; i++){
-                          if(key.split(Constants.HARDWARE.parent_components[i]).length == 2) return true;
-                        }
-
-                        return false;
-                      }
-
-                      function titlelize(title){
-                        title = title.replace(/([A-Z0-9]+)/g, " $1").replace(/^\s+/, "");
-                        for(var i = 0; i < Constants.HARDWARE.uppercase_titles.length; i++){
-                          if(title.toLowerCase().indexOf((Constants.HARDWARE.uppercase_titles[i] + " ")) > -1){
-                            return title.toUpperCase();
-                          }
-                        }
-
-                        return title;
-                      }
-
-                      function camelcaseToLabel(obj){
-                        var transformed = [], label = "", value = "";
-                        for(var key in obj){
-                          label = key.replace(/([A-Z0-9]+)/g, " $1").replace(/^\s+/, "");
-                          if(obj[key] !== ""){
-                            value = obj[key];
-                            if(value == 1 || value == 0){
-                              value = (value == 1) ? 'Yes' : 'No';
-                            }
-                            transformed.push({key:label, value: value});
-                          }
-                        }
-
-                        return transformed;
-                      }
-
-                      function getSearchText(data){
-                        var searchText = "";
-                        for(var i = 0; i < data.length; i++){
-                          searchText += " " + data[i].key + " " + data[i].value;
-                        }
-
-                        return searchText;
-                      }
-
-                      for(var key in content.data){
-                        if(content.data.hasOwnProperty(key) &&
-                           key.indexOf(Constants.HARDWARE.component_key_filter) == 0){
-
-                          data = camelcaseToLabel(content.data[key]);
-                          searchText = getSearchText(data);
-                          title = key.split("/").pop();
-
-                          title = titlelize(title);
-
-                          if(!isSubComponent(key)){
-                              hardwareData.push(Object.assign({
-                                path: key,
-                                title: title,
-                                selected: false,
-                                expanded: false,
-                                search_text: title.toLowerCase() + " " + searchText.toLowerCase(),
-                                sub_components: [],
-                                original_data: {key: key, value: content.data[key]}
-                              }, {items: data}));
-
-                              keyIndexMap[key] = hardwareData.length - 1;
-                          }else{
-                            var tempParts = key.split("/");
-                            tempParts.pop();
-                            tempParts = tempParts.join("/");
-                            componentIndex = keyIndexMap[tempParts];
-                            data = content.data[key];
-                            data.title = title;
-                            hardwareData[componentIndex].sub_components.push(data);
-                            hardwareData[componentIndex].search_text += " " + title.toLowerCase();
-
-                            // Sort the subcomponents alphanumeric so they are displayed on the
-                            // inventory page in order (e.g. core 0, core 1, core 2, ... core 12, core 13)
-                            hardwareData[componentIndex].sub_components.sort(function (a, b) {
-                                return a.title.localeCompare(b.title, 'en', { numeric: true });
-                            });
-                          }
-                      }
-                    }
-
-                    if(callback){
-                       callback(hardwareData, content.data);
-                    }else{
-                       return { data: hardwareData, original_data: content.data};
-                    }
-                });
-              },
-              deleteLogs: function(logs) {
-                  var defer = $q.defer();
-                  var promises = [];
-
-                  function finished(){
-                      defer.resolve();
-                  }
-
-                  logs.forEach(function(item){
-                    promises.push($http({
-                                      method: 'POST',
-                                      url: DataService.getHost() + "/xyz/openbmc_project/logging/entry/"+item.Id+"/action/Delete",
-                                      headers: {
-                                          'Accept': 'application/json',
-                                          'Content-Type': 'application/json'
-                                      },
-                                      withCredentials: true,
-                                      data: JSON.stringify({"data": []})
-                                 }));
-                  });
-
-                  $q.all(promises).then(finished);
-
-                  return defer.promise;
-              },
-              resolveLogs: function(logs) {
-                  var defer = $q.defer();
-                  var promises = [];
-
-                  function finished(){
-                      defer.resolve();
-                  }
-
-                  logs.forEach(function(item){
-                    promises.push($http({
-                                      method: 'PUT',
-                                      url: DataService.getHost() + "/xyz/openbmc_project/logging/entry/"+item.Id+"/attr/Resolved",
-                                      headers: {
-                                          'Accept': 'application/json',
-                                          'Content-Type': 'application/json'
-                                      },
-                                      withCredentials: true,
-                                      data: JSON.stringify({"data": "1"})
-                                 }));
-                  });
-
-                  $q.all(promises).then(finished);
-
-                  return defer.promise;
-              },
-              getPowerConsumption: function(){
-                return $http({
-                  method: 'GET',
-                  url: DataService.getHost() + "/xyz/openbmc_project/sensors/power/total_power",
-                  headers: {
-                      'Accept': 'application/json',
-                      'Content-Type': 'application/json'
-                  },
-                  withCredentials: true
-                }).then(function(response){
-                    var json = JSON.stringify(response.data);
-                    var content = JSON.parse(json);
-
-                    return getScaledValue(content.data.Value,
-                                          content.data.Scale) + ' ' +
-                      Constants.POWER_CONSUMPTION_TEXT[content.data.Unit];
-                }, function(error){
-                  if ('Not Found' == error.statusText) {
-                    return Constants.POWER_CONSUMPTION_TEXT.notavailable;
-                  } else {
-                    throw error;
-                  }
-                });
-              },
-              getPowerCap: function(){
-                return $http({
-                  method: 'GET',
-                  url: DataService.getHost() + "/xyz/openbmc_project/control/host0/power_cap",
-                  headers: {
-                      'Accept': 'application/json',
-                      'Content-Type': 'application/json'
-                  },
-                  withCredentials: true
-                }).then(function(response){
-                    var json = JSON.stringify(response.data);
-                    var content = JSON.parse(json);
-
-                    return (false == content.data.PowerCapEnable) ?
-                        Constants.POWER_CAP_TEXT.disabled :
-                        content.data.PowerCap + ' ' + Constants.POWER_CAP_TEXT.unit;
-                });
-              },
-              setHostname: function(hostname){
-                return $http({
-                  method: 'PUT',
-                  url: DataService.getHost() + "/xyz/openbmc_project/network/config/attr/HostName",
-                  headers: {
-                      'Accept': 'application/json',
-                      'Content-Type': 'application/json'
-                  },
-                  withCredentials: true,
-                  data: JSON.stringify({"data": hostname})
-                }).then(function(response){
-                    return response.data;
-                });
-              },
-          };
-          return SERVICE;
-        }]);
-
-        })(window.angular);
+})(window.angular);
diff --git a/app/common/services/apiInterceptor.js b/app/common/services/apiInterceptor.js
index de344cd..b3f2ff4 100644
--- a/app/common/services/apiInterceptor.js
+++ b/app/common/services/apiInterceptor.js
@@ -7,60 +7,61 @@
 
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.common.services')
-        .service('apiInterceptor', ['$q', '$rootScope', 'dataService', function($q, $rootScope, dataService){
-            return {
-                'request': function(config){
-                    dataService.loading = true;
-                    // If caller has not defined a timeout, set to default of 20s
-                    if (config.timeout == null){
-                        config.timeout = 20000;
-                    }
-                    return config;
-                },
-                'response': function(response){
-                    dataService.loading = false;
+  angular
+    .module('app.common.services')
+    .service('apiInterceptor', ['$q', '$rootScope', 'dataService', function($q, $rootScope, dataService) {
+      return {
+        'request': function(config) {
+          dataService.loading = true;
+          // If caller has not defined a timeout, set to default of 20s
+          if (config.timeout == null) {
+            config.timeout = 20000;
+          }
+          return config;
+        },
+        'response': function(response) {
+          dataService.loading = false;
 
-                    //not interested in template requests
-                    if(!/^https?\:/i.test(response.config.url)){
-                        return response;
-                    }
+          //not interested in template requests
+          if (!/^https?\:/i.test(response.config.url)) {
+            return response;
+          }
 
-                    dataService.last_updated = new Date();
-                    if(!response){
-                        dataService.server_unreachable = true;
-                    }else{
-                        dataService.server_unreachable = false;
-                    }
+          dataService.last_updated = new Date();
+          if (!response) {
+            dataService.server_unreachable = true;
+          }
+          else {
+            dataService.server_unreachable = false;
+          }
 
-                    if(response && response.status == 'error' &&
-                       dataService.path != '/login'){
-                        $rootScope.$emit('timedout-user', {});
-                    }
+          if (response && response.status == 'error' &&
+            dataService.path != '/login') {
+            $rootScope.$emit('timedout-user', {});
+          }
 
-                    return response;
-                },
-                'responseError': function(rejection){
-                    if (dataService.ignoreHttpError === false)
-                    {
-                        // If unauthorized, log out
-                        if (rejection.status == 401){
-                            if (dataService.path != '/login'){
-                                $rootScope.$emit('timedout-user', {});
-                            }
-                        } else if (rejection.status == -1){
-                            dataService.server_unreachable = true;
-                        }
+          return response;
+        },
+        'responseError': function(rejection) {
+          if (dataService.ignoreHttpError === false) {
+            // If unauthorized, log out
+            if (rejection.status == 401) {
+              if (dataService.path != '/login') {
+                $rootScope.$emit('timedout-user', {});
+              }
+            }
+            else if (rejection.status == -1) {
+              dataService.server_unreachable = true;
+            }
 
-                        dataService.loading = false;
-                    }
-                    return $q.reject(rejection);
-                }
-            };
-        }]);
+            dataService.loading = false;
+          }
+          return $q.reject(rejection);
+        }
+      };
+    }]);
 
 })(window.angular);
diff --git a/app/common/services/constants.js b/app/common/services/constants.js
index 8b51341..d749ea8 100644
--- a/app/common/services/constants.js
+++ b/app/common/services/constants.js
@@ -7,161 +7,161 @@
 
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.common.services', [])
-        .service('Constants', function () {
-            return {
-                API_CREDENTIALS: {
-                    host_storage_key: 'API_HOST_KEY',
-                    default_protocol: 'https'
-                },
-                API_RESPONSE: {
-                    ERROR_STATUS: 'error',
-                    ERROR_MESSAGE: '401 Unauthorized',
-                    SUCCESS_STATUS: 'ok',
-                    SUCCESS_MESSAGE: '200 OK'
-                },
-                CHASSIS_POWER_STATE: {
-                    on: 'On',
-                    on_code: 'xyz.openbmc_project.State.Chassis.PowerState.On',
-                    off: 'Off',
-                    off_code: 'xyz.openbmc_project.State.Chassis.PowerState.Off'
-                },
-                HOST_STATE_TEXT: {
-                    on: 'Running',
-                    on_code: 'xyz.openbmc_project.State.Host.HostState.Running',
-                    off: 'Off',
-                    off_code: 'xyz.openbmc_project.State.Host.HostState.Off',
-                    error: 'Quiesced',
-                    error_code: 'xyz.openbmc_project.State.Host.HostState.Quiesced',
-                    unreachable: 'Unreachable'
-                },
-                HOST_STATE: {
-                    on: 1,
-                    off: -1,
-                    error: 0,
-                    unreachable: -2
-                },
-                LED_STATE: {
-                    on: true,
-                    off: false
-                },
-                LED_STATE_TEXT: {
-                    on: 'on',
-                    off: 'off'
-                },
-                SEVERITY_TO_HEALTH_MAP:{
-                    Emergency: 'Critical',
-                    Alert: 'Critical',
-                    Critical: 'Critical',
-                    Error: 'Warning',
-                    Warning: 'Warning',
-                    Notice: 'Good',
-                    Debug: 'Good',
-                    Informational: 'Good'
-                },
-                SEVERITY_TO_PRIORITY_MAP:{
-                    Emergency: 'High',
-                    Alert: 'High',
-                    Critical: 'High',
-                    Error: 'High',
-                    Warning: 'Medium',
-                    Notice: 'Low',
-                    Debug: 'Low',
-                    Informational: 'Low'
-                },
-                PAGINATION: {
-                    LOG_ITEMS_PER_PAGE: 25
-                },
-                HARDWARE: {
-                  component_key_filter: '/xyz/openbmc_project/inventory/system',
-                  parent_components: [
-                   /xyz\/openbmc_project\/inventory\/system\/chassis\/motherboard\/cpu\d+\//
-                  ],
-                  uppercase_titles: [
-                   'cpu', 'dimm'
-                  ]
-                },
-                SENSOR_UNIT_MAP: {
-                  'xyz.openbmc_project.Sensor.Value.Unit.RPMS': 'rpms',
-                  'xyz.openbmc_project.Sensor.Value.Unit.DegreesC': 'C',
-                  'xyz.openbmc_project.Sensor.Value.Unit.Volts': 'volts',
-                  'xyz.openbmc_project.Sensor.Value.Unit.Meters': 'meters',
-                  'xyz.openbmc_project.Sensor.Value.Unit.Watts': 'watts',
-                  'xyz.openbmc_project.Sensor.Value.Unit.Amperes': 'amperes',
-                  'xyz.openbmc_project.Sensor.Value.Unit.Joules': 'joules'
-                },
-                SERVER_HEALTH: {
-                    critical: 'Critical',
-                    warning: 'Warning',
-                    good: 'Good',
-                    unknown: 'Unknown'
-                },
-                SENSOR_SORT_ORDER: [
-                   'xyz.openbmc_project.Sensor.Value.Unit.DegreesC',
-                   'xyz.openbmc_project.Sensor.Value.Unit.RPMS',
-                   'xyz.openbmc_project.Sensor.Value.Unit.Meters',
-                   'xyz.openbmc_project.Sensor.Value.Unit.Volts',
-                   'xyz.openbmc_project.Sensor.Value.Unit.Amperes',
-                   'xyz.openbmc_project.Sensor.Value.Unit.Joules',
-                   'xyz.openbmc_project.Sensor.Value.Unit.Meters'
-                ],
-                SENSOR_SORT_ORDER_DEFAULT: 8,
-                FIRMWARE: {
-                    ACTIVATE_FIRMWARE: 'xyz.openbmc_project.Software.Activation.RequestedActivations.Active',
-                    FUNCTIONAL_OBJPATH: '/xyz/openbmc_project/software/functional'
-                },
-                POLL_INTERVALS: {
-                    ACTIVATION: 5000,
-                    DOWNLOAD_IMAGE: 5000,
-                    POWER_OP: 5000,
-                },
-                TIMEOUT: {
-                    ACTIVATION: 1000 * 60 * 10, // 10 mins
-                    DOWNLOAD_IMAGE: 1000 * 60 * 2, // 2 mins
-                    CHASSIS_OFF: 1000 * 60 * 5, // 5 mins
-                    HOST_ON: 1000 * 60 * 5, // 5 mins
-                    HOST_OFF: 1000 * 60 * 5, // 5 mins
-                },
-                MESSAGES: {
-                    POLL: {
-                        CHASSIS_OFF_TIMEOUT: 'Time out. Chassis did not reach power off state in allotted time.',
-                        HOST_ON_TIMEOUT: 'Time out. System did not reach Running state in allotted time.',
-                        HOST_OFF_TIMEOUT: 'Time out. System did not reach Off state in allotted time.',
-                        HOST_QUIESCED: 'System is in Error state.',
-                        DOWNLOAD_IMAGE_TIMEOUT: 'Time out. Did not download image in allotted time.',
-                    },
-                    POWER_OP: {
-                        POWER_ON_FAILED: 'Power On Failed',
-                        WARM_REBOOT_FAILED: 'Warm Reboot Failed',
-                        COLD_REBOOT_FAILED: 'Cold Reboot Failed',
-                        ORDERLY_SHUTDOWN_FAILED: 'Orderly Shutdown Failed',
-                        IMMEDIATE_SHUTDOWN_FAILED: 'Immediate Shutdown Failed',
-                    },
-                    SENSOR: {
-                        NO_SENSOR_DATA: 'There are no sensors found.',
-                        CRITICAL_NO_SENSOR_DATA: 'There are no sensors in Critical state.',
-                        WARNING_NO_SENSOR_DATA: 'There are no sensors in Warning state.',
-                        NORMAL_NO_SENSOR_DATA: 'There are no sensors in Normal state.'
-                    },
-                    ERROR_MODAL: {
-                        TITLE: 'Unexpected error',
-                        DESCRIPTION: 'Oops! An unexpected error occurred. Record specific details of the issue, then contact your company support services.'
-                    },
-                    ERROR_MESSAGE_DESC_TEMPLATE: '{{status}} - {{description}}',
-                },
-                POWER_CAP_TEXT: {
-                    unit: 'W',
-                    disabled: 'Not Enabled'
-                },
-                POWER_CONSUMPTION_TEXT: {
-                    'xyz.openbmc_project.Sensor.Value.Unit.Watts': 'W',
-                    notavailable: 'Not Available'
-                },
-            };
-        });
+  angular
+    .module('app.common.services', [])
+    .service('Constants', function() {
+      return {
+        API_CREDENTIALS: {
+          host_storage_key: 'API_HOST_KEY',
+          default_protocol: 'https'
+        },
+        API_RESPONSE: {
+          ERROR_STATUS: 'error',
+          ERROR_MESSAGE: '401 Unauthorized',
+          SUCCESS_STATUS: 'ok',
+          SUCCESS_MESSAGE: '200 OK'
+        },
+        CHASSIS_POWER_STATE: {
+          on: 'On',
+          on_code: 'xyz.openbmc_project.State.Chassis.PowerState.On',
+          off: 'Off',
+          off_code: 'xyz.openbmc_project.State.Chassis.PowerState.Off'
+        },
+        HOST_STATE_TEXT: {
+          on: 'Running',
+          on_code: 'xyz.openbmc_project.State.Host.HostState.Running',
+          off: 'Off',
+          off_code: 'xyz.openbmc_project.State.Host.HostState.Off',
+          error: 'Quiesced',
+          error_code: 'xyz.openbmc_project.State.Host.HostState.Quiesced',
+          unreachable: 'Unreachable'
+        },
+        HOST_STATE: {
+          on: 1,
+          off: -1,
+          error: 0,
+          unreachable: -2
+        },
+        LED_STATE: {
+          on: true,
+          off: false
+        },
+        LED_STATE_TEXT: {
+          on: 'on',
+          off: 'off'
+        },
+        SEVERITY_TO_HEALTH_MAP: {
+          Emergency: 'Critical',
+          Alert: 'Critical',
+          Critical: 'Critical',
+          Error: 'Warning',
+          Warning: 'Warning',
+          Notice: 'Good',
+          Debug: 'Good',
+          Informational: 'Good'
+        },
+        SEVERITY_TO_PRIORITY_MAP: {
+          Emergency: 'High',
+          Alert: 'High',
+          Critical: 'High',
+          Error: 'High',
+          Warning: 'Medium',
+          Notice: 'Low',
+          Debug: 'Low',
+          Informational: 'Low'
+        },
+        PAGINATION: {
+          LOG_ITEMS_PER_PAGE: 25
+        },
+        HARDWARE: {
+          component_key_filter: '/xyz/openbmc_project/inventory/system',
+          parent_components: [
+            /xyz\/openbmc_project\/inventory\/system\/chassis\/motherboard\/cpu\d+\//
+          ],
+          uppercase_titles: [
+            'cpu', 'dimm'
+          ]
+        },
+        SENSOR_UNIT_MAP: {
+          'xyz.openbmc_project.Sensor.Value.Unit.RPMS': 'rpms',
+          'xyz.openbmc_project.Sensor.Value.Unit.DegreesC': 'C',
+          'xyz.openbmc_project.Sensor.Value.Unit.Volts': 'volts',
+          'xyz.openbmc_project.Sensor.Value.Unit.Meters': 'meters',
+          'xyz.openbmc_project.Sensor.Value.Unit.Watts': 'watts',
+          'xyz.openbmc_project.Sensor.Value.Unit.Amperes': 'amperes',
+          'xyz.openbmc_project.Sensor.Value.Unit.Joules': 'joules'
+        },
+        SERVER_HEALTH: {
+          critical: 'Critical',
+          warning: 'Warning',
+          good: 'Good',
+          unknown: 'Unknown'
+        },
+        SENSOR_SORT_ORDER: [
+          'xyz.openbmc_project.Sensor.Value.Unit.DegreesC',
+          'xyz.openbmc_project.Sensor.Value.Unit.RPMS',
+          'xyz.openbmc_project.Sensor.Value.Unit.Meters',
+          'xyz.openbmc_project.Sensor.Value.Unit.Volts',
+          'xyz.openbmc_project.Sensor.Value.Unit.Amperes',
+          'xyz.openbmc_project.Sensor.Value.Unit.Joules',
+          'xyz.openbmc_project.Sensor.Value.Unit.Meters'
+        ],
+        SENSOR_SORT_ORDER_DEFAULT: 8,
+        FIRMWARE: {
+          ACTIVATE_FIRMWARE: 'xyz.openbmc_project.Software.Activation.RequestedActivations.Active',
+          FUNCTIONAL_OBJPATH: '/xyz/openbmc_project/software/functional'
+        },
+        POLL_INTERVALS: {
+          ACTIVATION: 5000,
+          DOWNLOAD_IMAGE: 5000,
+          POWER_OP: 5000,
+        },
+        TIMEOUT: {
+          ACTIVATION: 1000 * 60 * 10, // 10 mins
+          DOWNLOAD_IMAGE: 1000 * 60 * 2, // 2 mins
+          CHASSIS_OFF: 1000 * 60 * 5, // 5 mins
+          HOST_ON: 1000 * 60 * 5, // 5 mins
+          HOST_OFF: 1000 * 60 * 5, // 5 mins
+        },
+        MESSAGES: {
+          POLL: {
+            CHASSIS_OFF_TIMEOUT: 'Time out. Chassis did not reach power off state in allotted time.',
+            HOST_ON_TIMEOUT: 'Time out. System did not reach Running state in allotted time.',
+            HOST_OFF_TIMEOUT: 'Time out. System did not reach Off state in allotted time.',
+            HOST_QUIESCED: 'System is in Error state.',
+            DOWNLOAD_IMAGE_TIMEOUT: 'Time out. Did not download image in allotted time.',
+          },
+          POWER_OP: {
+            POWER_ON_FAILED: 'Power On Failed',
+            WARM_REBOOT_FAILED: 'Warm Reboot Failed',
+            COLD_REBOOT_FAILED: 'Cold Reboot Failed',
+            ORDERLY_SHUTDOWN_FAILED: 'Orderly Shutdown Failed',
+            IMMEDIATE_SHUTDOWN_FAILED: 'Immediate Shutdown Failed',
+          },
+          SENSOR: {
+            NO_SENSOR_DATA: 'There are no sensors found.',
+            CRITICAL_NO_SENSOR_DATA: 'There are no sensors in Critical state.',
+            WARNING_NO_SENSOR_DATA: 'There are no sensors in Warning state.',
+            NORMAL_NO_SENSOR_DATA: 'There are no sensors in Normal state.'
+          },
+          ERROR_MODAL: {
+            TITLE: 'Unexpected error',
+            DESCRIPTION: 'Oops! An unexpected error occurred. Record specific details of the issue, then contact your company support services.'
+          },
+          ERROR_MESSAGE_DESC_TEMPLATE: '{{status}} - {{description}}',
+        },
+        POWER_CAP_TEXT: {
+          unit: 'W',
+          disabled: 'Not Enabled'
+        },
+        POWER_CONSUMPTION_TEXT: {
+          'xyz.openbmc_project.Sensor.Value.Unit.Watts': 'W',
+          notavailable: 'Not Available'
+        },
+      };
+    });
 
 })(window.angular);
diff --git a/app/common/services/dataService.js b/app/common/services/dataService.js
index d39e757..79a3a0e 100644
--- a/app/common/services/dataService.js
+++ b/app/common/services/dataService.js
@@ -7,141 +7,144 @@
 
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.common.services')
-        .service('dataService', ['Constants', function (Constants) {
-            this.server_health = Constants.SERVER_HEALTH.unknown;
-            this.server_state = 'Unreachable';
-            this.server_status = -2;
-            this.chassis_state = 'On';
-            this.LED_state = Constants.LED_STATE_TEXT.off;
-            this.last_updated = new Date();
+  angular
+    .module('app.common.services')
+    .service('dataService', ['Constants', function(Constants) {
+      this.server_health = Constants.SERVER_HEALTH.unknown;
+      this.server_state = 'Unreachable';
+      this.server_status = -2;
+      this.chassis_state = 'On';
+      this.LED_state = Constants.LED_STATE_TEXT.off;
+      this.last_updated = new Date();
 
-            this.loading = false;
-            this.server_unreachable = false;
-            this.loading_message = "";
-            this.showNavigation = false;
-            this.bodyStyle = {};
-            this.path = '';
-            this.sensorData = [];
+      this.loading = false;
+      this.server_unreachable = false;
+      this.loading_message = '';
+      this.showNavigation = false;
+      this.bodyStyle = {};
+      this.path = '';
+      this.sensorData = [];
 
-            this.hostname = "";
-            this.mac_address = "";
-            this.remote_window_active = false;
+      this.hostname = '';
+      this.mac_address = '';
+      this.remote_window_active = false;
 
-            this.displayErrorModal = false;
-            this.errorModalDetails = {};
+      this.displayErrorModal = false;
+      this.errorModalDetails = {};
 
-            this.ignoreHttpError = false;
-            this.getServerId = function(){
-                 return this.host.replace(/^https?\:\/\//ig,"");
-            }
+      this.ignoreHttpError = false;
+      this.getServerId = function() {
+        return this.host.replace(/^https?\:\/\//ig, '');
+      };
 
-            this.reloadServerId = function(){
-                this.server_id = this.getServerId();
-            }
+      this.reloadServerId = function() {
+        this.server_id = this.getServerId();
+      };
 
-            this.getHost = function(){
-                if(sessionStorage.getItem(Constants.API_CREDENTIALS.host_storage_key) !== null){
-                    return sessionStorage.getItem(Constants.API_CREDENTIALS.host_storage_key);
-                }else{
-                    return Constants.API_CREDENTIALS.default_protocol + "://" +
-                           window.location.hostname +
-                           (window.location.port ? ":" + window.location.port : "");
-                }
-            }
+      this.getHost = function() {
+        if (sessionStorage.getItem(Constants.API_CREDENTIALS.host_storage_key) !== null) {
+          return sessionStorage.getItem(Constants.API_CREDENTIALS.host_storage_key);
+        }
+        else {
+          return Constants.API_CREDENTIALS.default_protocol + '://' +
+            window.location.hostname +
+            (window.location.port ? ':' + window.location.port : '');
+        }
+      };
 
-            this.setHost = function(hostWithPort){
-                hostWithPort = hostWithPort.replace(/^https?\:\/\//ig, '');
-                var hostURL = Constants.API_CREDENTIALS.default_protocol + "://" + hostWithPort;
-                sessionStorage.setItem(Constants.API_CREDENTIALS.host_storage_key, hostURL);
-                this.host = hostURL;
-                this.reloadServerId();
-            }
+      this.setHost = function(hostWithPort) {
+        hostWithPort = hostWithPort.replace(/^https?\:\/\//ig, '');
+        var hostURL = Constants.API_CREDENTIALS.default_protocol + '://' + hostWithPort;
+        sessionStorage.setItem(Constants.API_CREDENTIALS.host_storage_key, hostURL);
+        this.host = hostURL;
+        this.reloadServerId();
+      };
 
-            this.getUser = function(){
-                return sessionStorage.getItem('LOGIN_ID');
-            }
+      this.getUser = function() {
+        return sessionStorage.getItem('LOGIN_ID');
+      };
 
-            this.host = this.getHost();
-            this.server_id = this.getServerId();
+      this.host = this.getHost();
+      this.server_id = this.getServerId();
 
-            this.setNetworkInfo = function(data){
-                this.hostname = data.hostname;
-                this.mac_address = data.mac_address;
-            }
+      this.setNetworkInfo = function(data) {
+        this.hostname = data.hostname;
+        this.mac_address = data.mac_address;
+      };
 
-            this.setPowerOnState = function(){
-                this.server_state = Constants.HOST_STATE_TEXT.on;
-                this.server_status = Constants.HOST_STATE.on;
-            }
+      this.setPowerOnState = function() {
+        this.server_state = Constants.HOST_STATE_TEXT.on;
+        this.server_status = Constants.HOST_STATE.on;
+      };
 
-            this.setPowerOffState = function(){
-                this.server_state = Constants.HOST_STATE_TEXT.off;
-                this.server_status = Constants.HOST_STATE.off;
-            }
+      this.setPowerOffState = function() {
+        this.server_state = Constants.HOST_STATE_TEXT.off;
+        this.server_status = Constants.HOST_STATE.off;
+      };
 
-            this.setErrorState = function(){
-                this.server_state = Constants.HOST_STATE_TEXT.error;
-                this.server_status = Constants.HOST_STATE.error;
-            }
+      this.setErrorState = function() {
+        this.server_state = Constants.HOST_STATE_TEXT.error;
+        this.server_status = Constants.HOST_STATE.error;
+      };
 
-            this.setUnreachableState = function(){
-                this.server_state = Constants.HOST_STATE_TEXT.unreachable;
-                this.server_status = Constants.HOST_STATE.unreachable;
-            }
+      this.setUnreachableState = function() {
+        this.server_state = Constants.HOST_STATE_TEXT.unreachable;
+        this.server_status = Constants.HOST_STATE.unreachable;
+      };
 
-            this.setRemoteWindowActive = function(){
-                this.remote_window_active = true;
-            }
+      this.setRemoteWindowActive = function() {
+        this.remote_window_active = true;
+      };
 
-            this.setRemoteWindowInactive = function(){
-                this.remote_window_active = false;
-            }
+      this.setRemoteWindowInactive = function() {
+        this.remote_window_active = false;
+      };
 
-            this.updateServerHealth = function(logs){
-                var criticals = logs.filter(function(item){
-                    return item.health_flags.critical == true;
-                });
+      this.updateServerHealth = function(logs) {
+        var criticals = logs.filter(function(item) {
+          return item.health_flags.critical == true;
+        });
 
-                if(criticals.length){
-                    this.server_health = Constants.SERVER_HEALTH.critical;
-                    return;
-                }
+        if (criticals.length) {
+          this.server_health = Constants.SERVER_HEALTH.critical;
+          return;
+        }
 
-                var warnings = logs.filter(function(item){
-                    return item.health_flags.warning == true;
-                });
+        var warnings = logs.filter(function(item) {
+          return item.health_flags.warning == true;
+        });
 
-                if(warnings.length){
-                    this.server_health = Constants.SERVER_HEALTH.warning;
-                    return;
-                }
+        if (warnings.length) {
+          this.server_health = Constants.SERVER_HEALTH.warning;
+          return;
+        }
 
-                this.server_health = Constants.SERVER_HEALTH.good;
-            }
+        this.server_health = Constants.SERVER_HEALTH.good;
+      };
 
-            this.activateErrorModal = function(data){
-                if(data && data.hasOwnProperty('title')){
-                    this.errorModalDetails.title = data.title;
-                }else{
-                    this.errorModalDetails.title = Constants.MESSAGES.ERROR_MODAL.TITLE;
-                }
+      this.activateErrorModal = function(data) {
+        if (data && data.hasOwnProperty('title')) {
+          this.errorModalDetails.title = data.title;
+        }
+        else {
+          this.errorModalDetails.title = Constants.MESSAGES.ERROR_MODAL.TITLE;
+        }
 
-                if(data && data.hasOwnProperty('description')){
-                    this.errorModalDetails.description = data.description;
-                }else{
-                    this.errorModalDetails.description = Constants.MESSAGES.ERROR_MODAL.DESCRIPTION;
-                }
-                this.displayErrorModal = true;
-            }
+        if (data && data.hasOwnProperty('description')) {
+          this.errorModalDetails.description = data.description;
+        }
+        else {
+          this.errorModalDetails.description = Constants.MESSAGES.ERROR_MODAL.DESCRIPTION;
+        }
+        this.displayErrorModal = true;
+      };
 
-            this.deactivateErrorModal = function(){
-                this.displayErrorModal = false;
-            }
-        }]);
+      this.deactivateErrorModal = function() {
+        this.displayErrorModal = false;
+      };
+    }]);
 
 })(window.angular);
diff --git a/app/common/services/index.js b/app/common/services/index.js
index a33003a..d234069 100644
--- a/app/common/services/index.js
+++ b/app/common/services/index.js
@@ -5,13 +5,13 @@
  * @exports app/common/services/index
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.common.services', [
-            // Dependencies
-            // Basic resources
-        ]);
+  angular
+    .module('app.common.services', [
+      // Dependencies
+      // Basic resources
+    ]);
 
 })(window.angular);
diff --git a/app/common/services/userModel.js b/app/common/services/userModel.js
index e25d3f9..cd943f9 100644
--- a/app/common/services/userModel.js
+++ b/app/common/services/userModel.js
@@ -7,53 +7,59 @@
 
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.common.services')
-        .service('userModel', ['APIUtils',function(APIUtils){
-            return {
-                login : function(username, password, callback){
-                    APIUtils.login(username, password, function(response, error){
-                        if(response &&
-                            (response.status == APIUtils.API_RESPONSE.SUCCESS_STATUS
-                                || response.status === undefined)){
-                            sessionStorage.setItem('LOGIN_ID', username);
-                            callback(true);
-                        }else if(response && response.data && response.data.data
-                                 && response.data.data.description){
-                            callback(false, response.data.data.description);
-                        }else if(response && response.message){
-                            callback(false, response.message);
-                        }else if(error){
-                            callback(false, 'Server unreachable');
-                        }else{
-                            callback(false, 'Internal error');
-                        }
-                    });
-                },
-                isLoggedIn : function(){
-                    if(sessionStorage.getItem('LOGIN_ID') === null){
-                        return false;
-                    }
-                    return true;
-                },
-                logout : function(callback){
-                    APIUtils.logout(function(response, error){
-                        if(response &&
-                           response.status == APIUtils.API_RESPONSE.SUCCESS_STATUS){
-                            sessionStorage.removeItem('LOGIN_ID');
-                            sessionStorage.removeItem(APIUtils.HOST_SESSION_STORAGE_KEY);
-                            callback(true);
-                        }else if(response.status == APIUtils.API_RESPONSE.ERROR_STATUS){
-                            callback(false);
-                        }else{
-                            callback(false, error);
-                        }
-                    });
-                }
-            };
-        }]);
+  angular
+    .module('app.common.services')
+    .service('userModel', ['APIUtils', function(APIUtils) {
+      return {
+        login: function(username, password, callback) {
+          APIUtils.login(username, password, function(response, error) {
+            if (response &&
+              (response.status == APIUtils.API_RESPONSE.SUCCESS_STATUS ||
+                response.status === undefined)) {
+              sessionStorage.setItem('LOGIN_ID', username);
+              callback(true);
+            }
+            else if (response && response.data && response.data.data &&
+              response.data.data.description) {
+              callback(false, response.data.data.description);
+            }
+            else if (response && response.message) {
+              callback(false, response.message);
+            }
+            else if (error) {
+              callback(false, 'Server unreachable');
+            }
+            else {
+              callback(false, 'Internal error');
+            }
+          });
+        },
+        isLoggedIn: function() {
+          if (sessionStorage.getItem('LOGIN_ID') === null) {
+            return false;
+          }
+          return true;
+        },
+        logout: function(callback) {
+          APIUtils.logout(function(response, error) {
+            if (response &&
+              response.status == APIUtils.API_RESPONSE.SUCCESS_STATUS) {
+              sessionStorage.removeItem('LOGIN_ID');
+              sessionStorage.removeItem(APIUtils.HOST_SESSION_STORAGE_KEY);
+              callback(true);
+            }
+            else if (response.status == APIUtils.API_RESPONSE.ERROR_STATUS) {
+              callback(false);
+            }
+            else {
+              callback(false, error);
+            }
+          });
+        }
+      };
+    }]);
 
 })(window.angular);
diff --git a/app/configuration/controllers/date-time-controller.js b/app/configuration/controllers/date-time-controller.js
index 9ad6dc1..341d175 100644
--- a/app/configuration/controllers/date-time-controller.js
+++ b/app/configuration/controllers/date-time-controller.js
@@ -6,20 +6,19 @@
  * @name dateTimeController
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.configuration')
-        .controller('dateTimeController', [
-            '$scope',
-            '$window',
-            'APIUtils',
-            'dataService',
-            function($scope, $window, APIUtils, dataService){
-                $scope.dataService = dataService;
-            }
-        ]
-    );
+  angular
+    .module('app.configuration')
+    .controller('dateTimeController', [
+      '$scope',
+      '$window',
+      'APIUtils',
+      'dataService',
+      function($scope, $window, APIUtils, dataService) {
+        $scope.dataService = dataService;
+      }
+    ]);
 
 })(angular);
diff --git a/app/configuration/controllers/file-controller.js b/app/configuration/controllers/file-controller.js
index b19af61..37c7ffb 100644
--- a/app/configuration/controllers/file-controller.js
+++ b/app/configuration/controllers/file-controller.js
@@ -6,20 +6,19 @@
  * @name fileController
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.configuration')
-        .controller('fileController', [
-            '$scope',
-            '$window',
-            'APIUtils',
-            'dataService',
-            function($scope, $window, APIUtils, dataService){
-                $scope.dataService = dataService;
-            }
-        ]
-    );
+  angular
+    .module('app.configuration')
+    .controller('fileController', [
+      '$scope',
+      '$window',
+      'APIUtils',
+      'dataService',
+      function($scope, $window, APIUtils, dataService) {
+        $scope.dataService = dataService;
+      }
+    ]);
 
 })(angular);
diff --git a/app/configuration/controllers/firmware-controller.js b/app/configuration/controllers/firmware-controller.js
index f5f0541..cf838ec 100644
--- a/app/configuration/controllers/firmware-controller.js
+++ b/app/configuration/controllers/firmware-controller.js
@@ -6,310 +6,313 @@
  * @name firmwareController
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.configuration')
-        .controller('firmwareController', [
-                '$scope',
-                '$window',
-                'APIUtils',
-                'dataService',
-                '$location',
-                '$anchorScroll',
-                'Constants',
-                '$interval',
-                '$q',
-                '$timeout',
-                function ($scope, $window, APIUtils, dataService, $location, $anchorScroll, Constants, $interval, $q, $timeout) {
-                    $scope.dataService = dataService;
+  angular
+    .module('app.configuration')
+    .controller('firmwareController', [
+      '$scope',
+      '$window',
+      'APIUtils',
+      'dataService',
+      '$location',
+      '$anchorScroll',
+      'Constants',
+      '$interval',
+      '$q',
+      '$timeout',
+      function($scope, $window, APIUtils, dataService, $location, $anchorScroll, Constants, $interval, $q, $timeout) {
+        $scope.dataService = dataService;
 
-                    //Scroll to target anchor
-                    $scope.gotoAnchor = function () {
-                        $location.hash('upload');
-                        $anchorScroll();
-                    };
+        //Scroll to target anchor
+        $scope.gotoAnchor = function() {
+          $location.hash('upload');
+          $anchorScroll();
+        };
 
-                    $scope.firmwares = [];
-                    $scope.bmcActiveVersion = "";
-                    $scope.hostActiveVersion = "";
-                    $scope.display_error = false;
-                    $scope.activate_confirm = false;
-                    $scope.delete_image_id = "";
-                    $scope.delete_image_version = "";
-                    $scope.activate_image_id = "";
-                    $scope.activate_image_version = "";
-                    $scope.activate_image_type = "";
-                    $scope.priority_image_id = "";
-                    $scope.priority_image_version = "";
-                    $scope.priority_from = -1;
-                    $scope.priority_to = -1;
-                    $scope.confirm_priority = false;
-                    $scope.file_empty = true;
-                    $scope.uploading = false;
-                    $scope.upload_success = false;
-                    $scope.activate = { reboot: true };
-                    $scope.download_error_msg = "";
-                    $scope.download_success = false;
+        $scope.firmwares = [];
+        $scope.bmcActiveVersion = '';
+        $scope.hostActiveVersion = '';
+        $scope.display_error = false;
+        $scope.activate_confirm = false;
+        $scope.delete_image_id = '';
+        $scope.delete_image_version = '';
+        $scope.activate_image_id = '';
+        $scope.activate_image_version = '';
+        $scope.activate_image_type = '';
+        $scope.priority_image_id = '';
+        $scope.priority_image_version = '';
+        $scope.priority_from = -1;
+        $scope.priority_to = -1;
+        $scope.confirm_priority = false;
+        $scope.file_empty = true;
+        $scope.uploading = false;
+        $scope.upload_success = false;
+        $scope.activate = {
+          reboot: true
+        };
+        $scope.download_error_msg = '';
+        $scope.download_success = false;
 
-                    var pollActivationTimer = undefined;
-                    var pollDownloadTimer = undefined;
+        var pollActivationTimer = undefined;
+        var pollDownloadTimer = undefined;
 
-                    $scope.error = {
-                        modal_title: "",
-                        title: "",
-                        desc: "",
-                        type: "warning"
-                    };
+        $scope.error = {
+          modal_title: '',
+          title: '',
+          desc: '',
+          type: 'warning'
+        };
 
-                    $scope.activateImage = function(imageId, imageVersion, imageType){
-                        $scope.activate_image_id = imageId;
-                        $scope.activate_image_version = imageVersion;
-                        $scope.activate_image_type = imageType;
-                        $scope.activate_confirm = true;
-                    }
+        $scope.activateImage = function(imageId, imageVersion, imageType) {
+          $scope.activate_image_id = imageId;
+          $scope.activate_image_version = imageVersion;
+          $scope.activate_image_type = imageType;
+          $scope.activate_confirm = true;
+        };
 
-                    $scope.displayError = function(data){
-                        $scope.error = data;
-                        $scope.display_error = true;
-                    }
+        $scope.displayError = function(data) {
+          $scope.error = data;
+          $scope.display_error = true;
+        };
 
-                    function waitForActive(imageId){
-                      var deferred = $q.defer();
-                      var startTime = new Date();
-                      pollActivationTimer = $interval(function(){
-                        APIUtils.getActivation(imageId).then(function(state){
-                          //@TODO: display an error message if image "Failed"
-                          if(((/\.Active$/).test(state.data)) || ((/\.Failed$/).test(state.data))){
-                            $interval.cancel(pollActivationTimer);
-                            pollActivationTimer = undefined;
-                            deferred.resolve(state);
-                          }
-                        }, function(error){
-                          $interval.cancel(pollActivationTimer);
-                          pollActivationTimer = undefined;
-                          console.log(error);
-                          deferred.reject(error);
-                        });
-                        var now = new Date();
-                        if((now.getTime() - startTime.getTime()) >= Constants.TIMEOUT.ACTIVATION){
-                          $interval.cancel(pollActivationTimer);
-                          pollActivationTimer = undefined;
-                          console.log("Time out activating image, " + imageId);
-                          deferred.reject("Time out. Image did not activate in allotted time.");
-                        }
-                      }, Constants.POLL_INTERVALS.ACTIVATION);
-                      return deferred.promise;
-                    }
+        function waitForActive(imageId) {
+          var deferred = $q.defer();
+          var startTime = new Date();
+          pollActivationTimer = $interval(function() {
+            APIUtils.getActivation(imageId).then(function(state) {
+              //@TODO: display an error message if image "Failed"
+              if (((/\.Active$/).test(state.data)) || ((/\.Failed$/).test(state.data))) {
+                $interval.cancel(pollActivationTimer);
+                pollActivationTimer = undefined;
+                deferred.resolve(state);
+              }
+            }, function(error) {
+              $interval.cancel(pollActivationTimer);
+              pollActivationTimer = undefined;
+              console.log(error);
+              deferred.reject(error);
+            });
+            var now = new Date();
+            if ((now.getTime() - startTime.getTime()) >= Constants.TIMEOUT.ACTIVATION) {
+              $interval.cancel(pollActivationTimer);
+              pollActivationTimer = undefined;
+              console.log('Time out activating image, ' + imageId);
+              deferred.reject('Time out. Image did not activate in allotted time.');
+            }
+          }, Constants.POLL_INTERVALS.ACTIVATION);
+          return deferred.promise;
+        }
 
-                    $scope.activateConfirmed = function(){
-                        APIUtils.activateImage($scope.activate_image_id).then(function(state){
-                          $scope.loadFirmwares();
-                          return state;
-                        }, function(error){
-                          $scope.displayError({
-                            modal_title: 'Error during activation call',
-                            title: 'Error during activation call',
-                            desc: JSON.stringify(error.data),
-                            type: 'Error'
-                          });
-                        }).then(function(activationState){
-                          waitForActive($scope.activate_image_id).then(function(state){
-                            $scope.loadFirmwares();
-                        }, function(error){
-                          $scope.displayError({
-                            modal_title: 'Error during image activation',
-                            title: 'Error during image activation',
-                            desc: JSON.stringify(error.data),
-                            type: 'Error'
-                          });
-                        }).then(function(state){
-                          // Only look at reboot if it's a BMC image
-                          if($scope.activate.reboot && ($scope.activate_image_type == 'BMC')){
-                            // Despite the new image being active, issue,
-                            // https://github.com/openbmc/openbmc/issues/2764, can cause a
-                            // system to brick, if the system reboots before the service to set
-                            // the U-Boot variables is complete. Wait 10 seconds before rebooting
-                            // to ensure this service is complete. This issue is fixed in newer images, but
-                            // the user may be updating from an older image that does not that have this fix.
-                            // TODO: remove this timeout after sufficient time has passed.
-                            $timeout(function() {
-                              APIUtils.bmcReboot(function(response){}, function(error){
-                                $scope.displayError({
-                                  modal_title: 'Error during BMC reboot',
-                                  title: 'Error during BMC reboot',
-                                  desc: JSON.stringify(error.data),
-                                  type: 'Error'
-                                });
-                              });
-                            }, 10000);
-                          }
-                        });
-                      });
-                      $scope.activate_confirm = false;
-                    }
+        $scope.activateConfirmed = function() {
+          APIUtils.activateImage($scope.activate_image_id).then(function(state) {
+            $scope.loadFirmwares();
+            return state;
+          }, function(error) {
+            $scope.displayError({
+              modal_title: 'Error during activation call',
+              title: 'Error during activation call',
+              desc: JSON.stringify(error.data),
+              type: 'Error'
+            });
+          }).then(function(activationState) {
+            waitForActive($scope.activate_image_id).then(function(state) {
+              $scope.loadFirmwares();
+            }, function(error) {
+              $scope.displayError({
+                modal_title: 'Error during image activation',
+                title: 'Error during image activation',
+                desc: JSON.stringify(error.data),
+                type: 'Error'
+              });
+            }).then(function(state) {
+              // Only look at reboot if it's a BMC image
+              if ($scope.activate.reboot && ($scope.activate_image_type == 'BMC')) {
+                // Despite the new image being active, issue,
+                // https://github.com/openbmc/openbmc/issues/2764, can cause a
+                // system to brick, if the system reboots before the service to set
+                // the U-Boot variables is complete. Wait 10 seconds before rebooting
+                // to ensure this service is complete. This issue is fixed in newer images, but
+                // the user may be updating from an older image that does not that have this fix.
+                // TODO: remove this timeout after sufficient time has passed.
+                $timeout(function() {
+                  APIUtils.bmcReboot(function(response) {}, function(error) {
+                    $scope.displayError({
+                      modal_title: 'Error during BMC reboot',
+                      title: 'Error during BMC reboot',
+                      desc: JSON.stringify(error.data),
+                      type: 'Error'
+                    });
+                  });
+                }, 10000);
+              }
+            });
+          });
+          $scope.activate_confirm = false;
+        };
 
-                    $scope.upload = function(){
-                      if($scope.file) {
-                        $scope.uploading = true;
-                        $scope.upload_success = false;
-                        APIUtils.uploadImage($scope.file).then(function(response){
-                          $scope.file = "";
-                          $scope.uploading = false;
-                          $scope.upload_success = true;
-                          $scope.loadFirmwares();
-                        }, function(error){
-                          $scope.uploading = false;
-                          console.log(error);
-                          $scope.displayError({
-                            modal_title: 'Error during image upload',
-                            title: 'Error during image upload',
-                            desc: error,
-                            type: 'Error'
-                          });
-                        });
-                      }
-                    }
+        $scope.upload = function() {
+          if ($scope.file) {
+            $scope.uploading = true;
+            $scope.upload_success = false;
+            APIUtils.uploadImage($scope.file).then(function(response) {
+              $scope.file = '';
+              $scope.uploading = false;
+              $scope.upload_success = true;
+              $scope.loadFirmwares();
+            }, function(error) {
+              $scope.uploading = false;
+              console.log(error);
+              $scope.displayError({
+                modal_title: 'Error during image upload',
+                title: 'Error during image upload',
+                desc: error,
+                type: 'Error'
+              });
+            });
+          }
+        };
 
-                    //TODO: openbmc/openbmc#1691 Add support to return
-                    //the id of the newly created image, downloaded via
-                    //tftp. Polling the number of software objects is a
-                    //near term solution.
-                    function waitForDownload(){
-                        var deferred = $q.defer();
-                        var startTime = new Date();
-                        pollDownloadTimer = $interval(function(){
-                            var now = new Date();
-                            if((now.getTime() - startTime.getTime()) >= Constants.TIMEOUT.DOWNLOAD_IMAGE){
-                                $interval.cancel(pollDownloadTimer);
-                                pollDownloadTimer = undefined;
-                                deferred.reject(new Error(Constants.MESSAGES.POLL.DOWNLOAD_IMAGE_TIMEOUT));
-                            }
+        //TODO: openbmc/openbmc#1691 Add support to return
+        //the id of the newly created image, downloaded via
+        //tftp. Polling the number of software objects is a
+        //near term solution.
+        function waitForDownload() {
+          var deferred = $q.defer();
+          var startTime = new Date();
+          pollDownloadTimer = $interval(function() {
+            var now = new Date();
+            if ((now.getTime() - startTime.getTime()) >= Constants.TIMEOUT.DOWNLOAD_IMAGE) {
+              $interval.cancel(pollDownloadTimer);
+              pollDownloadTimer = undefined;
+              deferred.reject(new Error(Constants.MESSAGES.POLL.DOWNLOAD_IMAGE_TIMEOUT));
+            }
 
-                            APIUtils.getFirmwares().then(function(response){
-                                if(response.data.length === $scope.firmwares.length + 1){
-                                    $interval.cancel(pollDownloadTimer);
-                                    pollDownloadTimer = undefined;
-                                    deferred.resolve(response.data);
-                                }
-                            }, function(error){
-                                $interval.cancel(pollDownloadTimer);
-                                pollDownloadTimer = undefined;
-                                deferred.reject(error);
-                            });
-                        }, Constants.POLL_INTERVALS.DOWNLOAD_IMAGE);
+            APIUtils.getFirmwares().then(function(response) {
+              if (response.data.length === $scope.firmwares.length + 1) {
+                $interval.cancel(pollDownloadTimer);
+                pollDownloadTimer = undefined;
+                deferred.resolve(response.data);
+              }
+            }, function(error) {
+              $interval.cancel(pollDownloadTimer);
+              pollDownloadTimer = undefined;
+              deferred.reject(error);
+            });
+          }, Constants.POLL_INTERVALS.DOWNLOAD_IMAGE);
 
-                        return deferred.promise;
-                    }
+          return deferred.promise;
+        }
 
-                    $scope.download = function(){
-                        $scope.download_success = false;
-                        $scope.download_error_msg = "";
-                        if(!$scope.download_host || !$scope.download_filename){
-                          $scope.download_error_msg = "Field is required!";
-                          return false;
-                        }
+        $scope.download = function() {
+          $scope.download_success = false;
+          $scope.download_error_msg = '';
+          if (!$scope.download_host || !$scope.download_filename) {
+            $scope.download_error_msg = 'Field is required!';
+            return false;
+          }
 
-                        $scope.downloading = true;
-                        APIUtils.getFirmwares().then(function(response){
-                            $scope.firmwares =  response.data;
-                        }).then(function(){
-                            return APIUtils.downloadImage($scope.download_host,
-                                    $scope.download_filename).then(function(downloadStatus){
-                                return downloadStatus;
-                            });
-                        }).then(function(downloadStatus){
-                            return waitForDownload();
-                        }).then(function(newFirmwareList){
-                            $scope.download_host = "";
-                            $scope.download_filename = "";
-                            $scope.downloading = false;
-                            $scope.download_success = true;
-                            $scope.loadFirmwares();
-                        }, function(error){
-                            console.log(error);
-                            $scope.displayError({
-                                modal_title: 'Error during downloading Image',
-                                title: 'Error during downloading Image',
-                                desc: error,
-                                type: 'Error'
-                            });
-                            $scope.downloading = false;
-                        });
-                    }
+          $scope.downloading = true;
+          APIUtils.getFirmwares().then(function(response) {
+            $scope.firmwares = response.data;
+          }).then(function() {
+            return APIUtils.downloadImage($scope.download_host,
+              $scope.download_filename).then(function(downloadStatus) {
+              return downloadStatus;
+            });
+          }).then(function(downloadStatus) {
+            return waitForDownload();
+          }).then(function(newFirmwareList) {
+            $scope.download_host = '';
+            $scope.download_filename = '';
+            $scope.downloading = false;
+            $scope.download_success = true;
+            $scope.loadFirmwares();
+          }, function(error) {
+            console.log(error);
+            $scope.displayError({
+              modal_title: 'Error during downloading Image',
+              title: 'Error during downloading Image',
+              desc: error,
+              type: 'Error'
+            });
+            $scope.downloading = false;
+          });
+        };
 
-                    $scope.changePriority = function(imageId, imageVersion, from, to){
-                        $scope.priority_image_id = imageId;
-                        $scope.priority_image_version = imageVersion;
-                        $scope.priority_from = from;
-                        $scope.priority_to = to;
-                        $scope.confirm_priority = true;
-                    }
+        $scope.changePriority = function(imageId, imageVersion, from, to) {
+          $scope.priority_image_id = imageId;
+          $scope.priority_image_version = imageVersion;
+          $scope.priority_from = from;
+          $scope.priority_to = to;
+          $scope.confirm_priority = true;
+        };
 
-                    $scope.confirmChangePriority = function(){
-                        $scope.loading = true;
-                        APIUtils.changePriority($scope.priority_image_id, $scope.priority_to).then(function(response){
-                            $scope.loading = false;
-                            if(response.status == 'error'){
-                                $scope.displayError({
-                                    modal_title: response.data.description,
-                                    title: response.data.description,
-                                    desc: response.data.exception,
-                                    type: 'Error'
-                                });
-                            }else{
-                                $scope.loadFirmwares();
-                            }
-                        });
-                        $scope.confirm_priority = false;
-                    }
-                    $scope.deleteImage = function(imageId, imageVersion){
-                        $scope.delete_image_id = imageId;
-                        $scope.delete_image_version = imageVersion;
-                        $scope.confirm_delete = true;
-                    }
-                    $scope.confirmDeleteImage = function(){
-                        $scope.loading = true;
-                        APIUtils.deleteImage($scope.delete_image_id).then(function(response){
-                            $scope.loading = false;
-                            if(response.status == 'error'){
-                                $scope.displayError({
-                                    modal_title: response.data.description,
-                                    title: response.data.description,
-                                    desc: response.data.exception,
-                                    type: 'Error'
-                                });
-                            }else{
-                                $scope.loadFirmwares();
-                            }
-                        });
-                        $scope.confirm_delete = false;
-                    }
-                    $scope.fileNameChanged = function(){
-                        $scope.file_empty = false;
-                    }
+        $scope.confirmChangePriority = function() {
+          $scope.loading = true;
+          APIUtils.changePriority($scope.priority_image_id, $scope.priority_to).then(function(response) {
+            $scope.loading = false;
+            if (response.status == 'error') {
+              $scope.displayError({
+                modal_title: response.data.description,
+                title: response.data.description,
+                desc: response.data.exception,
+                type: 'Error'
+              });
+            }
+            else {
+              $scope.loadFirmwares();
+            }
+          });
+          $scope.confirm_priority = false;
+        };
+        $scope.deleteImage = function(imageId, imageVersion) {
+          $scope.delete_image_id = imageId;
+          $scope.delete_image_version = imageVersion;
+          $scope.confirm_delete = true;
+        };
+        $scope.confirmDeleteImage = function() {
+          $scope.loading = true;
+          APIUtils.deleteImage($scope.delete_image_id).then(function(response) {
+            $scope.loading = false;
+            if (response.status == 'error') {
+              $scope.displayError({
+                modal_title: response.data.description,
+                title: response.data.description,
+                desc: response.data.exception,
+                type: 'Error'
+              });
+            }
+            else {
+              $scope.loadFirmwares();
+            }
+          });
+          $scope.confirm_delete = false;
+        };
+        $scope.fileNameChanged = function() {
+          $scope.file_empty = false;
+        };
 
-                    $scope.filters = {
-                        bmc: {
-                            imageType: 'BMC'
-                        },
-                        host: {
-                            imageType: 'Host'
-                        }
-                    };
+        $scope.filters = {
+          bmc: {
+            imageType: 'BMC'
+          },
+          host: {
+            imageType: 'Host'
+          }
+        };
 
-                    $scope.loadFirmwares = function(){
-                        APIUtils.getFirmwares().then(function(result){
-                           $scope.firmwares = result.data;
-                           $scope.bmcActiveVersion = result.bmcActiveVersion;
-                           $scope.hostActiveVersion = result.hostActiveVersion;
-                        });
-                    }
+        $scope.loadFirmwares = function() {
+          APIUtils.getFirmwares().then(function(result) {
+            $scope.firmwares = result.data;
+            $scope.bmcActiveVersion = result.bmcActiveVersion;
+            $scope.hostActiveVersion = result.hostActiveVersion;
+          });
+        };
 
-                    $scope.loadFirmwares();
-                }
-            ]
-        );
+        $scope.loadFirmwares();
+      }
+    ]);
 
 })(angular);
diff --git a/app/configuration/controllers/network-controller.js b/app/configuration/controllers/network-controller.js
index f08989b..4eff0cd 100644
--- a/app/configuration/controllers/network-controller.js
+++ b/app/configuration/controllers/network-controller.js
@@ -6,38 +6,37 @@
  * @name networkController
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.configuration')
-        .controller('networkController', [
-            '$scope',
-            '$window',
-            'APIUtils',
-            'dataService',
-            function($scope, $window, APIUtils, dataService){
-                $scope.dataService = dataService;
-                $scope.network = {};
-                $scope.interface = {};
-                $scope.networkDevice  = false;
-                $scope.hostname = "";
+  angular
+    .module('app.configuration')
+    .controller('networkController', [
+      '$scope',
+      '$window',
+      'APIUtils',
+      'dataService',
+      function($scope, $window, APIUtils, dataService) {
+        $scope.dataService = dataService;
+        $scope.network = {};
+        $scope.interface = {};
+        $scope.networkDevice = false;
+        $scope.hostname = '';
 
-                $scope.selectInterface = function(interfaceId){
-                    $scope.interface = $scope.network.interfaces[interfaceId];
-                    $scope.selectedInterface = interfaceId;
-                    $scope.networkDevice = false;
-                }
-                APIUtils.getNetworkInfo().then(function(data){
-                    $scope.network = data.formatted_data;
-                    $scope.hostname = data.hostname;
-                    if($scope.network.interface_ids.length){
-                       $scope.selectedInterface = $scope.network.interface_ids[0];
-                       $scope.interface = $scope.network.interfaces[$scope.selectedInterface];
-                    }
-                });
-            }
-        ]
-    );
+        $scope.selectInterface = function(interfaceId) {
+          $scope.interface = $scope.network.interfaces[interfaceId];
+          $scope.selectedInterface = interfaceId;
+          $scope.networkDevice = false;
+        };
+        APIUtils.getNetworkInfo().then(function(data) {
+          $scope.network = data.formatted_data;
+          $scope.hostname = data.hostname;
+          if ($scope.network.interface_ids.length) {
+            $scope.selectedInterface = $scope.network.interface_ids[0];
+            $scope.interface = $scope.network.interfaces[$scope.selectedInterface];
+          }
+        });
+      }
+    ]);
 
 })(angular);
diff --git a/app/configuration/controllers/security-controller.js b/app/configuration/controllers/security-controller.js
index eb6f698..d250ac7 100644
--- a/app/configuration/controllers/security-controller.js
+++ b/app/configuration/controllers/security-controller.js
@@ -6,20 +6,19 @@
  * @name securityController
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.configuration')
-        .controller('securityController', [
-            '$scope',
-            '$window',
-            'APIUtils',
-            'dataService',
-            function($scope, $window, APIUtils, dataService){
-                $scope.dataService = dataService;
-            }
-        ]
-    );
+  angular
+    .module('app.configuration')
+    .controller('securityController', [
+      '$scope',
+      '$window',
+      'APIUtils',
+      'dataService',
+      function($scope, $window, APIUtils, dataService) {
+        $scope.dataService = dataService;
+      }
+    ]);
 
 })(angular);
diff --git a/app/configuration/index.js b/app/configuration/index.js
index 0b5499e..869af04 100644
--- a/app/configuration/index.js
+++ b/app/configuration/index.js
@@ -5,45 +5,45 @@
  * @exports app/configuration/index
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.configuration', [
-            'ngRoute',
-            'app.constants',
-            'app.common.services'
-        ])
-        // Route configuration
-        .config(['$routeProvider', function ($routeProvider) {
-            $routeProvider
-                .when('/configuration/network', {
-                    'template': require('./controllers/network-controller.html'),
-                    'controller': 'networkController',
-                    authenticated: true
-                })
-                .when('/configuration/security', {
-                    'template': require('./controllers/security-controller.html'),
-                    'controller': 'securityController',
-                    authenticated: true
-                }).when('/configuration/date-time', {
-                    'template': require('./controllers/date-time-controller.html'),
-                    'controller': 'dateTimeController',
-                    authenticated: true
-                })
-                .when('/configuration/file', {
-                    'template': require('./controllers/file-controller.html'),
-                    'controller': 'fileController',
-                    authenticated: true
-                }).when('/configuration', {
-                    'template': require('./controllers/network-controller.html'),
-                    'controller': 'networkController',
-                    authenticated: true
-                }).when('/configuration/firmware', {
-                'template': require('./controllers/firmware-controller.html'),
-                'controller': 'firmwareController',
-                authenticated: true
-            });
-        }]);
+  angular
+    .module('app.configuration', [
+      'ngRoute',
+      'app.constants',
+      'app.common.services'
+    ])
+    // Route configuration
+    .config(['$routeProvider', function($routeProvider) {
+      $routeProvider
+        .when('/configuration/network', {
+          'template': require('./controllers/network-controller.html'),
+          'controller': 'networkController',
+          authenticated: true
+        })
+        .when('/configuration/security', {
+          'template': require('./controllers/security-controller.html'),
+          'controller': 'securityController',
+          authenticated: true
+        }).when('/configuration/date-time', {
+          'template': require('./controllers/date-time-controller.html'),
+          'controller': 'dateTimeController',
+          authenticated: true
+        })
+        .when('/configuration/file', {
+          'template': require('./controllers/file-controller.html'),
+          'controller': 'fileController',
+          authenticated: true
+        }).when('/configuration', {
+          'template': require('./controllers/network-controller.html'),
+          'controller': 'networkController',
+          authenticated: true
+        }).when('/configuration/firmware', {
+          'template': require('./controllers/firmware-controller.html'),
+          'controller': 'firmwareController',
+          authenticated: true
+        });
+    }]);
 
 })(window.angular);
diff --git a/app/constants/environment-constants.js b/app/constants/environment-constants.js
index d5ce783..a40beb5 100644
--- a/app/constants/environment-constants.js
+++ b/app/constants/environment-constants.js
@@ -6,24 +6,23 @@
  *
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.constants')
-        .constant('EnvironmentConstants', {
-            'inDevelopmentMode': true,
-            'RestConstants': {
-            },
-            FLASH_MESSAGE : {
-              duration: 2000,
-              classes: {
-                warning: 'message-warning',
-                info: 'message-info',
-                error: 'message-error',
-                success: 'message-success'
-              }
-            }
-        });
+  angular
+    .module('app.constants')
+    .constant('EnvironmentConstants', {
+      'inDevelopmentMode': true,
+      'RestConstants': {},
+      FLASH_MESSAGE: {
+        duration: 2000,
+        classes: {
+          warning: 'message-warning',
+          info: 'message-info',
+          error: 'message-error',
+          success: 'message-success'
+        }
+      }
+    });
 
 })(window.angular);
diff --git a/app/constants/index.js b/app/constants/index.js
index 43e38b6..5d7e18c 100644
--- a/app/constants/index.js
+++ b/app/constants/index.js
@@ -5,12 +5,11 @@
  * @exports app/constants/index
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.constants', [])
-        .constant('AppConstants', {
-        });
+  angular
+    .module('app.constants', [])
+    .constant('AppConstants', {});
 
 })(window.angular);
diff --git a/app/firmware/controllers/bmc-controller.js b/app/firmware/controllers/bmc-controller.js
index 42a4f18..78e87a7 100644
--- a/app/firmware/controllers/bmc-controller.js
+++ b/app/firmware/controllers/bmc-controller.js
@@ -6,20 +6,19 @@
  * @name bmcController
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.firmware')
-        .controller('bmcController', [
-            '$scope',
-            '$window',
-            'APIUtils',
-            'dataService',
-            function($scope, $window, APIUtils, dataService){
-                $scope.dataService = dataService;
-            }
-        ]
-    );
+  angular
+    .module('app.firmware')
+    .controller('bmcController', [
+      '$scope',
+      '$window',
+      'APIUtils',
+      'dataService',
+      function($scope, $window, APIUtils, dataService) {
+        $scope.dataService = dataService;
+      }
+    ]);
 
 })(angular);
diff --git a/app/firmware/controllers/server-controller.js b/app/firmware/controllers/server-controller.js
index 5d5da4a..2b1a673 100644
--- a/app/firmware/controllers/server-controller.js
+++ b/app/firmware/controllers/server-controller.js
@@ -6,20 +6,19 @@
  * @name serverController
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.firmware')
-        .controller('serverController', [
-            '$scope',
-            '$window',
-            'APIUtils',
-            'dataService',
-            function($scope, $window, APIUtils, dataService){
-                $scope.dataService = dataService;
-            }
-        ]
-    );
+  angular
+    .module('app.firmware')
+    .controller('serverController', [
+      '$scope',
+      '$window',
+      'APIUtils',
+      'dataService',
+      function($scope, $window, APIUtils, dataService) {
+        $scope.dataService = dataService;
+      }
+    ]);
 
 })(angular);
diff --git a/app/firmware/index.js b/app/firmware/index.js
index 9ac623b..3e4189c 100644
--- a/app/firmware/index.js
+++ b/app/firmware/index.js
@@ -5,33 +5,33 @@
  * @exports app/firmware/index
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.firmware', [
-            'ngRoute',
-            'app.constants',
-            'app.common.services'
-        ])
-        // Route configuration
-        .config(['$routeProvider', function ($routeProvider) {
-            $routeProvider
-                .when('/firmware/bmc', {
-                    'template': require('./controllers/bmc-controller.html'),
-                    'controller': 'bmcController',
-                    authenticated: true
-                })
-                .when('/firmware/server', {
-                    'template': require('./controllers/server-controller.html'),
-                    'controller': 'serverController',
-                    authenticated: true
-                })
-                .when('/firmware', {
-                    'template': reqire('./controllers/bmc-controller.html'),
-                    'controller': 'bmcController',
-                    authenticated: true
-                });
-        }]);
+  angular
+    .module('app.firmware', [
+      'ngRoute',
+      'app.constants',
+      'app.common.services'
+    ])
+    // Route configuration
+    .config(['$routeProvider', function($routeProvider) {
+      $routeProvider
+        .when('/firmware/bmc', {
+          'template': require('./controllers/bmc-controller.html'),
+          'controller': 'bmcController',
+          authenticated: true
+        })
+        .when('/firmware/server', {
+          'template': require('./controllers/server-controller.html'),
+          'controller': 'serverController',
+          authenticated: true
+        })
+        .when('/firmware', {
+          'template': reqire('./controllers/bmc-controller.html'),
+          'controller': 'bmcController',
+          authenticated: true
+        });
+    }]);
 
 })(window.angular);
diff --git a/app/index.js b/app/index.js
index d59fb9d..5797ec4 100644
--- a/app/index.js
+++ b/app/index.js
@@ -9,7 +9,7 @@
 
 import 'bootstrap/dist/css/bootstrap.css';
 import 'bootstrap/dist/css/bootstrap-theme.css';
-import "font-awesome/css/font-awesome.css"
+import 'font-awesome/css/font-awesome.css';
 import angular from 'angular';
 import angular_cookies from 'angular-cookies';
 import angular_sanitize from 'angular-sanitize';
@@ -20,156 +20,158 @@
 import angular_route from 'angular-route';
 import angular_utils from 'angularUtils/src/angularUtils.js';
 import angular_utils_pagination from 'angularUtils/src/directives/pagination/dirPagination.js';
-require('./styles/index.scss')
+require('./styles/index.scss');
 
 // TODO(Ed)  clean this up, add the appropriate imports to phosphor-webui
 
-import constants_index from './constants/index.js'
-import environment_constants from './constants/environment-constants.js'
+import constants_index from './constants/index.js';
+import environment_constants from './constants/environment-constants.js';
 
-import services_index from './common/services/index.js'
-import constants from './common/services/constants.js'
-import dataService from './common/services/dataService.js'
-import api_utils from './common/services/api-utils.js'
-import userModel from './common/services/userModel.js'
-import apiInterceptor from './common/services/apiInterceptor.js'
+import services_index from './common/services/index.js';
+import constants from './common/services/constants.js';
+import dataService from './common/services/dataService.js';
+import api_utils from './common/services/api-utils.js';
+import userModel from './common/services/userModel.js';
+import apiInterceptor from './common/services/apiInterceptor.js';
 
-import filters_index from './common/filters/index.js'
+import filters_index from './common/filters/index.js';
 
-import directives_index from './common/directives/index.js'
-import errors from './common/directives/errors.js'
-import app_header from './common/directives/app-header.js'
-import app_navigation from './common/directives/app-navigation.js'
-import confirm from './common/directives/confirm.js'
-import log_event from './common/directives/log-event.js'
-import log_filter from './common/directives/log-filter.js'
-import log_search_control from './common/directives/log-search-control.js'
-import toggle_flag from './common/directives/toggle-flag.js'
-import firmware_list from './common/directives/firmware-list.js'
-import file from './common/directives/file.js'
-import loader from './common/directives/loader.js'
-import paginate from './common/directives/paginate.js'
+import directives_index from './common/directives/index.js';
+import errors from './common/directives/errors.js';
+import app_header from './common/directives/app-header.js';
+import app_navigation from './common/directives/app-navigation.js';
+import confirm from './common/directives/confirm.js';
+import log_event from './common/directives/log-event.js';
+import log_filter from './common/directives/log-filter.js';
+import log_search_control from './common/directives/log-search-control.js';
+import toggle_flag from './common/directives/toggle-flag.js';
+import firmware_list from './common/directives/firmware-list.js';
+import file from './common/directives/file.js';
+import loader from './common/directives/loader.js';
+import paginate from './common/directives/paginate.js';
 
-import login_index from './login/index.js'
-import login_controller from './login/controllers/login-controller.js'
+import login_index from './login/index.js';
+import login_controller from './login/controllers/login-controller.js';
 
-import overview_index from './overview/index.js'
-import system_overview_controller from './overview/controllers/system-overview-controller.js'
+import overview_index from './overview/index.js';
+import system_overview_controller from './overview/controllers/system-overview-controller.js';
 
-import server_control_index from './server-control/index.js'
-import bmc_reboot_controller from './server-control/controllers/bmc-reboot-controller.js'
-import power_operations_controller from './server-control/controllers/power-operations-controller.js'
-import remote_console_controller from './server-control/controllers/remote-console-controller.js'
-import remote_console_window_controller from './server-control/controllers/remote-console-window-controller.js'
+import server_control_index from './server-control/index.js';
+import bmc_reboot_controller from './server-control/controllers/bmc-reboot-controller.js';
+import power_operations_controller from './server-control/controllers/power-operations-controller.js';
+import remote_console_controller from './server-control/controllers/remote-console-controller.js';
+import remote_console_window_controller from './server-control/controllers/remote-console-window-controller.js';
 
-import server_health_index from './server-health/index.js'
-import diagnostics_controller from './server-health/controllers/diagnostics-controller.js'
-import inventory_controller from './server-health/controllers/inventory-controller.js'
-import inventory_overview_controller from './server-health/controllers/inventory-overview-controller.js'
-import log_controller from './server-health/controllers/log-controller.js'
-import power_consumption_controller from './server-health/controllers/power-consumption-controller.js'
-import sensors_controller from './server-health/controllers/sensors-controller.js'
-import sensors_overview_controller from './server-health/controllers/sensors-overview-controller.js'
-import unit_id_controller from './server-health/controllers/unit-id-controller.js'
+import server_health_index from './server-health/index.js';
+import diagnostics_controller from './server-health/controllers/diagnostics-controller.js';
+import inventory_controller from './server-health/controllers/inventory-controller.js';
+import inventory_overview_controller from './server-health/controllers/inventory-overview-controller.js';
+import log_controller from './server-health/controllers/log-controller.js';
+import power_consumption_controller from './server-health/controllers/power-consumption-controller.js';
+import sensors_controller from './server-health/controllers/sensors-controller.js';
+import sensors_overview_controller from './server-health/controllers/sensors-overview-controller.js';
+import unit_id_controller from './server-health/controllers/unit-id-controller.js';
 
-import configuration_index from './configuration/index.js'
-import date_time_controller from './configuration/controllers/date-time-controller.js'
-import file_controller from './configuration/controllers/file-controller.js'
-import network_controller from './configuration/controllers/network-controller.js'
-import security_controller from './configuration/controllers/security-controller.js'
-import firmware_controller from './configuration/controllers/firmware-controller.js'
+import configuration_index from './configuration/index.js';
+import date_time_controller from './configuration/controllers/date-time-controller.js';
+import file_controller from './configuration/controllers/file-controller.js';
+import network_controller from './configuration/controllers/network-controller.js';
+import security_controller from './configuration/controllers/security-controller.js';
+import firmware_controller from './configuration/controllers/firmware-controller.js';
 
-import firmware_index from './firmware/index.js'
-import bmc_controller from './firmware/controllers/bmc-controller.js'
-import server_controller from './firmware/controllers/server-controller.js'
+import firmware_index from './firmware/index.js';
+import bmc_controller from './firmware/controllers/bmc-controller.js';
+import server_controller from './firmware/controllers/server-controller.js';
 
-import multi_server_index from './multi-server/index.js'
-import multi_server_controller from './multi-server/controllers/multi-server-controller.js'
+import multi_server_index from './multi-server/index.js';
+import multi_server_controller from './multi-server/controllers/multi-server-controller.js';
 
-import users_index from './users/index.js'
-import user_accounts_controller from './users/controllers/user-accounts-controller.js'
+import users_index from './users/index.js';
+import user_accounts_controller from './users/controllers/user-accounts-controller.js';
 
 import phosphor_templates from './templates.js';
 import phosphor_vendors from './vendors.js';
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app', [
-            // Dependencies
-            'ngRoute',
-            'angular-clipboard',
-            'angularUtils.directives.dirPagination',
-            // Basic resources
-            'app.constants',
-            'app.templates',
-            'app.vendors',
-            'app.common.services',
-            'app.common.directives',
-            'app.common.filters',
-            // Model resources
-            'app.login',
-            'app.overview',
-            'app.serverControl',
-            'app.serverHealth',
-            'app.configuration',
-            'app.users',
-            'app.multiServer'
-        ])
-        // Route configuration
-        .config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {
-            $locationProvider.hashPrefix('');
-            $routeProvider
-                .otherwise({
-                    'redirectTo': '/login'
-                });
-        }])
-        .config(['$compileProvider', function ($compileProvider) {
-          $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|tel|file|data|blob):/);
-        }])
-        .config(['$httpProvider', function($httpProvider){
-            $httpProvider.interceptors.push('apiInterceptor');
-        }])
-        .run(['$rootScope', '$location', 'dataService', 'userModel',
-           function($rootScope, $location, dataService, userModel){
-           $rootScope.dataService = dataService;
-           dataService.path = $location.path();
-           $rootScope.$on('$routeChangeStart', function(event, next, current){
-             if(next.$$route == null || next.$$route == undefined) return;
-             if(next.$$route.authenticated){
-               if(!userModel.isLoggedIn()){
-                 $location.path('/login');
-               }
-             }
+  angular
+    .module('app', [
+      // Dependencies
+      'ngRoute',
+      'angular-clipboard',
+      'angularUtils.directives.dirPagination',
+      // Basic resources
+      'app.constants',
+      'app.templates',
+      'app.vendors',
+      'app.common.services',
+      'app.common.directives',
+      'app.common.filters',
+      // Model resources
+      'app.login',
+      'app.overview',
+      'app.serverControl',
+      'app.serverHealth',
+      'app.configuration',
+      'app.users',
+      'app.multiServer'
+    ])
+    // Route configuration
+    .config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
+      $locationProvider.hashPrefix('');
+      $routeProvider
+        .otherwise({
+          'redirectTo': '/login'
+        });
+    }])
+    .config(['$compileProvider', function($compileProvider) {
+      $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|tel|file|data|blob):/);
+    }])
+    .config(['$httpProvider', function($httpProvider) {
+      $httpProvider.interceptors.push('apiInterceptor');
+    }])
+    .run(['$rootScope', '$location', 'dataService', 'userModel',
+      function($rootScope, $location, dataService, userModel) {
+        $rootScope.dataService = dataService;
+        dataService.path = $location.path();
+        $rootScope.$on('$routeChangeStart', function(event, next, current) {
+          if (next.$$route == null || next.$$route == undefined) return;
+          if (next.$$route.authenticated) {
+            if (!userModel.isLoggedIn()) {
+              $location.path('/login');
+            }
+          }
 
-             if(next.$$route.originalPath == '/' ||
-               next.$$route.originalPath == '/login'){
-                if(userModel.isLoggedIn()){
-                   if(current && current.$$route){
-                     $location.path(current.$$route.originalPath);
-                   }else{
-                     $location.path('/overview/server');
-                   }
-                }
-             }
-           });
-           $rootScope.$on('$locationChangeSuccess', function(event){
-               var path = $location.path();
-               dataService.path = path;
-               if(['/','/login','/logout'].indexOf(path) == -1 &&
-                path.indexOf('/login') == -1){
-                   dataService.showNavigation = true;
-               }else{
-                   dataService.showNavigation = false;
-               }
-           });
+          if (next.$$route.originalPath == '/' ||
+            next.$$route.originalPath == '/login') {
+            if (userModel.isLoggedIn()) {
+              if (current && current.$$route) {
+                $location.path(current.$$route.originalPath);
+              }
+              else {
+                $location.path('/overview/server');
+              }
+            }
+          }
+        });
+        $rootScope.$on('$locationChangeSuccess', function(event) {
+          var path = $location.path();
+          dataService.path = path;
+          if (['/', '/login', '/logout'].indexOf(path) == -1 &&
+            path.indexOf('/login') == -1) {
+            dataService.showNavigation = true;
+          }
+          else {
+            dataService.showNavigation = false;
+          }
+        });
 
-           $rootScope.$on('timedout-user', function(){
-             sessionStorage.removeItem('LOGIN_ID');
-             $location.path('/login');
-           });
-           }
-        ]);
+        $rootScope.$on('timedout-user', function() {
+          sessionStorage.removeItem('LOGIN_ID');
+          $location.path('/login');
+        });
+      }
+    ]);
 
 })(window.angular);
diff --git a/app/login/controllers/login-controller.js b/app/login/controllers/login-controller.js
index 594d3a1..03bbc15 100644
--- a/app/login/controllers/login-controller.js
+++ b/app/login/controllers/login-controller.js
@@ -6,53 +6,54 @@
  * @name LoginController
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.login')
-        .controller('LoginController', [
-            '$scope',
-            '$window',
-            'APIUtils',
-            'dataService',
-            'userModel',
-            '$routeParams',
-            function($scope, $window, APIUtils, dataService, userModel, $routeParams){
-                $scope.dataService = dataService;
-                $scope.host = $scope.dataService.host.replace(/^https?\:\/\//ig, '');
+  angular
+    .module('app.login')
+    .controller('LoginController', [
+      '$scope',
+      '$window',
+      'APIUtils',
+      'dataService',
+      'userModel',
+      '$routeParams',
+      function($scope, $window, APIUtils, dataService, userModel, $routeParams) {
+        $scope.dataService = dataService;
+        $scope.host = $scope.dataService.host.replace(/^https?\:\/\//ig, '');
 
-                $scope.tryLogin = function(host, username, password, event){
-                    if(event.keyCode === 13){
-                        $scope.login(host, username, password);
-                    }
-                };
-                $scope.login = function(host, username, password){
-                    $scope.error = false;
-                    $scope.description = false;
+        $scope.tryLogin = function(host, username, password, event) {
+          if (event.keyCode === 13) {
+            $scope.login(host, username, password);
+          }
+        };
+        $scope.login = function(host, username, password) {
+          $scope.error = false;
+          $scope.description = false;
 
-                    if(!username || username == "" ||
-                       !password || password == "" ||
-                       !host || host == ""
-                       ){
-                        return false;
-                    }else{
-                        $scope.dataService.setHost(host);
-                        userModel.login(username, password, function(status, description){
-                            if(status){
-                                $scope.$emit('user-logged-in',{});
-                                $window.location.hash = '#/overview/server';
-                            }else{
-                                $scope.error = true;
-                                if(description){
-                                   $scope.description = description;
-                                }
-                           };
-                        });
-                    }
+          if (!username || username == '' ||
+            !password || password == '' ||
+            !host || host == ''
+          ) {
+            return false;
+          }
+          else {
+            $scope.dataService.setHost(host);
+            userModel.login(username, password, function(status, description) {
+              if (status) {
+                $scope.$emit('user-logged-in', {});
+                $window.location.hash = '#/overview/server';
+              }
+              else {
+                $scope.error = true;
+                if (description) {
+                  $scope.description = description;
                 }
-            }
-        ]
-    );
+              }
+            });
+          }
+        };
+      }
+    ]);
 
 })(angular);
diff --git a/app/login/index.js b/app/login/index.js
index 8867065..04343f5 100644
--- a/app/login/index.js
+++ b/app/login/index.js
@@ -5,23 +5,23 @@
  * @exports app/login/index
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.login', [
-            'ngRoute',
-            'app.constants',
-            'app.common.services'
-        ])
-        // Route configuration
-        .config(['$routeProvider', function ($routeProvider) {
-            $routeProvider
-                .when('/login', {
-                    'template': require('./controllers/login-controller.html'),
-                    'controller': 'LoginController',
-                    authenticated: false
-                });
-        }]);
+  angular
+    .module('app.login', [
+      'ngRoute',
+      'app.constants',
+      'app.common.services'
+    ])
+    // Route configuration
+    .config(['$routeProvider', function($routeProvider) {
+      $routeProvider
+        .when('/login', {
+          'template': require('./controllers/login-controller.html'),
+          'controller': 'LoginController',
+          authenticated: false
+        });
+    }]);
 
 })(window.angular);
diff --git a/app/multi-server/controllers/multi-server-controller.js b/app/multi-server/controllers/multi-server-controller.js
index 627108f..71ec3ac 100644
--- a/app/multi-server/controllers/multi-server-controller.js
+++ b/app/multi-server/controllers/multi-server-controller.js
@@ -6,53 +6,54 @@
  * @name multiServerController
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.overview')
-        .controller('multiServerController', [
-            '$scope',
-            '$window',
-            'APIUtils',
-            'dataService',
-            function($scope, $window, APIUtils, dataService){
-                $scope.dataService = dataService;
-                $scope.customSearch = "";
-                $scope.searchTerms = [];
-                $scope.loading = false;
-                $scope.clear = function(){
-                    $scope.customSearch = "";
-                    $scope.searchTerms = [];
-                }
+  angular
+    .module('app.overview')
+    .controller('multiServerController', [
+      '$scope',
+      '$window',
+      'APIUtils',
+      'dataService',
+      function($scope, $window, APIUtils, dataService) {
+        $scope.dataService = dataService;
+        $scope.customSearch = '';
+        $scope.searchTerms = [];
+        $scope.loading = false;
+        $scope.clear = function() {
+          $scope.customSearch = '';
+          $scope.searchTerms = [];
+        };
 
-                $scope.doSearchOnEnter = function (event) {
-                    var search = $scope.customSearch.replace(/^\s+/g,'').replace(/\s+$/g,'');
-                    if (event.keyCode === 13 &&
-                        search.length >= 2) {
-                        $scope.searchTerms = $scope.customSearch.split(" ");
-                    }else{
-                        if(search.length == 0){
-                            $scope.searchTerms = [];
-                        }
-                    }
-                };
-
-                $scope.doSearchOnClick = function() {
-                    var search = $scope.customSearch.replace(/^\s+/g,'').replace(/\s+$/g,'');
-                    if (search.length >= 2) {
-                        $scope.searchTerms = $scope.customSearch.split(" ");
-                    }else{
-                        if(search.length == 0){
-                            $scope.searchTerms = [];
-                        }
-                    }
-                };
-                $scope.addServer = function(){
-                    $scope.multi_server_add = ! $scope.multi_server_add
-                }
+        $scope.doSearchOnEnter = function(event) {
+          var search = $scope.customSearch.replace(/^\s+/g, '').replace(/\s+$/g, '');
+          if (event.keyCode === 13 &&
+            search.length >= 2) {
+            $scope.searchTerms = $scope.customSearch.split(' ');
+          }
+          else {
+            if (search.length == 0) {
+              $scope.searchTerms = [];
             }
-        ]
-    );
+          }
+        };
 
-})(angular);
\ No newline at end of file
+        $scope.doSearchOnClick = function() {
+          var search = $scope.customSearch.replace(/^\s+/g, '').replace(/\s+$/g, '');
+          if (search.length >= 2) {
+            $scope.searchTerms = $scope.customSearch.split(' ');
+          }
+          else {
+            if (search.length == 0) {
+              $scope.searchTerms = [];
+            }
+          }
+        };
+        $scope.addServer = function() {
+          $scope.multi_server_add = !$scope.multi_server_add;
+        };
+      }
+    ]);
+
+})(angular);
diff --git a/app/multi-server/index.js b/app/multi-server/index.js
index c4f8e61..97bd67a 100644
--- a/app/multi-server/index.js
+++ b/app/multi-server/index.js
@@ -5,23 +5,23 @@
  * @exports app/multi-server
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.multiServer', [
-            'ngRoute',
-            'app.constants',
-            'app.common.services'
-        ])
-        // Route configuration
-        .config(['$routeProvider', function ($routeProvider) {
-            $routeProvider
-                .when('/multi-server/overview', {
-                    'template': require('./controllers/multi-server-controller.html'),
-                    'controller': 'multiServerController',
-                    authenticated: true
-                });
-        }]);
+  angular
+    .module('app.multiServer', [
+      'ngRoute',
+      'app.constants',
+      'app.common.services'
+    ])
+    // Route configuration
+    .config(['$routeProvider', function($routeProvider) {
+      $routeProvider
+        .when('/multi-server/overview', {
+          'template': require('./controllers/multi-server-controller.html'),
+          'controller': 'multiServerController',
+          authenticated: true
+        });
+    }]);
 
 })(window.angular);
diff --git a/app/overview/controllers/system-overview-controller.js b/app/overview/controllers/system-overview-controller.js
index 45ac8ae..c37765c 100644
--- a/app/overview/controllers/system-overview-controller.js
+++ b/app/overview/controllers/system-overview-controller.js
@@ -6,142 +6,142 @@
  * @name systemOverviewController
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.overview')
-        .controller('systemOverviewController', [
-            '$scope',
-            '$window',
-            'APIUtils',
-            'dataService',
-            '$q',
-            function($scope, $window, APIUtils, dataService, $q){
-                $scope.dataService = dataService;
-                $scope.dropdown_selected = false;
-                $scope.tmz = 'EDT';
-                $scope.logs = [];
-                $scope.server_info = {};
-                $scope.bmc_firmware = "";
-                $scope.bmc_time = "";
-                $scope.server_firmware = "";
-                $scope.power_consumption = "";
-                $scope.power_cap = "";
-                $scope.bmc_ip_addresses = [];
-                $scope.loading = false;
-                $scope.edit_hostname = false;
+  angular
+    .module('app.overview')
+    .controller('systemOverviewController', [
+      '$scope',
+      '$window',
+      'APIUtils',
+      'dataService',
+      '$q',
+      function($scope, $window, APIUtils, dataService, $q) {
+        $scope.dataService = dataService;
+        $scope.dropdown_selected = false;
+        $scope.tmz = 'EDT';
+        $scope.logs = [];
+        $scope.server_info = {};
+        $scope.bmc_firmware = '';
+        $scope.bmc_time = '';
+        $scope.server_firmware = '';
+        $scope.power_consumption = '';
+        $scope.power_cap = '';
+        $scope.bmc_ip_addresses = [];
+        $scope.loading = false;
+        $scope.edit_hostname = false;
 
-                loadOverviewData();
-                function loadOverviewData(){
-                    $scope.loading = true;
+        loadOverviewData();
 
-                    var getLogsPromise =
-                        APIUtils.getLogs().then(function(data){
-                            $scope.logs = data.data.filter(function(log){
-                                return log.severity_flags.high == true;
-                            });
-                        }, function(error){
-                            console.log(JSON.stringify(error));
-                        })
+        function loadOverviewData() {
+          $scope.loading = true;
 
-                    var getFirmwaresPromise =
-                        APIUtils.getFirmwares().then(function(data){
-                            $scope.bmc_firmware = data.bmcActiveVersion;
-                            $scope.server_firmware = data.hostActiveVersion;
-                        }, function(error){
-                            console.log(JSON.stringify(error));
-                        })
+          var getLogsPromise =
+            APIUtils.getLogs().then(function(data) {
+              $scope.logs = data.data.filter(function(log) {
+                return log.severity_flags.high == true;
+              });
+            }, function(error) {
+              console.log(JSON.stringify(error));
+            });
 
-                    var getLEDStatePromise =
-                        APIUtils.getLEDState().then(function(data){
-                            if(data == APIUtils.LED_STATE.on){
-                                dataService.LED_state = APIUtils.LED_STATE_TEXT.on;
-                            }else{
-                                dataService.LED_state = APIUtils.LED_STATE_TEXT.off;
-                            }
-                        }, function(error){
-                            console.log(JSON.stringify(error));
-                        })
+          var getFirmwaresPromise =
+            APIUtils.getFirmwares().then(function(data) {
+              $scope.bmc_firmware = data.bmcActiveVersion;
+              $scope.server_firmware = data.hostActiveVersion;
+            }, function(error) {
+              console.log(JSON.stringify(error));
+            });
 
-                    var getBMCTimePromise =
-                        APIUtils.getBMCTime().then(function(data){
-                            $scope.bmc_time = data.data.Elapsed / 1000;
-                        }, function(error){
-                            console.log(JSON.stringify(error));
-                        })
+          var getLEDStatePromise =
+            APIUtils.getLEDState().then(function(data) {
+              if (data == APIUtils.LED_STATE.on) {
+                dataService.LED_state = APIUtils.LED_STATE_TEXT.on;
+              }
+              else {
+                dataService.LED_state = APIUtils.LED_STATE_TEXT.off;
+              }
+            }, function(error) {
+              console.log(JSON.stringify(error));
+            });
 
-                    var getServerInfoPromise =
-                        APIUtils.getServerInfo().then(function(data){
-                            $scope.server_info = data.data;
-                        }, function(error){
-                            console.log(JSON.stringify(error));
-                        })
+          var getBMCTimePromise =
+            APIUtils.getBMCTime().then(function(data) {
+              $scope.bmc_time = data.data.Elapsed / 1000;
+            }, function(error) {
+              console.log(JSON.stringify(error));
+            });
 
-                    var getPowerConsumptionPromise =
-                        APIUtils.getPowerConsumption().then(function(data){
-                            $scope.power_consumption = data;
-                        }, function(error){
-                            console.log(JSON.stringify(error));
-                        })
+          var getServerInfoPromise =
+            APIUtils.getServerInfo().then(function(data) {
+              $scope.server_info = data.data;
+            }, function(error) {
+              console.log(JSON.stringify(error));
+            });
 
-                    var getPowerCapPromise =
-                        APIUtils.getPowerCap().then(function(data){
-                            $scope.power_cap = data;
-                        }, function(error){
-                            console.log(JSON.stringify(error));
-                        })
+          var getPowerConsumptionPromise =
+            APIUtils.getPowerConsumption().then(function(data) {
+              $scope.power_consumption = data;
+            }, function(error) {
+              console.log(JSON.stringify(error));
+            });
 
-                    var getNetworkInfoPromise =
-                        APIUtils.getNetworkInfo().then(function(data){
-                            // TODO: openbmc/openbmc#3150 Support IPV6 when
-                            // officially supported by the backend
-                            $scope.bmc_ip_addresses =
-                                data.formatted_data.ip_addresses.ipv4;
-                        }, function(error){
-                            console.log(JSON.stringify(error));
-                        })
+          var getPowerCapPromise =
+            APIUtils.getPowerCap().then(function(data) {
+              $scope.power_cap = data;
+            }, function(error) {
+              console.log(JSON.stringify(error));
+            });
 
-                    var promises = [
-                        getLogsPromise,
-                        getFirmwaresPromise,
-                        getLEDStatePromise,
-                        getBMCTimePromise,
-                        getServerInfoPromise,
-                        getPowerConsumptionPromise,
-                        getPowerCapPromise,
-                        getNetworkInfoPromise,
-                    ];
+          var getNetworkInfoPromise =
+            APIUtils.getNetworkInfo().then(function(data) {
+              // TODO: openbmc/openbmc#3150 Support IPV6 when
+              // officially supported by the backend
+              $scope.bmc_ip_addresses =
+                data.formatted_data.ip_addresses.ipv4;
+            }, function(error) {
+              console.log(JSON.stringify(error));
+            });
 
-                    $q.all(promises).finally(function(){
-                        $scope.loading = false;
-                    });
-                }
+          var promises = [
+            getLogsPromise,
+            getFirmwaresPromise,
+            getLEDStatePromise,
+            getBMCTimePromise,
+            getServerInfoPromise,
+            getPowerConsumptionPromise,
+            getPowerCapPromise,
+            getNetworkInfoPromise,
+          ];
 
-                $scope.toggleLED = function(){
-                    var toggleState = (dataService.LED_state == APIUtils.LED_STATE_TEXT.on) ?
-                        APIUtils.LED_STATE.off : APIUtils.LED_STATE.on;
-                        dataService.LED_state = (dataService.LED_state == APIUtils.LED_STATE_TEXT.on) ?
-                        APIUtils.LED_STATE_TEXT.off : APIUtils.LED_STATE_TEXT.on;
-                    APIUtils.setLEDState(toggleState, function(status){
-                    });
-                }
+          $q.all(promises).finally(function() {
+            $scope.loading = false;
+          });
+        }
 
-                $scope.saveHostname = function(hostname) {
-                    $scope.edit_hostname = false;
-                    $scope.loading = true;
-                    APIUtils.setHostname(hostname).then(function(data){
-                        APIUtils.getNetworkInfo().then(function(data){
-                            dataService.setNetworkInfo(data);
-                        });
-                    },
-                    function(error){
-                        console.log(error);
-                    });
-                    $scope.loading = false;
-                }
-            }
-        ]
-    );
+        $scope.toggleLED = function() {
+          var toggleState = (dataService.LED_state == APIUtils.LED_STATE_TEXT.on) ?
+            APIUtils.LED_STATE.off : APIUtils.LED_STATE.on;
+          dataService.LED_state = (dataService.LED_state == APIUtils.LED_STATE_TEXT.on) ?
+            APIUtils.LED_STATE_TEXT.off : APIUtils.LED_STATE_TEXT.on;
+          APIUtils.setLEDState(toggleState, function(status) {});
+        };
+
+        $scope.saveHostname = function(hostname) {
+          $scope.edit_hostname = false;
+          $scope.loading = true;
+          APIUtils.setHostname(hostname).then(function(data) {
+              APIUtils.getNetworkInfo().then(function(data) {
+                dataService.setNetworkInfo(data);
+              });
+            },
+            function(error) {
+              console.log(error);
+            });
+          $scope.loading = false;
+        };
+      }
+    ]);
 
 })(angular);
diff --git a/app/overview/index.js b/app/overview/index.js
index 3a07ed8..aa3f023 100644
--- a/app/overview/index.js
+++ b/app/overview/index.js
@@ -5,28 +5,28 @@
  * @exports app/overview/index
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.overview', [
-            'ngRoute',
-            'app.constants',
-            'app.common.services'
-        ])
-        // Route configuration
-        .config(['$routeProvider', function ($routeProvider) {
-            $routeProvider
-                .when('/overview/server', {
-                    'template': require('./controllers/system-overview-controller.html'),
-                    'controller': 'systemOverviewController',
-                    authenticated: true
-                })
-                .when('/overview', {
-                    'template': require('./controllers/system-overview-controller.html'),
-                    'controller': 'systemOverviewController',
-                    authenticated: true
-                });
-        }]);
+  angular
+    .module('app.overview', [
+      'ngRoute',
+      'app.constants',
+      'app.common.services'
+    ])
+    // Route configuration
+    .config(['$routeProvider', function($routeProvider) {
+      $routeProvider
+        .when('/overview/server', {
+          'template': require('./controllers/system-overview-controller.html'),
+          'controller': 'systemOverviewController',
+          authenticated: true
+        })
+        .when('/overview', {
+          'template': require('./controllers/system-overview-controller.html'),
+          'controller': 'systemOverviewController',
+          authenticated: true
+        });
+    }]);
 
 })(window.angular);
diff --git a/app/server-control/controllers/bmc-reboot-controller.js b/app/server-control/controllers/bmc-reboot-controller.js
index 9899eed..8be09eb 100644
--- a/app/server-control/controllers/bmc-reboot-controller.js
+++ b/app/server-control/controllers/bmc-reboot-controller.js
@@ -6,34 +6,33 @@
  * @name bmcRebootController
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.serverControl')
-        .controller('bmcRebootController', [
-            '$scope',
-            '$window',
-            'APIUtils',
-            'dataService',
-            function($scope, $window, APIUtils, dataService){
-                $scope.dataService = dataService;
-                $scope.confirm = false;
-                $scope.rebootConfirm = function(){
-                    if($scope.confirm) {
-                        return;
-                    }
-                    $scope.confirm = true;
-                };
-                $scope.reboot = function(){
-                    dataService.setUnreachableState();
-                    APIUtils.bmcReboot(function(response){
-                        //@NOTE: using common event to reload server status, may be a better event listener name?
-                        $scope.$emit('user-logged-in',{});
-                    });
-                };
-            }
-        ]
-    );
+  angular
+    .module('app.serverControl')
+    .controller('bmcRebootController', [
+      '$scope',
+      '$window',
+      'APIUtils',
+      'dataService',
+      function($scope, $window, APIUtils, dataService) {
+        $scope.dataService = dataService;
+        $scope.confirm = false;
+        $scope.rebootConfirm = function() {
+          if ($scope.confirm) {
+            return;
+          }
+          $scope.confirm = true;
+        };
+        $scope.reboot = function() {
+          dataService.setUnreachableState();
+          APIUtils.bmcReboot(function(response) {
+            //@NOTE: using common event to reload server status, may be a better event listener name?
+            $scope.$emit('user-logged-in', {});
+          });
+        };
+      }
+    ]);
 
 })(angular);
diff --git a/app/server-control/controllers/power-operations-controller.js b/app/server-control/controllers/power-operations-controller.js
index 910c50e..06fb371 100644
--- a/app/server-control/controllers/power-operations-controller.js
+++ b/app/server-control/controllers/power-operations-controller.js
@@ -6,291 +6,305 @@
  * @name powerOperationsController
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.serverControl')
-        .controller('powerOperationsController', [
-            '$scope',
-            'APIUtils',
-            'dataService',
-            'Constants',
-            '$timeout',
-            '$interval',
-            '$interpolate',
-            '$q',
-            function($scope, APIUtils, dataService, Constants, $timeout,
-                     $interval, $interpolate, $q){
-                $scope.dataService = dataService;
-                $scope.confirm = false;
-                $scope.power_confirm = false;
-                $scope.warmboot_confirm = false;
-                $scope.coldboot_confirm = false;
-                $scope.orderly_confirm = false;
-                $scope.immediately_confirm = false;
-                $scope.loading = false;
+  angular
+    .module('app.serverControl')
+    .controller('powerOperationsController', [
+      '$scope',
+      'APIUtils',
+      'dataService',
+      'Constants',
+      '$timeout',
+      '$interval',
+      '$interpolate',
+      '$q',
+      function($scope, APIUtils, dataService, Constants, $timeout,
+        $interval, $interpolate, $q) {
+        $scope.dataService = dataService;
+        $scope.confirm = false;
+        $scope.power_confirm = false;
+        $scope.warmboot_confirm = false;
+        $scope.coldboot_confirm = false;
+        $scope.orderly_confirm = false;
+        $scope.immediately_confirm = false;
+        $scope.loading = false;
 
-                var pollChassisStatusTimer = undefined;
-                var pollHostStatusTimer = undefined;
-                var pollStartTime = null;
+        var pollChassisStatusTimer = undefined;
+        var pollHostStatusTimer = undefined;
+        var pollStartTime = null;
 
-                //@TODO: call api and get proper state
-                $scope.toggleState = function(){
-                    dataService.server_state = (dataService.server_state == 'Running') ? 'Off': 'Running';
-                }
+        //@TODO: call api and get proper state
+        $scope.toggleState = function() {
+          dataService.server_state = (dataService.server_state == 'Running') ? 'Off' : 'Running';
+        };
 
-                $scope.powerOn = function(){
-                    $scope.loading = true;
-                    dataService.setUnreachableState();
-                    APIUtils.hostPowerOn().then(function(response){
-                        return response;
-                    }).then(function(lastStatus) {
-                        pollStartTime = new Date();
-                        return pollHostStatusTillOn();
-                    }).then(function(hostState) {
-                        $scope.loading = false;
-                    }).catch(function(error){
-                        dataService.activateErrorModal(
-                          {title: Constants.MESSAGES.POWER_OP.POWER_ON_FAILED,
-                           description: error.statusText ?
-                               $interpolate(Constants.MESSAGES.ERROR_MESSAGE_DESC_TEMPLATE)(
-                                   {status: error.status, description: error.statusText}) :
-                               error });
-                        $scope.loading = false;
-                    });
-                }
-                $scope.powerOnConfirm = function(){
-                    if($scope.confirm) {
-                        return;
-                    }
-                    $scope.confirm = true;
-                    $scope.power_confirm = true;
-                };
+        $scope.powerOn = function() {
+          $scope.loading = true;
+          dataService.setUnreachableState();
+          APIUtils.hostPowerOn().then(function(response) {
+            return response;
+          }).then(function(lastStatus) {
+            pollStartTime = new Date();
+            return pollHostStatusTillOn();
+          }).then(function(hostState) {
+            $scope.loading = false;
+          }).catch(function(error) {
+            dataService.activateErrorModal({
+              title: Constants.MESSAGES.POWER_OP.POWER_ON_FAILED,
+              description: error.statusText ?
+                $interpolate(Constants.MESSAGES.ERROR_MESSAGE_DESC_TEMPLATE)({
+                  status: error.status,
+                  description: error.statusText
+                }) : error
+            });
+            $scope.loading = false;
+          });
+        };
+        $scope.powerOnConfirm = function() {
+          if ($scope.confirm) {
+            return;
+          }
+          $scope.confirm = true;
+          $scope.power_confirm = true;
+        };
 
-                function setHostState(state){
-                    if(state == Constants.HOST_STATE_TEXT.off_code){
-                        dataService.setPowerOffState();
-                    }else if(state == Constants.HOST_STATE_TEXT.on_code){
-                        dataService.setPowerOnState();
-                    }else{
-                        dataService.setErrorState();
-                    }
-                }
+        function setHostState(state) {
+          if (state == Constants.HOST_STATE_TEXT.off_code) {
+            dataService.setPowerOffState();
+          }
+          else if (state == Constants.HOST_STATE_TEXT.on_code) {
+            dataService.setPowerOnState();
+          }
+          else {
+            dataService.setErrorState();
+          }
+        }
 
-                function pollChassisStatusTillOff(){
-                    var deferred = $q.defer();
-                    pollChassisStatusTimer = $interval(function(){
-                        var now = new Date();
-                        if((now.getTime() - pollStartTime.getTime()) >= Constants.TIMEOUT.CHASSIS_OFF){
-                            $interval.cancel(pollChassisStatusTimer);
-                            pollChassisStatusTimer = undefined;
-                            deferred.reject(new Error(Constants.MESSAGES.POLL.CHASSIS_OFF_TIMEOUT));
-                        }
-                        APIUtils.getChassisState().then(function(state){
-                            if(state === Constants.CHASSIS_POWER_STATE.off_code){
-                                $interval.cancel(pollChassisStatusTimer);
-                                pollChassisStatusTimer = undefined;
-                                deferred.resolve(state);
-                            }
-                        }).catch(function(error){
-                            $interval.cancel(pollChassisStatusTimer);
-                            pollChassisStatusTimer = undefined;
-                            deferred.reject(error);
-                        });
-                    }, Constants.POLL_INTERVALS.POWER_OP);
-
-                    return deferred.promise;
-                }
-                function pollHostStatusTillOn(){
-                    var deferred = $q.defer();
-                    pollHostStatusTimer = $interval(function(){
-                        var now = new Date();
-                        if((now.getTime() - pollStartTime.getTime()) >= Constants.TIMEOUT.HOST_ON){
-                            $interval.cancel(pollHostStatusTimer);
-                            pollHostStatusTimer = undefined;
-                            deferred.reject(new Error(Constants.MESSAGES.POLL.HOST_ON_TIMEOUT));
-                        }
-                        APIUtils.getHostState().then(function(state){
-                            setHostState(state);
-                            if(state === Constants.HOST_STATE_TEXT.on_code){
-                                $interval.cancel(pollHostStatusTimer);
-                                pollHostStatusTimer = undefined;
-                                deferred.resolve(state);
-                            }else if(state === Constants.HOST_STATE_TEXT.error_code){
-                                $interval.cancel(pollHostStatusTimer);
-                                pollHostStatusTimer = undefined;
-                                deferred.reject(new Error(Constants.MESSAGES.POLL.HOST_QUIESCED));
-                            }
-                        }).catch(function(error){
-                            $interval.cancel(pollHostStatusTimer);
-                            pollHostStatusTimer = undefined;
-                            deferred.reject(error);
-                        });
-                    }, Constants.POLL_INTERVALS.POWER_OP);
-
-                    return deferred.promise;
-                }
-                function pollHostStatusTillOff(){
-                    var deferred = $q.defer();
-                    pollHostStatusTimer = $interval(function(){
-                        var now = new Date();
-                        if((now.getTime() - pollStartTime.getTime()) >= Constants.TIMEOUT.HOST_OFF){
-                            $interval.cancel(pollHostStatusTimer);
-                            pollHostStatusTimer = undefined;
-                            deferred.reject(new Error(Constants.MESSAGES.POLL.HOST_OFF_TIMEOUT));
-                        }
-                        APIUtils.getHostState().then(function(state){
-                            setHostState(state);
-                            if(state === Constants.HOST_STATE_TEXT.off_code){
-                                $interval.cancel(pollHostStatusTimer);
-                                pollHostStatusTimer = undefined;
-                                deferred.resolve(state);
-                            }
-                        }).catch(function(error){
-                            $interval.cancel(pollHostStatusTimer);
-                            pollHostStatusTimer = undefined;
-                            deferred.reject(error);
-                        });
-                    }, Constants.POLL_INTERVALS.POWER_OP);
-
-                    return deferred.promise;
-                }
-                $scope.warmReboot = function(){
-                    $scope.loading = true;
-                    dataService.setUnreachableState();
-                    APIUtils.hostReboot().then(function(response){
-                        return response;
-                    }).then(function(lastStatus) {
-                        pollStartTime = new Date();
-                        return pollHostStatusTillOff();
-                    }).then(function(hostState) {
-                        pollStartTime = new Date();
-                        return pollHostStatusTillOn();
-                    }).then(function(hostState) {
-                        $scope.loading = false;
-                    }).catch(function(error){
-                        dataService.activateErrorModal(
-                          {title: Constants.MESSAGES.POWER_OP.WARM_REBOOT_FAILED,
-                           description: error.statusText ?
-                               $interpolate(Constants.MESSAGES.ERROR_MESSAGE_DESC_TEMPLATE)(
-                                   {status: error.status, description: error.statusText}) :
-                               error });
-                        $scope.loading = false;
-                    });
-                };
-                $scope.testState = function(){
-                    $timeout(function(){
-                        dataService.setPowerOffState();
-                        $timeout(function(){
-                            dataService.setPowerOnState();
-                        }, 2000);
-                    }, 1000);
-                };
-                $scope.warmRebootConfirm = function(){
-                    if($scope.confirm) {
-                        return;
-                    }
-                    $scope.confirm = true;
-                    $scope.warmboot_confirm = true;
-                };
-
-                $scope.coldReboot = function(){
-                    $scope.loading = true;
-                    dataService.setUnreachableState();
-                    APIUtils.chassisPowerOff().then(function(state){
-                        return state;
-                    }).then(function(lastState) {
-                        pollStartTime = new Date();
-                        return pollChassisStatusTillOff();
-                    }).then(function(chassisState) {
-                        return APIUtils.hostPowerOn().then(function(hostState){
-                            return hostState;
-                        })
-                    }).then(function(hostState) {
-                        pollStartTime = new Date();
-                        return pollHostStatusTillOn();
-                    }).then(function(state) {
-                        $scope.loading = false;
-                    }).catch(function(error){
-                        dataService.activateErrorModal(
-                          {title: Constants.MESSAGES.POWER_OP.COLD_REBOOT_FAILED,
-                           description: error.statusText ?
-                               $interpolate(Constants.MESSAGES.ERROR_MESSAGE_DESC_TEMPLATE)(
-                                   {status: error.status, description: error.statusText}) :
-                               error });
-                        $scope.loading = false;
-                    });
-                };
-                $scope.coldRebootConfirm = function(){
-                    if($scope.confirm) {
-                        return;
-                    }
-                    $scope.confirm = true;
-                    $scope.coldboot_confirm = true;
-                };
-
-                $scope.orderlyShutdown = function(){
-                    $scope.loading = true;
-                    dataService.setUnreachableState();
-                    APIUtils.hostPowerOff().then(function(response){
-                        return response;
-                    }).then(function(lastStatus) {
-                        pollStartTime = new Date();
-                        return pollHostStatusTillOff()
-                    }).then(function(hostState) {
-                        pollStartTime = new Date();
-                        return pollChassisStatusTillOff();
-                    }).then(function(chassisState) {
-                        $scope.loading = false;
-                    }).catch(function(error){
-                        dataService.activateErrorModal(
-                          {title: Constants.MESSAGES.POWER_OP.ORDERLY_SHUTDOWN_FAILED,
-                           description: error.statusText ?
-                               $interpolate(Constants.MESSAGES.ERROR_MESSAGE_DESC_TEMPLATE)(
-                                   {status: error.status, description: error.statusText}) :
-                               error });
-                        $scope.loading = false;
-                    });
-                };
-                $scope.orderlyShutdownConfirm = function(){
-                    if($scope.confirm) {
-                        return;
-                    }
-                    $scope.confirm = true;
-                    $scope.orderly_confirm = true;
-                };
-
-                $scope.immediateShutdown = function(){
-                    $scope.loading = true;
-                    dataService.setUnreachableState();
-                    APIUtils.chassisPowerOff().then(function(response){
-                        return response;
-                    }).then(function(lastStatus) {
-                        pollStartTime = new Date();
-                        return pollChassisStatusTillOff();
-                    }).then(function(chassisState) {
-                        dataService.setPowerOffState();
-                        $scope.loading = false;
-                    }).catch(function(error){
-                        dataService.activateErrorModal(
-                          {title: Constants.MESSAGES.POWER_OP.IMMEDIATE_SHUTDOWN_FAILED,
-                           description: error.statusText ?
-                               $interpolate(Constants.MESSAGES.ERROR_MESSAGE_DESC_TEMPLATE)(
-                                   {status: error.status, description: error.statusText}) :
-                               error });
-                        $scope.loading = false;
-                    });
-                };
-                $scope.immediateShutdownConfirm = function(){
-                    if($scope.confirm) {
-                        return;
-                    }
-                    $scope.confirm = true;
-                    $scope.immediately_confirm = true;
-                };
+        function pollChassisStatusTillOff() {
+          var deferred = $q.defer();
+          pollChassisStatusTimer = $interval(function() {
+            var now = new Date();
+            if ((now.getTime() - pollStartTime.getTime()) >= Constants.TIMEOUT.CHASSIS_OFF) {
+              $interval.cancel(pollChassisStatusTimer);
+              pollChassisStatusTimer = undefined;
+              deferred.reject(new Error(Constants.MESSAGES.POLL.CHASSIS_OFF_TIMEOUT));
             }
-        ]
-    );
+            APIUtils.getChassisState().then(function(state) {
+              if (state === Constants.CHASSIS_POWER_STATE.off_code) {
+                $interval.cancel(pollChassisStatusTimer);
+                pollChassisStatusTimer = undefined;
+                deferred.resolve(state);
+              }
+            }).catch(function(error) {
+              $interval.cancel(pollChassisStatusTimer);
+              pollChassisStatusTimer = undefined;
+              deferred.reject(error);
+            });
+          }, Constants.POLL_INTERVALS.POWER_OP);
+
+          return deferred.promise;
+        }
+
+        function pollHostStatusTillOn() {
+          var deferred = $q.defer();
+          pollHostStatusTimer = $interval(function() {
+            var now = new Date();
+            if ((now.getTime() - pollStartTime.getTime()) >= Constants.TIMEOUT.HOST_ON) {
+              $interval.cancel(pollHostStatusTimer);
+              pollHostStatusTimer = undefined;
+              deferred.reject(new Error(Constants.MESSAGES.POLL.HOST_ON_TIMEOUT));
+            }
+            APIUtils.getHostState().then(function(state) {
+              setHostState(state);
+              if (state === Constants.HOST_STATE_TEXT.on_code) {
+                $interval.cancel(pollHostStatusTimer);
+                pollHostStatusTimer = undefined;
+                deferred.resolve(state);
+              }
+              else if (state === Constants.HOST_STATE_TEXT.error_code) {
+                $interval.cancel(pollHostStatusTimer);
+                pollHostStatusTimer = undefined;
+                deferred.reject(new Error(Constants.MESSAGES.POLL.HOST_QUIESCED));
+              }
+            }).catch(function(error) {
+              $interval.cancel(pollHostStatusTimer);
+              pollHostStatusTimer = undefined;
+              deferred.reject(error);
+            });
+          }, Constants.POLL_INTERVALS.POWER_OP);
+
+          return deferred.promise;
+        }
+
+        function pollHostStatusTillOff() {
+          var deferred = $q.defer();
+          pollHostStatusTimer = $interval(function() {
+            var now = new Date();
+            if ((now.getTime() - pollStartTime.getTime()) >= Constants.TIMEOUT.HOST_OFF) {
+              $interval.cancel(pollHostStatusTimer);
+              pollHostStatusTimer = undefined;
+              deferred.reject(new Error(Constants.MESSAGES.POLL.HOST_OFF_TIMEOUT));
+            }
+            APIUtils.getHostState().then(function(state) {
+              setHostState(state);
+              if (state === Constants.HOST_STATE_TEXT.off_code) {
+                $interval.cancel(pollHostStatusTimer);
+                pollHostStatusTimer = undefined;
+                deferred.resolve(state);
+              }
+            }).catch(function(error) {
+              $interval.cancel(pollHostStatusTimer);
+              pollHostStatusTimer = undefined;
+              deferred.reject(error);
+            });
+          }, Constants.POLL_INTERVALS.POWER_OP);
+
+          return deferred.promise;
+        }
+        $scope.warmReboot = function() {
+          $scope.loading = true;
+          dataService.setUnreachableState();
+          APIUtils.hostReboot().then(function(response) {
+            return response;
+          }).then(function(lastStatus) {
+            pollStartTime = new Date();
+            return pollHostStatusTillOff();
+          }).then(function(hostState) {
+            pollStartTime = new Date();
+            return pollHostStatusTillOn();
+          }).then(function(hostState) {
+            $scope.loading = false;
+          }).catch(function(error) {
+            dataService.activateErrorModal({
+              title: Constants.MESSAGES.POWER_OP.WARM_REBOOT_FAILED,
+              description: error.statusText ?
+                $interpolate(Constants.MESSAGES.ERROR_MESSAGE_DESC_TEMPLATE)({
+                  status: error.status,
+                  description: error.statusText
+                }) : error
+            });
+            $scope.loading = false;
+          });
+        };
+        $scope.testState = function() {
+          $timeout(function() {
+            dataService.setPowerOffState();
+            $timeout(function() {
+              dataService.setPowerOnState();
+            }, 2000);
+          }, 1000);
+        };
+        $scope.warmRebootConfirm = function() {
+          if ($scope.confirm) {
+            return;
+          }
+          $scope.confirm = true;
+          $scope.warmboot_confirm = true;
+        };
+
+        $scope.coldReboot = function() {
+          $scope.loading = true;
+          dataService.setUnreachableState();
+          APIUtils.chassisPowerOff().then(function(state) {
+            return state;
+          }).then(function(lastState) {
+            pollStartTime = new Date();
+            return pollChassisStatusTillOff();
+          }).then(function(chassisState) {
+            return APIUtils.hostPowerOn().then(function(hostState) {
+              return hostState;
+            });
+          }).then(function(hostState) {
+            pollStartTime = new Date();
+            return pollHostStatusTillOn();
+          }).then(function(state) {
+            $scope.loading = false;
+          }).catch(function(error) {
+            dataService.activateErrorModal({
+              title: Constants.MESSAGES.POWER_OP.COLD_REBOOT_FAILED,
+              description: error.statusText ?
+                $interpolate(Constants.MESSAGES.ERROR_MESSAGE_DESC_TEMPLATE)({
+                  status: error.status,
+                  description: error.statusText
+                }) : error
+            });
+            $scope.loading = false;
+          });
+        };
+        $scope.coldRebootConfirm = function() {
+          if ($scope.confirm) {
+            return;
+          }
+          $scope.confirm = true;
+          $scope.coldboot_confirm = true;
+        };
+
+        $scope.orderlyShutdown = function() {
+          $scope.loading = true;
+          dataService.setUnreachableState();
+          APIUtils.hostPowerOff().then(function(response) {
+            return response;
+          }).then(function(lastStatus) {
+            pollStartTime = new Date();
+            return pollHostStatusTillOff();
+          }).then(function(hostState) {
+            pollStartTime = new Date();
+            return pollChassisStatusTillOff();
+          }).then(function(chassisState) {
+            $scope.loading = false;
+          }).catch(function(error) {
+            dataService.activateErrorModal({
+              title: Constants.MESSAGES.POWER_OP.ORDERLY_SHUTDOWN_FAILED,
+              description: error.statusText ?
+                $interpolate(Constants.MESSAGES.ERROR_MESSAGE_DESC_TEMPLATE)({
+                  status: error.status,
+                  description: error.statusText
+                }) : error
+            });
+            $scope.loading = false;
+          });
+        };
+        $scope.orderlyShutdownConfirm = function() {
+          if ($scope.confirm) {
+            return;
+          }
+          $scope.confirm = true;
+          $scope.orderly_confirm = true;
+        };
+
+        $scope.immediateShutdown = function() {
+          $scope.loading = true;
+          dataService.setUnreachableState();
+          APIUtils.chassisPowerOff().then(function(response) {
+            return response;
+          }).then(function(lastStatus) {
+            pollStartTime = new Date();
+            return pollChassisStatusTillOff();
+          }).then(function(chassisState) {
+            dataService.setPowerOffState();
+            $scope.loading = false;
+          }).catch(function(error) {
+            dataService.activateErrorModal({
+              title: Constants.MESSAGES.POWER_OP.IMMEDIATE_SHUTDOWN_FAILED,
+              description: error.statusText ?
+                $interpolate(Constants.MESSAGES.ERROR_MESSAGE_DESC_TEMPLATE)({
+                  status: error.status,
+                  description: error.statusText
+                }) : error
+            });
+            $scope.loading = false;
+          });
+        };
+        $scope.immediateShutdownConfirm = function() {
+          if ($scope.confirm) {
+            return;
+          }
+          $scope.confirm = true;
+          $scope.immediately_confirm = true;
+        };
+      }
+    ]);
 
 })(angular);
diff --git a/app/server-control/controllers/remote-console-controller.js b/app/server-control/controllers/remote-console-controller.js
index ee6a591..c2e1435 100644
--- a/app/server-control/controllers/remote-console-controller.js
+++ b/app/server-control/controllers/remote-console-controller.js
@@ -6,72 +6,75 @@
  * @name remoteConsoleController
  */
 
-import {hterm, lib} from 'hterm-umdjs';
+import {
+  hterm,
+  lib
+}
+from 'hterm-umdjs';
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.serverControl')
-        .controller('remoteConsoleController', [
-            '$scope',
-            '$window',
-            'APIUtils',
-            'dataService',
-            function($scope, $window, APIUtils, dataService){
-                $scope.dataService = dataService;
+  angular
+    .module('app.serverControl')
+    .controller('remoteConsoleController', [
+      '$scope',
+      '$window',
+      'APIUtils',
+      'dataService',
+      function($scope, $window, APIUtils, dataService) {
+        $scope.dataService = dataService;
 
-                // See https://github.com/macton/hterm for available hterm options
+        // See https://github.com/macton/hterm for available hterm options
 
-                hterm.defaultStorage = new lib.Storage.Local();
-                var term = new hterm.Terminal("host-console");
-                term.decorate(document.querySelector('#terminal'));
-                //Set cursor color
-                term.prefs_.set('cursor-color', 'rgba(83, 146, 255, .5)');
-                //Set background color
-                term.prefs_.set('background-color', '#19273c');
-                //Allows keyboard input
-                term.installKeyboard();
+        hterm.defaultStorage = new lib.Storage.Local();
+        var term = new hterm.Terminal('host-console');
+        term.decorate(document.querySelector('#terminal'));
+        //Set cursor color
+        term.prefs_.set('cursor-color', 'rgba(83, 146, 255, .5)');
+        //Set background color
+        term.prefs_.set('background-color', '#19273c');
+        //Allows keyboard input
+        term.installKeyboard();
 
-                //The BMC exposes a websocket at /console0. This can be read
-                //or written to access the host serial console.
-                var hostname = dataService.getHost().replace("https://", '');
-                var host = "wss://" + hostname + "/console0";
-                var ws = new WebSocket(host);
-                ws.onmessage = function (evt) {
-                    //websocket -> terminal
-                    term.io.print(evt.data);
-                };
+        //The BMC exposes a websocket at /console0. This can be read
+        //or written to access the host serial console.
+        var hostname = dataService.getHost().replace('https://', '');
+        var host = 'wss://' + hostname + '/console0';
+        var ws = new WebSocket(host);
+        ws.onmessage = function(evt) {
+          //websocket -> terminal
+          term.io.print(evt.data);
+        };
 
-                //terminal -> websocket
-                term.onTerminalReady = function() {
-                    var io = term.io.push();
-                    io.onVTKeystroke = function(str) {
-                        ws.send(str);
-                    };
-                    io.sendString = function(str) {
-                        ws.send(str);
-                    };
-                };
+        //terminal -> websocket
+        term.onTerminalReady = function() {
+          var io = term.io.push();
+          io.onVTKeystroke = function(str) {
+            ws.send(str);
+          };
+          io.sendString = function(str) {
+            ws.send(str);
+          };
+        };
 
-                ws.onopen = function() {
-                    console.log("websocket opened");
-                };
-                ws.onclose = function() {
-                    console.log("websocket closed");
-                };
-                $scope.$on("$destroy", function() {
-                    if(ws) {
-                        ws.close();
-                    }
-                });
+        ws.onopen = function() {
+          console.log('websocket opened');
+        };
+        ws.onclose = function() {
+          console.log('websocket closed');
+        };
+        $scope.$on('$destroy', function() {
+          if (ws) {
+            ws.close();
+          }
+        });
 
-                $scope.openTerminalWindow = function(){
-                    dataService.setRemoteWindowActive();
-                    $window.open('#/server-control/remote-console-window','Remote Console Window','directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=no,width=600,height=400');
-                }
-            }
-        ]
-    );
+        $scope.openTerminalWindow = function() {
+          dataService.setRemoteWindowActive();
+          $window.open('#/server-control/remote-console-window', 'Remote Console Window', 'directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=no,width=600,height=400');
+        };
+      }
+    ]);
 
 })(angular);
diff --git a/app/server-control/controllers/remote-console-window-controller.js b/app/server-control/controllers/remote-console-window-controller.js
index d9a342f..685b45e 100644
--- a/app/server-control/controllers/remote-console-window-controller.js
+++ b/app/server-control/controllers/remote-console-window-controller.js
@@ -6,58 +6,57 @@
  * @name remoteConsoleController
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.serverControl')
-        .controller('remoteConsoleWindowController', [
-            '$scope',
-            '$window',
-            'APIUtils',
-            'dataService',
-            function($scope, $window, APIUtils, dataService){
-                $scope.dataService = dataService;
-                dataService.showNavigation = false;
+  angular
+    .module('app.serverControl')
+    .controller('remoteConsoleWindowController', [
+      '$scope',
+      '$window',
+      'APIUtils',
+      'dataService',
+      function($scope, $window, APIUtils, dataService) {
+        $scope.dataService = dataService;
+        dataService.showNavigation = false;
 
-                // See https://github.com/macton/hterm for available hterm options
+        // See https://github.com/macton/hterm for available hterm options
 
-                //Storage
-                hterm.defaultStorage = new lib.Storage.Local();
+        //Storage
+        hterm.defaultStorage = new lib.Storage.Local();
 
-                var term = new hterm.Terminal("foo");
-                term.onTerminalReady = function() {
-                    var io = term.io.push();
-                    io.onVTKeystroke = function(str) {
-                        console.log(str)
-                        term.io.print(str);
-                    };
-                    io.sendString = function(str) {
-                        console.log(str)
-                    };
-                };
-                term.decorate(document.querySelector('#terminal'));
+        var term = new hterm.Terminal('foo');
+        term.onTerminalReady = function() {
+          var io = term.io.push();
+          io.onVTKeystroke = function(str) {
+            console.log(str);
+            term.io.print(str);
+          };
+          io.sendString = function(str) {
+            console.log(str);
+          };
+        };
+        term.decorate(document.querySelector('#terminal'));
 
-                //Set cursor color
-                term.prefs_.set('cursor-color', 'rgba(83, 146, 255, .5)');
+        //Set cursor color
+        term.prefs_.set('cursor-color', 'rgba(83, 146, 255, .5)');
 
-                //Set background color
-                term.prefs_.set('background-color', '#19273c');
+        //Set background color
+        term.prefs_.set('background-color', '#19273c');
 
-                //Print to console window
-                term.io.println('OpenBMC ver.00');
-                term.io.println('This is not an actual live connection.');
-                term.io.print('root@IBM:');
+        //Print to console window
+        term.io.println('OpenBMC ver.00');
+        term.io.println('This is not an actual live connection.');
+        term.io.print('root@IBM:');
 
-                //Allows keyboard input
-                term.installKeyboard();
+        //Allows keyboard input
+        term.installKeyboard();
 
-                $scope.close = function(){
-                    dataService.setRemoteWindowInactive();
-                    $window.close();
-                }
-            }
-        ]
-    );
+        $scope.close = function() {
+          dataService.setRemoteWindowInactive();
+          $window.close();
+        };
+      }
+    ]);
 
 })(angular);
diff --git a/app/server-control/index.js b/app/server-control/index.js
index 41cb1ac..12debcf 100644
--- a/app/server-control/index.js
+++ b/app/server-control/index.js
@@ -5,48 +5,48 @@
  * @exports app/server-control/index
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.serverControl', [
-            'ngRoute',
-            'app.constants',
-            'app.common.services'
-        ])
-        // Route configuration
-        .config(['$routeProvider', function ($routeProvider) {
-            $routeProvider
-                .when('/server-control/bmc-reboot', {
-                    'template': require('./controllers/bmc-reboot-controller.html'),
-                    'controller': 'bmcRebootController',
-                    authenticated: true
-                })
-                .when('/server-control/server-led', {
-                    'template': require('../server-health/controllers/unit-id-controller.html'),
-                    'controller': 'unitIdController',
-                    authenticated: true
-                })
-                .when('/server-control/power-operations', {
-                    'template': require('./controllers/power-operations-controller.html'),
-                    'controller': 'powerOperationsController',
-                    authenticated: true
-                })
-                .when('/server-control/remote-console', {
-                    'template': require('./controllers/remote-console-controller.html'),
-                    'controller': 'remoteConsoleController',
-                    authenticated: true
-                })
-                .when('/server-control/remote-console-window', {
-                    'template': require('./controllers/remote-console-window-controller.html'),
-                    'controller': 'remoteConsoleWindowController',
-                    authenticated: true
-                })
-                .when('/server-control', {
-                    'template': require('./controllers/power-operations-controller.html'),
-                    'controller': 'powerOperationsController',
-                    authenticated: true
-                });
-        }]);
+  angular
+    .module('app.serverControl', [
+      'ngRoute',
+      'app.constants',
+      'app.common.services'
+    ])
+    // Route configuration
+    .config(['$routeProvider', function($routeProvider) {
+      $routeProvider
+        .when('/server-control/bmc-reboot', {
+          'template': require('./controllers/bmc-reboot-controller.html'),
+          'controller': 'bmcRebootController',
+          authenticated: true
+        })
+        .when('/server-control/server-led', {
+          'template': require('../server-health/controllers/unit-id-controller.html'),
+          'controller': 'unitIdController',
+          authenticated: true
+        })
+        .when('/server-control/power-operations', {
+          'template': require('./controllers/power-operations-controller.html'),
+          'controller': 'powerOperationsController',
+          authenticated: true
+        })
+        .when('/server-control/remote-console', {
+          'template': require('./controllers/remote-console-controller.html'),
+          'controller': 'remoteConsoleController',
+          authenticated: true
+        })
+        .when('/server-control/remote-console-window', {
+          'template': require('./controllers/remote-console-window-controller.html'),
+          'controller': 'remoteConsoleWindowController',
+          authenticated: true
+        })
+        .when('/server-control', {
+          'template': require('./controllers/power-operations-controller.html'),
+          'controller': 'powerOperationsController',
+          authenticated: true
+        });
+    }]);
 
 })(window.angular);
diff --git a/app/server-health/controllers/diagnostics-controller.js b/app/server-health/controllers/diagnostics-controller.js
index 0db5ad3..b28d61f 100644
--- a/app/server-health/controllers/diagnostics-controller.js
+++ b/app/server-health/controllers/diagnostics-controller.js
@@ -6,20 +6,19 @@
  * @name diagnosticsController
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.serverHealth')
-        .controller('diagnosticsController', [
-            '$scope',
-            '$window',
-            'APIUtils',
-            'dataService',
-            function($scope, $window, APIUtils, dataService){
-                $scope.dataService = dataService;
-            }
-        ]
-    );
+  angular
+    .module('app.serverHealth')
+    .controller('diagnosticsController', [
+      '$scope',
+      '$window',
+      'APIUtils',
+      'dataService',
+      function($scope, $window, APIUtils, dataService) {
+        $scope.dataService = dataService;
+      }
+    ]);
 
 })(angular);
diff --git a/app/server-health/controllers/inventory-controller.js b/app/server-health/controllers/inventory-controller.js
index 5fca94f..17c9057 100644
--- a/app/server-health/controllers/inventory-controller.js
+++ b/app/server-health/controllers/inventory-controller.js
@@ -6,23 +6,22 @@
  * @name inventoryController
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.serverHealth')
-        .controller('inventoryController', [
-            '$scope',
-            '$window',
-            'APIUtils',
-            'dataService',
-            function($scope, $window, APIUtils, dataService){
-                $scope.dataService = dataService;
+  angular
+    .module('app.serverHealth')
+    .controller('inventoryController', [
+      '$scope',
+      '$window',
+      'APIUtils',
+      'dataService',
+      function($scope, $window, APIUtils, dataService) {
+        $scope.dataService = dataService;
 
-                // Force to top of page when viewing single group
-                $window.scrollTo(0, 0);
-            }
-        ]
-    );
+        // Force to top of page when viewing single group
+        $window.scrollTo(0, 0);
+      }
+    ]);
 
 })(angular);
diff --git a/app/server-health/controllers/inventory-overview-controller.js b/app/server-health/controllers/inventory-overview-controller.js
index 7dc89af..a0dad75 100644
--- a/app/server-health/controllers/inventory-overview-controller.js
+++ b/app/server-health/controllers/inventory-overview-controller.js
@@ -6,70 +6,71 @@
  * @name inventoryOverviewController
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.serverHealth')
-        .controller('inventoryOverviewController', [
-            '$scope',
-            '$window',
-            'APIUtils',
-            'dataService',
-            function($scope, $window, APIUtils, dataService){
-                $scope.dataService = dataService;
-                $scope.hardwares = [];
-                $scope.originalData = {};
-                $scope.customSearch = "";
-                $scope.searchTerms = [];
-                $scope.loading = false;
+  angular
+    .module('app.serverHealth')
+    .controller('inventoryOverviewController', [
+      '$scope',
+      '$window',
+      'APIUtils',
+      'dataService',
+      function($scope, $window, APIUtils, dataService) {
+        $scope.dataService = dataService;
+        $scope.hardwares = [];
+        $scope.originalData = {};
+        $scope.customSearch = '';
+        $scope.searchTerms = [];
+        $scope.loading = false;
 
-                $scope.loading = true;
-                APIUtils.getHardwares(function(data, originalData){
-                    $scope.hardwares = data;
-                    $scope.originalData = JSON.stringify(originalData);
-                    $scope.loading = false;
-                });
+        $scope.loading = true;
+        APIUtils.getHardwares(function(data, originalData) {
+          $scope.hardwares = data;
+          $scope.originalData = JSON.stringify(originalData);
+          $scope.loading = false;
+        });
 
-                $scope.clear = function(){
-                    $scope.customSearch = "";
-                    $scope.searchTerms = [];
-                }
+        $scope.clear = function() {
+          $scope.customSearch = '';
+          $scope.searchTerms = [];
+        };
 
-                $scope.doSearchOnEnter = function (event) {
-                    var search = $scope.customSearch.replace(/^\s+/g,'').replace(/\s+$/g,'');
-                    if (event.keyCode === 13 &&
-                        search.length >= 2) {
-                        $scope.searchTerms = $scope.customSearch.split(" ");
-                    }else{
-                        if(search.length == 0){
-                            $scope.searchTerms = [];
-                        }
-                    }
-                };
-
-                $scope.doSearchOnClick = function() {
-                    var search = $scope.customSearch.replace(/^\s+/g,'').replace(/\s+$/g,'');
-                    if (search.length >= 2) {
-                        $scope.searchTerms = $scope.customSearch.split(" ");
-                    }else{
-                        if(search.length == 0){
-                            $scope.searchTerms = [];
-                        }
-                    }
-                }
-
-                $scope.filterBySearchTerms = function(hardware){
-
-                    if(!$scope.searchTerms.length) return true;
-
-                    for(var i = 0, length = $scope.searchTerms.length; i < length; i++){
-                        if(hardware.search_text.indexOf($scope.searchTerms[i].toLowerCase()) == -1) return false;
-                    }
-                    return true;
-                }
+        $scope.doSearchOnEnter = function(event) {
+          var search = $scope.customSearch.replace(/^\s+/g, '').replace(/\s+$/g, '');
+          if (event.keyCode === 13 &&
+            search.length >= 2) {
+            $scope.searchTerms = $scope.customSearch.split(' ');
+          }
+          else {
+            if (search.length == 0) {
+              $scope.searchTerms = [];
             }
-        ]
-    );
+          }
+        };
+
+        $scope.doSearchOnClick = function() {
+          var search = $scope.customSearch.replace(/^\s+/g, '').replace(/\s+$/g, '');
+          if (search.length >= 2) {
+            $scope.searchTerms = $scope.customSearch.split(' ');
+          }
+          else {
+            if (search.length == 0) {
+              $scope.searchTerms = [];
+            }
+          }
+        };
+
+        $scope.filterBySearchTerms = function(hardware) {
+
+          if (!$scope.searchTerms.length) return true;
+
+          for (var i = 0, length = $scope.searchTerms.length; i < length; i++) {
+            if (hardware.search_text.indexOf($scope.searchTerms[i].toLowerCase()) == -1) return false;
+          }
+          return true;
+        };
+      }
+    ]);
 
 })(angular);
diff --git a/app/server-health/controllers/log-controller.js b/app/server-health/controllers/log-controller.js
index 8c5df7c..1a01242 100644
--- a/app/server-health/controllers/log-controller.js
+++ b/app/server-health/controllers/log-controller.js
@@ -6,192 +6,192 @@
  * @name logController
  */
 
-window.angular && (function (angular) {
-    'use strict';
-    angular
-        .module('app.serverHealth')
-        .config(function(paginationTemplateProvider) {
-            paginationTemplateProvider.setString(require('../../common/directives/dirPagination.tpl.html'));
-        })
-        .controller('logController', [
-            '$scope',
-            '$window',
-            'APIUtils',
-            'dataService',
-            'Constants',
-            '$routeParams',
-            '$filter',
-            function($scope, $window, APIUtils, dataService, Constants, $routeParams, $filter){
-                $scope.dataService = dataService;
-                $scope.logs = [];
-                $scope.tmz = 'EDT';
-                $scope.itemsPerPage = Constants.PAGINATION.LOG_ITEMS_PER_PAGE;
-                $scope.loading = false;
-                var expandedSelectedIdOnce = false;
+window.angular && (function(angular) {
+  'use strict';
+  angular
+    .module('app.serverHealth')
+    .config(function(paginationTemplateProvider) {
+      paginationTemplateProvider.setString(require('../../common/directives/dirPagination.tpl.html'));
+    })
+    .controller('logController', [
+      '$scope',
+      '$window',
+      'APIUtils',
+      'dataService',
+      'Constants',
+      '$routeParams',
+      '$filter',
+      function($scope, $window, APIUtils, dataService, Constants, $routeParams, $filter) {
+        $scope.dataService = dataService;
+        $scope.logs = [];
+        $scope.tmz = 'EDT';
+        $scope.itemsPerPage = Constants.PAGINATION.LOG_ITEMS_PER_PAGE;
+        $scope.loading = false;
+        var expandedSelectedIdOnce = false;
 
-                var sensorType = $routeParams.type;
-                var eventId = $routeParams.id;
+        var sensorType = $routeParams.type;
+        var eventId = $routeParams.id;
 
-                // priority buttons
-                $scope.selectedSeverity = {
-                    all: true,
-                    low: false,
-                    medium: false,
-                    high: false
-                };
+        // priority buttons
+        $scope.selectedSeverity = {
+          all: true,
+          low: false,
+          medium: false,
+          high: false
+        };
 
-                if(sensorType == 'high'){
-                    $scope.selectedSeverity.all = false;
-                    $scope.selectedSeverity.high = true;
-                }
+        if (sensorType == 'high') {
+          $scope.selectedSeverity.all = false;
+          $scope.selectedSeverity.high = true;
+        }
 
-                $scope.selectedStatus = {
-                    all: true,
-                    resolved: false
-                };
+        $scope.selectedStatus = {
+          all: true,
+          resolved: false
+        };
 
-                $scope.customSearch = "";
-                $scope.searchItems = [];
-                $scope.selectedEvents = [];
+        $scope.customSearch = '';
+        $scope.searchItems = [];
+        $scope.selectedEvents = [];
 
 
-                if(eventId){
-                    $scope.customSearch = "#"+eventId;
-                    $scope.searchItems.push("#"+eventId);
-                }
+        if (eventId) {
+          $scope.customSearch = '#' + eventId;
+          $scope.searchItems.push('#' + eventId);
+        }
 
-                $scope.loadLogs = function(){
-                    $scope.loading = true;
-                    APIUtils.getLogs().then(function(result){
-                        if(eventId && expandedSelectedIdOnce == false){
-                            var log = result.data.filter(function(item){
-                                return item.Id == eventId;
-                            });
+        $scope.loadLogs = function() {
+          $scope.loading = true;
+          APIUtils.getLogs().then(function(result) {
+            if (eventId && expandedSelectedIdOnce == false) {
+              var log = result.data.filter(function(item) {
+                return item.Id == eventId;
+              });
 
-                            if(log.length){
-                                log[0].meta = true;
-                            }
-                            expandedSelectedIdOnce = true;
-                        }
-                        dataService.updateServerHealth(result.data);
-                        $scope.logs = result.data;
-                        $scope.originalData = result.original;
-                        $scope.loading = false;
-                    });
-                };
-                $scope.jsonData = function(data){
-                    return JSON.stringify(data);
-                };
-
-                $scope.filterBySeverity = function(log){
-                    if($scope.selectedSeverity.all) return true;
-
-                    return( (log.severity_flags.low && $scope.selectedSeverity.low) ||
-                            (log.severity_flags.medium && $scope.selectedSeverity.medium) ||
-                            (log.severity_flags.high && $scope.selectedSeverity.high)
-                    );
-                }
-
-                $scope.filterByStatus = function(log){
-                    if ($scope.selectedStatus.all) return true;
-                    return( (log.Resolved && $scope.selectedStatus.resolved)||
-                            (!log.Resolved && !$scope.selectedStatus.resolved)
-                    );
-                }
-
-                $scope.filterByDate = function(log){
-                    var endDate;
-                    if($scope.end_date && typeof $scope.end_date.getTime === 'function'){
-                       endDate = new Date($scope.end_date.getTime());
-                       endDate.setTime(endDate.getTime() + 86399000);
-                    }
-
-                    if($scope.start_date && endDate){
-                        var date = new Date($filter('date')(log.Timestamp, 'MM/dd/yyyy  HH:mm:ss', $scope.tmz));
-                        return (date >= $scope.start_date &&
-                               date <= endDate );
-                    }else{
-                        return true;
-                    }
-                }
-
-                $scope.filterBySearchTerms = function(log){
-                    if(!$scope.searchItems.length) return true;
-
-                    for(var i = 0, length = $scope.searchItems.length; i < length; i++){
-                        if(log.search_text.indexOf($scope.searchItems[i].toLowerCase()) == -1) return false;
-                    }
-                    return true;
-                }
-
-                $scope.addSearchItem = function(searchTerms){
-                    var terms = searchTerms.split(" ");
-                    terms.forEach(function(searchTerm){
-                        if($scope.searchItems.indexOf(searchTerm) == -1){
-                            $scope.searchItems.push(searchTerm);
-                        }
-                    });
-                }
-
-                $scope.clearSearchItem = function(searchTerm){
-                    $scope.searchItems = [];
-                }
-
-                $scope.removeSearchItem = function(searchTerm){
-                    var termIndex = $scope.searchItems.indexOf(searchTerm);
-
-                    if(termIndex > -1){
-                        $scope.searchItems.splice(termIndex,1);
-                    }
-                }
-
-                $scope.$watch('all', function(){
-                    $scope.logs.forEach(function(item){
-                        item.selected = $scope.all;
-                    });
-                });
-
-                function updateExportData(){
-                    $scope.export_name = ($scope.selectedEvents.length == 1) ? $scope.selectedEvents[0].Id + ".json" : "export.json";
-                    var data = {};
-                    $scope.selectedEvents.forEach(function(item){
-                        data[item.data.key] = item.data.value;
-                    });
-                    $scope.export_data = JSON.stringify(data);
-                }
-
-
-                $scope.accept = function(){
-                    APIUtils.deleteLogs($scope.selectedEvents).then(function(){
-                        $scope.confirm = false;
-                        $scope.loadLogs();
-                    });
-                }
-
-                $scope.resolve = function(){
-                    var events = $scope.selectedEvents.filter(function(item){
-                        return item.Resolved != 1;
-                    });
-
-                    if(!events.length) return;
-
-                    APIUtils.resolveLogs(events).then(function(){
-                        events.forEach(function(item){
-                            item.Resolved = 1;
-                        });
-                    });
-                }
-
-                $scope.$watch('logs', function(){
-                    $scope.selectedEvents = $scope.logs.filter(function(item){
-                        return item.selected;
-                    });
-                    updateExportData();
-                }, true);
-
-                $scope.loadLogs();
+              if (log.length) {
+                log[0].meta = true;
+              }
+              expandedSelectedIdOnce = true;
             }
-        ]
-    );
+            dataService.updateServerHealth(result.data);
+            $scope.logs = result.data;
+            $scope.originalData = result.original;
+            $scope.loading = false;
+          });
+        };
+        $scope.jsonData = function(data) {
+          return JSON.stringify(data);
+        };
+
+        $scope.filterBySeverity = function(log) {
+          if ($scope.selectedSeverity.all) return true;
+
+          return ((log.severity_flags.low && $scope.selectedSeverity.low) ||
+            (log.severity_flags.medium && $scope.selectedSeverity.medium) ||
+            (log.severity_flags.high && $scope.selectedSeverity.high)
+          );
+        };
+
+        $scope.filterByStatus = function(log) {
+          if ($scope.selectedStatus.all) return true;
+          return ((log.Resolved && $scope.selectedStatus.resolved) ||
+            (!log.Resolved && !$scope.selectedStatus.resolved)
+          );
+        };
+
+        $scope.filterByDate = function(log) {
+          var endDate;
+          if ($scope.end_date && typeof $scope.end_date.getTime === 'function') {
+            endDate = new Date($scope.end_date.getTime());
+            endDate.setTime(endDate.getTime() + 86399000);
+          }
+
+          if ($scope.start_date && endDate) {
+            var date = new Date($filter('date')(log.Timestamp, 'MM/dd/yyyy  HH:mm:ss', $scope.tmz));
+            return (date >= $scope.start_date &&
+              date <= endDate);
+          }
+          else {
+            return true;
+          }
+        };
+
+        $scope.filterBySearchTerms = function(log) {
+          if (!$scope.searchItems.length) return true;
+
+          for (var i = 0, length = $scope.searchItems.length; i < length; i++) {
+            if (log.search_text.indexOf($scope.searchItems[i].toLowerCase()) == -1) return false;
+          }
+          return true;
+        };
+
+        $scope.addSearchItem = function(searchTerms) {
+          var terms = searchTerms.split(' ');
+          terms.forEach(function(searchTerm) {
+            if ($scope.searchItems.indexOf(searchTerm) == -1) {
+              $scope.searchItems.push(searchTerm);
+            }
+          });
+        };
+
+        $scope.clearSearchItem = function(searchTerm) {
+          $scope.searchItems = [];
+        };
+
+        $scope.removeSearchItem = function(searchTerm) {
+          var termIndex = $scope.searchItems.indexOf(searchTerm);
+
+          if (termIndex > -1) {
+            $scope.searchItems.splice(termIndex, 1);
+          }
+        };
+
+        $scope.$watch('all', function() {
+          $scope.logs.forEach(function(item) {
+            item.selected = $scope.all;
+          });
+        });
+
+        function updateExportData() {
+          $scope.export_name = ($scope.selectedEvents.length == 1) ? $scope.selectedEvents[0].Id + '.json' : 'export.json';
+          var data = {};
+          $scope.selectedEvents.forEach(function(item) {
+            data[item.data.key] = item.data.value;
+          });
+          $scope.export_data = JSON.stringify(data);
+        }
+
+
+        $scope.accept = function() {
+          APIUtils.deleteLogs($scope.selectedEvents).then(function() {
+            $scope.confirm = false;
+            $scope.loadLogs();
+          });
+        };
+
+        $scope.resolve = function() {
+          var events = $scope.selectedEvents.filter(function(item) {
+            return item.Resolved != 1;
+          });
+
+          if (!events.length) return;
+
+          APIUtils.resolveLogs(events).then(function() {
+            events.forEach(function(item) {
+              item.Resolved = 1;
+            });
+          });
+        };
+
+        $scope.$watch('logs', function() {
+          $scope.selectedEvents = $scope.logs.filter(function(item) {
+            return item.selected;
+          });
+          updateExportData();
+        }, true);
+
+        $scope.loadLogs();
+      }
+    ]);
 
 })(angular);
diff --git a/app/server-health/controllers/power-consumption-controller.js b/app/server-health/controllers/power-consumption-controller.js
index 9e035d6..9a74e6d 100644
--- a/app/server-health/controllers/power-consumption-controller.js
+++ b/app/server-health/controllers/power-consumption-controller.js
@@ -6,20 +6,19 @@
  * @name powerConsumptionController
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.serverHealth')
-        .controller('powerConsumptionController', [
-            '$scope',
-            '$window',
-            'APIUtils',
-            'dataService',
-            function($scope, $window, APIUtils, dataService){
-                $scope.dataService = dataService;
-            }
-        ]
-    );
+  angular
+    .module('app.serverHealth')
+    .controller('powerConsumptionController', [
+      '$scope',
+      '$window',
+      'APIUtils',
+      'dataService',
+      function($scope, $window, APIUtils, dataService) {
+        $scope.dataService = dataService;
+      }
+    ]);
 
 })(angular);
diff --git a/app/server-health/controllers/sensors-controller.js b/app/server-health/controllers/sensors-controller.js
index c0ad76e..70f3e9c 100644
--- a/app/server-health/controllers/sensors-controller.js
+++ b/app/server-health/controllers/sensors-controller.js
@@ -6,133 +6,136 @@
  * @name sensorsController
  */
 
-window.angular && (function (angular) {
-    'use strict';
-    var sensorData = [];
-    angular
-        .module('app.overview')
-        .controller('sensorsController', [
-            '$scope',
-            '$log',
-            '$window',
-            'APIUtils',
-            'dataService',
-            '$routeParams',
-            function($scope, $log, $window, APIUtils, dataService, $routeParams){
-                $scope.dataService = dataService;
-                $scope.customSearch = "";
-                $scope.dropdown_selected = false;
-                $scope.$log = $log;
-                $scope.data = {};
-                $scope.searchTerms = [];
+window.angular && (function(angular) {
+  'use strict';
+  var sensorData = [];
+  angular
+    .module('app.overview')
+    .controller('sensorsController', [
+      '$scope',
+      '$log',
+      '$window',
+      'APIUtils',
+      'dataService',
+      '$routeParams',
+      function($scope, $log, $window, APIUtils, dataService, $routeParams) {
+        $scope.dataService = dataService;
+        $scope.customSearch = '';
+        $scope.dropdown_selected = false;
+        $scope.$log = $log;
+        $scope.data = {};
+        $scope.searchTerms = [];
 
-                $scope.selectedSeverity = {
-                    all: true,
-                    normal: false,
-                    warning: false,
-                    critical: false
-                };
+        $scope.selectedSeverity = {
+          all: true,
+          normal: false,
+          warning: false,
+          critical: false
+        };
 
-                var sensorType = $routeParams.type;
+        var sensorType = $routeParams.type;
 
-                $scope.export_name = sensorType + "_sensors.json";
+        $scope.export_name = sensorType + '_sensors.json';
 
-                $scope.toggleSeverityAll = function(){
-                    $scope.selectedSeverity.all = !$scope.selectedSeverity.all;
+        $scope.toggleSeverityAll = function() {
+          $scope.selectedSeverity.all = !$scope.selectedSeverity.all;
 
-                    if($scope.selectedSeverity.all){
-                        $scope.selectedSeverity.normal = false;
-                        $scope.selectedSeverity.warning = false;
-                        $scope.selectedSeverity.critical = false;
-                    }
-                }
+          if ($scope.selectedSeverity.all) {
+            $scope.selectedSeverity.normal = false;
+            $scope.selectedSeverity.warning = false;
+            $scope.selectedSeverity.critical = false;
+          }
+        };
 
-                $scope.toggleSeverity = function(severity){
-                    $scope.selectedSeverity[severity] = !$scope.selectedSeverity[severity];
+        $scope.toggleSeverity = function(severity) {
+          $scope.selectedSeverity[severity] = !$scope.selectedSeverity[severity];
 
-                    if($scope.selectedSeverity.normal &&
-                       $scope.selectedSeverity.warning &&
-                       $scope.selectedSeverity.critical){
-                        $scope.selectedSeverity.all = true;
-                        $scope.selectedSeverity.normal = false;
-                        $scope.selectedSeverity.warning = false;
-                        $scope.selectedSeverity.critical = false;
-                    }else{
-                        $scope.selectedSeverity.all = false;
-                    }
-                }
+          if ($scope.selectedSeverity.normal &&
+            $scope.selectedSeverity.warning &&
+            $scope.selectedSeverity.critical) {
+            $scope.selectedSeverity.all = true;
+            $scope.selectedSeverity.normal = false;
+            $scope.selectedSeverity.warning = false;
+            $scope.selectedSeverity.critical = false;
+          }
+          else {
+            $scope.selectedSeverity.all = false;
+          }
+        };
 
-                $scope.doSearchOnEnter = function (event) {
-                    var search = $scope.customSearch.replace(/^\s+/g,'').replace(/\s+$/g,'');
-                    if (event.keyCode === 13 &&
-                        search.length >= 2) {
-                        $scope.searchTerms = $scope.customSearch.split(" ");
-                    }else{
-                        if(search.length == 0){
-                            $scope.searchTerms = [];
-                        }
-                    }
-                };
-
-                $scope.doSearchOnClick = function() {
-                    var search = $scope.customSearch.replace(/^\s+/g,'').replace(/\s+$/g,'');
-                    if (search.length >= 2) {
-                        $scope.searchTerms = $scope.customSearch.split(" ");
-                    }else{
-                        if(search.length == 0){
-                            $scope.searchTerms = [];
-                        }
-                    }
-                }
-
-                $scope.jsonData = function(data){
-                    var dt = {};
-                    data.data.forEach(function(item){
-                        dt[item.original_data.key] = item.original_data.value;
-                    });
-                    return JSON.stringify(dt);
-                };
-
-                $scope.filterBySeverity = function(sensor){
-                    if($scope.selectedSeverity.all) return true;
-
-                    return( (sensor.severity_flags.normal && $scope.selectedSeverity.normal) ||
-                            (sensor.severity_flags.warning && $scope.selectedSeverity.warning) ||
-                            (sensor.severity_flags.critical && $scope.selectedSeverity.critical)
-                    );
-                }
-                $scope.filterBySearchTerms = function(sensor){
-
-                    if(!$scope.searchTerms.length) return true;
-
-                    for(var i = 0, length = $scope.searchTerms.length; i < length; i++){
-                        if(sensor.search_text.indexOf($scope.searchTerms[i].toLowerCase()) == -1) return false;
-                    }
-                    return true;
-                }
-
-                function setSensorData(){
-                    var data = dataService.sensorData.sensors.filter(function(item){
-                        return item.type == sensorType;
-                    });
-                    if(data.length){
-                        sensorData = data[0];
-                        $scope.data = sensorData;
-                        $scope.export_data = $scope.jsonData($scope.data);
-                    }
-                }
-
-                if(!dataService.sensorData.sensors){
-                    APIUtils.getAllSensorStatus(function(data, originalData){
-                        dataService.sensorData = data;
-                        setSensorData();
-                    });
-                }else{
-                    setSensorData();
-                }
-
+        $scope.doSearchOnEnter = function(event) {
+          var search = $scope.customSearch.replace(/^\s+/g, '').replace(/\s+$/g, '');
+          if (event.keyCode === 13 &&
+            search.length >= 2) {
+            $scope.searchTerms = $scope.customSearch.split(' ');
+          }
+          else {
+            if (search.length == 0) {
+              $scope.searchTerms = [];
             }
-        ]
-    );
+          }
+        };
 
-})(angular);
\ No newline at end of file
+        $scope.doSearchOnClick = function() {
+          var search = $scope.customSearch.replace(/^\s+/g, '').replace(/\s+$/g, '');
+          if (search.length >= 2) {
+            $scope.searchTerms = $scope.customSearch.split(' ');
+          }
+          else {
+            if (search.length == 0) {
+              $scope.searchTerms = [];
+            }
+          }
+        };
+
+        $scope.jsonData = function(data) {
+          var dt = {};
+          data.data.forEach(function(item) {
+            dt[item.original_data.key] = item.original_data.value;
+          });
+          return JSON.stringify(dt);
+        };
+
+        $scope.filterBySeverity = function(sensor) {
+          if ($scope.selectedSeverity.all) return true;
+
+          return ((sensor.severity_flags.normal && $scope.selectedSeverity.normal) ||
+            (sensor.severity_flags.warning && $scope.selectedSeverity.warning) ||
+            (sensor.severity_flags.critical && $scope.selectedSeverity.critical)
+          );
+        };
+        $scope.filterBySearchTerms = function(sensor) {
+
+          if (!$scope.searchTerms.length) return true;
+
+          for (var i = 0, length = $scope.searchTerms.length; i < length; i++) {
+            if (sensor.search_text.indexOf($scope.searchTerms[i].toLowerCase()) == -1) return false;
+          }
+          return true;
+        };
+
+        function setSensorData() {
+          var data = dataService.sensorData.sensors.filter(function(item) {
+            return item.type == sensorType;
+          });
+          if (data.length) {
+            sensorData = data[0];
+            $scope.data = sensorData;
+            $scope.export_data = $scope.jsonData($scope.data);
+          }
+        }
+
+        if (!dataService.sensorData.sensors) {
+          APIUtils.getAllSensorStatus(function(data, originalData) {
+            dataService.sensorData = data;
+            setSensorData();
+          });
+        }
+        else {
+          setSensorData();
+        }
+
+      }
+    ]);
+
+})(angular);
diff --git a/app/server-health/controllers/sensors-overview-controller.js b/app/server-health/controllers/sensors-overview-controller.js
index 9218476..683d071 100644
--- a/app/server-health/controllers/sensors-overview-controller.js
+++ b/app/server-health/controllers/sensors-overview-controller.js
@@ -6,138 +6,140 @@
  * @name sensorsOverviewController
  */
 
-window.angular && (function (angular) {
-    'use strict';
-    angular
-        .module('app.overview')
-        .controller('sensorsOverviewController', [
-            '$scope',
-            '$log',
-            '$window',
-            'APIUtils',
-            'dataService',
-            'Constants',
-            function($scope, $log, $window, APIUtils, dataService, Constants){
-                $scope.dataService = dataService;
+window.angular && (function(angular) {
+  'use strict';
+  angular
+    .module('app.overview')
+    .controller('sensorsOverviewController', [
+      '$scope',
+      '$log',
+      '$window',
+      'APIUtils',
+      'dataService',
+      'Constants',
+      function($scope, $log, $window, APIUtils, dataService, Constants) {
+        $scope.dataService = dataService;
 
-                $scope.dropdown_selected = false;
+        $scope.dropdown_selected = false;
 
-                $scope.$log = $log;
-                $scope.customSearch = "";
-                $scope.searchTerms = [];
-                $scope.messages = Constants.MESSAGES.SENSOR;
-                $scope.selectedSeverity = {
-                    all: true,
-                    normal: false,
-                    warning: false,
-                    critical: false
-                };
-                $scope.export_name = "sensors.json";
-                $scope.loading = false;
-                $scope.jsonData = function(data){
-                    var dt = {};
-                    data.data.forEach(function(item){
-                        dt[item.original_data.key] = item.original_data.value;
-                    });
-                    return JSON.stringify(dt);
-                };
+        $scope.$log = $log;
+        $scope.customSearch = '';
+        $scope.searchTerms = [];
+        $scope.messages = Constants.MESSAGES.SENSOR;
+        $scope.selectedSeverity = {
+          all: true,
+          normal: false,
+          warning: false,
+          critical: false
+        };
+        $scope.export_name = 'sensors.json';
+        $scope.loading = false;
+        $scope.jsonData = function(data) {
+          var dt = {};
+          data.data.forEach(function(item) {
+            dt[item.original_data.key] = item.original_data.value;
+          });
+          return JSON.stringify(dt);
+        };
 
-                $scope.clear = function(){
-                    $scope.customSearch = "";
-                    $scope.searchTerms = [];
-                }
+        $scope.clear = function() {
+          $scope.customSearch = '';
+          $scope.searchTerms = [];
+        };
 
-                $scope.doSearchOnEnter = function (event) {
-                    var search = $scope.customSearch.replace(/^\s+/g,'').replace(/\s+$/g,'');
-                    if (event.keyCode === 13 &&
-                        search.length >= 2) {
-                        $scope.searchTerms = $scope.customSearch.split(" ");
-                    }else{
-                        if(search.length == 0){
-                            $scope.searchTerms = [];
-                        }
-                    }
-                };
-
-                $scope.doSearchOnClick = function() {
-                    var search = $scope.customSearch.replace(/^\s+/g,'').replace(/\s+$/g,'');
-                    if (search.length >= 2) {
-                        $scope.searchTerms = $scope.customSearch.split(" ");
-                    }else{
-                        if(search.length == 0){
-                            $scope.searchTerms = [];
-                        }
-                    }
-                }
-
-                $scope.toggleSeverityAll = function(){
-                    $scope.selectedSeverity.all = !$scope.selectedSeverity.all;
-
-                    if($scope.selectedSeverity.all){
-                        $scope.selectedSeverity.normal = false;
-                        $scope.selectedSeverity.warning = false;
-                        $scope.selectedSeverity.critical = false;
-                    }
-                }
-
-                $scope.toggleSeverity = function(severity){
-                    $scope.selectedSeverity[severity] = !$scope.selectedSeverity[severity];
-
-                   if(['normal', 'warning', 'critical'].indexOf(severity) > -1){
-                       if($scope.selectedSeverity[severity] == false &&
-                          (!$scope.selectedSeverity.normal &&
-                           !$scope.selectedSeverity.warning &&
-                           !$scope.selectedSeverity.critical
-                          )){
-                           $scope.selectedSeverity.all = true;
-                           return;
-                       }
-                   }
-
-                    if($scope.selectedSeverity.normal &&
-                       $scope.selectedSeverity.warning &&
-                       $scope.selectedSeverity.critical){
-                        $scope.selectedSeverity.all = true;
-                        $scope.selectedSeverity.normal = false;
-                        $scope.selectedSeverity.warning = false;
-                        $scope.selectedSeverity.critical = false;
-                    }else{
-                        $scope.selectedSeverity.all = false;
-                    }
-                }
-
-                $scope.filterBySeverity = function(sensor){
-                    if($scope.selectedSeverity.all) return true;
-
-                    return( (sensor.severity_flags.normal && $scope.selectedSeverity.normal) ||
-                            (sensor.severity_flags.warning && $scope.selectedSeverity.warning) ||
-                            (sensor.severity_flags.critical && $scope.selectedSeverity.critical)
-                    );
-                }
-                $scope.filterBySearchTerms = function(sensor){
-
-                    if(!$scope.searchTerms.length) return true;
-
-                    for(var i = 0, length = $scope.searchTerms.length; i < length; i++){
-                        if(sensor.search_text.indexOf($scope.searchTerms[i].toLowerCase()) == -1) return false;
-                    }
-                    return true;
-                }
-
-                $scope.loadSensorData = function(){
-                    $scope.loading = true;
-                    APIUtils.getAllSensorStatus(function(data, originalData){
-                        $scope.data = data;
-                        $scope.originalData = originalData;
-                        dataService.sensorData = data;
-                        $scope.export_data = JSON.stringify(originalData);
-                        $scope.loading = false;
-                    });
-                };
-
-                $scope.loadSensorData();
+        $scope.doSearchOnEnter = function(event) {
+          var search = $scope.customSearch.replace(/^\s+/g, '').replace(/\s+$/g, '');
+          if (event.keyCode === 13 &&
+            search.length >= 2) {
+            $scope.searchTerms = $scope.customSearch.split(' ');
+          }
+          else {
+            if (search.length == 0) {
+              $scope.searchTerms = [];
             }
-        ]
-    );
+          }
+        };
 
-})(angular);
\ No newline at end of file
+        $scope.doSearchOnClick = function() {
+          var search = $scope.customSearch.replace(/^\s+/g, '').replace(/\s+$/g, '');
+          if (search.length >= 2) {
+            $scope.searchTerms = $scope.customSearch.split(' ');
+          }
+          else {
+            if (search.length == 0) {
+              $scope.searchTerms = [];
+            }
+          }
+        };
+
+        $scope.toggleSeverityAll = function() {
+          $scope.selectedSeverity.all = !$scope.selectedSeverity.all;
+
+          if ($scope.selectedSeverity.all) {
+            $scope.selectedSeverity.normal = false;
+            $scope.selectedSeverity.warning = false;
+            $scope.selectedSeverity.critical = false;
+          }
+        };
+
+        $scope.toggleSeverity = function(severity) {
+          $scope.selectedSeverity[severity] = !$scope.selectedSeverity[severity];
+
+          if (['normal', 'warning', 'critical'].indexOf(severity) > -1) {
+            if ($scope.selectedSeverity[severity] == false &&
+              (!$scope.selectedSeverity.normal &&
+                !$scope.selectedSeverity.warning &&
+                !$scope.selectedSeverity.critical
+              )) {
+              $scope.selectedSeverity.all = true;
+              return;
+            }
+          }
+
+          if ($scope.selectedSeverity.normal &&
+            $scope.selectedSeverity.warning &&
+            $scope.selectedSeverity.critical) {
+            $scope.selectedSeverity.all = true;
+            $scope.selectedSeverity.normal = false;
+            $scope.selectedSeverity.warning = false;
+            $scope.selectedSeverity.critical = false;
+          }
+          else {
+            $scope.selectedSeverity.all = false;
+          }
+        };
+
+        $scope.filterBySeverity = function(sensor) {
+          if ($scope.selectedSeverity.all) return true;
+
+          return ((sensor.severity_flags.normal && $scope.selectedSeverity.normal) ||
+            (sensor.severity_flags.warning && $scope.selectedSeverity.warning) ||
+            (sensor.severity_flags.critical && $scope.selectedSeverity.critical)
+          );
+        };
+        $scope.filterBySearchTerms = function(sensor) {
+
+          if (!$scope.searchTerms.length) return true;
+
+          for (var i = 0, length = $scope.searchTerms.length; i < length; i++) {
+            if (sensor.search_text.indexOf($scope.searchTerms[i].toLowerCase()) == -1) return false;
+          }
+          return true;
+        };
+
+        $scope.loadSensorData = function() {
+          $scope.loading = true;
+          APIUtils.getAllSensorStatus(function(data, originalData) {
+            $scope.data = data;
+            $scope.originalData = originalData;
+            dataService.sensorData = data;
+            $scope.export_data = JSON.stringify(originalData);
+            $scope.loading = false;
+          });
+        };
+
+        $scope.loadSensorData();
+      }
+    ]);
+
+})(angular);
diff --git a/app/server-health/controllers/unit-id-controller.js b/app/server-health/controllers/unit-id-controller.js
index 806f024..4cd8055 100644
--- a/app/server-health/controllers/unit-id-controller.js
+++ b/app/server-health/controllers/unit-id-controller.js
@@ -6,41 +6,40 @@
  * @name unitIdController
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.serverHealth')
-        .controller('unitIdController', [
-            '$scope',
-            '$window',
-            'APIUtils',
-            'dataService',
-            function($scope, $window, APIUtils, dataService){
-                $scope.dataService = dataService;
+  angular
+    .module('app.serverHealth')
+    .controller('unitIdController', [
+      '$scope',
+      '$window',
+      'APIUtils',
+      'dataService',
+      function($scope, $window, APIUtils, dataService) {
+        $scope.dataService = dataService;
 
-                APIUtils.getLEDState().then(function(state){
-                    $scope.displayLEDState(state);
-                });
+        APIUtils.getLEDState().then(function(state) {
+          $scope.displayLEDState(state);
+        });
 
-                $scope.displayLEDState = function(state){
-                    if(state == APIUtils.LED_STATE.on){
-                        dataService.LED_state = APIUtils.LED_STATE_TEXT.on;
-                    }else{
-                        dataService.LED_state = APIUtils.LED_STATE_TEXT.off;
-                    }
-                }
+        $scope.displayLEDState = function(state) {
+          if (state == APIUtils.LED_STATE.on) {
+            dataService.LED_state = APIUtils.LED_STATE_TEXT.on;
+          }
+          else {
+            dataService.LED_state = APIUtils.LED_STATE_TEXT.off;
+          }
+        };
 
-                $scope.toggleLED = function(){
-                    var toggleState = (dataService.LED_state == APIUtils.LED_STATE_TEXT.on) ?
-                        APIUtils.LED_STATE.off : APIUtils.LED_STATE.on;
-                        dataService.LED_state = (dataService.LED_state == APIUtils.LED_STATE_TEXT.on) ?
-                        APIUtils.LED_STATE_TEXT.off : APIUtils.LED_STATE_TEXT.on;
-                    APIUtils.setLEDState(toggleState, function(status){
-                    });
-                }
-            }
-        ]
-    );
+        $scope.toggleLED = function() {
+          var toggleState = (dataService.LED_state == APIUtils.LED_STATE_TEXT.on) ?
+            APIUtils.LED_STATE.off : APIUtils.LED_STATE.on;
+          dataService.LED_state = (dataService.LED_state == APIUtils.LED_STATE_TEXT.on) ?
+            APIUtils.LED_STATE_TEXT.off : APIUtils.LED_STATE_TEXT.on;
+          APIUtils.setLEDState(toggleState, function(status) {});
+        };
+      }
+    ]);
 
 })(angular);
diff --git a/app/server-health/index.js b/app/server-health/index.js
index 57670ce..c090f82 100644
--- a/app/server-health/index.js
+++ b/app/server-health/index.js
@@ -5,68 +5,68 @@
  * @exports app/server-health/index
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.serverHealth', [
-            'ngRoute',
-            'app.constants',
-            'app.common.services'
-        ])
-        // Route configuration
-        .config(['$routeProvider', function ($routeProvider) {
-            $routeProvider
-                .when('/server-health/event-log', {
-                    'template': require('./controllers/log-controller.html'),
-                    'controller': 'logController',
-                    authenticated: true
-                })
-                .when('/server-health/event-log/:type', {
-                    'template': require('./controllers/log-controller.html'),
-                    'controller': 'logController',
-                    authenticated: true
-                })
-                .when('/server-health/event-log/:type/:id', {
-                    'template': require('./controllers/log-controller.html'),
-                    'controller': 'logController',
-                    authenticated: true
-                })
-                .when('/server-health/inventory-overview', {
-                    'template': require('./controllers/inventory-overview-controller.html'),
-                    'controller': 'inventoryOverviewController',
-                    authenticated: true
-                })
-                .when('/server-health/inventory', {
-                    'template': require('./controllers/inventory-controller.html'),
-                    'controller': 'inventoryController',
-                    authenticated: true
-                })
-                .when('/server-health/sensors-overview', {
-                    'template': require('./controllers/sensors-overview-controller.html'),
-                    'controller': 'sensorsOverviewController',
-                    authenticated: true
-                })
-                .when('/server-health/sensors/:type', {
-                    'template': require('./controllers/sensors-controller.html'),
-                    'controller': 'sensorsController',
-                    authenticated: true
-                })
-                .when('/server-health/power-consumption', {
-                    'template': require('./controllers/power-consumption-controller.html'),
-                    'controller': 'powerConsumptionController',
-                    authenticated: true
-                })
-                .when('/server-health/diagnostics', {
-                    'template': require('./controllers/diagnostics-controller.html'),
-                    'controller': 'diagnosticsController',
-                    authenticated: true
-                })
-                .when('/server-health', {
-                    'template': require('./controllers/log-controller.html'),
-                    'controller': 'logController',
-                    authenticated: true
-                });
-        }]);
+  angular
+    .module('app.serverHealth', [
+      'ngRoute',
+      'app.constants',
+      'app.common.services'
+    ])
+    // Route configuration
+    .config(['$routeProvider', function($routeProvider) {
+      $routeProvider
+        .when('/server-health/event-log', {
+          'template': require('./controllers/log-controller.html'),
+          'controller': 'logController',
+          authenticated: true
+        })
+        .when('/server-health/event-log/:type', {
+          'template': require('./controllers/log-controller.html'),
+          'controller': 'logController',
+          authenticated: true
+        })
+        .when('/server-health/event-log/:type/:id', {
+          'template': require('./controllers/log-controller.html'),
+          'controller': 'logController',
+          authenticated: true
+        })
+        .when('/server-health/inventory-overview', {
+          'template': require('./controllers/inventory-overview-controller.html'),
+          'controller': 'inventoryOverviewController',
+          authenticated: true
+        })
+        .when('/server-health/inventory', {
+          'template': require('./controllers/inventory-controller.html'),
+          'controller': 'inventoryController',
+          authenticated: true
+        })
+        .when('/server-health/sensors-overview', {
+          'template': require('./controllers/sensors-overview-controller.html'),
+          'controller': 'sensorsOverviewController',
+          authenticated: true
+        })
+        .when('/server-health/sensors/:type', {
+          'template': require('./controllers/sensors-controller.html'),
+          'controller': 'sensorsController',
+          authenticated: true
+        })
+        .when('/server-health/power-consumption', {
+          'template': require('./controllers/power-consumption-controller.html'),
+          'controller': 'powerConsumptionController',
+          authenticated: true
+        })
+        .when('/server-health/diagnostics', {
+          'template': require('./controllers/diagnostics-controller.html'),
+          'controller': 'diagnosticsController',
+          authenticated: true
+        })
+        .when('/server-health', {
+          'template': require('./controllers/log-controller.html'),
+          'controller': 'logController',
+          authenticated: true
+        });
+    }]);
 
 })(window.angular);
diff --git a/app/templates.js b/app/templates.js
index c1c7cc3..5cc6852 100644
--- a/app/templates.js
+++ b/app/templates.js
@@ -5,13 +5,13 @@
  * @exports app/templates
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    /**
-     * Used for gulp template cache plugin.
-     */
-    angular
-        .module('app.templates', []);
+  /**
+   * Used for gulp template cache plugin.
+   */
+  angular
+    .module('app.templates', []);
 
 })(window.angular);
diff --git a/app/users/controllers/user-accounts-controller.js b/app/users/controllers/user-accounts-controller.js
index 2cccbd7..2d65d8a 100644
--- a/app/users/controllers/user-accounts-controller.js
+++ b/app/users/controllers/user-accounts-controller.js
@@ -6,57 +6,56 @@
  * @name userAccountsController
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.users')
-        .controller('userAccountsController', [
-            '$scope',
-            '$window',
-            'APIUtils',
-            'dataService',
-            function($scope, $window, APIUtils, dataService){
-                $scope.dataService = dataService;
-                $scope.state = "none";
-                $scope.errorMsg = "";
+  angular
+    .module('app.users')
+    .controller('userAccountsController', [
+      '$scope',
+      '$window',
+      'APIUtils',
+      'dataService',
+      function($scope, $window, APIUtils, dataService) {
+        $scope.dataService = dataService;
+        $scope.state = 'none';
+        $scope.errorMsg = '';
 
-                $scope.changePassword = function(oldPassword, newPassword, confirmNewPassword){
-                    var user = $scope.dataService.getUser();
-                    if(!oldPassword || !newPassword || !confirmNewPassword ){
-                        $scope.state = "error";
-                        $scope.errorMsg = "Field is required!";
-                        return false;
-                    }
-                    if (newPassword !== confirmNewPassword){
-                        $scope.state = "error";
-                        $scope.errorMsg = "New passwords do not match!";
-                        return false;
-                    }
-                    if (newPassword === oldPassword){
-                        $scope.state = "error";
-                        $scope.errorMsg = "New password and old password match!";
-                        return false;
-                    }
+        $scope.changePassword = function(oldPassword, newPassword, confirmNewPassword) {
+          var user = $scope.dataService.getUser();
+          if (!oldPassword || !newPassword || !confirmNewPassword) {
+            $scope.state = 'error';
+            $scope.errorMsg = 'Field is required!';
+            return false;
+          }
+          if (newPassword !== confirmNewPassword) {
+            $scope.state = 'error';
+            $scope.errorMsg = 'New passwords do not match!';
+            return false;
+          }
+          if (newPassword === oldPassword) {
+            $scope.state = 'error';
+            $scope.errorMsg = 'New password and old password match!';
+            return false;
+          }
 
-                    // Verify the oldPassword is correct
-                    APIUtils.testPassword(user, oldPassword).then(function(state){
-                        APIUtils.changePassword(user, newPassword).then(function(response){
-                            // Clear the textboxes on a success
-                            $scope.passwordVerify = '';
-                            $scope.password = '';
-                            $scope.oldPassword = '';
-                            $scope.state = "success";
-                        }, function(error){
-                            $scope.state = "error";
-                            $scope.errorMsg = "Error changing password!";
-                        });
-                    }, function(error){
-                        $scope.state = "error";
-                        $scope.errorMsg = "Old password is not correct!";
-                    });
-                }
-            }
-        ]
-    );
+          // Verify the oldPassword is correct
+          APIUtils.testPassword(user, oldPassword).then(function(state) {
+            APIUtils.changePassword(user, newPassword).then(function(response) {
+              // Clear the textboxes on a success
+              $scope.passwordVerify = '';
+              $scope.password = '';
+              $scope.oldPassword = '';
+              $scope.state = 'success';
+            }, function(error) {
+              $scope.state = 'error';
+              $scope.errorMsg = 'Error changing password!';
+            });
+          }, function(error) {
+            $scope.state = 'error';
+            $scope.errorMsg = 'Old password is not correct!';
+          });
+        };
+      }
+    ]);
 })(angular);
diff --git a/app/users/index.js b/app/users/index.js
index d238b97..4dfa1f2 100644
--- a/app/users/index.js
+++ b/app/users/index.js
@@ -5,28 +5,28 @@
  * @exports app/users/index
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.users', [
-            'ngRoute',
-            'app.constants',
-            'app.common.services'
-        ])
-        // Route configuration
-        .config(['$routeProvider', function ($routeProvider) {
-            $routeProvider
-                .when('/users/manage-accounts', {
-                    'template': require('./controllers/user-accounts-controller.html'),
-                    'controller': 'userAccountsController',
-                    authenticated: true
-                })
-                .when('/users', {
-                    'template': require('./controllers/user-accounts-controller.html'),
-                    'controller': 'userAccountsController',
-                    authenticated: true
-                });
-        }]);
+  angular
+    .module('app.users', [
+      'ngRoute',
+      'app.constants',
+      'app.common.services'
+    ])
+    // Route configuration
+    .config(['$routeProvider', function($routeProvider) {
+      $routeProvider
+        .when('/users/manage-accounts', {
+          'template': require('./controllers/user-accounts-controller.html'),
+          'controller': 'userAccountsController',
+          authenticated: true
+        })
+        .when('/users', {
+          'template': require('./controllers/user-accounts-controller.html'),
+          'controller': 'userAccountsController',
+          authenticated: true
+        });
+    }]);
 
 })(window.angular);
diff --git a/app/vendors.js b/app/vendors.js
index 2a403b4..232abde 100644
--- a/app/vendors.js
+++ b/app/vendors.js
@@ -5,9 +5,9 @@
  * @exports app/vendors
  */
 
-window.angular && (function (angular) {
-    'use strict';
+window.angular && (function(angular) {
+  'use strict';
 
-    angular
-        .module('app.vendors', [])
+  angular
+    .module('app.vendors', []);
 })(window.angular);
diff --git a/app/vendors/hterm/hterm_all.js b/app/vendors/hterm/hterm_all.js
index 4bab739..2c551c2 100644
--- a/app/vendors/hterm/hterm_all.js
+++ b/app/vendors/hterm/hterm_all.js
@@ -90,13 +90,15 @@
 
   try {
     throw new Error();
-  } catch (ex) {
+  }
+  catch (ex) {
     var stackArray = ex.stack.split('\n');
     // In Safari, the resulting stackArray will only have 2 elements and the
     // individual strings are formatted differently.
     if (stackArray.length >= 3) {
       source = stackArray[2].replace(/^\s*at\s+/, '');
-    } else {
+    }
+    else {
       source = stackArray[1].replace(/^\s*global code@/, '');
     }
   }
@@ -105,7 +107,8 @@
     var path = arguments[i];
     if (path instanceof Array) {
       lib.rtdep.apply(lib, path);
-    } else {
+    }
+    else {
       var ary = this.runtimeDependencies_[path];
       if (!ary)
         ary = this.runtimeDependencies_[path] = [];
@@ -185,7 +188,8 @@
       if (opt_logFunction)
         opt_logFunction('init: ' + rec[0]);
       rec[1](lib.f.alarm(initNext));
-    } else {
+    }
+    else {
       onInit();
     }
   };
@@ -240,23 +244,23 @@
 
   // CSS rgb color, rgb(rrr,ggg,bbb).
   rgb: new RegExp(
-      ('^/s*rgb/s*/(/s*(/d{1,3})/s*,/s*(/d{1,3})/s*,' +
-       '/s*(/d{1,3})/s*/)/s*$'
-       ).replace(/\//g, '\\'), 'i'),
+    ('^/s*rgb/s*/(/s*(/d{1,3})/s*,/s*(/d{1,3})/s*,' +
+      '/s*(/d{1,3})/s*/)/s*$'
+    ).replace(/\//g, '\\'), 'i'),
 
   // CSS rgb color, rgb(rrr,ggg,bbb,aaa).
   rgba: new RegExp(
-      ('^/s*rgba/s*' +
-       '/(/s*(/d{1,3})/s*,/s*(/d{1,3})/s*,/s*(/d{1,3})/s*' +
-       '(?:,/s*(/d+(?:/./d+)?)/s*)/)/s*$'
-       ).replace(/\//g, '\\'), 'i'),
+    ('^/s*rgba/s*' +
+      '/(/s*(/d{1,3})/s*,/s*(/d{1,3})/s*,/s*(/d{1,3})/s*' +
+      '(?:,/s*(/d+(?:/./d+)?)/s*)/)/s*$'
+    ).replace(/\//g, '\\'), 'i'),
 
   // Either RGB or RGBA.
   rgbx: new RegExp(
-      ('^/s*rgba?/s*' +
-       '/(/s*(/d{1,3})/s*,/s*(/d{1,3})/s*,/s*(/d{1,3})/s*' +
-       '(?:,/s*(/d+(?:/./d+)?)/s*)?/)/s*$'
-       ).replace(/\//g, '\\'), 'i'),
+    ('^/s*rgba?/s*' +
+      '/(/s*(/d{1,3})/s*,/s*(/d{1,3})/s*,/s*(/d{1,3})/s*' +
+      '(?:,/s*(/d+(?:/./d+)?)/s*)?/)/s*$'
+    ).replace(/\//g, '\\'), 'i'),
 
   // An X11 "rgb:dddd/dddd/dddd" value.
   x11rgb: /^\s*rgb:([a-f0-9]{1,4})\/([a-f0-9]{1,4})\/([a-f0-9]{1,4})\s*$/i,
@@ -324,9 +328,9 @@
   // Normalize to 16 bits.
   function norm16(v) {
     v = parseInt(v, 16);
-    return size == 2 ? v :         // 16 bit
-           size == 1 ? v << 4 :    // 8 bit
-           v >> (4 * (size - 2));  // 24 or 32 bit
+    return size == 2 ? v : // 16 bit
+      size == 1 ? v << 4 : // 8 bit
+      v >> (4 * (size - 2)); // 24 or 32 bit
   }
   return lib.colors.arrayToRGBA([r, g, b].map(norm16));
 };
@@ -405,7 +409,7 @@
   function convert(hex) {
     if (hex.length == 4) {
       hex = hex.replace(hex16, function(h, r, g, b) {
-        return "#" + r + r + g + g + b + b;
+        return '#' + r + r + g + g + b + b;
       });
     }
     var ary = hex.match(hex24);
@@ -413,15 +417,16 @@
       return null;
 
     return 'rgb(' + parseInt(ary[1], 16) + ', ' +
-        parseInt(ary[2], 16) + ', ' +
-        parseInt(ary[3], 16) + ')';
+      parseInt(ary[2], 16) + ', ' +
+      parseInt(ary[3], 16) + ')';
   }
 
   if (arg instanceof Array) {
     for (var i = 0; i < arg.length; i++) {
       arg[i] = convert(arg[i]);
     }
-  } else {
+  }
+  else {
     arg = convert(arg);
   }
 
@@ -446,15 +451,16 @@
     if (!ary)
       return null;
     return '#' + lib.f.zpad(((parseInt(ary[0]) << 16) |
-                             (parseInt(ary[1]) <<  8) |
-                             (parseInt(ary[2]) <<  0)).toString(16), 6);
+      (parseInt(ary[1]) << 8) |
+      (parseInt(ary[2]) << 0)).toString(16), 6);
   }
 
   if (arg instanceof Array) {
     for (var i = 0; i < arg.length; i++) {
       arg[i] = convert(arg[i]);
     }
-  } else {
+  }
+  else {
     arg = convert(arg);
   }
 
@@ -521,7 +527,8 @@
       ary.shift();
       return ary;
     }
-  } else {
+  }
+  else {
     var ary = color.match(lib.colors.re_.rgb);
     if (ary) {
       ary.shift();
@@ -564,62 +571,61 @@
 /**
  * The stock color palette.
  */
-lib.colors.stockColorPalette = lib.colors.hexToRGB
-  ([// The "ANSI 16"...
-    '#000000', '#CC0000', '#4E9A06', '#C4A000',
-    '#3465A4', '#75507B', '#06989A', '#D3D7CF',
-    '#555753', '#EF2929', '#00BA13', '#FCE94F',
-    '#729FCF', '#F200CB', '#00B5BD', '#EEEEEC',
+lib.colors.stockColorPalette = lib.colors.hexToRGB([ // The "ANSI 16"...
+  '#000000', '#CC0000', '#4E9A06', '#C4A000',
+  '#3465A4', '#75507B', '#06989A', '#D3D7CF',
+  '#555753', '#EF2929', '#00BA13', '#FCE94F',
+  '#729FCF', '#F200CB', '#00B5BD', '#EEEEEC',
 
-    // The 6x6 color cubes...
-    '#000000', '#00005F', '#000087', '#0000AF', '#0000D7', '#0000FF',
-    '#005F00', '#005F5F', '#005F87', '#005FAF', '#005FD7', '#005FFF',
-    '#008700', '#00875F', '#008787', '#0087AF', '#0087D7', '#0087FF',
-    '#00AF00', '#00AF5F', '#00AF87', '#00AFAF', '#00AFD7', '#00AFFF',
-    '#00D700', '#00D75F', '#00D787', '#00D7AF', '#00D7D7', '#00D7FF',
-    '#00FF00', '#00FF5F', '#00FF87', '#00FFAF', '#00FFD7', '#00FFFF',
+  // The 6x6 color cubes...
+  '#000000', '#00005F', '#000087', '#0000AF', '#0000D7', '#0000FF',
+  '#005F00', '#005F5F', '#005F87', '#005FAF', '#005FD7', '#005FFF',
+  '#008700', '#00875F', '#008787', '#0087AF', '#0087D7', '#0087FF',
+  '#00AF00', '#00AF5F', '#00AF87', '#00AFAF', '#00AFD7', '#00AFFF',
+  '#00D700', '#00D75F', '#00D787', '#00D7AF', '#00D7D7', '#00D7FF',
+  '#00FF00', '#00FF5F', '#00FF87', '#00FFAF', '#00FFD7', '#00FFFF',
 
-    '#5F0000', '#5F005F', '#5F0087', '#5F00AF', '#5F00D7', '#5F00FF',
-    '#5F5F00', '#5F5F5F', '#5F5F87', '#5F5FAF', '#5F5FD7', '#5F5FFF',
-    '#5F8700', '#5F875F', '#5F8787', '#5F87AF', '#5F87D7', '#5F87FF',
-    '#5FAF00', '#5FAF5F', '#5FAF87', '#5FAFAF', '#5FAFD7', '#5FAFFF',
-    '#5FD700', '#5FD75F', '#5FD787', '#5FD7AF', '#5FD7D7', '#5FD7FF',
-    '#5FFF00', '#5FFF5F', '#5FFF87', '#5FFFAF', '#5FFFD7', '#5FFFFF',
+  '#5F0000', '#5F005F', '#5F0087', '#5F00AF', '#5F00D7', '#5F00FF',
+  '#5F5F00', '#5F5F5F', '#5F5F87', '#5F5FAF', '#5F5FD7', '#5F5FFF',
+  '#5F8700', '#5F875F', '#5F8787', '#5F87AF', '#5F87D7', '#5F87FF',
+  '#5FAF00', '#5FAF5F', '#5FAF87', '#5FAFAF', '#5FAFD7', '#5FAFFF',
+  '#5FD700', '#5FD75F', '#5FD787', '#5FD7AF', '#5FD7D7', '#5FD7FF',
+  '#5FFF00', '#5FFF5F', '#5FFF87', '#5FFFAF', '#5FFFD7', '#5FFFFF',
 
-    '#870000', '#87005F', '#870087', '#8700AF', '#8700D7', '#8700FF',
-    '#875F00', '#875F5F', '#875F87', '#875FAF', '#875FD7', '#875FFF',
-    '#878700', '#87875F', '#878787', '#8787AF', '#8787D7', '#8787FF',
-    '#87AF00', '#87AF5F', '#87AF87', '#87AFAF', '#87AFD7', '#87AFFF',
-    '#87D700', '#87D75F', '#87D787', '#87D7AF', '#87D7D7', '#87D7FF',
-    '#87FF00', '#87FF5F', '#87FF87', '#87FFAF', '#87FFD7', '#87FFFF',
+  '#870000', '#87005F', '#870087', '#8700AF', '#8700D7', '#8700FF',
+  '#875F00', '#875F5F', '#875F87', '#875FAF', '#875FD7', '#875FFF',
+  '#878700', '#87875F', '#878787', '#8787AF', '#8787D7', '#8787FF',
+  '#87AF00', '#87AF5F', '#87AF87', '#87AFAF', '#87AFD7', '#87AFFF',
+  '#87D700', '#87D75F', '#87D787', '#87D7AF', '#87D7D7', '#87D7FF',
+  '#87FF00', '#87FF5F', '#87FF87', '#87FFAF', '#87FFD7', '#87FFFF',
 
-    '#AF0000', '#AF005F', '#AF0087', '#AF00AF', '#AF00D7', '#AF00FF',
-    '#AF5F00', '#AF5F5F', '#AF5F87', '#AF5FAF', '#AF5FD7', '#AF5FFF',
-    '#AF8700', '#AF875F', '#AF8787', '#AF87AF', '#AF87D7', '#AF87FF',
-    '#AFAF00', '#AFAF5F', '#AFAF87', '#AFAFAF', '#AFAFD7', '#AFAFFF',
-    '#AFD700', '#AFD75F', '#AFD787', '#AFD7AF', '#AFD7D7', '#AFD7FF',
-    '#AFFF00', '#AFFF5F', '#AFFF87', '#AFFFAF', '#AFFFD7', '#AFFFFF',
+  '#AF0000', '#AF005F', '#AF0087', '#AF00AF', '#AF00D7', '#AF00FF',
+  '#AF5F00', '#AF5F5F', '#AF5F87', '#AF5FAF', '#AF5FD7', '#AF5FFF',
+  '#AF8700', '#AF875F', '#AF8787', '#AF87AF', '#AF87D7', '#AF87FF',
+  '#AFAF00', '#AFAF5F', '#AFAF87', '#AFAFAF', '#AFAFD7', '#AFAFFF',
+  '#AFD700', '#AFD75F', '#AFD787', '#AFD7AF', '#AFD7D7', '#AFD7FF',
+  '#AFFF00', '#AFFF5F', '#AFFF87', '#AFFFAF', '#AFFFD7', '#AFFFFF',
 
-    '#D70000', '#D7005F', '#D70087', '#D700AF', '#D700D7', '#D700FF',
-    '#D75F00', '#D75F5F', '#D75F87', '#D75FAF', '#D75FD7', '#D75FFF',
-    '#D78700', '#D7875F', '#D78787', '#D787AF', '#D787D7', '#D787FF',
-    '#D7AF00', '#D7AF5F', '#D7AF87', '#D7AFAF', '#D7AFD7', '#D7AFFF',
-    '#D7D700', '#D7D75F', '#D7D787', '#D7D7AF', '#D7D7D7', '#D7D7FF',
-    '#D7FF00', '#D7FF5F', '#D7FF87', '#D7FFAF', '#D7FFD7', '#D7FFFF',
+  '#D70000', '#D7005F', '#D70087', '#D700AF', '#D700D7', '#D700FF',
+  '#D75F00', '#D75F5F', '#D75F87', '#D75FAF', '#D75FD7', '#D75FFF',
+  '#D78700', '#D7875F', '#D78787', '#D787AF', '#D787D7', '#D787FF',
+  '#D7AF00', '#D7AF5F', '#D7AF87', '#D7AFAF', '#D7AFD7', '#D7AFFF',
+  '#D7D700', '#D7D75F', '#D7D787', '#D7D7AF', '#D7D7D7', '#D7D7FF',
+  '#D7FF00', '#D7FF5F', '#D7FF87', '#D7FFAF', '#D7FFD7', '#D7FFFF',
 
-    '#FF0000', '#FF005F', '#FF0087', '#FF00AF', '#FF00D7', '#FF00FF',
-    '#FF5F00', '#FF5F5F', '#FF5F87', '#FF5FAF', '#FF5FD7', '#FF5FFF',
-    '#FF8700', '#FF875F', '#FF8787', '#FF87AF', '#FF87D7', '#FF87FF',
-    '#FFAF00', '#FFAF5F', '#FFAF87', '#FFAFAF', '#FFAFD7', '#FFAFFF',
-    '#FFD700', '#FFD75F', '#FFD787', '#FFD7AF', '#FFD7D7', '#FFD7FF',
-    '#FFFF00', '#FFFF5F', '#FFFF87', '#FFFFAF', '#FFFFD7', '#FFFFFF',
+  '#FF0000', '#FF005F', '#FF0087', '#FF00AF', '#FF00D7', '#FF00FF',
+  '#FF5F00', '#FF5F5F', '#FF5F87', '#FF5FAF', '#FF5FD7', '#FF5FFF',
+  '#FF8700', '#FF875F', '#FF8787', '#FF87AF', '#FF87D7', '#FF87FF',
+  '#FFAF00', '#FFAF5F', '#FFAF87', '#FFAFAF', '#FFAFD7', '#FFAFFF',
+  '#FFD700', '#FFD75F', '#FFD787', '#FFD7AF', '#FFD7D7', '#FFD7FF',
+  '#FFFF00', '#FFFF5F', '#FFFF87', '#FFFFAF', '#FFFFD7', '#FFFFFF',
 
-    // The greyscale ramp...
-    '#080808', '#121212', '#1C1C1C', '#262626', '#303030', '#3A3A3A',
-    '#444444', '#4E4E4E', '#585858', '#626262', '#6C6C6C', '#767676',
-    '#808080', '#8A8A8A', '#949494', '#9E9E9E', '#A8A8A8', '#B2B2B2',
-    '#BCBCBC', '#C6C6C6', '#D0D0D0', '#DADADA', '#E4E4E4', '#EEEEEE'
-   ]);
+  // The greyscale ramp...
+  '#080808', '#121212', '#1C1C1C', '#262626', '#303030', '#3A3A3A',
+  '#444444', '#4E4E4E', '#585858', '#626262', '#6C6C6C', '#767676',
+  '#808080', '#8A8A8A', '#949494', '#9E9E9E', '#A8A8A8', '#B2B2B2',
+  '#BCBCBC', '#C6C6C6', '#D0D0D0', '#DADADA', '#E4E4E4', '#EEEEEE'
+]);
 
 /**
  * The current color palette, possibly with user changes.
@@ -630,664 +636,664 @@
  * Named colors according to the stock X11 rgb.txt file.
  */
 lib.colors.colorNames = {
-  "aliceblue": "rgb(240, 248, 255)",
-  "antiquewhite": "rgb(250, 235, 215)",
-  "antiquewhite1": "rgb(255, 239, 219)",
-  "antiquewhite2": "rgb(238, 223, 204)",
-  "antiquewhite3": "rgb(205, 192, 176)",
-  "antiquewhite4": "rgb(139, 131, 120)",
-  "aquamarine": "rgb(127, 255, 212)",
-  "aquamarine1": "rgb(127, 255, 212)",
-  "aquamarine2": "rgb(118, 238, 198)",
-  "aquamarine3": "rgb(102, 205, 170)",
-  "aquamarine4": "rgb(69, 139, 116)",
-  "azure": "rgb(240, 255, 255)",
-  "azure1": "rgb(240, 255, 255)",
-  "azure2": "rgb(224, 238, 238)",
-  "azure3": "rgb(193, 205, 205)",
-  "azure4": "rgb(131, 139, 139)",
-  "beige": "rgb(245, 245, 220)",
-  "bisque": "rgb(255, 228, 196)",
-  "bisque1": "rgb(255, 228, 196)",
-  "bisque2": "rgb(238, 213, 183)",
-  "bisque3": "rgb(205, 183, 158)",
-  "bisque4": "rgb(139, 125, 107)",
-  "black": "rgb(0, 0, 0)",
-  "blanchedalmond": "rgb(255, 235, 205)",
-  "blue": "rgb(0, 0, 255)",
-  "blue1": "rgb(0, 0, 255)",
-  "blue2": "rgb(0, 0, 238)",
-  "blue3": "rgb(0, 0, 205)",
-  "blue4": "rgb(0, 0, 139)",
-  "blueviolet": "rgb(138, 43, 226)",
-  "brown": "rgb(165, 42, 42)",
-  "brown1": "rgb(255, 64, 64)",
-  "brown2": "rgb(238, 59, 59)",
-  "brown3": "rgb(205, 51, 51)",
-  "brown4": "rgb(139, 35, 35)",
-  "burlywood": "rgb(222, 184, 135)",
-  "burlywood1": "rgb(255, 211, 155)",
-  "burlywood2": "rgb(238, 197, 145)",
-  "burlywood3": "rgb(205, 170, 125)",
-  "burlywood4": "rgb(139, 115, 85)",
-  "cadetblue": "rgb(95, 158, 160)",
-  "cadetblue1": "rgb(152, 245, 255)",
-  "cadetblue2": "rgb(142, 229, 238)",
-  "cadetblue3": "rgb(122, 197, 205)",
-  "cadetblue4": "rgb(83, 134, 139)",
-  "chartreuse": "rgb(127, 255, 0)",
-  "chartreuse1": "rgb(127, 255, 0)",
-  "chartreuse2": "rgb(118, 238, 0)",
-  "chartreuse3": "rgb(102, 205, 0)",
-  "chartreuse4": "rgb(69, 139, 0)",
-  "chocolate": "rgb(210, 105, 30)",
-  "chocolate1": "rgb(255, 127, 36)",
-  "chocolate2": "rgb(238, 118, 33)",
-  "chocolate3": "rgb(205, 102, 29)",
-  "chocolate4": "rgb(139, 69, 19)",
-  "coral": "rgb(255, 127, 80)",
-  "coral1": "rgb(255, 114, 86)",
-  "coral2": "rgb(238, 106, 80)",
-  "coral3": "rgb(205, 91, 69)",
-  "coral4": "rgb(139, 62, 47)",
-  "cornflowerblue": "rgb(100, 149, 237)",
-  "cornsilk": "rgb(255, 248, 220)",
-  "cornsilk1": "rgb(255, 248, 220)",
-  "cornsilk2": "rgb(238, 232, 205)",
-  "cornsilk3": "rgb(205, 200, 177)",
-  "cornsilk4": "rgb(139, 136, 120)",
-  "cyan": "rgb(0, 255, 255)",
-  "cyan1": "rgb(0, 255, 255)",
-  "cyan2": "rgb(0, 238, 238)",
-  "cyan3": "rgb(0, 205, 205)",
-  "cyan4": "rgb(0, 139, 139)",
-  "darkblue": "rgb(0, 0, 139)",
-  "darkcyan": "rgb(0, 139, 139)",
-  "darkgoldenrod": "rgb(184, 134, 11)",
-  "darkgoldenrod1": "rgb(255, 185, 15)",
-  "darkgoldenrod2": "rgb(238, 173, 14)",
-  "darkgoldenrod3": "rgb(205, 149, 12)",
-  "darkgoldenrod4": "rgb(139, 101, 8)",
-  "darkgray": "rgb(169, 169, 169)",
-  "darkgreen": "rgb(0, 100, 0)",
-  "darkgrey": "rgb(169, 169, 169)",
-  "darkkhaki": "rgb(189, 183, 107)",
-  "darkmagenta": "rgb(139, 0, 139)",
-  "darkolivegreen": "rgb(85, 107, 47)",
-  "darkolivegreen1": "rgb(202, 255, 112)",
-  "darkolivegreen2": "rgb(188, 238, 104)",
-  "darkolivegreen3": "rgb(162, 205, 90)",
-  "darkolivegreen4": "rgb(110, 139, 61)",
-  "darkorange": "rgb(255, 140, 0)",
-  "darkorange1": "rgb(255, 127, 0)",
-  "darkorange2": "rgb(238, 118, 0)",
-  "darkorange3": "rgb(205, 102, 0)",
-  "darkorange4": "rgb(139, 69, 0)",
-  "darkorchid": "rgb(153, 50, 204)",
-  "darkorchid1": "rgb(191, 62, 255)",
-  "darkorchid2": "rgb(178, 58, 238)",
-  "darkorchid3": "rgb(154, 50, 205)",
-  "darkorchid4": "rgb(104, 34, 139)",
-  "darkred": "rgb(139, 0, 0)",
-  "darksalmon": "rgb(233, 150, 122)",
-  "darkseagreen": "rgb(143, 188, 143)",
-  "darkseagreen1": "rgb(193, 255, 193)",
-  "darkseagreen2": "rgb(180, 238, 180)",
-  "darkseagreen3": "rgb(155, 205, 155)",
-  "darkseagreen4": "rgb(105, 139, 105)",
-  "darkslateblue": "rgb(72, 61, 139)",
-  "darkslategray": "rgb(47, 79, 79)",
-  "darkslategray1": "rgb(151, 255, 255)",
-  "darkslategray2": "rgb(141, 238, 238)",
-  "darkslategray3": "rgb(121, 205, 205)",
-  "darkslategray4": "rgb(82, 139, 139)",
-  "darkslategrey": "rgb(47, 79, 79)",
-  "darkturquoise": "rgb(0, 206, 209)",
-  "darkviolet": "rgb(148, 0, 211)",
-  "debianred": "rgb(215, 7, 81)",
-  "deeppink": "rgb(255, 20, 147)",
-  "deeppink1": "rgb(255, 20, 147)",
-  "deeppink2": "rgb(238, 18, 137)",
-  "deeppink3": "rgb(205, 16, 118)",
-  "deeppink4": "rgb(139, 10, 80)",
-  "deepskyblue": "rgb(0, 191, 255)",
-  "deepskyblue1": "rgb(0, 191, 255)",
-  "deepskyblue2": "rgb(0, 178, 238)",
-  "deepskyblue3": "rgb(0, 154, 205)",
-  "deepskyblue4": "rgb(0, 104, 139)",
-  "dimgray": "rgb(105, 105, 105)",
-  "dimgrey": "rgb(105, 105, 105)",
-  "dodgerblue": "rgb(30, 144, 255)",
-  "dodgerblue1": "rgb(30, 144, 255)",
-  "dodgerblue2": "rgb(28, 134, 238)",
-  "dodgerblue3": "rgb(24, 116, 205)",
-  "dodgerblue4": "rgb(16, 78, 139)",
-  "firebrick": "rgb(178, 34, 34)",
-  "firebrick1": "rgb(255, 48, 48)",
-  "firebrick2": "rgb(238, 44, 44)",
-  "firebrick3": "rgb(205, 38, 38)",
-  "firebrick4": "rgb(139, 26, 26)",
-  "floralwhite": "rgb(255, 250, 240)",
-  "forestgreen": "rgb(34, 139, 34)",
-  "gainsboro": "rgb(220, 220, 220)",
-  "ghostwhite": "rgb(248, 248, 255)",
-  "gold": "rgb(255, 215, 0)",
-  "gold1": "rgb(255, 215, 0)",
-  "gold2": "rgb(238, 201, 0)",
-  "gold3": "rgb(205, 173, 0)",
-  "gold4": "rgb(139, 117, 0)",
-  "goldenrod": "rgb(218, 165, 32)",
-  "goldenrod1": "rgb(255, 193, 37)",
-  "goldenrod2": "rgb(238, 180, 34)",
-  "goldenrod3": "rgb(205, 155, 29)",
-  "goldenrod4": "rgb(139, 105, 20)",
-  "gray": "rgb(190, 190, 190)",
-  "gray0": "rgb(0, 0, 0)",
-  "gray1": "rgb(3, 3, 3)",
-  "gray10": "rgb(26, 26, 26)",
-  "gray100": "rgb(255, 255, 255)",
-  "gray11": "rgb(28, 28, 28)",
-  "gray12": "rgb(31, 31, 31)",
-  "gray13": "rgb(33, 33, 33)",
-  "gray14": "rgb(36, 36, 36)",
-  "gray15": "rgb(38, 38, 38)",
-  "gray16": "rgb(41, 41, 41)",
-  "gray17": "rgb(43, 43, 43)",
-  "gray18": "rgb(46, 46, 46)",
-  "gray19": "rgb(48, 48, 48)",
-  "gray2": "rgb(5, 5, 5)",
-  "gray20": "rgb(51, 51, 51)",
-  "gray21": "rgb(54, 54, 54)",
-  "gray22": "rgb(56, 56, 56)",
-  "gray23": "rgb(59, 59, 59)",
-  "gray24": "rgb(61, 61, 61)",
-  "gray25": "rgb(64, 64, 64)",
-  "gray26": "rgb(66, 66, 66)",
-  "gray27": "rgb(69, 69, 69)",
-  "gray28": "rgb(71, 71, 71)",
-  "gray29": "rgb(74, 74, 74)",
-  "gray3": "rgb(8, 8, 8)",
-  "gray30": "rgb(77, 77, 77)",
-  "gray31": "rgb(79, 79, 79)",
-  "gray32": "rgb(82, 82, 82)",
-  "gray33": "rgb(84, 84, 84)",
-  "gray34": "rgb(87, 87, 87)",
-  "gray35": "rgb(89, 89, 89)",
-  "gray36": "rgb(92, 92, 92)",
-  "gray37": "rgb(94, 94, 94)",
-  "gray38": "rgb(97, 97, 97)",
-  "gray39": "rgb(99, 99, 99)",
-  "gray4": "rgb(10, 10, 10)",
-  "gray40": "rgb(102, 102, 102)",
-  "gray41": "rgb(105, 105, 105)",
-  "gray42": "rgb(107, 107, 107)",
-  "gray43": "rgb(110, 110, 110)",
-  "gray44": "rgb(112, 112, 112)",
-  "gray45": "rgb(115, 115, 115)",
-  "gray46": "rgb(117, 117, 117)",
-  "gray47": "rgb(120, 120, 120)",
-  "gray48": "rgb(122, 122, 122)",
-  "gray49": "rgb(125, 125, 125)",
-  "gray5": "rgb(13, 13, 13)",
-  "gray50": "rgb(127, 127, 127)",
-  "gray51": "rgb(130, 130, 130)",
-  "gray52": "rgb(133, 133, 133)",
-  "gray53": "rgb(135, 135, 135)",
-  "gray54": "rgb(138, 138, 138)",
-  "gray55": "rgb(140, 140, 140)",
-  "gray56": "rgb(143, 143, 143)",
-  "gray57": "rgb(145, 145, 145)",
-  "gray58": "rgb(148, 148, 148)",
-  "gray59": "rgb(150, 150, 150)",
-  "gray6": "rgb(15, 15, 15)",
-  "gray60": "rgb(153, 153, 153)",
-  "gray61": "rgb(156, 156, 156)",
-  "gray62": "rgb(158, 158, 158)",
-  "gray63": "rgb(161, 161, 161)",
-  "gray64": "rgb(163, 163, 163)",
-  "gray65": "rgb(166, 166, 166)",
-  "gray66": "rgb(168, 168, 168)",
-  "gray67": "rgb(171, 171, 171)",
-  "gray68": "rgb(173, 173, 173)",
-  "gray69": "rgb(176, 176, 176)",
-  "gray7": "rgb(18, 18, 18)",
-  "gray70": "rgb(179, 179, 179)",
-  "gray71": "rgb(181, 181, 181)",
-  "gray72": "rgb(184, 184, 184)",
-  "gray73": "rgb(186, 186, 186)",
-  "gray74": "rgb(189, 189, 189)",
-  "gray75": "rgb(191, 191, 191)",
-  "gray76": "rgb(194, 194, 194)",
-  "gray77": "rgb(196, 196, 196)",
-  "gray78": "rgb(199, 199, 199)",
-  "gray79": "rgb(201, 201, 201)",
-  "gray8": "rgb(20, 20, 20)",
-  "gray80": "rgb(204, 204, 204)",
-  "gray81": "rgb(207, 207, 207)",
-  "gray82": "rgb(209, 209, 209)",
-  "gray83": "rgb(212, 212, 212)",
-  "gray84": "rgb(214, 214, 214)",
-  "gray85": "rgb(217, 217, 217)",
-  "gray86": "rgb(219, 219, 219)",
-  "gray87": "rgb(222, 222, 222)",
-  "gray88": "rgb(224, 224, 224)",
-  "gray89": "rgb(227, 227, 227)",
-  "gray9": "rgb(23, 23, 23)",
-  "gray90": "rgb(229, 229, 229)",
-  "gray91": "rgb(232, 232, 232)",
-  "gray92": "rgb(235, 235, 235)",
-  "gray93": "rgb(237, 237, 237)",
-  "gray94": "rgb(240, 240, 240)",
-  "gray95": "rgb(242, 242, 242)",
-  "gray96": "rgb(245, 245, 245)",
-  "gray97": "rgb(247, 247, 247)",
-  "gray98": "rgb(250, 250, 250)",
-  "gray99": "rgb(252, 252, 252)",
-  "green": "rgb(0, 255, 0)",
-  "green1": "rgb(0, 255, 0)",
-  "green2": "rgb(0, 238, 0)",
-  "green3": "rgb(0, 205, 0)",
-  "green4": "rgb(0, 139, 0)",
-  "greenyellow": "rgb(173, 255, 47)",
-  "grey": "rgb(190, 190, 190)",
-  "grey0": "rgb(0, 0, 0)",
-  "grey1": "rgb(3, 3, 3)",
-  "grey10": "rgb(26, 26, 26)",
-  "grey100": "rgb(255, 255, 255)",
-  "grey11": "rgb(28, 28, 28)",
-  "grey12": "rgb(31, 31, 31)",
-  "grey13": "rgb(33, 33, 33)",
-  "grey14": "rgb(36, 36, 36)",
-  "grey15": "rgb(38, 38, 38)",
-  "grey16": "rgb(41, 41, 41)",
-  "grey17": "rgb(43, 43, 43)",
-  "grey18": "rgb(46, 46, 46)",
-  "grey19": "rgb(48, 48, 48)",
-  "grey2": "rgb(5, 5, 5)",
-  "grey20": "rgb(51, 51, 51)",
-  "grey21": "rgb(54, 54, 54)",
-  "grey22": "rgb(56, 56, 56)",
-  "grey23": "rgb(59, 59, 59)",
-  "grey24": "rgb(61, 61, 61)",
-  "grey25": "rgb(64, 64, 64)",
-  "grey26": "rgb(66, 66, 66)",
-  "grey27": "rgb(69, 69, 69)",
-  "grey28": "rgb(71, 71, 71)",
-  "grey29": "rgb(74, 74, 74)",
-  "grey3": "rgb(8, 8, 8)",
-  "grey30": "rgb(77, 77, 77)",
-  "grey31": "rgb(79, 79, 79)",
-  "grey32": "rgb(82, 82, 82)",
-  "grey33": "rgb(84, 84, 84)",
-  "grey34": "rgb(87, 87, 87)",
-  "grey35": "rgb(89, 89, 89)",
-  "grey36": "rgb(92, 92, 92)",
-  "grey37": "rgb(94, 94, 94)",
-  "grey38": "rgb(97, 97, 97)",
-  "grey39": "rgb(99, 99, 99)",
-  "grey4": "rgb(10, 10, 10)",
-  "grey40": "rgb(102, 102, 102)",
-  "grey41": "rgb(105, 105, 105)",
-  "grey42": "rgb(107, 107, 107)",
-  "grey43": "rgb(110, 110, 110)",
-  "grey44": "rgb(112, 112, 112)",
-  "grey45": "rgb(115, 115, 115)",
-  "grey46": "rgb(117, 117, 117)",
-  "grey47": "rgb(120, 120, 120)",
-  "grey48": "rgb(122, 122, 122)",
-  "grey49": "rgb(125, 125, 125)",
-  "grey5": "rgb(13, 13, 13)",
-  "grey50": "rgb(127, 127, 127)",
-  "grey51": "rgb(130, 130, 130)",
-  "grey52": "rgb(133, 133, 133)",
-  "grey53": "rgb(135, 135, 135)",
-  "grey54": "rgb(138, 138, 138)",
-  "grey55": "rgb(140, 140, 140)",
-  "grey56": "rgb(143, 143, 143)",
-  "grey57": "rgb(145, 145, 145)",
-  "grey58": "rgb(148, 148, 148)",
-  "grey59": "rgb(150, 150, 150)",
-  "grey6": "rgb(15, 15, 15)",
-  "grey60": "rgb(153, 153, 153)",
-  "grey61": "rgb(156, 156, 156)",
-  "grey62": "rgb(158, 158, 158)",
-  "grey63": "rgb(161, 161, 161)",
-  "grey64": "rgb(163, 163, 163)",
-  "grey65": "rgb(166, 166, 166)",
-  "grey66": "rgb(168, 168, 168)",
-  "grey67": "rgb(171, 171, 171)",
-  "grey68": "rgb(173, 173, 173)",
-  "grey69": "rgb(176, 176, 176)",
-  "grey7": "rgb(18, 18, 18)",
-  "grey70": "rgb(179, 179, 179)",
-  "grey71": "rgb(181, 181, 181)",
-  "grey72": "rgb(184, 184, 184)",
-  "grey73": "rgb(186, 186, 186)",
-  "grey74": "rgb(189, 189, 189)",
-  "grey75": "rgb(191, 191, 191)",
-  "grey76": "rgb(194, 194, 194)",
-  "grey77": "rgb(196, 196, 196)",
-  "grey78": "rgb(199, 199, 199)",
-  "grey79": "rgb(201, 201, 201)",
-  "grey8": "rgb(20, 20, 20)",
-  "grey80": "rgb(204, 204, 204)",
-  "grey81": "rgb(207, 207, 207)",
-  "grey82": "rgb(209, 209, 209)",
-  "grey83": "rgb(212, 212, 212)",
-  "grey84": "rgb(214, 214, 214)",
-  "grey85": "rgb(217, 217, 217)",
-  "grey86": "rgb(219, 219, 219)",
-  "grey87": "rgb(222, 222, 222)",
-  "grey88": "rgb(224, 224, 224)",
-  "grey89": "rgb(227, 227, 227)",
-  "grey9": "rgb(23, 23, 23)",
-  "grey90": "rgb(229, 229, 229)",
-  "grey91": "rgb(232, 232, 232)",
-  "grey92": "rgb(235, 235, 235)",
-  "grey93": "rgb(237, 237, 237)",
-  "grey94": "rgb(240, 240, 240)",
-  "grey95": "rgb(242, 242, 242)",
-  "grey96": "rgb(245, 245, 245)",
-  "grey97": "rgb(247, 247, 247)",
-  "grey98": "rgb(250, 250, 250)",
-  "grey99": "rgb(252, 252, 252)",
-  "honeydew": "rgb(240, 255, 240)",
-  "honeydew1": "rgb(240, 255, 240)",
-  "honeydew2": "rgb(224, 238, 224)",
-  "honeydew3": "rgb(193, 205, 193)",
-  "honeydew4": "rgb(131, 139, 131)",
-  "hotpink": "rgb(255, 105, 180)",
-  "hotpink1": "rgb(255, 110, 180)",
-  "hotpink2": "rgb(238, 106, 167)",
-  "hotpink3": "rgb(205, 96, 144)",
-  "hotpink4": "rgb(139, 58, 98)",
-  "indianred": "rgb(205, 92, 92)",
-  "indianred1": "rgb(255, 106, 106)",
-  "indianred2": "rgb(238, 99, 99)",
-  "indianred3": "rgb(205, 85, 85)",
-  "indianred4": "rgb(139, 58, 58)",
-  "ivory": "rgb(255, 255, 240)",
-  "ivory1": "rgb(255, 255, 240)",
-  "ivory2": "rgb(238, 238, 224)",
-  "ivory3": "rgb(205, 205, 193)",
-  "ivory4": "rgb(139, 139, 131)",
-  "khaki": "rgb(240, 230, 140)",
-  "khaki1": "rgb(255, 246, 143)",
-  "khaki2": "rgb(238, 230, 133)",
-  "khaki3": "rgb(205, 198, 115)",
-  "khaki4": "rgb(139, 134, 78)",
-  "lavender": "rgb(230, 230, 250)",
-  "lavenderblush": "rgb(255, 240, 245)",
-  "lavenderblush1": "rgb(255, 240, 245)",
-  "lavenderblush2": "rgb(238, 224, 229)",
-  "lavenderblush3": "rgb(205, 193, 197)",
-  "lavenderblush4": "rgb(139, 131, 134)",
-  "lawngreen": "rgb(124, 252, 0)",
-  "lemonchiffon": "rgb(255, 250, 205)",
-  "lemonchiffon1": "rgb(255, 250, 205)",
-  "lemonchiffon2": "rgb(238, 233, 191)",
-  "lemonchiffon3": "rgb(205, 201, 165)",
-  "lemonchiffon4": "rgb(139, 137, 112)",
-  "lightblue": "rgb(173, 216, 230)",
-  "lightblue1": "rgb(191, 239, 255)",
-  "lightblue2": "rgb(178, 223, 238)",
-  "lightblue3": "rgb(154, 192, 205)",
-  "lightblue4": "rgb(104, 131, 139)",
-  "lightcoral": "rgb(240, 128, 128)",
-  "lightcyan": "rgb(224, 255, 255)",
-  "lightcyan1": "rgb(224, 255, 255)",
-  "lightcyan2": "rgb(209, 238, 238)",
-  "lightcyan3": "rgb(180, 205, 205)",
-  "lightcyan4": "rgb(122, 139, 139)",
-  "lightgoldenrod": "rgb(238, 221, 130)",
-  "lightgoldenrod1": "rgb(255, 236, 139)",
-  "lightgoldenrod2": "rgb(238, 220, 130)",
-  "lightgoldenrod3": "rgb(205, 190, 112)",
-  "lightgoldenrod4": "rgb(139, 129, 76)",
-  "lightgoldenrodyellow": "rgb(250, 250, 210)",
-  "lightgray": "rgb(211, 211, 211)",
-  "lightgreen": "rgb(144, 238, 144)",
-  "lightgrey": "rgb(211, 211, 211)",
-  "lightpink": "rgb(255, 182, 193)",
-  "lightpink1": "rgb(255, 174, 185)",
-  "lightpink2": "rgb(238, 162, 173)",
-  "lightpink3": "rgb(205, 140, 149)",
-  "lightpink4": "rgb(139, 95, 101)",
-  "lightsalmon": "rgb(255, 160, 122)",
-  "lightsalmon1": "rgb(255, 160, 122)",
-  "lightsalmon2": "rgb(238, 149, 114)",
-  "lightsalmon3": "rgb(205, 129, 98)",
-  "lightsalmon4": "rgb(139, 87, 66)",
-  "lightseagreen": "rgb(32, 178, 170)",
-  "lightskyblue": "rgb(135, 206, 250)",
-  "lightskyblue1": "rgb(176, 226, 255)",
-  "lightskyblue2": "rgb(164, 211, 238)",
-  "lightskyblue3": "rgb(141, 182, 205)",
-  "lightskyblue4": "rgb(96, 123, 139)",
-  "lightslateblue": "rgb(132, 112, 255)",
-  "lightslategray": "rgb(119, 136, 153)",
-  "lightslategrey": "rgb(119, 136, 153)",
-  "lightsteelblue": "rgb(176, 196, 222)",
-  "lightsteelblue1": "rgb(202, 225, 255)",
-  "lightsteelblue2": "rgb(188, 210, 238)",
-  "lightsteelblue3": "rgb(162, 181, 205)",
-  "lightsteelblue4": "rgb(110, 123, 139)",
-  "lightyellow": "rgb(255, 255, 224)",
-  "lightyellow1": "rgb(255, 255, 224)",
-  "lightyellow2": "rgb(238, 238, 209)",
-  "lightyellow3": "rgb(205, 205, 180)",
-  "lightyellow4": "rgb(139, 139, 122)",
-  "limegreen": "rgb(50, 205, 50)",
-  "linen": "rgb(250, 240, 230)",
-  "magenta": "rgb(255, 0, 255)",
-  "magenta1": "rgb(255, 0, 255)",
-  "magenta2": "rgb(238, 0, 238)",
-  "magenta3": "rgb(205, 0, 205)",
-  "magenta4": "rgb(139, 0, 139)",
-  "maroon": "rgb(176, 48, 96)",
-  "maroon1": "rgb(255, 52, 179)",
-  "maroon2": "rgb(238, 48, 167)",
-  "maroon3": "rgb(205, 41, 144)",
-  "maroon4": "rgb(139, 28, 98)",
-  "mediumaquamarine": "rgb(102, 205, 170)",
-  "mediumblue": "rgb(0, 0, 205)",
-  "mediumorchid": "rgb(186, 85, 211)",
-  "mediumorchid1": "rgb(224, 102, 255)",
-  "mediumorchid2": "rgb(209, 95, 238)",
-  "mediumorchid3": "rgb(180, 82, 205)",
-  "mediumorchid4": "rgb(122, 55, 139)",
-  "mediumpurple": "rgb(147, 112, 219)",
-  "mediumpurple1": "rgb(171, 130, 255)",
-  "mediumpurple2": "rgb(159, 121, 238)",
-  "mediumpurple3": "rgb(137, 104, 205)",
-  "mediumpurple4": "rgb(93, 71, 139)",
-  "mediumseagreen": "rgb(60, 179, 113)",
-  "mediumslateblue": "rgb(123, 104, 238)",
-  "mediumspringgreen": "rgb(0, 250, 154)",
-  "mediumturquoise": "rgb(72, 209, 204)",
-  "mediumvioletred": "rgb(199, 21, 133)",
-  "midnightblue": "rgb(25, 25, 112)",
-  "mintcream": "rgb(245, 255, 250)",
-  "mistyrose": "rgb(255, 228, 225)",
-  "mistyrose1": "rgb(255, 228, 225)",
-  "mistyrose2": "rgb(238, 213, 210)",
-  "mistyrose3": "rgb(205, 183, 181)",
-  "mistyrose4": "rgb(139, 125, 123)",
-  "moccasin": "rgb(255, 228, 181)",
-  "navajowhite": "rgb(255, 222, 173)",
-  "navajowhite1": "rgb(255, 222, 173)",
-  "navajowhite2": "rgb(238, 207, 161)",
-  "navajowhite3": "rgb(205, 179, 139)",
-  "navajowhite4": "rgb(139, 121, 94)",
-  "navy": "rgb(0, 0, 128)",
-  "navyblue": "rgb(0, 0, 128)",
-  "oldlace": "rgb(253, 245, 230)",
-  "olivedrab": "rgb(107, 142, 35)",
-  "olivedrab1": "rgb(192, 255, 62)",
-  "olivedrab2": "rgb(179, 238, 58)",
-  "olivedrab3": "rgb(154, 205, 50)",
-  "olivedrab4": "rgb(105, 139, 34)",
-  "orange": "rgb(255, 165, 0)",
-  "orange1": "rgb(255, 165, 0)",
-  "orange2": "rgb(238, 154, 0)",
-  "orange3": "rgb(205, 133, 0)",
-  "orange4": "rgb(139, 90, 0)",
-  "orangered": "rgb(255, 69, 0)",
-  "orangered1": "rgb(255, 69, 0)",
-  "orangered2": "rgb(238, 64, 0)",
-  "orangered3": "rgb(205, 55, 0)",
-  "orangered4": "rgb(139, 37, 0)",
-  "orchid": "rgb(218, 112, 214)",
-  "orchid1": "rgb(255, 131, 250)",
-  "orchid2": "rgb(238, 122, 233)",
-  "orchid3": "rgb(205, 105, 201)",
-  "orchid4": "rgb(139, 71, 137)",
-  "palegoldenrod": "rgb(238, 232, 170)",
-  "palegreen": "rgb(152, 251, 152)",
-  "palegreen1": "rgb(154, 255, 154)",
-  "palegreen2": "rgb(144, 238, 144)",
-  "palegreen3": "rgb(124, 205, 124)",
-  "palegreen4": "rgb(84, 139, 84)",
-  "paleturquoise": "rgb(175, 238, 238)",
-  "paleturquoise1": "rgb(187, 255, 255)",
-  "paleturquoise2": "rgb(174, 238, 238)",
-  "paleturquoise3": "rgb(150, 205, 205)",
-  "paleturquoise4": "rgb(102, 139, 139)",
-  "palevioletred": "rgb(219, 112, 147)",
-  "palevioletred1": "rgb(255, 130, 171)",
-  "palevioletred2": "rgb(238, 121, 159)",
-  "palevioletred3": "rgb(205, 104, 137)",
-  "palevioletred4": "rgb(139, 71, 93)",
-  "papayawhip": "rgb(255, 239, 213)",
-  "peachpuff": "rgb(255, 218, 185)",
-  "peachpuff1": "rgb(255, 218, 185)",
-  "peachpuff2": "rgb(238, 203, 173)",
-  "peachpuff3": "rgb(205, 175, 149)",
-  "peachpuff4": "rgb(139, 119, 101)",
-  "peru": "rgb(205, 133, 63)",
-  "pink": "rgb(255, 192, 203)",
-  "pink1": "rgb(255, 181, 197)",
-  "pink2": "rgb(238, 169, 184)",
-  "pink3": "rgb(205, 145, 158)",
-  "pink4": "rgb(139, 99, 108)",
-  "plum": "rgb(221, 160, 221)",
-  "plum1": "rgb(255, 187, 255)",
-  "plum2": "rgb(238, 174, 238)",
-  "plum3": "rgb(205, 150, 205)",
-  "plum4": "rgb(139, 102, 139)",
-  "powderblue": "rgb(176, 224, 230)",
-  "purple": "rgb(160, 32, 240)",
-  "purple1": "rgb(155, 48, 255)",
-  "purple2": "rgb(145, 44, 238)",
-  "purple3": "rgb(125, 38, 205)",
-  "purple4": "rgb(85, 26, 139)",
-  "red": "rgb(255, 0, 0)",
-  "red1": "rgb(255, 0, 0)",
-  "red2": "rgb(238, 0, 0)",
-  "red3": "rgb(205, 0, 0)",
-  "red4": "rgb(139, 0, 0)",
-  "rosybrown": "rgb(188, 143, 143)",
-  "rosybrown1": "rgb(255, 193, 193)",
-  "rosybrown2": "rgb(238, 180, 180)",
-  "rosybrown3": "rgb(205, 155, 155)",
-  "rosybrown4": "rgb(139, 105, 105)",
-  "royalblue": "rgb(65, 105, 225)",
-  "royalblue1": "rgb(72, 118, 255)",
-  "royalblue2": "rgb(67, 110, 238)",
-  "royalblue3": "rgb(58, 95, 205)",
-  "royalblue4": "rgb(39, 64, 139)",
-  "saddlebrown": "rgb(139, 69, 19)",
-  "salmon": "rgb(250, 128, 114)",
-  "salmon1": "rgb(255, 140, 105)",
-  "salmon2": "rgb(238, 130, 98)",
-  "salmon3": "rgb(205, 112, 84)",
-  "salmon4": "rgb(139, 76, 57)",
-  "sandybrown": "rgb(244, 164, 96)",
-  "seagreen": "rgb(46, 139, 87)",
-  "seagreen1": "rgb(84, 255, 159)",
-  "seagreen2": "rgb(78, 238, 148)",
-  "seagreen3": "rgb(67, 205, 128)",
-  "seagreen4": "rgb(46, 139, 87)",
-  "seashell": "rgb(255, 245, 238)",
-  "seashell1": "rgb(255, 245, 238)",
-  "seashell2": "rgb(238, 229, 222)",
-  "seashell3": "rgb(205, 197, 191)",
-  "seashell4": "rgb(139, 134, 130)",
-  "sienna": "rgb(160, 82, 45)",
-  "sienna1": "rgb(255, 130, 71)",
-  "sienna2": "rgb(238, 121, 66)",
-  "sienna3": "rgb(205, 104, 57)",
-  "sienna4": "rgb(139, 71, 38)",
-  "skyblue": "rgb(135, 206, 235)",
-  "skyblue1": "rgb(135, 206, 255)",
-  "skyblue2": "rgb(126, 192, 238)",
-  "skyblue3": "rgb(108, 166, 205)",
-  "skyblue4": "rgb(74, 112, 139)",
-  "slateblue": "rgb(106, 90, 205)",
-  "slateblue1": "rgb(131, 111, 255)",
-  "slateblue2": "rgb(122, 103, 238)",
-  "slateblue3": "rgb(105, 89, 205)",
-  "slateblue4": "rgb(71, 60, 139)",
-  "slategray": "rgb(112, 128, 144)",
-  "slategray1": "rgb(198, 226, 255)",
-  "slategray2": "rgb(185, 211, 238)",
-  "slategray3": "rgb(159, 182, 205)",
-  "slategray4": "rgb(108, 123, 139)",
-  "slategrey": "rgb(112, 128, 144)",
-  "snow": "rgb(255, 250, 250)",
-  "snow1": "rgb(255, 250, 250)",
-  "snow2": "rgb(238, 233, 233)",
-  "snow3": "rgb(205, 201, 201)",
-  "snow4": "rgb(139, 137, 137)",
-  "springgreen": "rgb(0, 255, 127)",
-  "springgreen1": "rgb(0, 255, 127)",
-  "springgreen2": "rgb(0, 238, 118)",
-  "springgreen3": "rgb(0, 205, 102)",
-  "springgreen4": "rgb(0, 139, 69)",
-  "steelblue": "rgb(70, 130, 180)",
-  "steelblue1": "rgb(99, 184, 255)",
-  "steelblue2": "rgb(92, 172, 238)",
-  "steelblue3": "rgb(79, 148, 205)",
-  "steelblue4": "rgb(54, 100, 139)",
-  "tan": "rgb(210, 180, 140)",
-  "tan1": "rgb(255, 165, 79)",
-  "tan2": "rgb(238, 154, 73)",
-  "tan3": "rgb(205, 133, 63)",
-  "tan4": "rgb(139, 90, 43)",
-  "thistle": "rgb(216, 191, 216)",
-  "thistle1": "rgb(255, 225, 255)",
-  "thistle2": "rgb(238, 210, 238)",
-  "thistle3": "rgb(205, 181, 205)",
-  "thistle4": "rgb(139, 123, 139)",
-  "tomato": "rgb(255, 99, 71)",
-  "tomato1": "rgb(255, 99, 71)",
-  "tomato2": "rgb(238, 92, 66)",
-  "tomato3": "rgb(205, 79, 57)",
-  "tomato4": "rgb(139, 54, 38)",
-  "turquoise": "rgb(64, 224, 208)",
-  "turquoise1": "rgb(0, 245, 255)",
-  "turquoise2": "rgb(0, 229, 238)",
-  "turquoise3": "rgb(0, 197, 205)",
-  "turquoise4": "rgb(0, 134, 139)",
-  "violet": "rgb(238, 130, 238)",
-  "violetred": "rgb(208, 32, 144)",
-  "violetred1": "rgb(255, 62, 150)",
-  "violetred2": "rgb(238, 58, 140)",
-  "violetred3": "rgb(205, 50, 120)",
-  "violetred4": "rgb(139, 34, 82)",
-  "wheat": "rgb(245, 222, 179)",
-  "wheat1": "rgb(255, 231, 186)",
-  "wheat2": "rgb(238, 216, 174)",
-  "wheat3": "rgb(205, 186, 150)",
-  "wheat4": "rgb(139, 126, 102)",
-  "white": "rgb(255, 255, 255)",
-  "whitesmoke": "rgb(245, 245, 245)",
-  "yellow": "rgb(255, 255, 0)",
-  "yellow1": "rgb(255, 255, 0)",
-  "yellow2": "rgb(238, 238, 0)",
-  "yellow3": "rgb(205, 205, 0)",
-  "yellow4": "rgb(139, 139, 0)",
-  "yellowgreen": "rgb(154, 205, 50)"
+  'aliceblue': 'rgb(240, 248, 255)',
+  'antiquewhite': 'rgb(250, 235, 215)',
+  'antiquewhite1': 'rgb(255, 239, 219)',
+  'antiquewhite2': 'rgb(238, 223, 204)',
+  'antiquewhite3': 'rgb(205, 192, 176)',
+  'antiquewhite4': 'rgb(139, 131, 120)',
+  'aquamarine': 'rgb(127, 255, 212)',
+  'aquamarine1': 'rgb(127, 255, 212)',
+  'aquamarine2': 'rgb(118, 238, 198)',
+  'aquamarine3': 'rgb(102, 205, 170)',
+  'aquamarine4': 'rgb(69, 139, 116)',
+  'azure': 'rgb(240, 255, 255)',
+  'azure1': 'rgb(240, 255, 255)',
+  'azure2': 'rgb(224, 238, 238)',
+  'azure3': 'rgb(193, 205, 205)',
+  'azure4': 'rgb(131, 139, 139)',
+  'beige': 'rgb(245, 245, 220)',
+  'bisque': 'rgb(255, 228, 196)',
+  'bisque1': 'rgb(255, 228, 196)',
+  'bisque2': 'rgb(238, 213, 183)',
+  'bisque3': 'rgb(205, 183, 158)',
+  'bisque4': 'rgb(139, 125, 107)',
+  'black': 'rgb(0, 0, 0)',
+  'blanchedalmond': 'rgb(255, 235, 205)',
+  'blue': 'rgb(0, 0, 255)',
+  'blue1': 'rgb(0, 0, 255)',
+  'blue2': 'rgb(0, 0, 238)',
+  'blue3': 'rgb(0, 0, 205)',
+  'blue4': 'rgb(0, 0, 139)',
+  'blueviolet': 'rgb(138, 43, 226)',
+  'brown': 'rgb(165, 42, 42)',
+  'brown1': 'rgb(255, 64, 64)',
+  'brown2': 'rgb(238, 59, 59)',
+  'brown3': 'rgb(205, 51, 51)',
+  'brown4': 'rgb(139, 35, 35)',
+  'burlywood': 'rgb(222, 184, 135)',
+  'burlywood1': 'rgb(255, 211, 155)',
+  'burlywood2': 'rgb(238, 197, 145)',
+  'burlywood3': 'rgb(205, 170, 125)',
+  'burlywood4': 'rgb(139, 115, 85)',
+  'cadetblue': 'rgb(95, 158, 160)',
+  'cadetblue1': 'rgb(152, 245, 255)',
+  'cadetblue2': 'rgb(142, 229, 238)',
+  'cadetblue3': 'rgb(122, 197, 205)',
+  'cadetblue4': 'rgb(83, 134, 139)',
+  'chartreuse': 'rgb(127, 255, 0)',
+  'chartreuse1': 'rgb(127, 255, 0)',
+  'chartreuse2': 'rgb(118, 238, 0)',
+  'chartreuse3': 'rgb(102, 205, 0)',
+  'chartreuse4': 'rgb(69, 139, 0)',
+  'chocolate': 'rgb(210, 105, 30)',
+  'chocolate1': 'rgb(255, 127, 36)',
+  'chocolate2': 'rgb(238, 118, 33)',
+  'chocolate3': 'rgb(205, 102, 29)',
+  'chocolate4': 'rgb(139, 69, 19)',
+  'coral': 'rgb(255, 127, 80)',
+  'coral1': 'rgb(255, 114, 86)',
+  'coral2': 'rgb(238, 106, 80)',
+  'coral3': 'rgb(205, 91, 69)',
+  'coral4': 'rgb(139, 62, 47)',
+  'cornflowerblue': 'rgb(100, 149, 237)',
+  'cornsilk': 'rgb(255, 248, 220)',
+  'cornsilk1': 'rgb(255, 248, 220)',
+  'cornsilk2': 'rgb(238, 232, 205)',
+  'cornsilk3': 'rgb(205, 200, 177)',
+  'cornsilk4': 'rgb(139, 136, 120)',
+  'cyan': 'rgb(0, 255, 255)',
+  'cyan1': 'rgb(0, 255, 255)',
+  'cyan2': 'rgb(0, 238, 238)',
+  'cyan3': 'rgb(0, 205, 205)',
+  'cyan4': 'rgb(0, 139, 139)',
+  'darkblue': 'rgb(0, 0, 139)',
+  'darkcyan': 'rgb(0, 139, 139)',
+  'darkgoldenrod': 'rgb(184, 134, 11)',
+  'darkgoldenrod1': 'rgb(255, 185, 15)',
+  'darkgoldenrod2': 'rgb(238, 173, 14)',
+  'darkgoldenrod3': 'rgb(205, 149, 12)',
+  'darkgoldenrod4': 'rgb(139, 101, 8)',
+  'darkgray': 'rgb(169, 169, 169)',
+  'darkgreen': 'rgb(0, 100, 0)',
+  'darkgrey': 'rgb(169, 169, 169)',
+  'darkkhaki': 'rgb(189, 183, 107)',
+  'darkmagenta': 'rgb(139, 0, 139)',
+  'darkolivegreen': 'rgb(85, 107, 47)',
+  'darkolivegreen1': 'rgb(202, 255, 112)',
+  'darkolivegreen2': 'rgb(188, 238, 104)',
+  'darkolivegreen3': 'rgb(162, 205, 90)',
+  'darkolivegreen4': 'rgb(110, 139, 61)',
+  'darkorange': 'rgb(255, 140, 0)',
+  'darkorange1': 'rgb(255, 127, 0)',
+  'darkorange2': 'rgb(238, 118, 0)',
+  'darkorange3': 'rgb(205, 102, 0)',
+  'darkorange4': 'rgb(139, 69, 0)',
+  'darkorchid': 'rgb(153, 50, 204)',
+  'darkorchid1': 'rgb(191, 62, 255)',
+  'darkorchid2': 'rgb(178, 58, 238)',
+  'darkorchid3': 'rgb(154, 50, 205)',
+  'darkorchid4': 'rgb(104, 34, 139)',
+  'darkred': 'rgb(139, 0, 0)',
+  'darksalmon': 'rgb(233, 150, 122)',
+  'darkseagreen': 'rgb(143, 188, 143)',
+  'darkseagreen1': 'rgb(193, 255, 193)',
+  'darkseagreen2': 'rgb(180, 238, 180)',
+  'darkseagreen3': 'rgb(155, 205, 155)',
+  'darkseagreen4': 'rgb(105, 139, 105)',
+  'darkslateblue': 'rgb(72, 61, 139)',
+  'darkslategray': 'rgb(47, 79, 79)',
+  'darkslategray1': 'rgb(151, 255, 255)',
+  'darkslategray2': 'rgb(141, 238, 238)',
+  'darkslategray3': 'rgb(121, 205, 205)',
+  'darkslategray4': 'rgb(82, 139, 139)',
+  'darkslategrey': 'rgb(47, 79, 79)',
+  'darkturquoise': 'rgb(0, 206, 209)',
+  'darkviolet': 'rgb(148, 0, 211)',
+  'debianred': 'rgb(215, 7, 81)',
+  'deeppink': 'rgb(255, 20, 147)',
+  'deeppink1': 'rgb(255, 20, 147)',
+  'deeppink2': 'rgb(238, 18, 137)',
+  'deeppink3': 'rgb(205, 16, 118)',
+  'deeppink4': 'rgb(139, 10, 80)',
+  'deepskyblue': 'rgb(0, 191, 255)',
+  'deepskyblue1': 'rgb(0, 191, 255)',
+  'deepskyblue2': 'rgb(0, 178, 238)',
+  'deepskyblue3': 'rgb(0, 154, 205)',
+  'deepskyblue4': 'rgb(0, 104, 139)',
+  'dimgray': 'rgb(105, 105, 105)',
+  'dimgrey': 'rgb(105, 105, 105)',
+  'dodgerblue': 'rgb(30, 144, 255)',
+  'dodgerblue1': 'rgb(30, 144, 255)',
+  'dodgerblue2': 'rgb(28, 134, 238)',
+  'dodgerblue3': 'rgb(24, 116, 205)',
+  'dodgerblue4': 'rgb(16, 78, 139)',
+  'firebrick': 'rgb(178, 34, 34)',
+  'firebrick1': 'rgb(255, 48, 48)',
+  'firebrick2': 'rgb(238, 44, 44)',
+  'firebrick3': 'rgb(205, 38, 38)',
+  'firebrick4': 'rgb(139, 26, 26)',
+  'floralwhite': 'rgb(255, 250, 240)',
+  'forestgreen': 'rgb(34, 139, 34)',
+  'gainsboro': 'rgb(220, 220, 220)',
+  'ghostwhite': 'rgb(248, 248, 255)',
+  'gold': 'rgb(255, 215, 0)',
+  'gold1': 'rgb(255, 215, 0)',
+  'gold2': 'rgb(238, 201, 0)',
+  'gold3': 'rgb(205, 173, 0)',
+  'gold4': 'rgb(139, 117, 0)',
+  'goldenrod': 'rgb(218, 165, 32)',
+  'goldenrod1': 'rgb(255, 193, 37)',
+  'goldenrod2': 'rgb(238, 180, 34)',
+  'goldenrod3': 'rgb(205, 155, 29)',
+  'goldenrod4': 'rgb(139, 105, 20)',
+  'gray': 'rgb(190, 190, 190)',
+  'gray0': 'rgb(0, 0, 0)',
+  'gray1': 'rgb(3, 3, 3)',
+  'gray10': 'rgb(26, 26, 26)',
+  'gray100': 'rgb(255, 255, 255)',
+  'gray11': 'rgb(28, 28, 28)',
+  'gray12': 'rgb(31, 31, 31)',
+  'gray13': 'rgb(33, 33, 33)',
+  'gray14': 'rgb(36, 36, 36)',
+  'gray15': 'rgb(38, 38, 38)',
+  'gray16': 'rgb(41, 41, 41)',
+  'gray17': 'rgb(43, 43, 43)',
+  'gray18': 'rgb(46, 46, 46)',
+  'gray19': 'rgb(48, 48, 48)',
+  'gray2': 'rgb(5, 5, 5)',
+  'gray20': 'rgb(51, 51, 51)',
+  'gray21': 'rgb(54, 54, 54)',
+  'gray22': 'rgb(56, 56, 56)',
+  'gray23': 'rgb(59, 59, 59)',
+  'gray24': 'rgb(61, 61, 61)',
+  'gray25': 'rgb(64, 64, 64)',
+  'gray26': 'rgb(66, 66, 66)',
+  'gray27': 'rgb(69, 69, 69)',
+  'gray28': 'rgb(71, 71, 71)',
+  'gray29': 'rgb(74, 74, 74)',
+  'gray3': 'rgb(8, 8, 8)',
+  'gray30': 'rgb(77, 77, 77)',
+  'gray31': 'rgb(79, 79, 79)',
+  'gray32': 'rgb(82, 82, 82)',
+  'gray33': 'rgb(84, 84, 84)',
+  'gray34': 'rgb(87, 87, 87)',
+  'gray35': 'rgb(89, 89, 89)',
+  'gray36': 'rgb(92, 92, 92)',
+  'gray37': 'rgb(94, 94, 94)',
+  'gray38': 'rgb(97, 97, 97)',
+  'gray39': 'rgb(99, 99, 99)',
+  'gray4': 'rgb(10, 10, 10)',
+  'gray40': 'rgb(102, 102, 102)',
+  'gray41': 'rgb(105, 105, 105)',
+  'gray42': 'rgb(107, 107, 107)',
+  'gray43': 'rgb(110, 110, 110)',
+  'gray44': 'rgb(112, 112, 112)',
+  'gray45': 'rgb(115, 115, 115)',
+  'gray46': 'rgb(117, 117, 117)',
+  'gray47': 'rgb(120, 120, 120)',
+  'gray48': 'rgb(122, 122, 122)',
+  'gray49': 'rgb(125, 125, 125)',
+  'gray5': 'rgb(13, 13, 13)',
+  'gray50': 'rgb(127, 127, 127)',
+  'gray51': 'rgb(130, 130, 130)',
+  'gray52': 'rgb(133, 133, 133)',
+  'gray53': 'rgb(135, 135, 135)',
+  'gray54': 'rgb(138, 138, 138)',
+  'gray55': 'rgb(140, 140, 140)',
+  'gray56': 'rgb(143, 143, 143)',
+  'gray57': 'rgb(145, 145, 145)',
+  'gray58': 'rgb(148, 148, 148)',
+  'gray59': 'rgb(150, 150, 150)',
+  'gray6': 'rgb(15, 15, 15)',
+  'gray60': 'rgb(153, 153, 153)',
+  'gray61': 'rgb(156, 156, 156)',
+  'gray62': 'rgb(158, 158, 158)',
+  'gray63': 'rgb(161, 161, 161)',
+  'gray64': 'rgb(163, 163, 163)',
+  'gray65': 'rgb(166, 166, 166)',
+  'gray66': 'rgb(168, 168, 168)',
+  'gray67': 'rgb(171, 171, 171)',
+  'gray68': 'rgb(173, 173, 173)',
+  'gray69': 'rgb(176, 176, 176)',
+  'gray7': 'rgb(18, 18, 18)',
+  'gray70': 'rgb(179, 179, 179)',
+  'gray71': 'rgb(181, 181, 181)',
+  'gray72': 'rgb(184, 184, 184)',
+  'gray73': 'rgb(186, 186, 186)',
+  'gray74': 'rgb(189, 189, 189)',
+  'gray75': 'rgb(191, 191, 191)',
+  'gray76': 'rgb(194, 194, 194)',
+  'gray77': 'rgb(196, 196, 196)',
+  'gray78': 'rgb(199, 199, 199)',
+  'gray79': 'rgb(201, 201, 201)',
+  'gray8': 'rgb(20, 20, 20)',
+  'gray80': 'rgb(204, 204, 204)',
+  'gray81': 'rgb(207, 207, 207)',
+  'gray82': 'rgb(209, 209, 209)',
+  'gray83': 'rgb(212, 212, 212)',
+  'gray84': 'rgb(214, 214, 214)',
+  'gray85': 'rgb(217, 217, 217)',
+  'gray86': 'rgb(219, 219, 219)',
+  'gray87': 'rgb(222, 222, 222)',
+  'gray88': 'rgb(224, 224, 224)',
+  'gray89': 'rgb(227, 227, 227)',
+  'gray9': 'rgb(23, 23, 23)',
+  'gray90': 'rgb(229, 229, 229)',
+  'gray91': 'rgb(232, 232, 232)',
+  'gray92': 'rgb(235, 235, 235)',
+  'gray93': 'rgb(237, 237, 237)',
+  'gray94': 'rgb(240, 240, 240)',
+  'gray95': 'rgb(242, 242, 242)',
+  'gray96': 'rgb(245, 245, 245)',
+  'gray97': 'rgb(247, 247, 247)',
+  'gray98': 'rgb(250, 250, 250)',
+  'gray99': 'rgb(252, 252, 252)',
+  'green': 'rgb(0, 255, 0)',
+  'green1': 'rgb(0, 255, 0)',
+  'green2': 'rgb(0, 238, 0)',
+  'green3': 'rgb(0, 205, 0)',
+  'green4': 'rgb(0, 139, 0)',
+  'greenyellow': 'rgb(173, 255, 47)',
+  'grey': 'rgb(190, 190, 190)',
+  'grey0': 'rgb(0, 0, 0)',
+  'grey1': 'rgb(3, 3, 3)',
+  'grey10': 'rgb(26, 26, 26)',
+  'grey100': 'rgb(255, 255, 255)',
+  'grey11': 'rgb(28, 28, 28)',
+  'grey12': 'rgb(31, 31, 31)',
+  'grey13': 'rgb(33, 33, 33)',
+  'grey14': 'rgb(36, 36, 36)',
+  'grey15': 'rgb(38, 38, 38)',
+  'grey16': 'rgb(41, 41, 41)',
+  'grey17': 'rgb(43, 43, 43)',
+  'grey18': 'rgb(46, 46, 46)',
+  'grey19': 'rgb(48, 48, 48)',
+  'grey2': 'rgb(5, 5, 5)',
+  'grey20': 'rgb(51, 51, 51)',
+  'grey21': 'rgb(54, 54, 54)',
+  'grey22': 'rgb(56, 56, 56)',
+  'grey23': 'rgb(59, 59, 59)',
+  'grey24': 'rgb(61, 61, 61)',
+  'grey25': 'rgb(64, 64, 64)',
+  'grey26': 'rgb(66, 66, 66)',
+  'grey27': 'rgb(69, 69, 69)',
+  'grey28': 'rgb(71, 71, 71)',
+  'grey29': 'rgb(74, 74, 74)',
+  'grey3': 'rgb(8, 8, 8)',
+  'grey30': 'rgb(77, 77, 77)',
+  'grey31': 'rgb(79, 79, 79)',
+  'grey32': 'rgb(82, 82, 82)',
+  'grey33': 'rgb(84, 84, 84)',
+  'grey34': 'rgb(87, 87, 87)',
+  'grey35': 'rgb(89, 89, 89)',
+  'grey36': 'rgb(92, 92, 92)',
+  'grey37': 'rgb(94, 94, 94)',
+  'grey38': 'rgb(97, 97, 97)',
+  'grey39': 'rgb(99, 99, 99)',
+  'grey4': 'rgb(10, 10, 10)',
+  'grey40': 'rgb(102, 102, 102)',
+  'grey41': 'rgb(105, 105, 105)',
+  'grey42': 'rgb(107, 107, 107)',
+  'grey43': 'rgb(110, 110, 110)',
+  'grey44': 'rgb(112, 112, 112)',
+  'grey45': 'rgb(115, 115, 115)',
+  'grey46': 'rgb(117, 117, 117)',
+  'grey47': 'rgb(120, 120, 120)',
+  'grey48': 'rgb(122, 122, 122)',
+  'grey49': 'rgb(125, 125, 125)',
+  'grey5': 'rgb(13, 13, 13)',
+  'grey50': 'rgb(127, 127, 127)',
+  'grey51': 'rgb(130, 130, 130)',
+  'grey52': 'rgb(133, 133, 133)',
+  'grey53': 'rgb(135, 135, 135)',
+  'grey54': 'rgb(138, 138, 138)',
+  'grey55': 'rgb(140, 140, 140)',
+  'grey56': 'rgb(143, 143, 143)',
+  'grey57': 'rgb(145, 145, 145)',
+  'grey58': 'rgb(148, 148, 148)',
+  'grey59': 'rgb(150, 150, 150)',
+  'grey6': 'rgb(15, 15, 15)',
+  'grey60': 'rgb(153, 153, 153)',
+  'grey61': 'rgb(156, 156, 156)',
+  'grey62': 'rgb(158, 158, 158)',
+  'grey63': 'rgb(161, 161, 161)',
+  'grey64': 'rgb(163, 163, 163)',
+  'grey65': 'rgb(166, 166, 166)',
+  'grey66': 'rgb(168, 168, 168)',
+  'grey67': 'rgb(171, 171, 171)',
+  'grey68': 'rgb(173, 173, 173)',
+  'grey69': 'rgb(176, 176, 176)',
+  'grey7': 'rgb(18, 18, 18)',
+  'grey70': 'rgb(179, 179, 179)',
+  'grey71': 'rgb(181, 181, 181)',
+  'grey72': 'rgb(184, 184, 184)',
+  'grey73': 'rgb(186, 186, 186)',
+  'grey74': 'rgb(189, 189, 189)',
+  'grey75': 'rgb(191, 191, 191)',
+  'grey76': 'rgb(194, 194, 194)',
+  'grey77': 'rgb(196, 196, 196)',
+  'grey78': 'rgb(199, 199, 199)',
+  'grey79': 'rgb(201, 201, 201)',
+  'grey8': 'rgb(20, 20, 20)',
+  'grey80': 'rgb(204, 204, 204)',
+  'grey81': 'rgb(207, 207, 207)',
+  'grey82': 'rgb(209, 209, 209)',
+  'grey83': 'rgb(212, 212, 212)',
+  'grey84': 'rgb(214, 214, 214)',
+  'grey85': 'rgb(217, 217, 217)',
+  'grey86': 'rgb(219, 219, 219)',
+  'grey87': 'rgb(222, 222, 222)',
+  'grey88': 'rgb(224, 224, 224)',
+  'grey89': 'rgb(227, 227, 227)',
+  'grey9': 'rgb(23, 23, 23)',
+  'grey90': 'rgb(229, 229, 229)',
+  'grey91': 'rgb(232, 232, 232)',
+  'grey92': 'rgb(235, 235, 235)',
+  'grey93': 'rgb(237, 237, 237)',
+  'grey94': 'rgb(240, 240, 240)',
+  'grey95': 'rgb(242, 242, 242)',
+  'grey96': 'rgb(245, 245, 245)',
+  'grey97': 'rgb(247, 247, 247)',
+  'grey98': 'rgb(250, 250, 250)',
+  'grey99': 'rgb(252, 252, 252)',
+  'honeydew': 'rgb(240, 255, 240)',
+  'honeydew1': 'rgb(240, 255, 240)',
+  'honeydew2': 'rgb(224, 238, 224)',
+  'honeydew3': 'rgb(193, 205, 193)',
+  'honeydew4': 'rgb(131, 139, 131)',
+  'hotpink': 'rgb(255, 105, 180)',
+  'hotpink1': 'rgb(255, 110, 180)',
+  'hotpink2': 'rgb(238, 106, 167)',
+  'hotpink3': 'rgb(205, 96, 144)',
+  'hotpink4': 'rgb(139, 58, 98)',
+  'indianred': 'rgb(205, 92, 92)',
+  'indianred1': 'rgb(255, 106, 106)',
+  'indianred2': 'rgb(238, 99, 99)',
+  'indianred3': 'rgb(205, 85, 85)',
+  'indianred4': 'rgb(139, 58, 58)',
+  'ivory': 'rgb(255, 255, 240)',
+  'ivory1': 'rgb(255, 255, 240)',
+  'ivory2': 'rgb(238, 238, 224)',
+  'ivory3': 'rgb(205, 205, 193)',
+  'ivory4': 'rgb(139, 139, 131)',
+  'khaki': 'rgb(240, 230, 140)',
+  'khaki1': 'rgb(255, 246, 143)',
+  'khaki2': 'rgb(238, 230, 133)',
+  'khaki3': 'rgb(205, 198, 115)',
+  'khaki4': 'rgb(139, 134, 78)',
+  'lavender': 'rgb(230, 230, 250)',
+  'lavenderblush': 'rgb(255, 240, 245)',
+  'lavenderblush1': 'rgb(255, 240, 245)',
+  'lavenderblush2': 'rgb(238, 224, 229)',
+  'lavenderblush3': 'rgb(205, 193, 197)',
+  'lavenderblush4': 'rgb(139, 131, 134)',
+  'lawngreen': 'rgb(124, 252, 0)',
+  'lemonchiffon': 'rgb(255, 250, 205)',
+  'lemonchiffon1': 'rgb(255, 250, 205)',
+  'lemonchiffon2': 'rgb(238, 233, 191)',
+  'lemonchiffon3': 'rgb(205, 201, 165)',
+  'lemonchiffon4': 'rgb(139, 137, 112)',
+  'lightblue': 'rgb(173, 216, 230)',
+  'lightblue1': 'rgb(191, 239, 255)',
+  'lightblue2': 'rgb(178, 223, 238)',
+  'lightblue3': 'rgb(154, 192, 205)',
+  'lightblue4': 'rgb(104, 131, 139)',
+  'lightcoral': 'rgb(240, 128, 128)',
+  'lightcyan': 'rgb(224, 255, 255)',
+  'lightcyan1': 'rgb(224, 255, 255)',
+  'lightcyan2': 'rgb(209, 238, 238)',
+  'lightcyan3': 'rgb(180, 205, 205)',
+  'lightcyan4': 'rgb(122, 139, 139)',
+  'lightgoldenrod': 'rgb(238, 221, 130)',
+  'lightgoldenrod1': 'rgb(255, 236, 139)',
+  'lightgoldenrod2': 'rgb(238, 220, 130)',
+  'lightgoldenrod3': 'rgb(205, 190, 112)',
+  'lightgoldenrod4': 'rgb(139, 129, 76)',
+  'lightgoldenrodyellow': 'rgb(250, 250, 210)',
+  'lightgray': 'rgb(211, 211, 211)',
+  'lightgreen': 'rgb(144, 238, 144)',
+  'lightgrey': 'rgb(211, 211, 211)',
+  'lightpink': 'rgb(255, 182, 193)',
+  'lightpink1': 'rgb(255, 174, 185)',
+  'lightpink2': 'rgb(238, 162, 173)',
+  'lightpink3': 'rgb(205, 140, 149)',
+  'lightpink4': 'rgb(139, 95, 101)',
+  'lightsalmon': 'rgb(255, 160, 122)',
+  'lightsalmon1': 'rgb(255, 160, 122)',
+  'lightsalmon2': 'rgb(238, 149, 114)',
+  'lightsalmon3': 'rgb(205, 129, 98)',
+  'lightsalmon4': 'rgb(139, 87, 66)',
+  'lightseagreen': 'rgb(32, 178, 170)',
+  'lightskyblue': 'rgb(135, 206, 250)',
+  'lightskyblue1': 'rgb(176, 226, 255)',
+  'lightskyblue2': 'rgb(164, 211, 238)',
+  'lightskyblue3': 'rgb(141, 182, 205)',
+  'lightskyblue4': 'rgb(96, 123, 139)',
+  'lightslateblue': 'rgb(132, 112, 255)',
+  'lightslategray': 'rgb(119, 136, 153)',
+  'lightslategrey': 'rgb(119, 136, 153)',
+  'lightsteelblue': 'rgb(176, 196, 222)',
+  'lightsteelblue1': 'rgb(202, 225, 255)',
+  'lightsteelblue2': 'rgb(188, 210, 238)',
+  'lightsteelblue3': 'rgb(162, 181, 205)',
+  'lightsteelblue4': 'rgb(110, 123, 139)',
+  'lightyellow': 'rgb(255, 255, 224)',
+  'lightyellow1': 'rgb(255, 255, 224)',
+  'lightyellow2': 'rgb(238, 238, 209)',
+  'lightyellow3': 'rgb(205, 205, 180)',
+  'lightyellow4': 'rgb(139, 139, 122)',
+  'limegreen': 'rgb(50, 205, 50)',
+  'linen': 'rgb(250, 240, 230)',
+  'magenta': 'rgb(255, 0, 255)',
+  'magenta1': 'rgb(255, 0, 255)',
+  'magenta2': 'rgb(238, 0, 238)',
+  'magenta3': 'rgb(205, 0, 205)',
+  'magenta4': 'rgb(139, 0, 139)',
+  'maroon': 'rgb(176, 48, 96)',
+  'maroon1': 'rgb(255, 52, 179)',
+  'maroon2': 'rgb(238, 48, 167)',
+  'maroon3': 'rgb(205, 41, 144)',
+  'maroon4': 'rgb(139, 28, 98)',
+  'mediumaquamarine': 'rgb(102, 205, 170)',
+  'mediumblue': 'rgb(0, 0, 205)',
+  'mediumorchid': 'rgb(186, 85, 211)',
+  'mediumorchid1': 'rgb(224, 102, 255)',
+  'mediumorchid2': 'rgb(209, 95, 238)',
+  'mediumorchid3': 'rgb(180, 82, 205)',
+  'mediumorchid4': 'rgb(122, 55, 139)',
+  'mediumpurple': 'rgb(147, 112, 219)',
+  'mediumpurple1': 'rgb(171, 130, 255)',
+  'mediumpurple2': 'rgb(159, 121, 238)',
+  'mediumpurple3': 'rgb(137, 104, 205)',
+  'mediumpurple4': 'rgb(93, 71, 139)',
+  'mediumseagreen': 'rgb(60, 179, 113)',
+  'mediumslateblue': 'rgb(123, 104, 238)',
+  'mediumspringgreen': 'rgb(0, 250, 154)',
+  'mediumturquoise': 'rgb(72, 209, 204)',
+  'mediumvioletred': 'rgb(199, 21, 133)',
+  'midnightblue': 'rgb(25, 25, 112)',
+  'mintcream': 'rgb(245, 255, 250)',
+  'mistyrose': 'rgb(255, 228, 225)',
+  'mistyrose1': 'rgb(255, 228, 225)',
+  'mistyrose2': 'rgb(238, 213, 210)',
+  'mistyrose3': 'rgb(205, 183, 181)',
+  'mistyrose4': 'rgb(139, 125, 123)',
+  'moccasin': 'rgb(255, 228, 181)',
+  'navajowhite': 'rgb(255, 222, 173)',
+  'navajowhite1': 'rgb(255, 222, 173)',
+  'navajowhite2': 'rgb(238, 207, 161)',
+  'navajowhite3': 'rgb(205, 179, 139)',
+  'navajowhite4': 'rgb(139, 121, 94)',
+  'navy': 'rgb(0, 0, 128)',
+  'navyblue': 'rgb(0, 0, 128)',
+  'oldlace': 'rgb(253, 245, 230)',
+  'olivedrab': 'rgb(107, 142, 35)',
+  'olivedrab1': 'rgb(192, 255, 62)',
+  'olivedrab2': 'rgb(179, 238, 58)',
+  'olivedrab3': 'rgb(154, 205, 50)',
+  'olivedrab4': 'rgb(105, 139, 34)',
+  'orange': 'rgb(255, 165, 0)',
+  'orange1': 'rgb(255, 165, 0)',
+  'orange2': 'rgb(238, 154, 0)',
+  'orange3': 'rgb(205, 133, 0)',
+  'orange4': 'rgb(139, 90, 0)',
+  'orangered': 'rgb(255, 69, 0)',
+  'orangered1': 'rgb(255, 69, 0)',
+  'orangered2': 'rgb(238, 64, 0)',
+  'orangered3': 'rgb(205, 55, 0)',
+  'orangered4': 'rgb(139, 37, 0)',
+  'orchid': 'rgb(218, 112, 214)',
+  'orchid1': 'rgb(255, 131, 250)',
+  'orchid2': 'rgb(238, 122, 233)',
+  'orchid3': 'rgb(205, 105, 201)',
+  'orchid4': 'rgb(139, 71, 137)',
+  'palegoldenrod': 'rgb(238, 232, 170)',
+  'palegreen': 'rgb(152, 251, 152)',
+  'palegreen1': 'rgb(154, 255, 154)',
+  'palegreen2': 'rgb(144, 238, 144)',
+  'palegreen3': 'rgb(124, 205, 124)',
+  'palegreen4': 'rgb(84, 139, 84)',
+  'paleturquoise': 'rgb(175, 238, 238)',
+  'paleturquoise1': 'rgb(187, 255, 255)',
+  'paleturquoise2': 'rgb(174, 238, 238)',
+  'paleturquoise3': 'rgb(150, 205, 205)',
+  'paleturquoise4': 'rgb(102, 139, 139)',
+  'palevioletred': 'rgb(219, 112, 147)',
+  'palevioletred1': 'rgb(255, 130, 171)',
+  'palevioletred2': 'rgb(238, 121, 159)',
+  'palevioletred3': 'rgb(205, 104, 137)',
+  'palevioletred4': 'rgb(139, 71, 93)',
+  'papayawhip': 'rgb(255, 239, 213)',
+  'peachpuff': 'rgb(255, 218, 185)',
+  'peachpuff1': 'rgb(255, 218, 185)',
+  'peachpuff2': 'rgb(238, 203, 173)',
+  'peachpuff3': 'rgb(205, 175, 149)',
+  'peachpuff4': 'rgb(139, 119, 101)',
+  'peru': 'rgb(205, 133, 63)',
+  'pink': 'rgb(255, 192, 203)',
+  'pink1': 'rgb(255, 181, 197)',
+  'pink2': 'rgb(238, 169, 184)',
+  'pink3': 'rgb(205, 145, 158)',
+  'pink4': 'rgb(139, 99, 108)',
+  'plum': 'rgb(221, 160, 221)',
+  'plum1': 'rgb(255, 187, 255)',
+  'plum2': 'rgb(238, 174, 238)',
+  'plum3': 'rgb(205, 150, 205)',
+  'plum4': 'rgb(139, 102, 139)',
+  'powderblue': 'rgb(176, 224, 230)',
+  'purple': 'rgb(160, 32, 240)',
+  'purple1': 'rgb(155, 48, 255)',
+  'purple2': 'rgb(145, 44, 238)',
+  'purple3': 'rgb(125, 38, 205)',
+  'purple4': 'rgb(85, 26, 139)',
+  'red': 'rgb(255, 0, 0)',
+  'red1': 'rgb(255, 0, 0)',
+  'red2': 'rgb(238, 0, 0)',
+  'red3': 'rgb(205, 0, 0)',
+  'red4': 'rgb(139, 0, 0)',
+  'rosybrown': 'rgb(188, 143, 143)',
+  'rosybrown1': 'rgb(255, 193, 193)',
+  'rosybrown2': 'rgb(238, 180, 180)',
+  'rosybrown3': 'rgb(205, 155, 155)',
+  'rosybrown4': 'rgb(139, 105, 105)',
+  'royalblue': 'rgb(65, 105, 225)',
+  'royalblue1': 'rgb(72, 118, 255)',
+  'royalblue2': 'rgb(67, 110, 238)',
+  'royalblue3': 'rgb(58, 95, 205)',
+  'royalblue4': 'rgb(39, 64, 139)',
+  'saddlebrown': 'rgb(139, 69, 19)',
+  'salmon': 'rgb(250, 128, 114)',
+  'salmon1': 'rgb(255, 140, 105)',
+  'salmon2': 'rgb(238, 130, 98)',
+  'salmon3': 'rgb(205, 112, 84)',
+  'salmon4': 'rgb(139, 76, 57)',
+  'sandybrown': 'rgb(244, 164, 96)',
+  'seagreen': 'rgb(46, 139, 87)',
+  'seagreen1': 'rgb(84, 255, 159)',
+  'seagreen2': 'rgb(78, 238, 148)',
+  'seagreen3': 'rgb(67, 205, 128)',
+  'seagreen4': 'rgb(46, 139, 87)',
+  'seashell': 'rgb(255, 245, 238)',
+  'seashell1': 'rgb(255, 245, 238)',
+  'seashell2': 'rgb(238, 229, 222)',
+  'seashell3': 'rgb(205, 197, 191)',
+  'seashell4': 'rgb(139, 134, 130)',
+  'sienna': 'rgb(160, 82, 45)',
+  'sienna1': 'rgb(255, 130, 71)',
+  'sienna2': 'rgb(238, 121, 66)',
+  'sienna3': 'rgb(205, 104, 57)',
+  'sienna4': 'rgb(139, 71, 38)',
+  'skyblue': 'rgb(135, 206, 235)',
+  'skyblue1': 'rgb(135, 206, 255)',
+  'skyblue2': 'rgb(126, 192, 238)',
+  'skyblue3': 'rgb(108, 166, 205)',
+  'skyblue4': 'rgb(74, 112, 139)',
+  'slateblue': 'rgb(106, 90, 205)',
+  'slateblue1': 'rgb(131, 111, 255)',
+  'slateblue2': 'rgb(122, 103, 238)',
+  'slateblue3': 'rgb(105, 89, 205)',
+  'slateblue4': 'rgb(71, 60, 139)',
+  'slategray': 'rgb(112, 128, 144)',
+  'slategray1': 'rgb(198, 226, 255)',
+  'slategray2': 'rgb(185, 211, 238)',
+  'slategray3': 'rgb(159, 182, 205)',
+  'slategray4': 'rgb(108, 123, 139)',
+  'slategrey': 'rgb(112, 128, 144)',
+  'snow': 'rgb(255, 250, 250)',
+  'snow1': 'rgb(255, 250, 250)',
+  'snow2': 'rgb(238, 233, 233)',
+  'snow3': 'rgb(205, 201, 201)',
+  'snow4': 'rgb(139, 137, 137)',
+  'springgreen': 'rgb(0, 255, 127)',
+  'springgreen1': 'rgb(0, 255, 127)',
+  'springgreen2': 'rgb(0, 238, 118)',
+  'springgreen3': 'rgb(0, 205, 102)',
+  'springgreen4': 'rgb(0, 139, 69)',
+  'steelblue': 'rgb(70, 130, 180)',
+  'steelblue1': 'rgb(99, 184, 255)',
+  'steelblue2': 'rgb(92, 172, 238)',
+  'steelblue3': 'rgb(79, 148, 205)',
+  'steelblue4': 'rgb(54, 100, 139)',
+  'tan': 'rgb(210, 180, 140)',
+  'tan1': 'rgb(255, 165, 79)',
+  'tan2': 'rgb(238, 154, 73)',
+  'tan3': 'rgb(205, 133, 63)',
+  'tan4': 'rgb(139, 90, 43)',
+  'thistle': 'rgb(216, 191, 216)',
+  'thistle1': 'rgb(255, 225, 255)',
+  'thistle2': 'rgb(238, 210, 238)',
+  'thistle3': 'rgb(205, 181, 205)',
+  'thistle4': 'rgb(139, 123, 139)',
+  'tomato': 'rgb(255, 99, 71)',
+  'tomato1': 'rgb(255, 99, 71)',
+  'tomato2': 'rgb(238, 92, 66)',
+  'tomato3': 'rgb(205, 79, 57)',
+  'tomato4': 'rgb(139, 54, 38)',
+  'turquoise': 'rgb(64, 224, 208)',
+  'turquoise1': 'rgb(0, 245, 255)',
+  'turquoise2': 'rgb(0, 229, 238)',
+  'turquoise3': 'rgb(0, 197, 205)',
+  'turquoise4': 'rgb(0, 134, 139)',
+  'violet': 'rgb(238, 130, 238)',
+  'violetred': 'rgb(208, 32, 144)',
+  'violetred1': 'rgb(255, 62, 150)',
+  'violetred2': 'rgb(238, 58, 140)',
+  'violetred3': 'rgb(205, 50, 120)',
+  'violetred4': 'rgb(139, 34, 82)',
+  'wheat': 'rgb(245, 222, 179)',
+  'wheat1': 'rgb(255, 231, 186)',
+  'wheat2': 'rgb(238, 216, 174)',
+  'wheat3': 'rgb(205, 186, 150)',
+  'wheat4': 'rgb(139, 126, 102)',
+  'white': 'rgb(255, 255, 255)',
+  'whitesmoke': 'rgb(245, 245, 245)',
+  'yellow': 'rgb(255, 255, 0)',
+  'yellow1': 'rgb(255, 255, 0)',
+  'yellow2': 'rgb(238, 238, 0)',
+  'yellow3': 'rgb(205, 205, 0)',
+  'yellow4': 'rgb(139, 139, 0)',
+  'yellowgreen': 'rgb(154, 205, 50)'
 };
 // SOURCE FILE: libdot/js/lib_f.js
 // Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
@@ -1316,19 +1322,20 @@
  */
 lib.f.replaceVars = function(str, vars) {
   return str.replace(/%([a-z]*)\(([^\)]+)\)/gi, function(match, fn, varname) {
-      if (typeof vars[varname] == 'undefined')
-        throw 'Unknown variable: ' + varname;
+    if (typeof vars[varname] == 'undefined')
+      throw 'Unknown variable: ' + varname;
 
-      var rv = vars[varname];
+    var rv = vars[varname];
 
-      if (fn in lib.f.replaceVars.functions) {
-        rv = lib.f.replaceVars.functions[fn](rv);
-      } else if (fn) {
-        throw 'Unknown escape function: ' + fn;
-      }
+    if (fn in lib.f.replaceVars.functions) {
+      rv = lib.f.replaceVars.functions[fn](rv);
+    }
+    else if (fn) {
+      throw 'Unknown escape function: ' + fn;
+    }
 
-      return rv;
-    });
+    return rv;
+  });
 };
 
 /**
@@ -1348,7 +1355,9 @@
       "'": '&#39;'
     };
 
-    return str.replace(/[<>&\"\']/g, function(m) { return map[m] });
+    return str.replace(/[<>&\"\']/g, function(m) {
+      return map[m];
+    });
   }
 };
 
@@ -1361,10 +1370,11 @@
 lib.f.getAcceptLanguages = function(callback) {
   if (lib.f.getAcceptLanguages.chromeSupported()) {
     chrome.i18n.getAcceptLanguages(callback);
-  } else {
+  }
+  else {
     setTimeout(function() {
-        callback([navigator.language.replace(/-/g, '_')]);
-      }, 0);
+      callback([navigator.language.replace(/-/g, '_')]);
+    }, 0);
   }
 };
 
@@ -1481,7 +1491,7 @@
   return f.whitespace.substr(0, length);
 };
 
- /**
+/**
  * Ensure that a function is called within a certain time limit.
  *
  * Simple usage looks like this...
@@ -1571,7 +1581,8 @@
 
   try {
     throw new Error();
-  } catch (ex) {
+  }
+  catch (ex) {
     stackArray = ex.stack.split('\n');
   }
 
@@ -1594,12 +1605,13 @@
  * @param {number} denominator
  * @return {number}
  */
-lib.f.smartFloorDivide = function(numerator,  denominator) {
+lib.f.smartFloorDivide = function(numerator, denominator) {
   var val = numerator / denominator;
   var ceiling = Math.ceil(val);
   if (ceiling - val < .0001) {
     return ceiling;
-  } else {
+  }
+  else {
     return Math.floor(val);
   }
 };
@@ -1626,7 +1638,9 @@
  */
 lib.MessageManager = function(languages) {
   this.languages_ = languages.map(
-      function(el) { return el.replace(/-/g, '_') });
+    function(el) {
+      return el.replace(/-/g, '_');
+    });
 
   if (this.languages_.indexOf('en') == -1)
     this.languages_.unshift('en');
@@ -1646,13 +1660,14 @@
 
     if (!def.placeholders) {
       this.messages[key] = def.message;
-    } else {
+    }
+    else {
       // Replace "$NAME$" placeholders with "$1", etc.
       this.messages[key] = def.message.replace(
-          /\$([a-z][^\s\$]+)\$/ig,
-          function(m, name) {
-            return defs[key].placeholders[name.toLowerCase()].content;
-          });
+        /\$([a-z][^\s\$]+)\$/ig,
+        function(m, name) {
+          return defs[key].placeholders[name.toLowerCase()].content;
+        });
     }
   }
 };
@@ -1668,7 +1683,7 @@
  *     loaded.
  */
 lib.MessageManager.prototype.findAndLoadMessages = function(
-    pattern, onComplete) {
+  pattern, onComplete) {
   var languages = this.languages_.concat();
   var loaded = [];
   var failed = [];
@@ -1676,21 +1691,23 @@
   function onLanguageComplete(state) {
     if (state) {
       loaded = languages.shift();
-    } else {
+    }
+    else {
       failed = languages.shift();
     }
 
     if (languages.length) {
       tryNextLanguage();
-    } else {
+    }
+    else {
       onComplete(loaded, failed);
     }
   }
 
   var tryNextLanguage = function() {
     this.loadMessages(this.replaceReferences(pattern, languages),
-                      onLanguageComplete.bind(this, true),
-                      onLanguageComplete.bind(this, false));
+      onLanguageComplete.bind(this, true),
+      onLanguageComplete.bind(this, false));
   }.bind(this);
 
   tryNextLanguage();
@@ -1700,7 +1717,7 @@
  * Load messages from a messages.json file.
  */
 lib.MessageManager.prototype.loadMessages = function(
-    url, onSuccess, opt_onError) {
+  url, onSuccess, opt_onError) {
   var xhr = new XMLHttpRequest();
 
   xhr.onloadend = function() {
@@ -1726,16 +1743,16 @@
  * @param {Array} args Array containing the argument values.
  */
 lib.MessageManager.replaceReferences = function(msg, args) {
-  return msg.replace(/\$(\d+)/g, function (m, index) {
-      return args[index - 1];
-    });
+  return msg.replace(/\$(\d+)/g, function(m, index) {
+    return args[index - 1];
+  });
 };
 
 /**
  * Per-instance copy of replaceReferences.
  */
 lib.MessageManager.prototype.replaceReferences =
-    lib.MessageManager.replaceReferences;
+  lib.MessageManager.replaceReferences;
 
 /**
  * Get a message by name, optionally replacing arguments too.
@@ -1751,7 +1768,8 @@
   if (msgname in this.messages) {
     message = this.messages[msgname];
 
-  } else {
+  }
+  else {
     if (window.chrome.i18n)
       message = chrome.i18n.getMessage(msgname);
 
@@ -1793,7 +1811,9 @@
 lib.MessageManager.prototype.processI18nAttributes = function(dom) {
   // Convert the "lower-and-dashes" attribute names into
   // "UPPER_AND_UNDER" style.
-  function thunk(str) { return str.replace(/-/g, '_').toUpperCase() }
+  function thunk(str) {
+    return str.replace(/-/g, '_').toUpperCase();
+  }
 
   var nodes = dom.querySelectorAll('[i18n]');
 
@@ -1806,9 +1826,10 @@
 
     try {
       i18n = JSON.parse(i18n);
-    } catch (ex) {
+    }
+    catch (ex) {
       console.error('Can\'t parse ' + node.tagName + '#' + node.id + ': ' +
-                    i18n);
+        i18n);
       throw ex;
     }
 
@@ -1820,7 +1841,8 @@
       var msg = this.get(msgname);
       if (key == '_') {
         node.textContent = msg;
-      } else {
+      }
+      else {
         node.setAttribute(key, msg);
       }
     }
@@ -1913,7 +1935,7 @@
  * A local copy of the DEFAULT_VALUE constant to make it less verbose.
  */
 lib.PreferenceManager.Record.prototype.DEFAULT_VALUE =
-    lib.PreferenceManager.prototype.DEFAULT_VALUE;
+  lib.PreferenceManager.prototype.DEFAULT_VALUE;
 
 /**
  * Register a callback to be invoked when this preference changes.
@@ -2011,32 +2033,34 @@
   }
 
   var keys = Object.keys(this.prefRecords_).map(
-      function(el) { return this.prefix + el }.bind(this));
+    function(el) {
+      return this.prefix + el;
+    }.bind(this));
 
   if (this.trace)
     console.log('Preferences read: ' + this.prefix);
 
   this.storage.getItems(keys, function(items) {
-      var prefixLength = this.prefix.length;
+    var prefixLength = this.prefix.length;
 
-      for (var key in items) {
-        var value = items[key];
-        var name = key.substr(prefixLength);
-        var needSync = (name in this.childLists_ &&
-                        (JSON.stringify(value) !=
-                         JSON.stringify(this.prefRecords_[name].currentValue)));
+    for (var key in items) {
+      var value = items[key];
+      var name = key.substr(prefixLength);
+      var needSync = (name in this.childLists_ &&
+        (JSON.stringify(value) !=
+          JSON.stringify(this.prefRecords_[name].currentValue)));
 
-        this.prefRecords_[name].currentValue = value;
+      this.prefRecords_[name].currentValue = value;
 
-        if (needSync) {
-          pendingChildren++;
-          this.syncChildList(name, onChildComplete);
-        }
+      if (needSync) {
+        pendingChildren++;
+        this.syncChildList(name, onChildComplete);
       }
+    }
 
-      if (pendingChildren == 0 && opt_callback)
-        setTimeout(opt_callback);
-    }.bind(this));
+    if (pendingChildren == 0 && opt_callback)
+      setTimeout(opt_callback);
+  }.bind(this));
 };
 
 /**
@@ -2055,14 +2079,15 @@
  *     PreferenceManager as parameters.
  */
 lib.PreferenceManager.prototype.definePreference = function(
-    name, value, opt_onChange) {
+  name, value, opt_onChange) {
 
   var record = this.prefRecords_[name];
   if (record) {
     this.changeDefault(name, value);
-  } else {
+  }
+  else {
     record = this.prefRecords_[name] =
-        new lib.PreferenceManager.Record(name, value);
+      new lib.PreferenceManager.Record(name, value);
   }
 
   if (opt_onChange)
@@ -2101,11 +2126,11 @@
  *     preferences.
  */
 lib.PreferenceManager.prototype.defineChildren = function(
-    listName, childFactory) {
+  listName, childFactory) {
 
   // Define a preference to hold the ordered list of child ids.
   this.definePreference(listName, [],
-                        this.onChildListChange_.bind(this, listName));
+    this.onChildListChange_.bind(this, listName));
   this.childFactories_[listName] = childFactory;
   this.childLists_[listName] = {};
 };
@@ -2183,7 +2208,7 @@
  * @param {string} opt_id Optional id to override the generated id.
  */
 lib.PreferenceManager.prototype.createChild = function(listName, opt_hint,
-                                                       opt_id) {
+  opt_id) {
   var ids = this.get(listName);
   var id;
 
@@ -2192,7 +2217,8 @@
     if (ids.indexOf(id) != -1)
       throw new Error('Duplicate child: ' + listName + ': ' + id);
 
-  } else {
+  }
+  else {
     // Pick a random, unique 4-digit hex identifier for the new profile.
     while (!id || ids.indexOf(id) != -1) {
       id = Math.floor(Math.random() * 0xffff + 1).toString(16);
@@ -2292,7 +2318,8 @@
   for (var i = 0; i < a.length; i++) {
     if (b.indexOf(a[i]) != -1) {
       rv.common[a[i]] = true;
-    } else {
+    }
+    else {
       rv.added[a[i]] = true;
     }
   }
@@ -2320,9 +2347,10 @@
  *     is complete.
  */
 lib.PreferenceManager.prototype.syncChildList = function(
-    listName, opt_callback) {
+  listName, opt_callback) {
 
   var pendingChildren = 0;
+
   function onChildStorage() {
     if (--pendingChildren == 0 && opt_callback)
       opt_callback();
@@ -2408,7 +2436,7 @@
   }
 
   var keys = Object.keys(this.prefRecords_).map(function(el) {
-      return this.prefix + el;
+    return this.prefix + el;
   }.bind(this));
 
   this.storage.removeItems(keys);
@@ -2432,7 +2460,7 @@
 lib.PreferenceManager.prototype.diff = function(a, b) {
   // If the types are different, or the type is not a simple primitive one.
   if ((typeof a) !== (typeof b) ||
-      !(/^(undefined|boolean|number|string)$/.test(typeof a))) {
+    !(/^(undefined|boolean|number|string)$/.test(typeof a))) {
     return true;
   }
 
@@ -2507,7 +2535,8 @@
   if (this.diff(record.defaultValue, newValue)) {
     record.currentValue = newValue;
     this.storage.setItem(this.prefix + name, newValue);
-  } else {
+  }
+  else {
     record.currentValue = this.DEFAULT_VALUE;
     this.storage.removeItem(this.prefix + name);
   }
@@ -2550,10 +2579,14 @@
       var childIds = this.get(name);
       for (var i = 0; i < childIds.length; i++) {
         var id = childIds[i];
-        rv[name].push({id: id, json: this.getChild(name, id).exportAsJson()});
+        rv[name].push({
+          id: id,
+          json: this.getChild(name, id).exportAsJson()
+        });
       }
 
-    } else {
+    }
+    else {
       var record = this.prefRecords_[name];
       if (record.currentValue != this.DEFAULT_VALUE)
         rv[name] = record.currentValue;
@@ -2582,7 +2615,8 @@
         childPrefManager.importFromJson(childList[i].json);
       }
 
-    } else {
+    }
+    else {
       this.set(name, json[name]);
     }
   }
@@ -2622,7 +2656,8 @@
     if (this.diff(currentValue, newValue)) {
       if (typeof newValue == 'undefined') {
         record.currentValue = record.DEFAULT_VALUE;
-      } else {
+      }
+      else {
         record.currentValue = newValue;
       }
 
@@ -2895,8 +2930,8 @@
     return;
 
   // IE throws an exception if JSON.parse is given an empty string.
-  var prevValue = e.oldValue ? JSON.parse(e.oldValue) : "";
-  var curValue = e.newValue ? JSON.parse(e.newValue) : "";
+  var prevValue = e.oldValue ? JSON.parse(e.oldValue) : '';
+  var curValue = e.newValue ? JSON.parse(e.newValue) : '';
   var o = {};
   o[e.key] = {
     oldValue: prevValue,
@@ -2955,7 +2990,8 @@
   if (typeof value == 'string') {
     try {
       value = JSON.parse(value);
-    } catch (e) {
+    }
+    catch (e) {
       // If we can't parse the value, just return it unparsed.
     }
   }
@@ -2979,11 +3015,13 @@
     if (typeof value == 'string') {
       try {
         rv[key] = JSON.parse(value);
-      } catch (e) {
+      }
+      catch (e) {
         // If we can't parse the value, just return it unparsed.
         rv[key] = value;
       }
-    } else {
+    }
+    else {
       keys.splice(i, 1);
     }
   }
@@ -3005,7 +3043,7 @@
   this.storage_.setItem(key, JSON.stringify(value));
 
   if (opt_callback)
-  setTimeout(opt_callback, 0);
+    setTimeout(opt_callback, 0);
 };
 
 /**
@@ -3022,7 +3060,7 @@
   }
 
   if (opt_callback)
-  setTimeout(opt_callback, 0);
+    setTimeout(opt_callback, 0);
 };
 
 /**
@@ -3037,7 +3075,7 @@
   this.storage_.removeItem(key);
 
   if (opt_callback)
-  setTimeout(opt_callback, 0);
+    setTimeout(opt_callback, 0);
 };
 
 /**
@@ -3054,7 +3092,7 @@
   }
 
   if (opt_callback)
-  setTimeout(opt_callback, 0);
+    setTimeout(opt_callback, 0);
 };
 // SOURCE FILE: libdot/js/lib_storage_memory.js
 // Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
@@ -3102,7 +3140,10 @@
 lib.Storage.Memory.prototype.clear = function(opt_callback) {
   var e = {};
   for (var key in this.storage_) {
-    e[key] = {oldValue: this.storage_[key], newValue: (void 0)};
+    e[key] = {
+      oldValue: this.storage_[key],
+      newValue: (void 0)
+    };
   }
 
   this.storage_ = {};
@@ -3130,7 +3171,8 @@
   if (typeof value == 'string') {
     try {
       value = JSON.parse(value);
-    } catch (e) {
+    }
+    catch (e) {
       // If we can't parse the value, just return it unparsed.
     }
   }
@@ -3154,11 +3196,13 @@
     if (typeof value == 'string') {
       try {
         rv[key] = JSON.parse(value);
-      } catch (e) {
+      }
+      catch (e) {
         // If we can't parse the value, just return it unparsed.
         rv[key] = value;
       }
-    } else {
+    }
+    else {
       keys.splice(i, 1);
     }
   }
@@ -3181,7 +3225,10 @@
   this.storage_[key] = JSON.stringify(value);
 
   var e = {};
-  e[key] = {oldValue: oldValue, newValue: value};
+  e[key] = {
+    oldValue: oldValue,
+    newValue: value
+  };
 
   setTimeout(function() {
     for (var i = 0; i < this.observers_.length; i++) {
@@ -3190,7 +3237,7 @@
   }.bind(this), 0);
 
   if (opt_callback)
-  setTimeout(opt_callback, 0);
+    setTimeout(opt_callback, 0);
 };
 
 /**
@@ -3205,7 +3252,10 @@
   var e = {};
 
   for (var key in obj) {
-    e[key] = {oldValue: this.storage_[key], newValue: obj[key]};
+    e[key] = {
+      oldValue: this.storage_[key],
+      newValue: obj[key]
+    };
     this.storage_[key] = JSON.stringify(obj[key]);
   }
 
@@ -3216,7 +3266,7 @@
   }.bind(this));
 
   if (opt_callback)
-  setTimeout(opt_callback, 0);
+    setTimeout(opt_callback, 0);
 };
 
 /**
@@ -3231,7 +3281,7 @@
   delete this.storage_[key];
 
   if (opt_callback)
-  setTimeout(opt_callback, 0);
+    setTimeout(opt_callback, 0);
 };
 
 /**
@@ -3248,7 +3298,7 @@
   }
 
   if (opt_callback)
-  setTimeout(opt_callback, 0);
+    setTimeout(opt_callback, 0);
 };
 // SOURCE FILE: libdot/js/lib_test_manager.js
 // Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
@@ -3284,7 +3334,7 @@
  */
 lib.TestManager = function(opt_log) {
   this.log = opt_log || new lib.TestManager.Log();
-}
+};
 
 /**
  * Create a new test run object for this test manager.
@@ -3383,7 +3433,8 @@
 lib.TestManager.Log.prototype.print = function(str) {
   if (this.pending_) {
     this.pending_ += str;
-  } else {
+  }
+  else {
     this.pending_ = this.prefix_ + str;
   }
 };
@@ -3487,7 +3538,9 @@
   ctor.getTestList = lib.TestManager.Suite.getTestList;
   ctor.testList_ = [];
   ctor.testMap_ = {};
-  ctor.prototype = { __proto__: lib.TestManager.Suite.prototype };
+  ctor.prototype = {
+    __proto__: lib.TestManager.Suite.prototype
+  };
 
   lib.TestManager.Suite.subclasses.push(ctor);
 
@@ -3675,9 +3728,9 @@
 lib.TestManager.Test.prototype.run = function(result) {
   try {
     // Tests are applied to the parent lib.TestManager.Suite subclass.
-    this.testFunction_.apply(result.suite,
-                             [result, result.testRun.cx]);
-  } catch (ex) {
+    this.testFunction_.apply(result.suite, [result, result.testRun.cx]);
+  }
+  catch (ex) {
     if (ex instanceof lib.TestManager.Result.TestComplete)
       return;
 
@@ -3686,7 +3739,8 @@
     if (ex.stack) {
       if (ex.stack instanceof Array) {
         result.println(ex.stack.join('\n'));
-      } else {
+      }
+      else {
         result.println(ex.stack);
       }
     }
@@ -3782,7 +3836,7 @@
 };
 
 lib.TestManager.TestRun.prototype.selectSuite = function(
-    suiteClass, opt_pattern) {
+  suiteClass, opt_pattern) {
   var pattern = opt_pattern || this.ALL_TESTS;
   var selectCount = 0;
   var testList = suiteClass.getTestList();
@@ -3795,7 +3849,8 @@
       if (pattern instanceof RegExp) {
         if (!pattern.test(test.testName))
           continue;
-      } else if (test.testName != pattern) {
+      }
+      else if (test.testName != pattern) {
         continue;
       }
     }
@@ -3825,7 +3880,7 @@
 
   for (var i = 0; i < lib.TestManager.Suite.subclasses.length; i++) {
     selectCount += this.selectSuite(lib.TestManager.Suite.subclasses[i],
-                                    pattern);
+      pattern);
   }
 
   if (!selectCount) {
@@ -3840,10 +3895,10 @@
  * that would otherwise go uncaught.
  */
 lib.TestManager.TestRun.prototype.onUncaughtException_ = function(
-    message, file, line) {
+  message, file, line) {
 
   if (message.indexOf('Uncaught lib.TestManager.Result.TestComplete') == 0 ||
-      message.indexOf('status: passed') != -1) {
+    message.indexOf('status: passed') != -1) {
     // This is a result.pass() or result.fail() call from a callback.  We're
     // already going to deal with it as part of the completeTest_() call
     // that raised it.  We can safely squelch this error message.
@@ -3864,7 +3919,7 @@
     when = 'after';
 
   this.log.println('Uncaught exception ' + when + ' test case: ' +
-                   this.currentResult.test.fullName);
+    this.currentResult.test.fullName);
   this.log.println(message + ', ' + file + ':' + line);
 
   this.currentResult.completeTest_(this.currentResult.FAILED, false);
@@ -3884,7 +3939,7 @@
  *     this function.
  */
 lib.TestManager.TestRun.prototype.onTestRunComplete_ = function(
-    opt_skipTimeout) {
+  opt_skipTimeout) {
   if (!opt_skipTimeout) {
     // The final test may have left a lingering setTimeout(..., 0), or maybe
     // poked at the DOM in a way that will trigger a event to fire at the end
@@ -3898,8 +3953,8 @@
 
   this.log.popPrefix();
   this.log.println('} ' + this.passes.length + ' passed, ' +
-                   this.failures.length + ' failed, '  +
-                   this.msToSeconds_(this.duration));
+    this.failures.length + ' failed, ' +
+    this.msToSeconds_(this.duration));
   this.log.println('');
 
   this.summarize();
@@ -3919,25 +3974,28 @@
   try {
     this.testManager.testPostamble(result, this.cx);
     result.suite.postamble(result, this.ctx);
-  } catch (ex) {
+  }
+  catch (ex) {
     this.log.println('Unexpected exception in postamble: ' +
-                     (ex.stack ? ex.stack : ex));
+      (ex.stack ? ex.stack : ex));
     this.panic = true;
   }
 
   this.log.popPrefix();
   this.log.print('} ' + result.status + ', ' +
-                 this.msToSeconds_(result.duration));
+    this.msToSeconds_(result.duration));
   this.log.flush();
 
   if (result.status == result.FAILED) {
     this.failures.push(result);
     this.currentSuite = null;
-  } else if (result.status == result.PASSED) {
+  }
+  else if (result.status == result.PASSED) {
     this.passes.push(result);
-  } else {
+  }
+  else {
     this.log.println('Unknown result status: ' + result.test.fullName + ': ' +
-                     result.status);
+      result.status);
     return this.panic = true;
   }
 
@@ -3964,9 +4022,9 @@
  *     time around.
  */
 lib.TestManager.TestRun.prototype.onResultReComplete = function(
-    result, lateStatus) {
+  result, lateStatus) {
   this.log.println('Late complete for test: ' + result.test.fullName + ': ' +
-                   lateStatus);
+    lateStatus);
 
   // Consider any late completion a failure, even if it's a double-pass, since
   // it's a misuse of the testing API.
@@ -4000,7 +4058,8 @@
       this.log.println('Initializing suite: ' + test.suiteClass.suiteName);
       suite = new test.suiteClass(this.testManager, this.cx);
     }
-  } catch (ex) {
+  }
+  catch (ex) {
     // If test suite setup fails we're not even going to try to run the tests.
     this.log.println('Exception during setup: ' + (ex.stack ? ex.stack : ex));
     this.panic = true;
@@ -4017,9 +4076,10 @@
     suite.preamble(this.currentResult, this.cx);
 
     this.testQueue_.shift();
-  } catch (ex) {
+  }
+  catch (ex) {
     this.log.println('Unexpected exception during test preamble: ' +
-                     (ex.stack ? ex.stack : ex));
+      (ex.stack ? ex.stack : ex));
     this.log.popPrefix();
     this.log.println('}');
 
@@ -4030,11 +4090,12 @@
 
   try {
     this.currentResult.run();
-  } catch (ex) {
+  }
+  catch (ex) {
     // Result.run() should catch test exceptions and turn them into failures.
     // If we got here, it means there is trouble in the testing framework.
     this.log.println('Unexpected exception during test run: ' +
-                     (ex.stack ? ex.stack : ex));
+      (ex.stack ? ex.stack : ex));
     this.panic = true;
   }
 };
@@ -4086,7 +4147,7 @@
 
   if (this.testQueue_.length) {
     this.log.println('Test run incomplete: ' + this.testQueue_.length +
-                     ' test(s) were not run.');
+      ' test(s) were not run.');
   }
 };
 
@@ -4147,8 +4208,8 @@
  * Possible values for this.status.
  */
 lib.TestManager.Result.prototype.PENDING = 'pending';
-lib.TestManager.Result.prototype.FAILED  = 'FAILED';
-lib.TestManager.Result.prototype.PASSED  = 'passed';
+lib.TestManager.Result.prototype.FAILED = 'FAILED';
+lib.TestManager.Result.prototype.PASSED = 'passed';
 
 /**
  * Exception thrown when a test completes (pass or fail), to ensure no more of
@@ -4160,8 +4221,8 @@
 
 lib.TestManager.Result.TestComplete.prototype.toString = function() {
   return 'lib.TestManager.Result.TestComplete: ' + this.result.test.fullName +
-      ', status: ' + this.result.status;
-}
+    ', status: ' + this.result.status;
+};
 
 /**
  * Start the test associated with this result.
@@ -4240,7 +4301,8 @@
     this.status = status;
 
     this.testRun.onResultComplete(this);
-  } else {
+  }
+  else {
     this.testRun.onResultReComplete(this, status);
   }
 
@@ -4280,19 +4342,22 @@
  *     of the caller.
  */
 lib.TestManager.Result.prototype.assertEQ = function(
-    actual, expected, opt_name) {
+  actual, expected, opt_name) {
   // Utility function to pretty up the log.
   function format(value) {
     if (typeof value == 'number')
       return value;
 
     var str = String(value);
-    var ary = str.split('\n').map(function (e) { return JSON.stringify(e) });
+    var ary = str.split('\n').map(function(e) {
+      return JSON.stringify(e);
+    });
     if (ary.length > 1) {
       // If the string has newlines, start it off on its own line so that
       // it's easier to compare against another string with newlines.
       return '\n' + ary.join('\n');
-    } else {
+    }
+    else {
       return ary.join('\n');
     }
   }
@@ -4308,7 +4373,7 @@
   var name = opt_name ? '[' + opt_name + ']' : '';
 
   this.fail('assertEQ' + name + ': ' + this.getCallerLocation_(1) + ': ' +
-            format(actual) + ' !== ' + format(expected));
+    format(actual) + ' !== ' + format(expected));
 };
 
 /**
@@ -4332,7 +4397,7 @@
   var name = opt_name ? '[' + opt_name + ']' : '';
 
   this.fail('assert' + name + ': ' + this.getCallerLocation_(1) + ': ' +
-            String(actual));
+    String(actual));
 };
 
 /**
@@ -4348,7 +4413,8 @@
 lib.TestManager.Result.prototype.getCallerLocation_ = function(frameIndex) {
   try {
     throw new Error();
-  } catch (ex) {
+  }
+  catch (ex) {
     var frame = ex.stack.split('\n')[frameIndex + 2];
     var ary = frame.match(/([^/]+:\d+):\d+\)?$/);
     return ary ? ary[1] : '???';
@@ -4425,30 +4491,37 @@
     if (this.bytesLeft == 0) {
       if (c <= 0x7F) {
         ret += str.charAt(i);
-      } else if (0xC0 <= c && c <= 0xDF) {
+      }
+      else if (0xC0 <= c && c <= 0xDF) {
         this.codePoint = c - 0xC0;
         this.bytesLeft = 1;
         this.lowerBound = 0x80;
-      } else if (0xE0 <= c && c <= 0xEF) {
+      }
+      else if (0xE0 <= c && c <= 0xEF) {
         this.codePoint = c - 0xE0;
         this.bytesLeft = 2;
         this.lowerBound = 0x800;
-      } else if (0xF0 <= c && c <= 0xF7) {
+      }
+      else if (0xF0 <= c && c <= 0xF7) {
         this.codePoint = c - 0xF0;
         this.bytesLeft = 3;
         this.lowerBound = 0x10000;
-      } else if (0xF8 <= c && c <= 0xFB) {
+      }
+      else if (0xF8 <= c && c <= 0xFB) {
         this.codePoint = c - 0xF8;
         this.bytesLeft = 4;
         this.lowerBound = 0x200000;
-      } else if (0xFC <= c && c <= 0xFD) {
+      }
+      else if (0xFC <= c && c <= 0xFD) {
         this.codePoint = c - 0xFC;
         this.bytesLeft = 5;
         this.lowerBound = 0x4000000;
-      } else {
-        ret += '\ufffd';
       }
-    } else {
+      else {
+        ret += '�';
+      }
+    }
+    else {
       if (0x80 <= c && c <= 0xBF) {
         this.bytesLeft--;
         this.codePoint = (this.codePoint << 6) + (c - 0x80);
@@ -4456,15 +4529,17 @@
           // Got a full sequence. Check if it's within bounds and
           // filter out surrogate pairs.
           var codePoint = this.codePoint;
-          if (codePoint < this.lowerBound
-              || (0xD800 <= codePoint && codePoint <= 0xDFFF)
-              || codePoint > 0x10FFFF) {
-            ret += '\ufffd';
-          } else {
+          if (codePoint < this.lowerBound ||
+            (0xD800 <= codePoint && codePoint <= 0xDFFF) ||
+            codePoint > 0x10FFFF) {
+            ret += '�';
+          }
+          else {
             // Encode as UTF-16 in the output.
             if (codePoint < 0x10000) {
               ret += String.fromCharCode(codePoint);
-            } else {
+            }
+            else {
               // Surrogate pair.
               codePoint -= 0x10000;
               ret += String.fromCharCode(
@@ -4473,10 +4548,11 @@
             }
           }
         }
-      } else {
+      }
+      else {
         // Too few bytes in multi-byte sequence. Rewind stream so we
         // don't lose the next byte.
-        ret += '\ufffd';
+        ret += '�';
         this.bytesLeft = 0;
         i--;
       }
@@ -4516,17 +4592,20 @@
     var c = str.charCodeAt(i);
     if (0xDC00 <= c && c <= 0xDFFF) {
       c = 0xFFFD;
-    } else if (0xD800 <= c && c <= 0xDBFF) {
-      if (i+1 < str.length) {
-        var d = str.charCodeAt(i+1);
+    }
+    else if (0xD800 <= c && c <= 0xDBFF) {
+      if (i + 1 < str.length) {
+        var d = str.charCodeAt(i + 1);
         if (0xDC00 <= d && d <= 0xDFFF) {
           // Swallow a surrogate pair.
           c = 0x10000 + ((c & 0x3FF) << 10) + (d & 0x3FF);
           i++;
-        } else {
+        }
+        else {
           c = 0xFFFD;
         }
-      } else {
+      }
+      else {
         c = 0xFFFD;
       }
     }
@@ -4536,13 +4615,16 @@
     if (c <= 0x7F) {
       ret += str.charAt(i);
       continue;
-    } else if (c <= 0x7FF) {
+    }
+    else if (c <= 0x7FF) {
       ret += String.fromCharCode(0xC0 | (c >>> 6));
       bytesLeft = 1;
-    } else if (c <= 0xFFFF) {
+    }
+    else if (c <= 0xFFFF) {
       ret += String.fromCharCode(0xE0 | (c >>> 12));
       bytesLeft = 2;
-    } else /* if (c <= 0x10FFFF) */ {
+    }
+    else /* if (c <= 0x10FFFF) */ {
       ret += String.fromCharCode(0xF0 | (c >>> 18));
       bytesLeft = 3;
     }
@@ -4700,7 +4782,8 @@
         'configurable': true,
         'writable': true
       });
-    } else {
+    }
+    else {
       String.prototype.codePointAt = codePointAt;
     }
   }());
@@ -4723,111 +4806,309 @@
 // Sorted list of non-overlapping intervals of non-spacing characters
 // generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c"
 lib.wc.combining = [
-    [ 0x0300, 0x036F ], [ 0x0483, 0x0486 ], [ 0x0488, 0x0489 ],
-    [ 0x0591, 0x05BD ], [ 0x05BF, 0x05BF ], [ 0x05C1, 0x05C2 ],
-    [ 0x05C4, 0x05C5 ], [ 0x05C7, 0x05C7 ], [ 0x0600, 0x0603 ],
-    [ 0x0610, 0x0615 ], [ 0x064B, 0x065E ], [ 0x0670, 0x0670 ],
-    [ 0x06D6, 0x06E4 ], [ 0x06E7, 0x06E8 ], [ 0x06EA, 0x06ED ],
-    [ 0x070F, 0x070F ], [ 0x0711, 0x0711 ], [ 0x0730, 0x074A ],
-    [ 0x07A6, 0x07B0 ], [ 0x07EB, 0x07F3 ], [ 0x0901, 0x0902 ],
-    [ 0x093C, 0x093C ], [ 0x0941, 0x0948 ], [ 0x094D, 0x094D ],
-    [ 0x0951, 0x0954 ], [ 0x0962, 0x0963 ], [ 0x0981, 0x0981 ],
-    [ 0x09BC, 0x09BC ], [ 0x09C1, 0x09C4 ], [ 0x09CD, 0x09CD ],
-    [ 0x09E2, 0x09E3 ], [ 0x0A01, 0x0A02 ], [ 0x0A3C, 0x0A3C ],
-    [ 0x0A41, 0x0A42 ], [ 0x0A47, 0x0A48 ], [ 0x0A4B, 0x0A4D ],
-    [ 0x0A70, 0x0A71 ], [ 0x0A81, 0x0A82 ], [ 0x0ABC, 0x0ABC ],
-    [ 0x0AC1, 0x0AC5 ], [ 0x0AC7, 0x0AC8 ], [ 0x0ACD, 0x0ACD ],
-    [ 0x0AE2, 0x0AE3 ], [ 0x0B01, 0x0B01 ], [ 0x0B3C, 0x0B3C ],
-    [ 0x0B3F, 0x0B3F ], [ 0x0B41, 0x0B43 ], [ 0x0B4D, 0x0B4D ],
-    [ 0x0B56, 0x0B56 ], [ 0x0B82, 0x0B82 ], [ 0x0BC0, 0x0BC0 ],
-    [ 0x0BCD, 0x0BCD ], [ 0x0C3E, 0x0C40 ], [ 0x0C46, 0x0C48 ],
-    [ 0x0C4A, 0x0C4D ], [ 0x0C55, 0x0C56 ], [ 0x0CBC, 0x0CBC ],
-    [ 0x0CBF, 0x0CBF ], [ 0x0CC6, 0x0CC6 ], [ 0x0CCC, 0x0CCD ],
-    [ 0x0CE2, 0x0CE3 ], [ 0x0D41, 0x0D43 ], [ 0x0D4D, 0x0D4D ],
-    [ 0x0DCA, 0x0DCA ], [ 0x0DD2, 0x0DD4 ], [ 0x0DD6, 0x0DD6 ],
-    [ 0x0E31, 0x0E31 ], [ 0x0E34, 0x0E3A ], [ 0x0E47, 0x0E4E ],
-    [ 0x0EB1, 0x0EB1 ], [ 0x0EB4, 0x0EB9 ], [ 0x0EBB, 0x0EBC ],
-    [ 0x0EC8, 0x0ECD ], [ 0x0F18, 0x0F19 ], [ 0x0F35, 0x0F35 ],
-    [ 0x0F37, 0x0F37 ], [ 0x0F39, 0x0F39 ], [ 0x0F71, 0x0F7E ],
-    [ 0x0F80, 0x0F84 ], [ 0x0F86, 0x0F87 ], [ 0x0F90, 0x0F97 ],
-    [ 0x0F99, 0x0FBC ], [ 0x0FC6, 0x0FC6 ], [ 0x102D, 0x1030 ],
-    [ 0x1032, 0x1032 ], [ 0x1036, 0x1037 ], [ 0x1039, 0x1039 ],
-    [ 0x1058, 0x1059 ], [ 0x1160, 0x11FF ], [ 0x135F, 0x135F ],
-    [ 0x1712, 0x1714 ], [ 0x1732, 0x1734 ], [ 0x1752, 0x1753 ],
-    [ 0x1772, 0x1773 ], [ 0x17B4, 0x17B5 ], [ 0x17B7, 0x17BD ],
-    [ 0x17C6, 0x17C6 ], [ 0x17C9, 0x17D3 ], [ 0x17DD, 0x17DD ],
-    [ 0x180B, 0x180D ], [ 0x18A9, 0x18A9 ], [ 0x1920, 0x1922 ],
-    [ 0x1927, 0x1928 ], [ 0x1932, 0x1932 ], [ 0x1939, 0x193B ],
-    [ 0x1A17, 0x1A18 ], [ 0x1B00, 0x1B03 ], [ 0x1B34, 0x1B34 ],
-    [ 0x1B36, 0x1B3A ], [ 0x1B3C, 0x1B3C ], [ 0x1B42, 0x1B42 ],
-    [ 0x1B6B, 0x1B73 ], [ 0x1DC0, 0x1DCA ], [ 0x1DFE, 0x1DFF ],
-    [ 0x200B, 0x200F ], [ 0x202A, 0x202E ], [ 0x2060, 0x2063 ],
-    [ 0x206A, 0x206F ], [ 0x20D0, 0x20EF ], [ 0x302A, 0x302F ],
-    [ 0x3099, 0x309A ], [ 0xA806, 0xA806 ], [ 0xA80B, 0xA80B ],
-    [ 0xA825, 0xA826 ], [ 0xFB1E, 0xFB1E ], [ 0xFE00, 0xFE0F ],
-    [ 0xFE20, 0xFE23 ], [ 0xFEFF, 0xFEFF ], [ 0xFFF9, 0xFFFB ],
-    [ 0x10A01, 0x10A03 ], [ 0x10A05, 0x10A06 ], [ 0x10A0C, 0x10A0F ],
-    [ 0x10A38, 0x10A3A ], [ 0x10A3F, 0x10A3F ], [ 0x1D167, 0x1D169 ],
-    [ 0x1D173, 0x1D182 ], [ 0x1D185, 0x1D18B ], [ 0x1D1AA, 0x1D1AD ],
-    [ 0x1D242, 0x1D244 ], [ 0xE0001, 0xE0001 ], [ 0xE0020, 0xE007F ],
-    [ 0xE0100, 0xE01EF ]
+  [0x0300, 0x036F],
+  [0x0483, 0x0486],
+  [0x0488, 0x0489],
+  [0x0591, 0x05BD],
+  [0x05BF, 0x05BF],
+  [0x05C1, 0x05C2],
+  [0x05C4, 0x05C5],
+  [0x05C7, 0x05C7],
+  [0x0600, 0x0603],
+  [0x0610, 0x0615],
+  [0x064B, 0x065E],
+  [0x0670, 0x0670],
+  [0x06D6, 0x06E4],
+  [0x06E7, 0x06E8],
+  [0x06EA, 0x06ED],
+  [0x070F, 0x070F],
+  [0x0711, 0x0711],
+  [0x0730, 0x074A],
+  [0x07A6, 0x07B0],
+  [0x07EB, 0x07F3],
+  [0x0901, 0x0902],
+  [0x093C, 0x093C],
+  [0x0941, 0x0948],
+  [0x094D, 0x094D],
+  [0x0951, 0x0954],
+  [0x0962, 0x0963],
+  [0x0981, 0x0981],
+  [0x09BC, 0x09BC],
+  [0x09C1, 0x09C4],
+  [0x09CD, 0x09CD],
+  [0x09E2, 0x09E3],
+  [0x0A01, 0x0A02],
+  [0x0A3C, 0x0A3C],
+  [0x0A41, 0x0A42],
+  [0x0A47, 0x0A48],
+  [0x0A4B, 0x0A4D],
+  [0x0A70, 0x0A71],
+  [0x0A81, 0x0A82],
+  [0x0ABC, 0x0ABC],
+  [0x0AC1, 0x0AC5],
+  [0x0AC7, 0x0AC8],
+  [0x0ACD, 0x0ACD],
+  [0x0AE2, 0x0AE3],
+  [0x0B01, 0x0B01],
+  [0x0B3C, 0x0B3C],
+  [0x0B3F, 0x0B3F],
+  [0x0B41, 0x0B43],
+  [0x0B4D, 0x0B4D],
+  [0x0B56, 0x0B56],
+  [0x0B82, 0x0B82],
+  [0x0BC0, 0x0BC0],
+  [0x0BCD, 0x0BCD],
+  [0x0C3E, 0x0C40],
+  [0x0C46, 0x0C48],
+  [0x0C4A, 0x0C4D],
+  [0x0C55, 0x0C56],
+  [0x0CBC, 0x0CBC],
+  [0x0CBF, 0x0CBF],
+  [0x0CC6, 0x0CC6],
+  [0x0CCC, 0x0CCD],
+  [0x0CE2, 0x0CE3],
+  [0x0D41, 0x0D43],
+  [0x0D4D, 0x0D4D],
+  [0x0DCA, 0x0DCA],
+  [0x0DD2, 0x0DD4],
+  [0x0DD6, 0x0DD6],
+  [0x0E31, 0x0E31],
+  [0x0E34, 0x0E3A],
+  [0x0E47, 0x0E4E],
+  [0x0EB1, 0x0EB1],
+  [0x0EB4, 0x0EB9],
+  [0x0EBB, 0x0EBC],
+  [0x0EC8, 0x0ECD],
+  [0x0F18, 0x0F19],
+  [0x0F35, 0x0F35],
+  [0x0F37, 0x0F37],
+  [0x0F39, 0x0F39],
+  [0x0F71, 0x0F7E],
+  [0x0F80, 0x0F84],
+  [0x0F86, 0x0F87],
+  [0x0F90, 0x0F97],
+  [0x0F99, 0x0FBC],
+  [0x0FC6, 0x0FC6],
+  [0x102D, 0x1030],
+  [0x1032, 0x1032],
+  [0x1036, 0x1037],
+  [0x1039, 0x1039],
+  [0x1058, 0x1059],
+  [0x1160, 0x11FF],
+  [0x135F, 0x135F],
+  [0x1712, 0x1714],
+  [0x1732, 0x1734],
+  [0x1752, 0x1753],
+  [0x1772, 0x1773],
+  [0x17B4, 0x17B5],
+  [0x17B7, 0x17BD],
+  [0x17C6, 0x17C6],
+  [0x17C9, 0x17D3],
+  [0x17DD, 0x17DD],
+  [0x180B, 0x180D],
+  [0x18A9, 0x18A9],
+  [0x1920, 0x1922],
+  [0x1927, 0x1928],
+  [0x1932, 0x1932],
+  [0x1939, 0x193B],
+  [0x1A17, 0x1A18],
+  [0x1B00, 0x1B03],
+  [0x1B34, 0x1B34],
+  [0x1B36, 0x1B3A],
+  [0x1B3C, 0x1B3C],
+  [0x1B42, 0x1B42],
+  [0x1B6B, 0x1B73],
+  [0x1DC0, 0x1DCA],
+  [0x1DFE, 0x1DFF],
+  [0x200B, 0x200F],
+  [0x202A, 0x202E],
+  [0x2060, 0x2063],
+  [0x206A, 0x206F],
+  [0x20D0, 0x20EF],
+  [0x302A, 0x302F],
+  [0x3099, 0x309A],
+  [0xA806, 0xA806],
+  [0xA80B, 0xA80B],
+  [0xA825, 0xA826],
+  [0xFB1E, 0xFB1E],
+  [0xFE00, 0xFE0F],
+  [0xFE20, 0xFE23],
+  [0xFEFF, 0xFEFF],
+  [0xFFF9, 0xFFFB],
+  [0x10A01, 0x10A03],
+  [0x10A05, 0x10A06],
+  [0x10A0C, 0x10A0F],
+  [0x10A38, 0x10A3A],
+  [0x10A3F, 0x10A3F],
+  [0x1D167, 0x1D169],
+  [0x1D173, 0x1D182],
+  [0x1D185, 0x1D18B],
+  [0x1D1AA, 0x1D1AD],
+  [0x1D242, 0x1D244],
+  [0xE0001, 0xE0001],
+  [0xE0020, 0xE007F],
+  [0xE0100, 0xE01EF]
 ];
 
 // Sorted list of non-overlapping intervals of East Asian Ambiguous characters
 // generated by "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c"
 lib.wc.ambiguous = [
-    [ 0x00A1, 0x00A1 ], [ 0x00A4, 0x00A4 ], [ 0x00A7, 0x00A8 ],
-    [ 0x00AA, 0x00AA ], [ 0x00AE, 0x00AE ], [ 0x00B0, 0x00B4 ],
-    [ 0x00B6, 0x00BA ], [ 0x00BC, 0x00BF ], [ 0x00C6, 0x00C6 ],
-    [ 0x00D0, 0x00D0 ], [ 0x00D7, 0x00D8 ], [ 0x00DE, 0x00E1 ],
-    [ 0x00E6, 0x00E6 ], [ 0x00E8, 0x00EA ], [ 0x00EC, 0x00ED ],
-    [ 0x00F0, 0x00F0 ], [ 0x00F2, 0x00F3 ], [ 0x00F7, 0x00FA ],
-    [ 0x00FC, 0x00FC ], [ 0x00FE, 0x00FE ], [ 0x0101, 0x0101 ],
-    [ 0x0111, 0x0111 ], [ 0x0113, 0x0113 ], [ 0x011B, 0x011B ],
-    [ 0x0126, 0x0127 ], [ 0x012B, 0x012B ], [ 0x0131, 0x0133 ],
-    [ 0x0138, 0x0138 ], [ 0x013F, 0x0142 ], [ 0x0144, 0x0144 ],
-    [ 0x0148, 0x014B ], [ 0x014D, 0x014D ], [ 0x0152, 0x0153 ],
-    [ 0x0166, 0x0167 ], [ 0x016B, 0x016B ], [ 0x01CE, 0x01CE ],
-    [ 0x01D0, 0x01D0 ], [ 0x01D2, 0x01D2 ], [ 0x01D4, 0x01D4 ],
-    [ 0x01D6, 0x01D6 ], [ 0x01D8, 0x01D8 ], [ 0x01DA, 0x01DA ],
-    [ 0x01DC, 0x01DC ], [ 0x0251, 0x0251 ], [ 0x0261, 0x0261 ],
-    [ 0x02C4, 0x02C4 ], [ 0x02C7, 0x02C7 ], [ 0x02C9, 0x02CB ],
-    [ 0x02CD, 0x02CD ], [ 0x02D0, 0x02D0 ], [ 0x02D8, 0x02DB ],
-    [ 0x02DD, 0x02DD ], [ 0x02DF, 0x02DF ], [ 0x0391, 0x03A1 ],
-    [ 0x03A3, 0x03A9 ], [ 0x03B1, 0x03C1 ], [ 0x03C3, 0x03C9 ],
-    [ 0x0401, 0x0401 ], [ 0x0410, 0x044F ], [ 0x0451, 0x0451 ],
-    [ 0x2010, 0x2010 ], [ 0x2013, 0x2016 ], [ 0x2018, 0x2019 ],
-    [ 0x201C, 0x201D ], [ 0x2020, 0x2022 ], [ 0x2024, 0x2027 ],
-    [ 0x2030, 0x2030 ], [ 0x2032, 0x2033 ], [ 0x2035, 0x2035 ],
-    [ 0x203B, 0x203B ], [ 0x203E, 0x203E ], [ 0x2074, 0x2074 ],
-    [ 0x207F, 0x207F ], [ 0x2081, 0x2084 ], [ 0x20AC, 0x20AC ],
-    [ 0x2103, 0x2103 ], [ 0x2105, 0x2105 ], [ 0x2109, 0x2109 ],
-    [ 0x2113, 0x2113 ], [ 0x2116, 0x2116 ], [ 0x2121, 0x2122 ],
-    [ 0x2126, 0x2126 ], [ 0x212B, 0x212B ], [ 0x2153, 0x2154 ],
-    [ 0x215B, 0x215E ], [ 0x2160, 0x216B ], [ 0x2170, 0x2179 ],
-    [ 0x2190, 0x2199 ], [ 0x21B8, 0x21B9 ], [ 0x21D2, 0x21D2 ],
-    [ 0x21D4, 0x21D4 ], [ 0x21E7, 0x21E7 ], [ 0x2200, 0x2200 ],
-    [ 0x2202, 0x2203 ], [ 0x2207, 0x2208 ], [ 0x220B, 0x220B ],
-    [ 0x220F, 0x220F ], [ 0x2211, 0x2211 ], [ 0x2215, 0x2215 ],
-    [ 0x221A, 0x221A ], [ 0x221D, 0x2220 ], [ 0x2223, 0x2223 ],
-    [ 0x2225, 0x2225 ], [ 0x2227, 0x222C ], [ 0x222E, 0x222E ],
-    [ 0x2234, 0x2237 ], [ 0x223C, 0x223D ], [ 0x2248, 0x2248 ],
-    [ 0x224C, 0x224C ], [ 0x2252, 0x2252 ], [ 0x2260, 0x2261 ],
-    [ 0x2264, 0x2267 ], [ 0x226A, 0x226B ], [ 0x226E, 0x226F ],
-    [ 0x2282, 0x2283 ], [ 0x2286, 0x2287 ], [ 0x2295, 0x2295 ],
-    [ 0x2299, 0x2299 ], [ 0x22A5, 0x22A5 ], [ 0x22BF, 0x22BF ],
-    [ 0x2312, 0x2312 ], [ 0x2460, 0x24E9 ], [ 0x24EB, 0x254B ],
-    [ 0x2550, 0x2573 ], [ 0x2580, 0x258F ], [ 0x2592, 0x2595 ],
-    [ 0x25A0, 0x25A1 ], [ 0x25A3, 0x25A9 ], [ 0x25B2, 0x25B3 ],
-    [ 0x25B6, 0x25B7 ], [ 0x25BC, 0x25BD ], [ 0x25C0, 0x25C1 ],
-    [ 0x25C6, 0x25C8 ], [ 0x25CB, 0x25CB ], [ 0x25CE, 0x25D1 ],
-    [ 0x25E2, 0x25E5 ], [ 0x25EF, 0x25EF ], [ 0x2605, 0x2606 ],
-    [ 0x2609, 0x2609 ], [ 0x260E, 0x260F ], [ 0x2614, 0x2615 ],
-    [ 0x261C, 0x261C ], [ 0x261E, 0x261E ], [ 0x2640, 0x2640 ],
-    [ 0x2642, 0x2642 ], [ 0x2660, 0x2661 ], [ 0x2663, 0x2665 ],
-    [ 0x2667, 0x266A ], [ 0x266C, 0x266D ], [ 0x266F, 0x266F ],
-    [ 0x273D, 0x273D ], [ 0x2776, 0x277F ], [ 0xE000, 0xF8FF ],
-    [ 0xFFFD, 0xFFFD ], [ 0xF0000, 0xFFFFD ], [ 0x100000, 0x10FFFD ]
+  [0x00A1, 0x00A1],
+  [0x00A4, 0x00A4],
+  [0x00A7, 0x00A8],
+  [0x00AA, 0x00AA],
+  [0x00AE, 0x00AE],
+  [0x00B0, 0x00B4],
+  [0x00B6, 0x00BA],
+  [0x00BC, 0x00BF],
+  [0x00C6, 0x00C6],
+  [0x00D0, 0x00D0],
+  [0x00D7, 0x00D8],
+  [0x00DE, 0x00E1],
+  [0x00E6, 0x00E6],
+  [0x00E8, 0x00EA],
+  [0x00EC, 0x00ED],
+  [0x00F0, 0x00F0],
+  [0x00F2, 0x00F3],
+  [0x00F7, 0x00FA],
+  [0x00FC, 0x00FC],
+  [0x00FE, 0x00FE],
+  [0x0101, 0x0101],
+  [0x0111, 0x0111],
+  [0x0113, 0x0113],
+  [0x011B, 0x011B],
+  [0x0126, 0x0127],
+  [0x012B, 0x012B],
+  [0x0131, 0x0133],
+  [0x0138, 0x0138],
+  [0x013F, 0x0142],
+  [0x0144, 0x0144],
+  [0x0148, 0x014B],
+  [0x014D, 0x014D],
+  [0x0152, 0x0153],
+  [0x0166, 0x0167],
+  [0x016B, 0x016B],
+  [0x01CE, 0x01CE],
+  [0x01D0, 0x01D0],
+  [0x01D2, 0x01D2],
+  [0x01D4, 0x01D4],
+  [0x01D6, 0x01D6],
+  [0x01D8, 0x01D8],
+  [0x01DA, 0x01DA],
+  [0x01DC, 0x01DC],
+  [0x0251, 0x0251],
+  [0x0261, 0x0261],
+  [0x02C4, 0x02C4],
+  [0x02C7, 0x02C7],
+  [0x02C9, 0x02CB],
+  [0x02CD, 0x02CD],
+  [0x02D0, 0x02D0],
+  [0x02D8, 0x02DB],
+  [0x02DD, 0x02DD],
+  [0x02DF, 0x02DF],
+  [0x0391, 0x03A1],
+  [0x03A3, 0x03A9],
+  [0x03B1, 0x03C1],
+  [0x03C3, 0x03C9],
+  [0x0401, 0x0401],
+  [0x0410, 0x044F],
+  [0x0451, 0x0451],
+  [0x2010, 0x2010],
+  [0x2013, 0x2016],
+  [0x2018, 0x2019],
+  [0x201C, 0x201D],
+  [0x2020, 0x2022],
+  [0x2024, 0x2027],
+  [0x2030, 0x2030],
+  [0x2032, 0x2033],
+  [0x2035, 0x2035],
+  [0x203B, 0x203B],
+  [0x203E, 0x203E],
+  [0x2074, 0x2074],
+  [0x207F, 0x207F],
+  [0x2081, 0x2084],
+  [0x20AC, 0x20AC],
+  [0x2103, 0x2103],
+  [0x2105, 0x2105],
+  [0x2109, 0x2109],
+  [0x2113, 0x2113],
+  [0x2116, 0x2116],
+  [0x2121, 0x2122],
+  [0x2126, 0x2126],
+  [0x212B, 0x212B],
+  [0x2153, 0x2154],
+  [0x215B, 0x215E],
+  [0x2160, 0x216B],
+  [0x2170, 0x2179],
+  [0x2190, 0x2199],
+  [0x21B8, 0x21B9],
+  [0x21D2, 0x21D2],
+  [0x21D4, 0x21D4],
+  [0x21E7, 0x21E7],
+  [0x2200, 0x2200],
+  [0x2202, 0x2203],
+  [0x2207, 0x2208],
+  [0x220B, 0x220B],
+  [0x220F, 0x220F],
+  [0x2211, 0x2211],
+  [0x2215, 0x2215],
+  [0x221A, 0x221A],
+  [0x221D, 0x2220],
+  [0x2223, 0x2223],
+  [0x2225, 0x2225],
+  [0x2227, 0x222C],
+  [0x222E, 0x222E],
+  [0x2234, 0x2237],
+  [0x223C, 0x223D],
+  [0x2248, 0x2248],
+  [0x224C, 0x224C],
+  [0x2252, 0x2252],
+  [0x2260, 0x2261],
+  [0x2264, 0x2267],
+  [0x226A, 0x226B],
+  [0x226E, 0x226F],
+  [0x2282, 0x2283],
+  [0x2286, 0x2287],
+  [0x2295, 0x2295],
+  [0x2299, 0x2299],
+  [0x22A5, 0x22A5],
+  [0x22BF, 0x22BF],
+  [0x2312, 0x2312],
+  [0x2460, 0x24E9],
+  [0x24EB, 0x254B],
+  [0x2550, 0x2573],
+  [0x2580, 0x258F],
+  [0x2592, 0x2595],
+  [0x25A0, 0x25A1],
+  [0x25A3, 0x25A9],
+  [0x25B2, 0x25B3],
+  [0x25B6, 0x25B7],
+  [0x25BC, 0x25BD],
+  [0x25C0, 0x25C1],
+  [0x25C6, 0x25C8],
+  [0x25CB, 0x25CB],
+  [0x25CE, 0x25D1],
+  [0x25E2, 0x25E5],
+  [0x25EF, 0x25EF],
+  [0x2605, 0x2606],
+  [0x2609, 0x2609],
+  [0x260E, 0x260F],
+  [0x2614, 0x2615],
+  [0x261C, 0x261C],
+  [0x261E, 0x261E],
+  [0x2640, 0x2640],
+  [0x2642, 0x2642],
+  [0x2660, 0x2661],
+  [0x2663, 0x2665],
+  [0x2667, 0x266A],
+  [0x266C, 0x266D],
+  [0x266F, 0x266F],
+  [0x273D, 0x273D],
+  [0x2776, 0x277F],
+  [0xE000, 0xF8FF],
+  [0xFFFD, 0xFFFD],
+  [0xF0000, 0xFFFFD],
+  [0x100000, 0x10FFFD]
 ];
 
 /**
@@ -4840,7 +5121,8 @@
  */
 lib.wc.isSpace = function(ucs) {
   // Auxiliary function for binary search in interval table.
-  var min = 0, max = lib.wc.combining.length - 1;
+  var min = 0,
+    max = lib.wc.combining.length - 1;
   var mid;
 
   if (ucs < lib.wc.combining[0][0] || ucs > lib.wc.combining[max][1])
@@ -4849,9 +5131,11 @@
     mid = Math.floor((min + max) / 2);
     if (ucs > lib.wc.combining[mid][1]) {
       min = mid + 1;
-    } else if (ucs < lib.wc.combining[mid][0]) {
+    }
+    else if (ucs < lib.wc.combining[mid][0]) {
       max = mid - 1;
-    } else {
+    }
+    else {
       return true;
     }
   }
@@ -4869,7 +5153,8 @@
  * character.
  */
 lib.wc.isCjkAmbiguous = function(ucs) {
-  var min = 0, max = lib.wc.ambiguous.length - 1;
+  var min = 0,
+    max = lib.wc.ambiguous.length - 1;
   var mid;
 
   if (ucs < lib.wc.ambiguous[0][0] || ucs > lib.wc.ambiguous[max][1])
@@ -4878,9 +5163,11 @@
     mid = Math.floor((min + max) / 2);
     if (ucs > lib.wc.ambiguous[mid][1]) {
       min = mid + 1;
-    } else if (ucs < lib.wc.ambiguous[mid][0]) {
+    }
+    else if (ucs < lib.wc.ambiguous[mid][0]) {
       max = mid - 1;
-    } else {
+    }
+    else {
       return true;
     }
   }
@@ -4898,7 +5185,8 @@
 lib.wc.charWidth = function(ucs) {
   if (lib.wc.regardCjkAmbiguous) {
     return lib.wc.charWidthRegardAmbiguous(ucs);
-  } else {
+  }
+  else {
     return lib.wc.charWidthDisregardAmbiguous(ucs);
   }
 };
@@ -4929,18 +5217,18 @@
   // If we arrive here, ucs is not a combining or C0/C1 control character.
   return 1 +
     (ucs >= 0x1100 &&
-     (ucs <= 0x115f ||             // Hangul Jamo init. consonants
-      ucs == 0x2329 || ucs == 0x232a ||
-      (ucs >= 0x2e80 && ucs <= 0xa4cf &&
-       ucs != 0x303f) ||           // CJK ... Yi
-      (ucs >= 0xac00 && ucs <= 0xd7a3) ||  // Hangul Syllables
-      (ucs >= 0xf900 && ucs <= 0xfaff) ||  // CJK Compatibility Ideographs
-      (ucs >= 0xfe10 && ucs <= 0xfe19) ||  // Vertical forms
-      (ucs >= 0xfe30 && ucs <= 0xfe6f) ||  // CJK Compatibility Forms
-      (ucs >= 0xff00 && ucs <= 0xff60) ||  // Fullwidth Forms
-      (ucs >= 0xffe0 && ucs <= 0xffe6) ||
-      (ucs >= 0x20000 && ucs <= 0x2fffd) ||
-      (ucs >= 0x30000 && ucs <= 0x3fffd)));
+      (ucs <= 0x115f || // Hangul Jamo init. consonants
+        ucs == 0x2329 || ucs == 0x232a ||
+        (ucs >= 0x2e80 && ucs <= 0xa4cf &&
+          ucs != 0x303f) || // CJK ... Yi
+        (ucs >= 0xac00 && ucs <= 0xd7a3) || // Hangul Syllables
+        (ucs >= 0xf900 && ucs <= 0xfaff) || // CJK Compatibility Ideographs
+        (ucs >= 0xfe10 && ucs <= 0xfe19) || // Vertical forms
+        (ucs >= 0xfe30 && ucs <= 0xfe6f) || // CJK Compatibility Forms
+        (ucs >= 0xff00 && ucs <= 0xff60) || // Fullwidth Forms
+        (ucs >= 0xffe0 && ucs <= 0xffe6) ||
+        (ucs >= 0x20000 && ucs <= 0x2fffd) ||
+        (ucs >= 0x30000 && ucs <= 0x3fffd)));
   // TODO: emoji characters usually require space for wide characters although
   // East Asian width spec says nothing. Should we add special cases for them?
 };
@@ -5001,9 +5289,7 @@
   }
 
   if (opt_width != undefined) {
-    for (endIndex = startIndex, width = 0;
-         endIndex < str.length && width < opt_width;
-         width += lib.wc.charWidth(str.charCodeAt(endIndex)), endIndex++);
+    for (endIndex = startIndex, width = 0; endIndex < str.length && width < opt_width; width += lib.wc.charWidth(str.charCodeAt(endIndex)), endIndex++);
     if (width > opt_width)
       endIndex--;
     return str.substring(startIndex, endIndex);
@@ -5025,13 +5311,13 @@
   return lib.wc.substr(str, start, end - start);
 };
 lib.resource.add('libdot/changelog/version', 'text/plain',
-'1.11' +
-''
+  '1.11' +
+  ''
 );
 
 lib.resource.add('libdot/changelog/date', 'text/plain',
-'2017-04-17' +
-''
+  '2017-04-17' +
+  ''
 );
 
 // SOURCE FILE: hterm/js/hterm.js
@@ -5073,7 +5359,7 @@
  * This is only displayed when the 'enable-clipboard-notice' preference
  * is enabled.
  */
-hterm.notifyCopyMessage = '\u2702';
+hterm.notifyCopyMessage = '✂';
 
 
 /**
@@ -5081,7 +5367,7 @@
  * bell.  \u226a is a unicode EIGHTH NOTE, %(title) will
  * be replaced by the terminal title.
  */
-hterm.desktopNotificationTitle = '\u266A %(title) \u266A';
+hterm.desktopNotificationTitle = '♪ %(title) ♪';
 
 /**
  * List of known hterm test suites.
@@ -5089,8 +5375,9 @@
  * A test harness should ensure that they all exist before running.
  */
 hterm.testDeps = ['hterm.ScrollPort.Tests', 'hterm.Screen.Tests',
-                  'hterm.Terminal.Tests', 'hterm.VT.Tests',
-                  'hterm.VT.CannedTests'];
+  'hterm.Terminal.Tests', 'hterm.VT.Tests',
+  'hterm.VT.CannedTests'
+];
 
 /**
  * The hterm init function, registered with lib.registerInit().
@@ -5109,7 +5396,8 @@
   function onTab(tab) {
     if (tab && window.chrome) {
       chrome.windows.get(tab.windowId, null, onWindow);
-    } else {
+    }
+    else {
       // TODO(rginda): This is where we end up for a v1 app's background page.
       // Maybe windowType = 'none' would be more appropriate, or something.
       hterm.windowType = 'normal';
@@ -5121,9 +5409,10 @@
     var ary = navigator.userAgent.match(/\sChrome\/(\d\d)/);
     var version = ary ? parseInt(ary[1]) : -1;
     if (window.chrome && chrome.storage && chrome.storage.sync &&
-        version > 21) {
+      version > 21) {
       hterm.defaultStorage = new lib.Storage.Chrome(chrome.storage.sync);
-    } else {
+    }
+    else {
       hterm.defaultStorage = new lib.Storage.Local();
     }
   }
@@ -5138,14 +5427,20 @@
 
   if (isPackagedApp) {
     // Packaged apps are never displayed in browser tabs.
-    setTimeout(onWindow.bind(null, {type: 'popup'}), 0);
-  } else {
+    setTimeout(onWindow.bind(null, {
+      type: 'popup'
+    }), 0);
+  }
+  else {
     if (window.chrome && chrome.tabs) {
       // The getCurrent method gets the tab that is "currently running", not the
       // topmost or focused tab.
       chrome.tabs.getCurrent(onTab);
-    } else {
-      setTimeout(onWindow.bind(null, {type: 'normal'}), 0);
+    }
+    else {
+      setTimeout(onWindow.bind(null, {
+        type: 'normal'
+      }), 0);
     }
   }
 });
@@ -5179,7 +5474,8 @@
 hterm.copySelectionToClipboard = function(document) {
   try {
     document.execCommand('copy');
-  } catch (firefoxException) {
+  }
+  catch (firefoxException) {
     // Ignore this. FF throws an exception if there was an error, even though
     // the spec says just return false.
   }
@@ -5193,7 +5489,8 @@
 hterm.pasteFromClipboard = function(document) {
   try {
     document.execCommand('paste');
-  } catch (firefoxException) {
+  }
+  catch (firefoxException) {
     // Ignore this. FF throws an exception if there was an error, even though
     // the spec says just return false.
   }
@@ -5331,7 +5628,7 @@
  */
 hterm.RowCol.prototype.equals = function(that) {
   return (this.row == that.row && this.column == that.column &&
-          this.overflow == that.overflow);
+    this.overflow == that.overflow);
 };
 
 /**
@@ -5342,7 +5639,7 @@
  */
 hterm.RowCol.prototype.toString = function() {
   return ('[hterm.RowCol: ' + this.row + ', ' + this.column + ', ' +
-          this.overflow + ']');
+    this.overflow + ']');
 };
 // SOURCE FILE: hterm/js/hterm_frame.js
 // Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
@@ -5409,9 +5706,13 @@
   this.messageChannel_ = new MessageChannel();
   this.messageChannel_.port1.onmessage = this.onMessage_.bind(this);
   this.messageChannel_.port1.start();
-  this.iframe_.contentWindow.postMessage(
-      {name: 'ipc-init', argv: [{messagePort: this.messageChannel_.port2}]},
-      this.url, [this.messageChannel_.port2]);
+  this.iframe_.contentWindow.postMessage({
+      name: 'ipc-init',
+      argv: [{
+        messagePort: this.messageChannel_.port2
+      }]
+    },
+    this.url, [this.messageChannel_.port2]);
 };
 
 /**
@@ -5424,17 +5725,16 @@
  */
 hterm.Frame.prototype.sendTerminalInfo_ = function() {
   lib.f.getAcceptLanguages(function(languages) {
-      this.postMessage('terminal-info', [{
-         acceptLanguages: languages,
-         foregroundColor: this.terminal_.getForegroundColor(),
-         backgroundColor: this.terminal_.getBackgroundColor(),
-         cursorColor: this.terminal_.getCursorColor(),
-         fontSize: this.terminal_.getFontSize(),
-         fontFamily: this.terminal_.getFontFamily(),
-         baseURL: lib.f.getURL('/')
-          }]
-        );
-    }.bind(this));
+    this.postMessage('terminal-info', [{
+      acceptLanguages: languages,
+      foregroundColor: this.terminal_.getForegroundColor(),
+      backgroundColor: this.terminal_.getBackgroundColor(),
+      cursorColor: this.terminal_.getCursorColor(),
+      fontSize: this.terminal_.getFontSize(),
+      fontFamily: this.terminal_.getFontFamily(),
+      baseURL: lib.f.getURL('/')
+    }]);
+  }.bind(this));
 };
 
 /**
@@ -5449,7 +5749,7 @@
  */
 hterm.Frame.prototype.close = function() {
   if (!this.container_ || !this.container_.parentNode)
-      return;
+    return;
 
   this.container_.parentNode.removeChild(this.container_);
   this.onClose();
@@ -5468,7 +5768,10 @@
   if (!this.messageChannel_)
     throw new Error('Message channel is not set up.');
 
-  this.messageChannel_.port1.postMessage({name: name, argv: argv});
+  this.messageChannel_.port1.postMessage({
+    name: name,
+    argv: argv
+  });
 };
 
 /**
@@ -5506,25 +5809,25 @@
 
   var container = this.container_ = document.createElement('div');
   container.style.cssText = (
-      'position: absolute;' +
-      'display: -webkit-flex;' +
-      '-webkit-flex-direction: column;' +
-      'top: 10%;' +
-      'left: 4%;' +
-      'width: 90%;' +
-      'height: 80%;' +
-      'box-shadow: 0 0 2px ' + this.terminal_.getForegroundColor() + ';' +
-      'border: 2px ' + this.terminal_.getForegroundColor() + ' solid;');
+    'position: absolute;' +
+    'display: -webkit-flex;' +
+    '-webkit-flex-direction: column;' +
+    'top: 10%;' +
+    'left: 4%;' +
+    'width: 90%;' +
+    'height: 80%;' +
+    'box-shadow: 0 0 2px ' + this.terminal_.getForegroundColor() + ';' +
+    'border: 2px ' + this.terminal_.getForegroundColor() + ' solid;');
 
   var header = document.createElement('div');
   header.style.cssText = (
-      'display: -webkit-flex;' +
-      '-webkit-justify-content: flex-end;' +
-      'height: ' + headerHeight + ';' +
-      'background-color: ' + this.terminal_.getForegroundColor() + ';' +
-      'color: ' + this.terminal_.getBackgroundColor() + ';' +
-      'font-size: 16px;' +
-      'font-family: ' + this.terminal_.getFontFamily());
+    'display: -webkit-flex;' +
+    '-webkit-justify-content: flex-end;' +
+    'height: ' + headerHeight + ';' +
+    'background-color: ' + this.terminal_.getForegroundColor() + ';' +
+    'color: ' + this.terminal_.getBackgroundColor() + ';' +
+    'font-size: 16px;' +
+    'font-family: ' + this.terminal_.getFontFamily());
   container.appendChild(header);
 
   if (false) {
@@ -5532,10 +5835,10 @@
     var button = document.createElement('div');
     button.setAttribute('role', 'button');
     button.style.cssText = (
-        'margin-top: -3px;' +
-        'margin-right: 3px;' +
-        'cursor: pointer;');
-    button.textContent = '\u2a2f';
+      'margin-top: -3px;' +
+      'margin-right: 3px;' +
+      'cursor: pointer;');
+    button.textContent = '⨯';
     button.addEventListener('click', this.onCloseClicked_.bind(this));
     header.appendChild(button);
   }
@@ -5543,9 +5846,9 @@
   var iframe = this.iframe_ = document.createElement('iframe');
   iframe.onload = this.onLoad_.bind(this);
   iframe.style.cssText = (
-      'display: -webkit-flex;' +
-      '-webkit-flex: 1;' +
-      'width: 100%');
+    'display: -webkit-flex;' +
+    '-webkit-flex: 1;' +
+    'width: 100%');
   iframe.setAttribute('src', this.url);
   iframe.setAttribute('seamless', true);
   container.appendChild(iframe);
@@ -5581,11 +5884,11 @@
   // The event handlers we are interested in, and their bound callbacks, saved
   // so they can be uninstalled with removeEventListener, when required.
   this.handlers_ = [
-      ['focusout', this.onFocusOut_.bind(this)],
-      ['keydown', this.onKeyDown_.bind(this)],
-      ['keypress', this.onKeyPress_.bind(this)],
-      ['keyup', this.onKeyUp_.bind(this)],
-      ['textInput', this.onTextInput_.bind(this)]
+    ['focusout', this.onFocusOut_.bind(this)],
+    ['keydown', this.onKeyDown_.bind(this)],
+    ['keypress', this.onKeyPress_.bind(this)],
+    ['keyup', this.onKeyUp_.bind(this)],
+    ['textInput', this.onTextInput_.bind(this)]
   ];
 
   /**
@@ -5817,7 +6120,8 @@
     var handler = this.handlers_[i];
     if (element) {
       element.addEventListener(handler[0], handler[1]);
-    } else {
+    }
+    else {
       this.keyboardElement_.removeEventListener(handler[0], handler[1]);
     }
   }
@@ -5874,7 +6178,8 @@
       ch = ch.toLowerCase();
     code = ch.charCodeAt(0) + 128;
 
-  } else if (e.charCode >= 32) {
+  }
+  else if (e.charCode >= 32) {
     ch = e.charCode;
   }
 
@@ -5931,6 +6236,7 @@
   var resolvedActionType = null;
 
   var self = this;
+
   function getAction(name) {
     // Get the key action for the given action name.  If the action is a
     // function, dispatch it.  If the action defers to the normal action,
@@ -5965,38 +6271,41 @@
 
   switch (this.altGrMode) {
     case 'ctrl-alt':
-    if (isPrintable && control && alt) {
-      // ctrl-alt-printable means altGr.  We clear out the control and
-      // alt modifiers and wait to see the charCode in the keydown event.
-      control = false;
-      alt = false;
-    }
-    break;
+      if (isPrintable && control && alt) {
+        // ctrl-alt-printable means altGr.  We clear out the control and
+        // alt modifiers and wait to see the charCode in the keydown event.
+        control = false;
+        alt = false;
+      }
+      break;
 
     case 'right-alt':
-    if (isPrintable && (this.terminal.keyboard.altKeyPressed & 2)) {
-      control = false;
-      alt = false;
-    }
-    break;
+      if (isPrintable && (this.terminal.keyboard.altKeyPressed & 2)) {
+        control = false;
+        alt = false;
+      }
+      break;
 
     case 'left-alt':
-    if (isPrintable && (this.terminal.keyboard.altKeyPressed & 1)) {
-      control = false;
-      alt = false;
-    }
-    break;
+      if (isPrintable && (this.terminal.keyboard.altKeyPressed & 1)) {
+        control = false;
+        alt = false;
+      }
+      break;
   }
 
   var action;
 
   if (control) {
     action = getAction('control');
-  } else if (alt) {
+  }
+  else if (alt) {
     action = getAction('alt');
-  } else if (meta) {
+  }
+  else if (meta) {
     action = getAction('meta');
-  } else {
+  }
+  else {
     action = getAction('normal');
   }
 
@@ -6073,9 +6382,11 @@
   // modifier has already been accounted for in the action.
   if (resolvedActionType == 'control') {
     control = false;
-  } else if (resolvedActionType == 'alt') {
+  }
+  else if (resolvedActionType == 'alt') {
     alt = false;
-  } else if (resolvedActionType == 'meta') {
+  }
+  else if (resolvedActionType == 'meta') {
     meta = false;
   }
 
@@ -6088,30 +6399,38 @@
 
     if (shift && !(alt || control)) {
       mod = ';2';
-    } else if (alt && !(shift || control)) {
+    }
+    else if (alt && !(shift || control)) {
       mod = ';3';
-    } else if (shift && alt && !control) {
+    }
+    else if (shift && alt && !control) {
       mod = ';4';
-    } else if (control && !(shift || alt)) {
+    }
+    else if (control && !(shift || alt)) {
       mod = ';5';
-    } else if (shift && control && !alt) {
+    }
+    else if (shift && control && !alt) {
       mod = ';6';
-    } else if (alt && control && !shift) {
+    }
+    else if (alt && control && !shift) {
       mod = ';7';
-    } else if (shift && alt && control) {
+    }
+    else if (shift && alt && control) {
       mod = ';8';
     }
 
     if (action.length == 3) {
       // Some of the CSI sequences have zero parameters unless modified.
       action = '\x1b[1' + mod + action.substr(2, 1);
-    } else {
+    }
+    else {
       // Others always have at least one parameter.
       action = action.substr(0, action.length - 1) + mod +
-          action.substr(action.length - 1);
+        action.substr(action.length - 1);
     }
 
-  } else {
+  }
+  else {
     if (action === DEFAULT) {
       action = keyDef.keyCap.substr((shift ? 1 : 0), 1);
 
@@ -6133,7 +6452,7 @@
     // string.  Otherwise, every overridden alt/meta action would have to
     // check alt/metaSendsEscape.
     if ((alt && this.altSendsWhat == 'escape') ||
-        (meta && this.metaSendsEscape)) {
+      (meta && this.metaSendsEscape)) {
       action = '\x1b' + action;
     }
   }
@@ -6161,7 +6480,7 @@
 /**
  * Remove all bindings.
  */
-hterm.Keyboard.Bindings.prototype.clear = function () {
+hterm.Keyboard.Bindings.prototype.clear = function() {
   this.bindings_ = {};
 };
 
@@ -6188,17 +6507,22 @@
 
   if (binding) {
     binding.action = action;
-  } else {
-    binding = {keyPattern: keyPattern, action: action};
+  }
+  else {
+    binding = {
+      keyPattern: keyPattern,
+      action: action
+    };
 
     if (!list) {
       this.bindings_[keyPattern.keyCode] = [binding];
-    } else {
+    }
+    else {
       this.bindings_[keyPattern.keyCode].push(binding);
 
       list.sort(function(a, b) {
         return hterm.Keyboard.KeyPattern.sortCompare(
-            a.keyPattern, b.keyPattern);
+          a.keyPattern, b.keyPattern);
       });
     }
   }
@@ -6244,7 +6568,8 @@
 
   try {
     sequence = p.parseKeySequence();
-  } catch (ex) {
+  }
+  catch (ex) {
     console.error(ex);
     return;
   }
@@ -6259,7 +6584,8 @@
     p.reset(action);
     try {
       action = p.parseKeyAction();
-    } catch (ex) {
+    }
+    catch (ex) {
       console.error(ex);
       return;
     }
@@ -6407,13 +6733,13 @@
  */
 hterm.Keyboard.KeyMap.prototype.addKeyDefs = function(var_args) {
   for (var i = 0; i < arguments.length; i++) {
-    this.addKeyDef(arguments[i][0],
-                   { keyCap: arguments[i][1],
-                     normal: arguments[i][2],
-                     control: arguments[i][3],
-                     alt: arguments[i][4],
-                     meta: arguments[i][5]
-                   });
+    this.addKeyDef(arguments[i][0], {
+      keyCap: arguments[i][1],
+      normal: arguments[i][2],
+      control: arguments[i][3],
+      alt: arguments[i][4],
+      meta: arguments[i][5]
+    });
   }
 };
 
@@ -6439,7 +6765,7 @@
   function ak(a, b) {
     return function(e, k) {
       var action = (e.shiftKey || e.ctrlKey || e.altKey || e.metaKey ||
-                    !self.keyboard.applicationKeypad) ? a : b;
+        !self.keyboard.applicationKeypad) ? a : b;
       return resolve(action, e, k);
     };
   }
@@ -6449,7 +6775,7 @@
   function ac(a, b) {
     return function(e, k) {
       var action = (e.shiftKey || e.ctrlKey || e.altKey || e.metaKey ||
-                    !self.keyboard.applicationCursor) ? a : b;
+        !self.keyboard.applicationCursor) ? a : b;
       return resolve(action, e, k);
     };
   }
@@ -6488,10 +6814,16 @@
   }
 
   // Compute a control character for a given character.
-  function ctl(ch) { return String.fromCharCode(ch.charCodeAt(0) - 64) }
+  function ctl(ch) {
+    return String.fromCharCode(ch.charCodeAt(0) - 64);
+  }
 
   // Call a method on the keymap instance.
-  function c(m) { return function (e, k) { return this[m](e, k) } }
+  function c(m) {
+    return function(e, k) {
+      return this[m](e, k);
+    }
+  }
 
   // Ignore if not trapping media keys.
   function med(fn) {
@@ -6500,8 +6832,8 @@
         // Block Back, Forward, and Reload keys to avoid navigating away from
         // the current page.
         return (e.keyCode == 166 || e.keyCode == 167 || e.keyCode == 168) ?
-            hterm.Keyboard.KeyActions.CANCEL :
-            hterm.Keyboard.KeyActions.PASS;
+          hterm.Keyboard.KeyActions.CANCEL :
+          hterm.Keyboard.KeyActions.PASS;
       }
       return resolve(fn, e, k);
     };
@@ -6521,120 +6853,45 @@
 
     // The browser sends the keycode 0 for some keys.  We'll just assume it's
     // going to do the right thing by default for those keys.
-    [0,   '[UNKNOWN]', PASS, PASS, PASS, PASS],
+    [0, '[UNKNOWN]', PASS, PASS, PASS, PASS],
 
     // First row.
-    [27,  '[ESC]', ESC,                       DEFAULT, DEFAULT,     DEFAULT],
-    [112, '[F1]',  mod(SS3 + 'P', CSI + 'P'), DEFAULT, CSI + "23~", DEFAULT],
-    [113, '[F2]',  mod(SS3 + 'Q', CSI + 'Q'), DEFAULT, CSI + "24~", DEFAULT],
-    [114, '[F3]',  mod(SS3 + 'R', CSI + 'R'), DEFAULT, CSI + "25~", DEFAULT],
-    [115, '[F4]',  mod(SS3 + 'S', CSI + 'S'), DEFAULT, CSI + "26~", DEFAULT],
-    [116, '[F5]',  CSI + '15~',               DEFAULT, CSI + "28~", DEFAULT],
-    [117, '[F6]',  CSI + '17~',               DEFAULT, CSI + "29~", DEFAULT],
-    [118, '[F7]',  CSI + '18~',               DEFAULT, CSI + "31~", DEFAULT],
-    [119, '[F8]',  CSI + '19~',               DEFAULT, CSI + "32~", DEFAULT],
-    [120, '[F9]',  CSI + '20~',               DEFAULT, CSI + "33~", DEFAULT],
-    [121, '[F10]', CSI + '21~',               DEFAULT, CSI + "34~", DEFAULT],
-    [122, '[F11]', CSI + '23~',               DEFAULT, CSI + "42~", DEFAULT],
-    [123, '[F12]', CSI + '24~',               DEFAULT, CSI + "43~", DEFAULT],
+    [27, '[ESC]', ESC, DEFAULT, DEFAULT, DEFAULT], [112, '[F1]', mod(SS3 + 'P', CSI + 'P'), DEFAULT, CSI + '23~', DEFAULT], [113, '[F2]', mod(SS3 + 'Q', CSI + 'Q'), DEFAULT, CSI + '24~', DEFAULT], [114, '[F3]', mod(SS3 + 'R', CSI + 'R'), DEFAULT, CSI + '25~', DEFAULT], [115, '[F4]', mod(SS3 + 'S', CSI + 'S'), DEFAULT, CSI + '26~', DEFAULT], [116, '[F5]', CSI + '15~', DEFAULT, CSI + '28~', DEFAULT], [117, '[F6]', CSI + '17~', DEFAULT, CSI + '29~', DEFAULT], [118, '[F7]', CSI + '18~', DEFAULT, CSI + '31~', DEFAULT], [119, '[F8]', CSI + '19~', DEFAULT, CSI + '32~', DEFAULT], [120, '[F9]', CSI + '20~', DEFAULT, CSI + '33~', DEFAULT], [121, '[F10]', CSI + '21~', DEFAULT, CSI + '34~', DEFAULT], [122, '[F11]', CSI + '23~', DEFAULT, CSI + '42~', DEFAULT], [123, '[F12]', CSI + '24~', DEFAULT, CSI + '43~', DEFAULT],
 
     // Second row.
-    [192, '`~', DEFAULT, sh(ctl('@'), ctl('^')),     DEFAULT,           PASS],
-    [49,  '1!', DEFAULT, c('onCtrlNum_'),    c('onAltNum_'), c('onMetaNum_')],
-    [50,  '2@', DEFAULT, c('onCtrlNum_'),    c('onAltNum_'), c('onMetaNum_')],
-    [51,  '3#', DEFAULT, c('onCtrlNum_'),    c('onAltNum_'), c('onMetaNum_')],
-    [52,  '4$', DEFAULT, c('onCtrlNum_'),    c('onAltNum_'), c('onMetaNum_')],
-    [53,  '5%', DEFAULT, c('onCtrlNum_'),    c('onAltNum_'), c('onMetaNum_')],
-    [54,  '6^', DEFAULT, c('onCtrlNum_'),    c('onAltNum_'), c('onMetaNum_')],
-    [55,  '7&', DEFAULT, c('onCtrlNum_'),    c('onAltNum_'), c('onMetaNum_')],
-    [56,  '8*', DEFAULT, c('onCtrlNum_'),    c('onAltNum_'), c('onMetaNum_')],
-    [57,  '9(', DEFAULT, c('onCtrlNum_'),    c('onAltNum_'), c('onMetaNum_')],
-    [48,  '0)', DEFAULT, c('onPlusMinusZero_'),c('onAltNum_'),c('onPlusMinusZero_')],
-    [189, '-_', DEFAULT, c('onPlusMinusZero_'), DEFAULT, c('onPlusMinusZero_')],
-    [187, '=+', DEFAULT, c('onPlusMinusZero_'), DEFAULT, c('onPlusMinusZero_')],
+    [192, '`~', DEFAULT, sh(ctl('@'), ctl('^')), DEFAULT, PASS], [49, '1!', DEFAULT, c('onCtrlNum_'), c('onAltNum_'), c('onMetaNum_')], [50, '2@', DEFAULT, c('onCtrlNum_'), c('onAltNum_'), c('onMetaNum_')], [51, '3#', DEFAULT, c('onCtrlNum_'), c('onAltNum_'), c('onMetaNum_')], [52, '4$', DEFAULT, c('onCtrlNum_'), c('onAltNum_'), c('onMetaNum_')], [53, '5%', DEFAULT, c('onCtrlNum_'), c('onAltNum_'), c('onMetaNum_')], [54, '6^', DEFAULT, c('onCtrlNum_'), c('onAltNum_'), c('onMetaNum_')], [55, '7&', DEFAULT, c('onCtrlNum_'), c('onAltNum_'), c('onMetaNum_')], [56, '8*', DEFAULT, c('onCtrlNum_'), c('onAltNum_'), c('onMetaNum_')], [57, '9(', DEFAULT, c('onCtrlNum_'), c('onAltNum_'), c('onMetaNum_')], [48, '0)', DEFAULT, c('onPlusMinusZero_'), c('onAltNum_'), c('onPlusMinusZero_')], [189, '-_', DEFAULT, c('onPlusMinusZero_'), DEFAULT, c('onPlusMinusZero_')], [187, '=+', DEFAULT, c('onPlusMinusZero_'), DEFAULT, c('onPlusMinusZero_')],
     // Firefox -_ and =+
-    [173, '-_', DEFAULT, c('onPlusMinusZero_'), DEFAULT, c('onPlusMinusZero_')],
-    [61, '=+', DEFAULT, c('onPlusMinusZero_'), DEFAULT, c('onPlusMinusZero_')],
+    [173, '-_', DEFAULT, c('onPlusMinusZero_'), DEFAULT, c('onPlusMinusZero_')], [61, '=+', DEFAULT, c('onPlusMinusZero_'), DEFAULT, c('onPlusMinusZero_')],
     // Firefox Italian +*
     [171, '+*', DEFAULT, c('onPlusMinusZero_'), DEFAULT, c('onPlusMinusZero_')],
 
-    [8,   '[BKSP]', bs('\x7f', '\b'), bs('\b', '\x7f'), DEFAULT,     DEFAULT],
+    [8, '[BKSP]', bs('\x7f', '\b'), bs('\b', '\x7f'), DEFAULT, DEFAULT],
 
     // Third row.
-    [9,   '[TAB]', sh('\t', CSI + 'Z'), STRIP,     PASS,    DEFAULT],
-    [81,  'qQ',    DEFAULT,             ctl('Q'),  DEFAULT, DEFAULT],
-    [87,  'wW',    DEFAULT,             ctl('W'),  DEFAULT, DEFAULT],
-    [69,  'eE',    DEFAULT,             ctl('E'),  DEFAULT, DEFAULT],
-    [82,  'rR',    DEFAULT,             ctl('R'),  DEFAULT, DEFAULT],
-    [84,  'tT',    DEFAULT,             ctl('T'),  DEFAULT, DEFAULT],
-    [89,  'yY',    DEFAULT,             ctl('Y'),  DEFAULT, DEFAULT],
-    [85,  'uU',    DEFAULT,             ctl('U'),  DEFAULT, DEFAULT],
-    [73,  'iI',    DEFAULT,             ctl('I'),  DEFAULT, DEFAULT],
-    [79,  'oO',    DEFAULT,             ctl('O'),  DEFAULT, DEFAULT],
-    [80,  'pP',    DEFAULT,             ctl('P'),  DEFAULT, DEFAULT],
-    [219, '[{',    DEFAULT,             ctl('['),  DEFAULT, DEFAULT],
-    [221, ']}',    DEFAULT,             ctl(']'),  DEFAULT, DEFAULT],
-    [220, '\\|',   DEFAULT,             ctl('\\'), DEFAULT, DEFAULT],
+    [9, '[TAB]', sh('\t', CSI + 'Z'), STRIP, PASS, DEFAULT], [81, 'qQ', DEFAULT, ctl('Q'), DEFAULT, DEFAULT], [87, 'wW', DEFAULT, ctl('W'), DEFAULT, DEFAULT], [69, 'eE', DEFAULT, ctl('E'), DEFAULT, DEFAULT], [82, 'rR', DEFAULT, ctl('R'), DEFAULT, DEFAULT], [84, 'tT', DEFAULT, ctl('T'), DEFAULT, DEFAULT], [89, 'yY', DEFAULT, ctl('Y'), DEFAULT, DEFAULT], [85, 'uU', DEFAULT, ctl('U'), DEFAULT, DEFAULT], [73, 'iI', DEFAULT, ctl('I'), DEFAULT, DEFAULT], [79, 'oO', DEFAULT, ctl('O'), DEFAULT, DEFAULT], [80, 'pP', DEFAULT, ctl('P'), DEFAULT, DEFAULT], [219, '[{', DEFAULT, ctl('['), DEFAULT, DEFAULT], [221, ']}', DEFAULT, ctl(']'), DEFAULT, DEFAULT], [220, '\\|', DEFAULT, ctl('\\'), DEFAULT, DEFAULT],
 
     // Fourth row. (We let Ctrl-Shift-J pass for Chrome DevTools.)
-    [20,  '[CAPS]',  PASS,    PASS,                           PASS,    DEFAULT],
-    [65,  'aA',      DEFAULT, ctl('A'),                       DEFAULT, DEFAULT],
-    [83,  'sS',      DEFAULT, ctl('S'),                       DEFAULT, DEFAULT],
-    [68,  'dD',      DEFAULT, ctl('D'),                       DEFAULT, DEFAULT],
-    [70,  'fF',      DEFAULT, ctl('F'),                       DEFAULT, DEFAULT],
-    [71,  'gG',      DEFAULT, ctl('G'),                       DEFAULT, DEFAULT],
-    [72,  'hH',      DEFAULT, ctl('H'),                       DEFAULT, DEFAULT],
-    [74,  'jJ',      DEFAULT, sh(ctl('J'), PASS),             DEFAULT, DEFAULT],
-    [75,  'kK',      DEFAULT, sh(ctl('K'), c('onClear_')),    DEFAULT, DEFAULT],
-    [76,  'lL',      DEFAULT, sh(ctl('L'), PASS),             DEFAULT, DEFAULT],
-    [186, ';:',      DEFAULT, STRIP,                          DEFAULT, DEFAULT],
-    [222, '\'"',     DEFAULT, STRIP,                          DEFAULT, DEFAULT],
-    [13,  '[ENTER]', '\r',    CANCEL,                         CANCEL,  DEFAULT],
+    [20, '[CAPS]', PASS, PASS, PASS, DEFAULT], [65, 'aA', DEFAULT, ctl('A'), DEFAULT, DEFAULT], [83, 'sS', DEFAULT, ctl('S'), DEFAULT, DEFAULT], [68, 'dD', DEFAULT, ctl('D'), DEFAULT, DEFAULT], [70, 'fF', DEFAULT, ctl('F'), DEFAULT, DEFAULT], [71, 'gG', DEFAULT, ctl('G'), DEFAULT, DEFAULT], [72, 'hH', DEFAULT, ctl('H'), DEFAULT, DEFAULT], [74, 'jJ', DEFAULT, sh(ctl('J'), PASS), DEFAULT, DEFAULT], [75, 'kK', DEFAULT, sh(ctl('K'), c('onClear_')), DEFAULT, DEFAULT], [76, 'lL', DEFAULT, sh(ctl('L'), PASS), DEFAULT, DEFAULT], [186, ';:', DEFAULT, STRIP, DEFAULT, DEFAULT], [222, '\'"', DEFAULT, STRIP, DEFAULT, DEFAULT], [13, '[ENTER]', '\r', CANCEL, CANCEL, DEFAULT],
 
     // Fifth row.  This includes the copy/paste shortcuts.  On some
     // platforms it's Ctrl-C/V, on others it's Meta-C/V.  We assume either
     // Ctrl-C/Meta-C should pass to the browser when there is a selection,
     // and Ctrl-Shift-V/Meta-*-V should always pass to the browser (since
     // these seem to be recognized as paste too).
-    [16,  '[SHIFT]', PASS, PASS,                   PASS,    DEFAULT],
-    [90,  'zZ',   DEFAULT, ctl('Z'),               DEFAULT, DEFAULT],
-    [88,  'xX',   DEFAULT, ctl('X'),               DEFAULT, DEFAULT],
-    [67,  'cC',   DEFAULT, c('onCtrlC_'),          DEFAULT, c('onMetaC_')],
-    [86,  'vV',   DEFAULT, c('onCtrlV_'),          DEFAULT, c('onMetaV_')],
-    [66,  'bB',   DEFAULT, sh(ctl('B'), PASS),     DEFAULT, sh(DEFAULT, PASS)],
-    [78,  'nN',   DEFAULT, c('onCtrlN_'),          DEFAULT, c('onMetaN_')],
-    [77,  'mM',   DEFAULT, ctl('M'),               DEFAULT, DEFAULT],
-    [188, ',<',   DEFAULT, alt(STRIP, PASS),       DEFAULT, DEFAULT],
-    [190, '.>',   DEFAULT, alt(STRIP, PASS),       DEFAULT, DEFAULT],
-    [191, '/?',   DEFAULT, sh(ctl('_'), ctl('?')), DEFAULT, DEFAULT],
+    [16, '[SHIFT]', PASS, PASS, PASS, DEFAULT], [90, 'zZ', DEFAULT, ctl('Z'), DEFAULT, DEFAULT], [88, 'xX', DEFAULT, ctl('X'), DEFAULT, DEFAULT], [67, 'cC', DEFAULT, c('onCtrlC_'), DEFAULT, c('onMetaC_')], [86, 'vV', DEFAULT, c('onCtrlV_'), DEFAULT, c('onMetaV_')], [66, 'bB', DEFAULT, sh(ctl('B'), PASS), DEFAULT, sh(DEFAULT, PASS)], [78, 'nN', DEFAULT, c('onCtrlN_'), DEFAULT, c('onMetaN_')], [77, 'mM', DEFAULT, ctl('M'), DEFAULT, DEFAULT], [188, ',<', DEFAULT, alt(STRIP, PASS), DEFAULT, DEFAULT], [190, '.>', DEFAULT, alt(STRIP, PASS), DEFAULT, DEFAULT], [191, '/?', DEFAULT, sh(ctl('_'), ctl('?')), DEFAULT, DEFAULT],
 
     // Sixth and final row.
-    [17,  '[CTRL]',  PASS,    PASS,     PASS,    PASS],
-    [18,  '[ALT]',   PASS,    PASS,     PASS,    PASS],
-    [91,  '[LAPL]',  PASS,    PASS,     PASS,    PASS],
-    [32,  ' ',       DEFAULT, ctl('@'), DEFAULT, DEFAULT],
-    [92,  '[RAPL]',  PASS,    PASS,     PASS,    PASS],
-    [93,  '[RMENU]', PASS,    PASS,     PASS,    PASS],
+    [17, '[CTRL]', PASS, PASS, PASS, PASS], [18, '[ALT]', PASS, PASS, PASS, PASS], [91, '[LAPL]', PASS, PASS, PASS, PASS], [32, ' ', DEFAULT, ctl('@'), DEFAULT, DEFAULT], [92, '[RAPL]', PASS, PASS, PASS, PASS], [93, '[RMENU]', PASS, PASS, PASS, PASS],
 
     // These things.
-    [42,  '[PRTSCR]', PASS, PASS, PASS, PASS],
-    [145, '[SCRLK]',  PASS, PASS, PASS, PASS],
-    [19,  '[BREAK]',  PASS, PASS, PASS, PASS],
+    [42, '[PRTSCR]', PASS, PASS, PASS, PASS], [145, '[SCRLK]', PASS, PASS, PASS, PASS], [19, '[BREAK]', PASS, PASS, PASS, PASS],
 
     // The block of six keys above the arrows.
-    [45,  '[INSERT]', c('onKeyInsert_'),   DEFAULT, DEFAULT, DEFAULT],
-    [36,  '[HOME]',   c('onKeyHome_'),     DEFAULT, DEFAULT, DEFAULT],
-    [33,  '[PGUP]',   c('onKeyPageUp_'),   DEFAULT, DEFAULT, DEFAULT],
-    [46,  '[DEL]',    c('onKeyDel_'),      DEFAULT, DEFAULT, DEFAULT],
-    [35,  '[END]',    c('onKeyEnd_'),      DEFAULT, DEFAULT, DEFAULT],
-    [34,  '[PGDOWN]', c('onKeyPageDown_'), DEFAULT, DEFAULT, DEFAULT],
+    [45, '[INSERT]', c('onKeyInsert_'), DEFAULT, DEFAULT, DEFAULT], [36, '[HOME]', c('onKeyHome_'), DEFAULT, DEFAULT, DEFAULT], [33, '[PGUP]', c('onKeyPageUp_'), DEFAULT, DEFAULT, DEFAULT], [46, '[DEL]', c('onKeyDel_'), DEFAULT, DEFAULT, DEFAULT], [35, '[END]', c('onKeyEnd_'), DEFAULT, DEFAULT, DEFAULT], [34, '[PGDOWN]', c('onKeyPageDown_'), DEFAULT, DEFAULT, DEFAULT],
 
     // Arrow keys.  When unmodified they respect the application cursor state,
     // otherwise they always send the CSI codes.
-    [38, '[UP]',    ac(CSI + 'A', SS3 + 'A'), DEFAULT, DEFAULT, DEFAULT],
-    [40, '[DOWN]',  ac(CSI + 'B', SS3 + 'B'), DEFAULT, DEFAULT, DEFAULT],
-    [39, '[RIGHT]', ac(CSI + 'C', SS3 + 'C'), DEFAULT, DEFAULT, DEFAULT],
-    [37, '[LEFT]',  ac(CSI + 'D', SS3 + 'D'), DEFAULT, DEFAULT, DEFAULT],
+    [38, '[UP]', ac(CSI + 'A', SS3 + 'A'), DEFAULT, DEFAULT, DEFAULT], [40, '[DOWN]', ac(CSI + 'B', SS3 + 'B'), DEFAULT, DEFAULT, DEFAULT], [39, '[RIGHT]', ac(CSI + 'C', SS3 + 'C'), DEFAULT, DEFAULT, DEFAULT], [37, '[LEFT]', ac(CSI + 'D', SS3 + 'D'), DEFAULT, DEFAULT, DEFAULT],
 
     [144, '[NUMLOCK]', PASS, PASS, PASS, PASS],
 
@@ -6642,30 +6899,10 @@
     // and 'block of six' for some keys, and null key codes for the rest.
 
     // Keypad with numlock on generates unique key codes...
-    [96,  '[KP0]', DEFAULT, DEFAULT, DEFAULT, DEFAULT],
-    [97,  '[KP1]', DEFAULT, DEFAULT, DEFAULT, DEFAULT],
-    [98,  '[KP2]', DEFAULT, DEFAULT, DEFAULT, DEFAULT],
-    [99,  '[KP3]', DEFAULT, DEFAULT, DEFAULT, DEFAULT],
-    [100, '[KP4]', DEFAULT, DEFAULT, DEFAULT, DEFAULT],
-    [101, '[KP5]', DEFAULT, DEFAULT, DEFAULT, DEFAULT],
-    [102, '[KP6]', DEFAULT, DEFAULT, DEFAULT, DEFAULT],
-    [103, '[KP7]', DEFAULT, DEFAULT, DEFAULT, DEFAULT],
-    [104, '[KP8]', DEFAULT, DEFAULT, DEFAULT, DEFAULT],
-    [105, '[KP9]', DEFAULT, DEFAULT, DEFAULT, DEFAULT],
-    [107, '[KP+]', DEFAULT, c('onPlusMinusZero_'), DEFAULT, c('onPlusMinusZero_')],
-    [109, '[KP-]', DEFAULT, c('onPlusMinusZero_'), DEFAULT, c('onPlusMinusZero_')],
-    [106, '[KP*]', DEFAULT, DEFAULT, DEFAULT, DEFAULT],
-    [111, '[KP/]', DEFAULT, DEFAULT, DEFAULT, DEFAULT],
-    [110, '[KP.]', DEFAULT, DEFAULT, DEFAULT, DEFAULT],
+    [96, '[KP0]', DEFAULT, DEFAULT, DEFAULT, DEFAULT], [97, '[KP1]', DEFAULT, DEFAULT, DEFAULT, DEFAULT], [98, '[KP2]', DEFAULT, DEFAULT, DEFAULT, DEFAULT], [99, '[KP3]', DEFAULT, DEFAULT, DEFAULT, DEFAULT], [100, '[KP4]', DEFAULT, DEFAULT, DEFAULT, DEFAULT], [101, '[KP5]', DEFAULT, DEFAULT, DEFAULT, DEFAULT], [102, '[KP6]', DEFAULT, DEFAULT, DEFAULT, DEFAULT], [103, '[KP7]', DEFAULT, DEFAULT, DEFAULT, DEFAULT], [104, '[KP8]', DEFAULT, DEFAULT, DEFAULT, DEFAULT], [105, '[KP9]', DEFAULT, DEFAULT, DEFAULT, DEFAULT], [107, '[KP+]', DEFAULT, c('onPlusMinusZero_'), DEFAULT, c('onPlusMinusZero_')], [109, '[KP-]', DEFAULT, c('onPlusMinusZero_'), DEFAULT, c('onPlusMinusZero_')], [106, '[KP*]', DEFAULT, DEFAULT, DEFAULT, DEFAULT], [111, '[KP/]', DEFAULT, DEFAULT, DEFAULT, DEFAULT], [110, '[KP.]', DEFAULT, DEFAULT, DEFAULT, DEFAULT],
 
     // Chrome OS keyboard top row.
-    [166, '[BACK]',   med(mod(SS3+'P', CSI+'P')), DEFAULT, CSI+"23~", DEFAULT],
-    [167, '[FWD]',    med(mod(SS3+'Q', CSI+'Q')), DEFAULT, CSI+"24~", DEFAULT],
-    [168, '[RELOAD]', med(mod(SS3+'R', CSI+'R')), DEFAULT, CSI+"25~", DEFAULT],
-    [183, '[FSCR]',   med(mod(SS3+'S', CSI+'S')), DEFAULT, CSI+"26~", DEFAULT],
-    [182, '[WINS]',   med(CSI + '15~'),           DEFAULT, CSI+"28~", DEFAULT],
-    [216, '[BRIT-]',  med(CSI + '17~'),           DEFAULT, CSI+"29~", DEFAULT],
-    [217, '[BRIT+]',  med(CSI + '18~'),           DEFAULT, CSI+"31~", DEFAULT]
+    [166, '[BACK]', med(mod(SS3 + 'P', CSI + 'P')), DEFAULT, CSI + '23~', DEFAULT], [167, '[FWD]', med(mod(SS3 + 'Q', CSI + 'Q')), DEFAULT, CSI + '24~', DEFAULT], [168, '[RELOAD]', med(mod(SS3 + 'R', CSI + 'R')), DEFAULT, CSI + '25~', DEFAULT], [183, '[FSCR]', med(mod(SS3 + 'S', CSI + 'S')), DEFAULT, CSI + '26~', DEFAULT], [182, '[WINS]', med(CSI + '15~'), DEFAULT, CSI + '28~', DEFAULT], [216, '[BRIT-]', med(CSI + '17~'), DEFAULT, CSI + '29~', DEFAULT], [217, '[BRIT+]', med(CSI + '18~'), DEFAULT, CSI + '31~', DEFAULT]
 
     // 173 [MUTE], 174 [VOL-] and 175 [VOL+] are trapped by the Chrome OS
     // window manager, so we'll never see them. Note that 173 is also
@@ -6689,7 +6926,7 @@
 hterm.Keyboard.KeyMap.prototype.onKeyHome_ = function(e) {
   if (!this.keyboard.homeKeysScroll ^ e.shiftKey) {
     if ((e.altey || e.ctrlKey || e.shiftKey) ||
-        !this.keyboard.applicationCursor) {
+      !this.keyboard.applicationCursor) {
       return '\x1b[H';
     }
 
@@ -6706,7 +6943,7 @@
 hterm.Keyboard.KeyMap.prototype.onKeyEnd_ = function(e) {
   if (!this.keyboard.homeKeysScroll ^ e.shiftKey) {
     if ((e.altKey || e.ctrlKey || e.shiftKey) ||
-        !this.keyboard.applicationCursor) {
+      !this.keyboard.applicationCursor) {
       return '\x1b[F';
     }
 
@@ -6738,7 +6975,7 @@
  */
 hterm.Keyboard.KeyMap.prototype.onKeyDel_ = function(e) {
   if (this.keyboard.altBackspaceIsMetaBackspace &&
-      this.keyboard.altKeyPressed && !e.altKey)
+    this.keyboard.altKeyPressed && !e.altKey)
     return '\x1b\x7f';
   return '\x1b[3~';
 };
@@ -6771,21 +7008,32 @@
  */
 hterm.Keyboard.KeyMap.prototype.onCtrlNum_ = function(e, keyDef) {
   // Compute a control character for a given character.
-  function ctl(ch) { return String.fromCharCode(ch.charCodeAt(0) - 64) }
+  function ctl(ch) {
+    return String.fromCharCode(ch.charCodeAt(0) - 64);
+  }
 
   if (this.keyboard.terminal.passCtrlNumber && !e.shiftKey)
     return hterm.Keyboard.KeyActions.PASS;
 
   switch (keyDef.keyCap.substr(0, 1)) {
-    case '1': return '1';
-    case '2': return ctl('@');
-    case '3': return ctl('[');
-    case '4': return ctl('\\');
-    case '5': return ctl(']');
-    case '6': return ctl('^');
-    case '7': return ctl('_');
-    case '8': return '\x7f';
-    case '9': return '9';
+    case '1':
+      return '1';
+    case '2':
+      return ctl('@');
+    case '3':
+      return ctl('[');
+    case '4':
+      return ctl('\\');
+    case '5':
+      return ctl(']');
+    case '6':
+      return ctl('^');
+    case '7':
+      return ctl('_');
+    case '8':
+      return '\x7f';
+    case '9':
+      return '9';
   }
 };
 
@@ -6848,9 +7096,9 @@
 hterm.Keyboard.KeyMap.prototype.onCtrlN_ = function(e, keyDef) {
   if (e.shiftKey) {
     window.open(document.location.href, '',
-                'chrome=no,close=yes,resize=yes,scrollbars=yes,' +
-                'minimizable=yes,width=' + window.innerWidth +
-                ',height=' + window.innerHeight);
+      'chrome=no,close=yes,resize=yes,scrollbars=yes,' +
+      'minimizable=yes,width=' + window.innerWidth +
+      ',height=' + window.innerHeight);
     return hterm.Keyboard.KeyActions.CANCEL;
   }
 
@@ -6867,7 +7115,7 @@
  */
 hterm.Keyboard.KeyMap.prototype.onCtrlV_ = function(e, keyDef) {
   if ((!e.shiftKey && this.keyboard.ctrlVPaste) ||
-      (e.shiftKey && !this.keyboard.ctrlVPaste)) {
+    (e.shiftKey && !this.keyboard.ctrlVPaste)) {
     return hterm.Keyboard.KeyActions.PASS;
   }
 
@@ -6880,9 +7128,9 @@
 hterm.Keyboard.KeyMap.prototype.onMetaN_ = function(e, keyDef) {
   if (e.shiftKey) {
     window.open(document.location.href, '',
-                'chrome=no,close=yes,resize=yes,scrollbars=yes,' +
-                'minimizable=yes,width=' + window.outerWidth +
-                ',height=' + window.outerHeight);
+      'chrome=no,close=yes,resize=yes,scrollbars=yes,' +
+      'minimizable=yes,width=' + window.outerWidth +
+      ',height=' + window.outerHeight);
     return hterm.Keyboard.KeyActions.CANCEL;
   }
 
@@ -6911,7 +7159,9 @@
 
   // Otherwise let the browser handle it as a copy command.
   if (this.keyboard.terminal.clearSelectionAfterCopy) {
-    setTimeout(function() { document.getSelection().collapseToEnd() }, 50);
+    setTimeout(function() {
+      document.getSelection().collapseToEnd();
+    }, 50);
   }
   return hterm.Keyboard.KeyActions.PASS;
 };
@@ -6927,8 +7177,8 @@
     return hterm.Keyboard.KeyActions.PASS;
 
   return this.keyboard.passMetaV ?
-      hterm.Keyboard.KeyActions.PASS :
-      hterm.Keyboard.KeyActions.DEFAULT;
+    hterm.Keyboard.KeyActions.PASS :
+    hterm.Keyboard.KeyActions.DEFAULT;
 };
 
 /**
@@ -6947,7 +7197,7 @@
     // ctrl-shift-PMZ controls zoom and this shift key is not pressed,
     // then we want to send the control code instead of affecting zoom.
     if (keyDef.keyCap == '-_')
-      return '\x1f';  // ^_
+      return '\x1f'; // ^_
 
     // Only ^_ is valid, the other sequences have no meaning.
     return hterm.Keyboard.KeyActions.CANCEL;
@@ -6961,13 +7211,15 @@
 
   var cap = keyDef.keyCap.substr(0, 1);
   if (cap == '0') {
-      this.keyboard.terminal.setFontSize(0);
-  } else {
+    this.keyboard.terminal.setFontSize(0);
+  }
+  else {
     var size = this.keyboard.terminal.getFontSize();
 
     if (cap == '-' || keyDef.keyCap == '[KP-]') {
       size -= 1;
-    } else {
+    }
+    else {
       size += 1;
     }
 
@@ -7202,31 +7454,37 @@
     if (token.type == 'integer') {
       rv.keyCode = token.value;
 
-    } else if (token.type == 'identifier') {
+    }
+    else if (token.type == 'identifier') {
       if (token.value in hterm.Parser.identifiers.modifierKeys) {
         var mod = hterm.Parser.identifiers.modifierKeys[token.value];
         if (rv[mod] && rv[mod] != '*')
           throw this.error('Duplicate modifier: ' + token.value);
         rv[mod] = true;
 
-      } else if (token.value in hterm.Parser.identifiers.keyCodes) {
+      }
+      else if (token.value in hterm.Parser.identifiers.keyCodes) {
         rv.keyCode = hterm.Parser.identifiers.keyCodes[token.value];
 
-      } else {
+      }
+      else {
         throw this.error('Unknown key: ' + token.value);
       }
 
-    } else if (token.type == 'symbol') {
+    }
+    else if (token.type == 'symbol') {
       if (token.value == '*') {
         for (var id in hterm.Parser.identifiers.modifierKeys) {
           var p = hterm.Parser.identifiers.modifierKeys[id];
           if (!rv[p])
-            rv[p] =  '*';
+            rv[p] = '*';
         }
-      } else {
+      }
+      else {
         throw this.error('Unexpected symbol: ' + token.value);
       }
-    } else {
+    }
+    else {
       throw this.error('Expected integer or identifier');
     }
 
@@ -7280,19 +7538,31 @@
 
 hterm.Parser.prototype.parseToken = function() {
   if (this.ch == '*') {
-    var rv = {type: 'symbol', value: this.ch};
+    var rv = {
+      type: 'symbol',
+      value: this.ch
+    };
     this.advance(1);
     return rv;
   }
 
   if (this.peekIdentifier())
-    return {type: 'identifier', value: this.parseIdentifier()};
+    return {
+      type: 'identifier',
+      value: this.parseIdentifier()
+    };
 
   if (this.peekString())
-    return {type: 'string', value: this.parseString()};
+    return {
+      type: 'string',
+      value: this.parseString()
+    };
 
   if (this.peekInteger())
-    return {type: 'integer', value: this.parseInteger()};
+    return {
+      type: 'integer',
+      value: this.parseInteger()
+    };
 
 
   throw this.error('Unexpected token');
@@ -7309,7 +7579,7 @@
   var base = 10;
 
   if (this.ch == '0' && this.pos < this.source.length - 1 &&
-      this.source.substr(this.pos + 1, 1) == 'x') {
+    this.source.substr(this.pos + 1, 1) == 'x') {
     return parseInt(this.parsePattern(/0x[0-9a-f]+/gi));
   }
 
@@ -7466,7 +7736,7 @@
   if (opt_expect) {
     if (this.ch.indexOf(opt_expect) == -1) {
       throw this.error('Expected one of ' + opt_expect + ', found: ' +
-          this.ch);
+        this.ch);
     }
   }
 };
@@ -7681,7 +7951,7 @@
  */
 hterm.PreferenceManager = function(profileId) {
   lib.PreferenceManager.call(this, hterm.defaultStorage,
-                             '/hterm/profiles/' + profileId);
+    '/hterm/profiles/' + profileId);
   var defs = hterm.PreferenceManager.defaultPreferences;
   Object.keys(defs).forEach(function(key) {
     this.definePreference(key, defs[key][1]);
@@ -7700,108 +7970,117 @@
 /**
  * List of categories, ordered by display order (top to bottom)
  */
-hterm.PreferenceManager.categoryDefinitions = [
-  { id: hterm.PreferenceManager.categories.Appearance,
-    text: 'Appearance (fonts, colors, images)'},
-  { id: hterm.PreferenceManager.categories.CopyPaste,
-    text: 'Copy & Paste'},
-  { id: hterm.PreferenceManager.categories.Encoding,
-    text: 'Encoding'},
-  { id: hterm.PreferenceManager.categories.Keyboard,
-    text: 'Keyboard'},
-  { id: hterm.PreferenceManager.categories.Scrolling,
-    text: 'Scrolling'},
-  { id: hterm.PreferenceManager.categories.Sounds,
-    text: 'Sounds'},
-  { id: hterm.PreferenceManager.categories.Miscellaneous,
-    text: 'Misc.'}
+hterm.PreferenceManager.categoryDefinitions = [{
+    id: hterm.PreferenceManager.categories.Appearance,
+    text: 'Appearance (fonts, colors, images)'
+  },
+  {
+    id: hterm.PreferenceManager.categories.CopyPaste,
+    text: 'Copy & Paste'
+  },
+  {
+    id: hterm.PreferenceManager.categories.Encoding,
+    text: 'Encoding'
+  },
+  {
+    id: hterm.PreferenceManager.categories.Keyboard,
+    text: 'Keyboard'
+  },
+  {
+    id: hterm.PreferenceManager.categories.Scrolling,
+    text: 'Scrolling'
+  },
+  {
+    id: hterm.PreferenceManager.categories.Sounds,
+    text: 'Sounds'
+  },
+  {
+    id: hterm.PreferenceManager.categories.Miscellaneous,
+    text: 'Misc.'
+  }
 ];
 
 
 hterm.PreferenceManager.defaultPreferences = {
-  'alt-gr-mode':
-  [hterm.PreferenceManager.categories.Keyboard, null,
-   [null, 'none', 'ctrl-alt', 'left-alt', 'right-alt'],
-   'Select an AltGr detection hack^Wheuristic.\n' +
-   '\n' +
-   '\'null\': Autodetect based on navigator.language:\n' +
-   '      \'en-us\' => \'none\', else => \'right-alt\'\n' +
-   '\'none\': Disable any AltGr related munging.\n' +
-   '\'ctrl-alt\': Assume Ctrl+Alt means AltGr.\n' +
-   '\'left-alt\': Assume left Alt means AltGr.\n' +
-   '\'right-alt\': Assume right Alt means AltGr.\n'],
-
-  'alt-backspace-is-meta-backspace':
-  [hterm.PreferenceManager.categories.Keyboard, false, 'bool',
-   'If set, undoes the Chrome OS Alt-Backspace->DEL remap, so that ' +
-   'alt-backspace indeed is alt-backspace.'],
-
-  'alt-is-meta':
-  [hterm.PreferenceManager.categories.Keyboard, false, 'bool',
-   'Set whether the alt key acts as a meta key or as a distinct alt key.'],
-
-  'alt-sends-what':
-  [hterm.PreferenceManager.categories.Keyboard, 'escape',
-   ['escape', '8-bit', 'browser-key'],
-   'Controls how the alt key is handled.\n' +
-   '\n' +
-   '  escape....... Send an ESC prefix.\n' +
-   '  8-bit........ Add 128 to the unshifted character as in xterm.\n' +
-   '  browser-key.. Wait for the keypress event and see what the browser \n' +
-   '                says.  (This won\'t work well on platforms where the \n' +
-   '                browser performs a default action for some alt sequences.)'
+  'alt-gr-mode': [hterm.PreferenceManager.categories.Keyboard, null, [null, 'none', 'ctrl-alt', 'left-alt', 'right-alt'],
+    'Select an AltGr detection hack^Wheuristic.\n' +
+    '\n' +
+    '\'null\': Autodetect based on navigator.language:\n' +
+    '      \'en-us\' => \'none\', else => \'right-alt\'\n' +
+    '\'none\': Disable any AltGr related munging.\n' +
+    '\'ctrl-alt\': Assume Ctrl+Alt means AltGr.\n' +
+    '\'left-alt\': Assume left Alt means AltGr.\n' +
+    '\'right-alt\': Assume right Alt means AltGr.\n'
   ],
 
-  'audible-bell-sound':
-  [hterm.PreferenceManager.categories.Sounds, 'lib-resource:hterm/audio/bell',
-   'url',
-   'URL of the terminal bell sound.  Empty string for no audible bell.'],
+  'alt-backspace-is-meta-backspace': [hterm.PreferenceManager.categories.Keyboard, false, 'bool',
+    'If set, undoes the Chrome OS Alt-Backspace->DEL remap, so that ' +
+    'alt-backspace indeed is alt-backspace.'
+  ],
 
-  'desktop-notification-bell':
-  [hterm.PreferenceManager.categories.Sounds, false, 'bool',
-   'If true, terminal bells in the background will create a Web ' +
-   'Notification. https://www.w3.org/TR/notifications/\n' +
-   '\n'+
-   'Displaying notifications requires permission from the user. When this ' +
-   'option is set to true, hterm will attempt to ask the user for permission ' +
-   'if necessary. Note browsers may not show this permission request if it ' +
-   'did not originate from a user action.\n' +
-   '\n' +
-   'Chrome extensions with the "notifications" permission have permission to ' +
-   'display notifications.'],
+  'alt-is-meta': [hterm.PreferenceManager.categories.Keyboard, false, 'bool',
+    'Set whether the alt key acts as a meta key or as a distinct alt key.'
+  ],
 
-  'background-color':
-  [hterm.PreferenceManager.categories.Appearance, 'rgb(16, 16, 16)', 'color',
-   'The background color for text with no other color attributes.'],
+  'alt-sends-what': [hterm.PreferenceManager.categories.Keyboard, 'escape', ['escape', '8-bit', 'browser-key'],
+    'Controls how the alt key is handled.\n' +
+    '\n' +
+    '  escape....... Send an ESC prefix.\n' +
+    '  8-bit........ Add 128 to the unshifted character as in xterm.\n' +
+    '  browser-key.. Wait for the keypress event and see what the browser \n' +
+    '                says.  (This won\'t work well on platforms where the \n' +
+    '                browser performs a default action for some alt sequences.)'
+  ],
 
-  'background-image':
-  [hterm.PreferenceManager.categories.Appearance, '', 'string',
-   'CSS value of the background image.  Empty string for no image.\n' +
-   '\n' +
-   'For example:\n' +
-   '  url(https://goo.gl/anedTK)\n' +
-   '  linear-gradient(top bottom, blue, red)'],
+  'audible-bell-sound': [hterm.PreferenceManager.categories.Sounds, 'lib-resource:hterm/audio/bell',
+    'url',
+    'URL of the terminal bell sound.  Empty string for no audible bell.'
+  ],
 
-  'background-size':
-  [hterm.PreferenceManager.categories.Appearance, '', 'string',
-   'CSS value of the background image size.  Defaults to none.'],
+  'desktop-notification-bell': [hterm.PreferenceManager.categories.Sounds, false, 'bool',
+    'If true, terminal bells in the background will create a Web ' +
+    'Notification. https://www.w3.org/TR/notifications/\n' +
+    '\n' +
+    'Displaying notifications requires permission from the user. When this ' +
+    'option is set to true, hterm will attempt to ask the user for permission ' +
+    'if necessary. Note browsers may not show this permission request if it ' +
+    'did not originate from a user action.\n' +
+    '\n' +
+    'Chrome extensions with the "notifications" permission have permission to ' +
+    'display notifications.'
+  ],
 
-  'background-position':
-  [hterm.PreferenceManager.categories.Appearance, '', 'string',
-   'CSS value of the background image position.\n' +
-   '\n' +
-   'For example:\n' +
-   '  10% 10%\n' +
-   '  center'],
+  'background-color': [hterm.PreferenceManager.categories.Appearance, 'rgb(16, 16, 16)', 'color',
+    'The background color for text with no other color attributes.'
+  ],
 
-  'backspace-sends-backspace':
-  [hterm.PreferenceManager.categories.Keyboard, false, 'bool',
-   'If true, the backspace should send BS (\'\\x08\', aka ^H).  Otherwise ' +
-   'the backspace key should send \'\\x7f\'.'],
+  'background-image': [hterm.PreferenceManager.categories.Appearance, '', 'string',
+    'CSS value of the background image.  Empty string for no image.\n' +
+    '\n' +
+    'For example:\n' +
+    '  url(https://goo.gl/anedTK)\n' +
+    '  linear-gradient(top bottom, blue, red)'
+  ],
 
-  'character-map-overrides':
-  [hterm.PreferenceManager.categories.Appearance, null, 'value',
-    'This is specified as an object. It is a sparse array, where each '  +
+  'background-size': [hterm.PreferenceManager.categories.Appearance, '', 'string',
+    'CSS value of the background image size.  Defaults to none.'
+  ],
+
+  'background-position': [hterm.PreferenceManager.categories.Appearance, '', 'string',
+    'CSS value of the background image position.\n' +
+    '\n' +
+    'For example:\n' +
+    '  10% 10%\n' +
+    '  center'
+  ],
+
+  'backspace-sends-backspace': [hterm.PreferenceManager.categories.Keyboard, false, 'bool',
+    'If true, the backspace should send BS (\'\\x08\', aka ^H).  Otherwise ' +
+    'the backspace key should send \'\\x7f\'.'
+  ],
+
+  'character-map-overrides': [hterm.PreferenceManager.categories.Appearance, null, 'value',
+    'This is specified as an object. It is a sparse array, where each ' +
     'property is the character set code and the value is an object that is ' +
     'a sparse array itself. In that sparse array, each property is the ' +
     'received character and the value is the displayed character.\n' +
@@ -7811,257 +8090,258 @@
     '"0":"\\u2588"}}'
   ],
 
-  'close-on-exit':
-  [hterm.PreferenceManager.categories.Miscellaneous, true, 'bool',
-   'Whether or not to close the window when the command exits.'],
+  'close-on-exit': [hterm.PreferenceManager.categories.Miscellaneous, true, 'bool',
+    'Whether or not to close the window when the command exits.'
+  ],
 
-  'cursor-blink':
-  [hterm.PreferenceManager.categories.Appearance, false, 'bool',
-   'Whether or not to blink the cursor by default.'],
+  'cursor-blink': [hterm.PreferenceManager.categories.Appearance, false, 'bool',
+    'Whether or not to blink the cursor by default.'
+  ],
 
-  'cursor-blink-cycle':
-  [hterm.PreferenceManager.categories.Appearance, [1000, 500], 'value',
-   'The cursor blink rate in milliseconds.\n' +
-   '\n' +
-   'A two element array, the first of which is how long the cursor should be ' +
-   'on, second is how long it should be off.'],
+  'cursor-blink-cycle': [hterm.PreferenceManager.categories.Appearance, [1000, 500], 'value',
+    'The cursor blink rate in milliseconds.\n' +
+    '\n' +
+    'A two element array, the first of which is how long the cursor should be ' +
+    'on, second is how long it should be off.'
+  ],
 
-  'cursor-color':
-  [hterm.PreferenceManager.categories.Appearance, 'rgba(255, 0, 0, 0.5)',
-   'color',
-   'The color of the visible cursor.'],
+  'cursor-color': [hterm.PreferenceManager.categories.Appearance, 'rgba(255, 0, 0, 0.5)',
+    'color',
+    'The color of the visible cursor.'
+  ],
 
-  'color-palette-overrides':
-  [hterm.PreferenceManager.categories.Appearance, null, 'value',
-   'Override colors in the default palette.\n' +
-   '\n' +
-   'This can be specified as an array or an object.  If specified as an ' +
-   'object it is assumed to be a sparse array, where each property ' +
-   'is a numeric index into the color palette.\n' +
-   '\n' +
-   'Values can be specified as almost any css color value.  This ' +
-   'includes #RGB, #RRGGBB, rgb(...), rgba(...), and any color names ' +
-   'that are also part of the stock X11 rgb.txt file.\n' +
-   '\n' +
-   'You can use \'null\' to specify that the default value should be not ' +
-   'be changed.  This is useful for skipping a small number of indices ' +
-   'when the value is specified as an array.'],
+  'color-palette-overrides': [hterm.PreferenceManager.categories.Appearance, null, 'value',
+    'Override colors in the default palette.\n' +
+    '\n' +
+    'This can be specified as an array or an object.  If specified as an ' +
+    'object it is assumed to be a sparse array, where each property ' +
+    'is a numeric index into the color palette.\n' +
+    '\n' +
+    'Values can be specified as almost any css color value.  This ' +
+    'includes #RGB, #RRGGBB, rgb(...), rgba(...), and any color names ' +
+    'that are also part of the stock X11 rgb.txt file.\n' +
+    '\n' +
+    'You can use \'null\' to specify that the default value should be not ' +
+    'be changed.  This is useful for skipping a small number of indices ' +
+    'when the value is specified as an array.'
+  ],
 
-  'copy-on-select':
-  [hterm.PreferenceManager.categories.CopyPaste, true, 'bool',
-   'Automatically copy mouse selection to the clipboard.'],
+  'copy-on-select': [hterm.PreferenceManager.categories.CopyPaste, true, 'bool',
+    'Automatically copy mouse selection to the clipboard.'
+  ],
 
-  'use-default-window-copy':
-  [hterm.PreferenceManager.categories.CopyPaste, false, 'bool',
-   'Whether to use the default window copy behavior'],
+  'use-default-window-copy': [hterm.PreferenceManager.categories.CopyPaste, false, 'bool',
+    'Whether to use the default window copy behavior'
+  ],
 
-  'clear-selection-after-copy':
-  [hterm.PreferenceManager.categories.CopyPaste, true, 'bool',
-   'Whether to clear the selection after copying.'],
+  'clear-selection-after-copy': [hterm.PreferenceManager.categories.CopyPaste, true, 'bool',
+    'Whether to clear the selection after copying.'
+  ],
 
-  'ctrl-plus-minus-zero-zoom':
-  [hterm.PreferenceManager.categories.Keyboard, true, 'bool',
-   'If true, Ctrl-Plus/Minus/Zero controls zoom.\n' +
-   'If false, Ctrl-Shift-Plus/Minus/Zero controls zoom, Ctrl-Minus sends ^_, ' +
-   'Ctrl-Plus/Zero do nothing.'],
+  'ctrl-plus-minus-zero-zoom': [hterm.PreferenceManager.categories.Keyboard, true, 'bool',
+    'If true, Ctrl-Plus/Minus/Zero controls zoom.\n' +
+    'If false, Ctrl-Shift-Plus/Minus/Zero controls zoom, Ctrl-Minus sends ^_, ' +
+    'Ctrl-Plus/Zero do nothing.'
+  ],
 
-  'ctrl-c-copy':
-  [hterm.PreferenceManager.categories.Keyboard, false, 'bool',
-   'Ctrl+C copies if true, send ^C to host if false.\n' +
-   'Ctrl+Shift+C sends ^C to host if true, copies if false.'],
+  'ctrl-c-copy': [hterm.PreferenceManager.categories.Keyboard, false, 'bool',
+    'Ctrl+C copies if true, send ^C to host if false.\n' +
+    'Ctrl+Shift+C sends ^C to host if true, copies if false.'
+  ],
 
-  'ctrl-v-paste':
-  [hterm.PreferenceManager.categories.Keyboard, false, 'bool',
-   'Ctrl+V pastes if true, send ^V to host if false.\n' +
-   'Ctrl+Shift+V sends ^V to host if true, pastes if false.'],
+  'ctrl-v-paste': [hterm.PreferenceManager.categories.Keyboard, false, 'bool',
+    'Ctrl+V pastes if true, send ^V to host if false.\n' +
+    'Ctrl+Shift+V sends ^V to host if true, pastes if false.'
+  ],
 
-  'east-asian-ambiguous-as-two-column':
-  [hterm.PreferenceManager.categories.Keyboard, false, 'bool',
-   'Set whether East Asian Ambiguous characters have two column width.'],
+  'east-asian-ambiguous-as-two-column': [hterm.PreferenceManager.categories.Keyboard, false, 'bool',
+    'Set whether East Asian Ambiguous characters have two column width.'
+  ],
 
-  'enable-8-bit-control':
-  [hterm.PreferenceManager.categories.Keyboard, false, 'bool',
-   'True to enable 8-bit control characters, false to ignore them.\n' +
-   '\n' +
-   'We\'ll respect the two-byte versions of these control characters ' +
-   'regardless of this setting.'],
+  'enable-8-bit-control': [hterm.PreferenceManager.categories.Keyboard, false, 'bool',
+    'True to enable 8-bit control characters, false to ignore them.\n' +
+    '\n' +
+    'We\'ll respect the two-byte versions of these control characters ' +
+    'regardless of this setting.'
+  ],
 
-  'enable-bold':
-  [hterm.PreferenceManager.categories.Appearance, null, 'tristate',
-   'True if we should use bold weight font for text with the bold/bright ' +
-   'attribute.  False to use the normal weight font.  Null to autodetect.'],
+  'enable-bold': [hterm.PreferenceManager.categories.Appearance, null, 'tristate',
+    'True if we should use bold weight font for text with the bold/bright ' +
+    'attribute.  False to use the normal weight font.  Null to autodetect.'
+  ],
 
-  'enable-bold-as-bright':
-  [hterm.PreferenceManager.categories.Appearance, true, 'bool',
-   'True if we should use bright colors (8-15 on a 16 color palette) ' +
-   'for any text with the bold attribute.  False otherwise.'],
+  'enable-bold-as-bright': [hterm.PreferenceManager.categories.Appearance, true, 'bool',
+    'True if we should use bright colors (8-15 on a 16 color palette) ' +
+    'for any text with the bold attribute.  False otherwise.'
+  ],
 
-  'enable-blink':
-  [hterm.PreferenceManager.categories.Appearance, true, 'bool',
-   'True if we should respect the blink attribute.  False to ignore it.  '],
+  'enable-blink': [hterm.PreferenceManager.categories.Appearance, true, 'bool',
+    'True if we should respect the blink attribute.  False to ignore it.  '
+  ],
 
-  'enable-clipboard-notice':
-  [hterm.PreferenceManager.categories.CopyPaste, true, 'bool',
-   'Show a message in the terminal when the host writes to the clipboard.'],
+  'enable-clipboard-notice': [hterm.PreferenceManager.categories.CopyPaste, true, 'bool',
+    'Show a message in the terminal when the host writes to the clipboard.'
+  ],
 
-  'enable-clipboard-write':
-  [hterm.PreferenceManager.categories.CopyPaste, true, 'bool',
-   'Allow the host to write directly to the system clipboard.'],
+  'enable-clipboard-write': [hterm.PreferenceManager.categories.CopyPaste, true, 'bool',
+    'Allow the host to write directly to the system clipboard.'
+  ],
 
-  'enable-dec12':
-  [hterm.PreferenceManager.categories.Miscellaneous, false, 'bool',
-   'Respect the host\'s attempt to change the cursor blink status using ' +
-   'DEC Private Mode 12.'],
+  'enable-dec12': [hterm.PreferenceManager.categories.Miscellaneous, false, 'bool',
+    'Respect the host\'s attempt to change the cursor blink status using ' +
+    'DEC Private Mode 12.'
+  ],
 
-  'environment':
-  [hterm.PreferenceManager.categories.Miscellaneous, {'TERM': 'xterm-256color'},
-   'value',
-   'The default environment variables, as an object.'],
+  'environment': [hterm.PreferenceManager.categories.Miscellaneous, {
+      'TERM': 'xterm-256color'
+    },
+    'value',
+    'The default environment variables, as an object.'
+  ],
 
-  'font-family':
-  [hterm.PreferenceManager.categories.Appearance,
-   '"DejaVu Sans Mono", "Everson Mono", FreeMono, "Menlo", "Terminal", ' +
-   'monospace', 'string',
-   'Default font family for the terminal text.'],
+  'font-family': [hterm.PreferenceManager.categories.Appearance,
+    '"DejaVu Sans Mono", "Everson Mono", FreeMono, "Menlo", "Terminal", ' +
+    'monospace', 'string',
+    'Default font family for the terminal text.'
+  ],
 
-  'font-size':
-  [hterm.PreferenceManager.categories.Appearance, 15, 'int',
-   'The default font size in pixels.'],
+  'font-size': [hterm.PreferenceManager.categories.Appearance, 15, 'int',
+    'The default font size in pixels.'
+  ],
 
-  'font-smoothing':
-  [hterm.PreferenceManager.categories.Appearance, 'antialiased', 'string',
-   'CSS font-smoothing property.'],
+  'font-smoothing': [hterm.PreferenceManager.categories.Appearance, 'antialiased', 'string',
+    'CSS font-smoothing property.'
+  ],
 
-  'foreground-color':
-  [hterm.PreferenceManager.categories.Appearance, 'rgb(240, 240, 240)', 'color',
-   'The foreground color for text with no other color attributes.'],
+  'foreground-color': [hterm.PreferenceManager.categories.Appearance, 'rgb(240, 240, 240)', 'color',
+    'The foreground color for text with no other color attributes.'
+  ],
 
-  'home-keys-scroll':
-  [hterm.PreferenceManager.categories.Keyboard, false, 'bool',
-   'If true, home/end will control the terminal scrollbar and shift home/end ' +
-   'will send the VT keycodes.  If false then home/end sends VT codes and ' +
-   'shift home/end scrolls.'],
+  'home-keys-scroll': [hterm.PreferenceManager.categories.Keyboard, false, 'bool',
+    'If true, home/end will control the terminal scrollbar and shift home/end ' +
+    'will send the VT keycodes.  If false then home/end sends VT codes and ' +
+    'shift home/end scrolls.'
+  ],
 
-  'keybindings':
-  [hterm.PreferenceManager.categories.Keyboard, null, 'value',
-   'A map of key sequence to key actions.  Key sequences include zero or ' +
-   'more modifier keys followed by a key code.  Key codes can be decimal or ' +
-   'hexadecimal numbers, or a key identifier.  Key actions can be specified ' +
-   'a string to send to the host, or an action identifier.  For a full ' +
-   'list of key code and action identifiers, see https://goo.gl/8AoD09.' +
-   '\n' +
-   '\n' +
-   'Sample keybindings:\n' +
-   '{ "Ctrl-Alt-K": "clearScrollback",\n' +
-   '  "Ctrl-Shift-L": "PASS",\n' +
-   '  "Ctrl-H": "\'HELLO\\n\'"\n' +
-   '}'],
+  'keybindings': [hterm.PreferenceManager.categories.Keyboard, null, 'value',
+    'A map of key sequence to key actions.  Key sequences include zero or ' +
+    'more modifier keys followed by a key code.  Key codes can be decimal or ' +
+    'hexadecimal numbers, or a key identifier.  Key actions can be specified ' +
+    'a string to send to the host, or an action identifier.  For a full ' +
+    'list of key code and action identifiers, see https://goo.gl/8AoD09.' +
+    '\n' +
+    '\n' +
+    'Sample keybindings:\n' +
+    '{ "Ctrl-Alt-K": "clearScrollback",\n' +
+    '  "Ctrl-Shift-L": "PASS",\n' +
+    '  "Ctrl-H": "\'HELLO\\n\'"\n' +
+    '}'
+  ],
 
-  'max-string-sequence':
-  [hterm.PreferenceManager.categories.Encoding, 100000, 'int',
-   'Max length of a DCS, OSC, PM, or APS sequence before we give up and ' +
-   'ignore the code.'],
+  'max-string-sequence': [hterm.PreferenceManager.categories.Encoding, 100000, 'int',
+    'Max length of a DCS, OSC, PM, or APS sequence before we give up and ' +
+    'ignore the code.'
+  ],
 
-  'media-keys-are-fkeys':
-  [hterm.PreferenceManager.categories.Keyboard, false, 'bool',
-   'If true, convert media keys to their Fkey equivalent. If false, let ' +
-   'the browser handle the keys.'],
+  'media-keys-are-fkeys': [hterm.PreferenceManager.categories.Keyboard, false, 'bool',
+    'If true, convert media keys to their Fkey equivalent. If false, let ' +
+    'the browser handle the keys.'
+  ],
 
-  'meta-sends-escape':
-  [hterm.PreferenceManager.categories.Keyboard, true, 'bool',
-   'Set whether the meta key sends a leading escape or not.'],
+  'meta-sends-escape': [hterm.PreferenceManager.categories.Keyboard, true, 'bool',
+    'Set whether the meta key sends a leading escape or not.'
+  ],
 
-  'mouse-paste-button':
-  [hterm.PreferenceManager.categories.CopyPaste, null,
-   [null, 0, 1, 2, 3, 4, 5, 6],
-   'Mouse paste button, or null to autodetect.\n' +
-   '\n' +
-   'For autodetect, we\'ll try to enable middle button paste for non-X11 ' +
-   'platforms.  On X11 we move it to button 3.'],
+  'mouse-paste-button': [hterm.PreferenceManager.categories.CopyPaste, null, [null, 0, 1, 2, 3, 4, 5, 6],
+    'Mouse paste button, or null to autodetect.\n' +
+    '\n' +
+    'For autodetect, we\'ll try to enable middle button paste for non-X11 ' +
+    'platforms.  On X11 we move it to button 3.'
+  ],
 
-  'page-keys-scroll':
-  [hterm.PreferenceManager.categories.Keyboard, false, 'bool',
-   'If true, page up/down will control the terminal scrollbar and shift ' +
-   'page up/down will send the VT keycodes.  If false then page up/down ' +
-   'sends VT codes and shift page up/down scrolls.'],
+  'page-keys-scroll': [hterm.PreferenceManager.categories.Keyboard, false, 'bool',
+    'If true, page up/down will control the terminal scrollbar and shift ' +
+    'page up/down will send the VT keycodes.  If false then page up/down ' +
+    'sends VT codes and shift page up/down scrolls.'
+  ],
 
-  'pass-alt-number':
-  [hterm.PreferenceManager.categories.Keyboard, null, 'tristate',
-   'Set whether we should pass Alt-1..9 to the browser.\n' +
-   '\n' +
-   'This is handy when running hterm in a browser tab, so that you don\'t ' +
-   'lose Chrome\'s "switch to tab" keyboard accelerators.  When not running ' +
-   'in a tab it\'s better to send these keys to the host so they can be ' +
-   'used in vim or emacs.\n' +
-   '\n' +
-   'If true, Alt-1..9 will be handled by the browser.  If false, Alt-1..9 ' +
-   'will be sent to the host.  If null, autodetect based on browser platform ' +
-   'and window type.'],
+  'pass-alt-number': [hterm.PreferenceManager.categories.Keyboard, null, 'tristate',
+    'Set whether we should pass Alt-1..9 to the browser.\n' +
+    '\n' +
+    'This is handy when running hterm in a browser tab, so that you don\'t ' +
+    'lose Chrome\'s "switch to tab" keyboard accelerators.  When not running ' +
+    'in a tab it\'s better to send these keys to the host so they can be ' +
+    'used in vim or emacs.\n' +
+    '\n' +
+    'If true, Alt-1..9 will be handled by the browser.  If false, Alt-1..9 ' +
+    'will be sent to the host.  If null, autodetect based on browser platform ' +
+    'and window type.'
+  ],
 
-  'pass-ctrl-number':
-  [hterm.PreferenceManager.categories.Keyboard, null, 'tristate',
-   'Set whether we should pass Ctrl-1..9 to the browser.\n' +
-   '\n' +
-   'This is handy when running hterm in a browser tab, so that you don\'t ' +
-   'lose Chrome\'s "switch to tab" keyboard accelerators.  When not running ' +
-   'in a tab it\'s better to send these keys to the host so they can be ' +
-   'used in vim or emacs.\n' +
-   '\n' +
-   'If true, Ctrl-1..9 will be handled by the browser.  If false, Ctrl-1..9 ' +
-   'will be sent to the host.  If null, autodetect based on browser platform ' +
-   'and window type.'],
+  'pass-ctrl-number': [hterm.PreferenceManager.categories.Keyboard, null, 'tristate',
+    'Set whether we should pass Ctrl-1..9 to the browser.\n' +
+    '\n' +
+    'This is handy when running hterm in a browser tab, so that you don\'t ' +
+    'lose Chrome\'s "switch to tab" keyboard accelerators.  When not running ' +
+    'in a tab it\'s better to send these keys to the host so they can be ' +
+    'used in vim or emacs.\n' +
+    '\n' +
+    'If true, Ctrl-1..9 will be handled by the browser.  If false, Ctrl-1..9 ' +
+    'will be sent to the host.  If null, autodetect based on browser platform ' +
+    'and window type.'
+  ],
 
-   'pass-meta-number':
-  [hterm.PreferenceManager.categories.Keyboard, null, 'tristate',
-   'Set whether we should pass Meta-1..9 to the browser.\n' +
-   '\n' +
-   'This is handy when running hterm in a browser tab, so that you don\'t ' +
-   'lose Chrome\'s "switch to tab" keyboard accelerators.  When not running ' +
-   'in a tab it\'s better to send these keys to the host so they can be ' +
-   'used in vim or emacs.\n' +
-   '\n' +
-   'If true, Meta-1..9 will be handled by the browser.  If false, Meta-1..9 ' +
-   'will be sent to the host.  If null, autodetect based on browser platform ' +
-   'and window type.'],
+  'pass-meta-number': [hterm.PreferenceManager.categories.Keyboard, null, 'tristate',
+    'Set whether we should pass Meta-1..9 to the browser.\n' +
+    '\n' +
+    'This is handy when running hterm in a browser tab, so that you don\'t ' +
+    'lose Chrome\'s "switch to tab" keyboard accelerators.  When not running ' +
+    'in a tab it\'s better to send these keys to the host so they can be ' +
+    'used in vim or emacs.\n' +
+    '\n' +
+    'If true, Meta-1..9 will be handled by the browser.  If false, Meta-1..9 ' +
+    'will be sent to the host.  If null, autodetect based on browser platform ' +
+    'and window type.'
+  ],
 
-  'pass-meta-v':
-  [hterm.PreferenceManager.categories.Keyboard, true, 'bool',
-   'Set whether meta-V gets passed to host.'],
+  'pass-meta-v': [hterm.PreferenceManager.categories.Keyboard, true, 'bool',
+    'Set whether meta-V gets passed to host.'
+  ],
 
-  'receive-encoding':
-  [hterm.PreferenceManager.categories.Encoding, 'utf-8', ['utf-8', 'raw'],
-   'Set the expected encoding for data received from the host.\n' +
-   '\n' +
-   'Valid values are \'utf-8\' and \'raw\'.'],
+  'receive-encoding': [hterm.PreferenceManager.categories.Encoding, 'utf-8', ['utf-8', 'raw'],
+    'Set the expected encoding for data received from the host.\n' +
+    '\n' +
+    'Valid values are \'utf-8\' and \'raw\'.'
+  ],
 
-  'scroll-on-keystroke':
-  [hterm.PreferenceManager.categories.Scrolling, true, 'bool',
-   'If true, scroll to the bottom on any keystroke.'],
+  'scroll-on-keystroke': [hterm.PreferenceManager.categories.Scrolling, true, 'bool',
+    'If true, scroll to the bottom on any keystroke.'
+  ],
 
-  'scroll-on-output':
-  [hterm.PreferenceManager.categories.Scrolling, false, 'bool',
-   'If true, scroll to the bottom on terminal output.'],
+  'scroll-on-output': [hterm.PreferenceManager.categories.Scrolling, false, 'bool',
+    'If true, scroll to the bottom on terminal output.'
+  ],
 
-  'scrollbar-visible':
-  [hterm.PreferenceManager.categories.Scrolling, true, 'bool',
-   'The vertical scrollbar mode.'],
+  'scrollbar-visible': [hterm.PreferenceManager.categories.Scrolling, true, 'bool',
+    'The vertical scrollbar mode.'
+  ],
 
-  'scroll-wheel-move-multiplier':
-  [hterm.PreferenceManager.categories.Scrolling, 1, 'int',
-   'The multiplier for the pixel delta in mousewheel event caused by the ' +
-   'scroll wheel. Alters how fast the page scrolls.'],
+  'scroll-wheel-move-multiplier': [hterm.PreferenceManager.categories.Scrolling, 1, 'int',
+    'The multiplier for the pixel delta in mousewheel event caused by the ' +
+    'scroll wheel. Alters how fast the page scrolls.'
+  ],
 
-  'send-encoding':
-  [hterm.PreferenceManager.categories.Encoding, 'utf-8', ['utf-8', 'raw'],
-   'Set the encoding for data sent to host.'],
+  'send-encoding': [hterm.PreferenceManager.categories.Encoding, 'utf-8', ['utf-8', 'raw'],
+    'Set the encoding for data sent to host.'
+  ],
 
-  'shift-insert-paste':
-  [hterm.PreferenceManager.categories.Keyboard, true, 'bool',
-   'Shift + Insert pastes if true, sent to host if false.'],
+  'shift-insert-paste': [hterm.PreferenceManager.categories.Keyboard, true, 'bool',
+    'Shift + Insert pastes if true, sent to host if false.'
+  ],
 
-  'user-css':
-  [hterm.PreferenceManager.categories.Appearance, '', 'url',
-   'URL of user stylesheet to include in the terminal document.']
+  'user-css': [hterm.PreferenceManager.categories.Appearance, '', 'url',
+    'URL of user stylesheet to include in the terminal document.'
+  ]
 };
 
 hterm.PreferenceManager.prototype = {
@@ -8159,7 +8439,8 @@
   if (opt_lastCallback) {
     if (list) {
       list.push(opt_lastCallback);
-    } else {
+    }
+    else {
       list = [opt_lastCallback];
     }
   }
@@ -8175,7 +8456,7 @@
 'use strict';
 
 lib.rtdep('lib.f', 'lib.wc',
-          'hterm.RowCol', 'hterm.Size', 'hterm.TextAttributes');
+  'hterm.RowCol', 'hterm.Size', 'hterm.TextAttributes');
 
 /**
  * @fileoverview This class represents a single terminal screen full of text.
@@ -8428,7 +8709,8 @@
   var text;
   if (this.textAttributes.isDefault()) {
     text = '';
-  } else {
+  }
+  else {
     text = lib.f.getWhitespace(this.columnCount_);
   }
 
@@ -8477,7 +8759,8 @@
   if (row >= this.rowsArray.length) {
     console.error('Row out of bounds: ' + row);
     row = this.rowsArray.length - 1;
-  } else if (row < 0) {
+  }
+  else if (row < 0) {
     console.error('Row out of bounds: ' + row);
     row = 0;
   }
@@ -8485,7 +8768,8 @@
   if (column >= this.columnCount_) {
     console.error('Column out of bounds: ' + column);
     column = this.columnCount_ - 1;
-  } else if (column < 0) {
+  }
+  else if (column < 0) {
     console.error('Column out of bounds: ' + column);
     column = 0;
   }
@@ -8507,7 +8791,8 @@
       node = this.cursorNode_;
       currentColumn = this.cursorPosition.column - this.cursorOffset_;
     }
-  } else {
+  }
+  else {
     this.cursorRowNode_ = rowNode;
   }
 
@@ -8534,7 +8819,8 @@
 hterm.Screen.prototype.syncSelectionCaret = function(selection) {
   try {
     selection.collapse(this.cursorNode_, this.cursorOffset_);
-  } catch (firefoxIgnoredException) {
+  }
+  catch (firefoxIgnoredException) {
     // FF can throw an exception if the range is off, rather than just not
     // performing the collapse.
   }
@@ -8596,7 +8882,7 @@
 
   if (this.cursorOffset_ < width - 1) {
     this.cursorNode_.textContent = hterm.TextAttributes.nodeSubstr(
-        this.cursorNode_, 0, this.cursorOffset_ + 1);
+      this.cursorNode_, 0, this.cursorOffset_ + 1);
   }
 
   // Remove all nodes after the cursor.
@@ -8612,7 +8898,8 @@
     // If the cursor was within the screen before we started then restore its
     // position.
     this.setCursorPosition(this.cursorPosition.row, currentColumn);
-  } else {
+  }
+  else {
     // Otherwise leave it at the the last column in the overflow state.
     this.cursorPosition.overflow = true;
   }
@@ -8659,21 +8946,23 @@
     // color, and strikethrough would be visible on whitespace, so we can't use
     // one of those spans to hold the text.
     if (!(this.textAttributes.underline ||
-          this.textAttributes.strikethrough ||
-          this.textAttributes.background ||
-          this.textAttributes.wcNode ||
-          this.textAttributes.tileData != null)) {
+        this.textAttributes.strikethrough ||
+        this.textAttributes.background ||
+        this.textAttributes.wcNode ||
+        this.textAttributes.tileData != null)) {
       // Best case scenario, we can just pretend the spaces were part of the
       // original string.
       str = ws + str;
-    } else if (cursorNode.nodeType == 3 ||
-               !(cursorNode.wcNode ||
-                 cursorNode.tileNode ||
-                 cursorNode.style.textDecoration ||
-                 cursorNode.style.backgroundColor)) {
+    }
+    else if (cursorNode.nodeType == 3 ||
+      !(cursorNode.wcNode ||
+        cursorNode.tileNode ||
+        cursorNode.style.textDecoration ||
+        cursorNode.style.backgroundColor)) {
       // Second best case, the current node is able to hold the whitespace.
       cursorNode.textContent = (cursorNodeText += ws);
-    } else {
+    }
+    else {
       // Worst case, we have to create a new node to hold the whitespace.
       var wsNode = cursorNode.ownerDocument.createTextNode(ws);
       this.cursorRowNode_.insertBefore(wsNode, cursorNode.nextSibling);
@@ -8690,12 +8979,14 @@
     // The new text can be placed directly in the cursor node.
     if (reverseOffset == 0) {
       cursorNode.textContent = cursorNodeText + str;
-    } else if (offset == 0) {
+    }
+    else if (offset == 0) {
       cursorNode.textContent = str + cursorNodeText;
-    } else {
+    }
+    else {
       cursorNode.textContent =
-          hterm.TextAttributes.nodeSubstr(cursorNode, 0, offset) +
-          str + hterm.TextAttributes.nodeSubstr(cursorNode, offset);
+        hterm.TextAttributes.nodeSubstr(cursorNode, 0, offset) +
+        str + hterm.TextAttributes.nodeSubstr(cursorNode, offset);
     }
 
     this.cursorOffset_ += strWidth;
@@ -8710,7 +9001,7 @@
     // At the beginning of the cursor node, the check the previous sibling.
     var previousSibling = cursorNode.previousSibling;
     if (previousSibling &&
-        this.textAttributes.matchesContainer(previousSibling)) {
+      this.textAttributes.matchesContainer(previousSibling)) {
       previousSibling.textContent += str;
       this.cursorNode_ = previousSibling;
       this.cursorOffset_ = lib.wc.strWidth(previousSibling.textContent);
@@ -8728,7 +9019,7 @@
     // At the end of the cursor node, the check the next sibling.
     var nextSibling = cursorNode.nextSibling;
     if (nextSibling &&
-        this.textAttributes.matchesContainer(nextSibling)) {
+      this.textAttributes.matchesContainer(nextSibling)) {
       nextSibling.textContent = str + nextSibling.textContent;
       this.cursorNode_ = nextSibling;
       this.cursorOffset_ = lib.wc.strWidth(str);
@@ -8769,7 +9060,7 @@
 
   var width = lib.wc.strWidth(str);
   if (this.textAttributes.matchesContainer(this.cursorNode_) &&
-      this.cursorNode_.textContent.substr(this.cursorOffset_) == str) {
+    this.cursorNode_.textContent.substr(this.cursorOffset_) == str) {
     // This overwrite would be a no-op, just move the cursor and return.
     this.cursorOffset_ += width;
     this.cursorPosition.column += width;
@@ -8805,7 +9096,7 @@
   while (node && count) {
     startLength = hterm.TextAttributes.nodeWidth(node);
     node.textContent = hterm.TextAttributes.nodeSubstr(node, 0, offset) +
-        hterm.TextAttributes.nodeSubstr(node, offset + count);
+      hterm.TextAttributes.nodeSubstr(node, offset + count);
     endLength = hterm.TextAttributes.nodeWidth(node);
     count -= startLength - endLength;
     if (offset < startLength && endLength && startLength == endLength) {
@@ -8833,11 +9124,13 @@
     if (cursorNode.previousSibling) {
       this.cursorNode_ = cursorNode.previousSibling;
       this.cursorOffset_ = hterm.TextAttributes.nodeWidth(
-          cursorNode.previousSibling);
-    } else if (cursorNode.nextSibling) {
+        cursorNode.previousSibling);
+    }
+    else if (cursorNode.nextSibling) {
       this.cursorNode_ = cursorNode.nextSibling;
       this.cursorOffset_ = 0;
-    } else {
+    }
+    else {
       var emptyNode = this.cursorRowNode_.ownerDocument.createTextNode('');
       this.cursorRowNode_.appendChild(emptyNode);
       this.cursorNode_ = emptyNode;
@@ -8858,7 +9151,7 @@
  **/
 hterm.Screen.prototype.getLineStartRow_ = function(row) {
   while (row.previousSibling &&
-         row.previousSibling.hasAttribute('line-overflow')) {
+    row.previousSibling.hasAttribute('line-overflow')) {
     row = row.previousSibling;
   }
   return row;
@@ -8872,12 +9165,13 @@
  * @return {string} Text content of line.
  **/
 hterm.Screen.prototype.getLineText_ = function(row) {
-  var rowText = "";
+  var rowText = '';
   while (row) {
     rowText += row.textContent;
     if (row.hasAttribute('line-overflow')) {
       row = row.nextSibling;
-    } else {
+    }
+    else {
       break;
     }
   }
@@ -8920,7 +9214,8 @@
     position += hterm.TextAttributes.nodeWidth(row);
     if (row.hasAttribute('line-overflow') && row.nextSibling) {
       row = row.nextSibling;
-    } else {
+    }
+    else {
       return -1;
     }
   }
@@ -8939,7 +9234,7 @@
 hterm.Screen.prototype.getPositionWithinRow_ = function(row, node, offset) {
   if (node.parentNode != row) {
     return this.getPositionWithinRow_(node.parentNode, node, offset) +
-           this.getPositionWithinRow_(row, node.parentNode, 0);
+      this.getPositionWithinRow_(row, node.parentNode, 0);
   }
   var position = 0;
   for (var i = 0; i < row.childNodes.length; i++) {
@@ -8964,7 +9259,8 @@
     if (row.hasAttribute('line-overflow') && row.nextSibling) {
       position -= hterm.TextAttributes.nodeWidth(row);
       row = row.nextSibling;
-    } else {
+    }
+    else {
       return -1;
     }
   }
@@ -8987,7 +9283,8 @@
       if (node.nodeName === 'SPAN') {
         /** Drill down to node contained by SPAN. **/
         return this.getNodeAndOffsetWithinRow_(node, position);
-      } else {
+      }
+      else {
         return [node, position];
       }
     }
@@ -9034,33 +9331,33 @@
     return;
 
   var startPosition = this.getPositionWithOverflow_(row,
-                                                    range.startContainer,
-                                                    range.startOffset);
+    range.startContainer,
+    range.startOffset);
   if (startPosition == -1)
     return;
   var endPosition = this.getPositionWithOverflow_(row,
-                                                  range.endContainer,
-                                                  range.endOffset);
+    range.endContainer,
+    range.endOffset);
   if (endPosition == -1)
     return;
 
   // Matches can start with '~' or '.', since paths frequently do.
-  var leftMatch   = '[^\\s\\[\\](){}<>"\'\\^!@#$%&*,;:`]';
-  var rightMatch  = '[^\\s\\[\\](){}<>"\'\\^!@#$%&*,;:~.`]';
+  var leftMatch = '[^\\s\\[\\](){}<>"\'\\^!@#$%&*,;:`]';
+  var rightMatch = '[^\\s\\[\\](){}<>"\'\\^!@#$%&*,;:~.`]';
   var insideMatch = '[^\\s\\[\\](){}<>"\'\\^]*';
 
   //Move start to the left.
   var rowText = this.getLineText_(row);
   var lineUpToRange = lib.wc.substring(rowText, 0, endPosition);
-  var leftRegularExpression = new RegExp(leftMatch + insideMatch + "$");
+  var leftRegularExpression = new RegExp(leftMatch + insideMatch + '$');
   var expandedStart = lineUpToRange.search(leftRegularExpression);
   if (expandedStart == -1 || expandedStart > startPosition)
     return;
 
   //Move end to the right.
   var lineFromRange = lib.wc.substring(rowText, startPosition,
-                                       lib.wc.strWidth(rowText));
-  var rightRegularExpression = new RegExp("^" + insideMatch + rightMatch);
+    lib.wc.strWidth(rowText));
+  var rightRegularExpression = new RegExp('^' + insideMatch + rightMatch);
   var found = lineFromRange.match(rightRegularExpression);
   if (!found)
     return;
@@ -9169,7 +9466,7 @@
   this.observers_ = {};
 
   this.DEBUG_ = false;
-}
+};
 
 /**
  * Proxy for the native selection object which understands how to walk up the
@@ -9222,7 +9519,7 @@
  * Returns null if none of the children are found.
  */
 hterm.ScrollPort.Selection.prototype.findFirstChild = function(
-    parent, childAry) {
+  parent, childAry) {
   var node = parent.firstChild;
 
   while (node) {
@@ -9290,7 +9587,7 @@
 
   if (!anchorRow) {
     console.error('Selection anchor is not rooted in a row node: ' +
-                  selection.anchorNode.nodeName);
+      selection.anchorNode.nodeName);
     return;
   }
 
@@ -9301,35 +9598,40 @@
 
   if (!focusRow) {
     console.error('Selection focus is not rooted in a row node: ' +
-                  selection.focusNode.nodeName);
+      selection.focusNode.nodeName);
     return;
   }
 
   if (anchorRow.rowIndex < focusRow.rowIndex) {
     anchorFirst();
 
-  } else if (anchorRow.rowIndex > focusRow.rowIndex) {
+  }
+  else if (anchorRow.rowIndex > focusRow.rowIndex) {
     focusFirst();
 
-  } else if (selection.focusNode == selection.anchorNode) {
+  }
+  else if (selection.focusNode == selection.anchorNode) {
     if (selection.anchorOffset < selection.focusOffset) {
       anchorFirst();
-    } else {
+    }
+    else {
       focusFirst();
     }
 
-  } else {
+  }
+  else {
     // The selection starts and ends in the same row, but isn't contained all
     // in a single node.
     var firstNode = this.findFirstChild(
-        anchorRow, [selection.anchorNode, selection.focusNode]);
+      anchorRow, [selection.anchorNode, selection.focusNode]);
 
     if (!firstNode)
       throw new Error('Unexpected error syncing selection.');
 
     if (firstNode == selection.anchorNode) {
       anchorFirst();
-    } else {
+    }
+    else {
       focusFirst();
     }
   }
@@ -9346,31 +9648,31 @@
 
   this.iframe_ = div.ownerDocument.createElement('iframe');
   this.iframe_.style.cssText = (
-      'border: 0;' +
-      'height: 100%;' +
-      'position: absolute;' +
-      'width: 100%');
+    'border: 0;' +
+    'height: 100%;' +
+    'position: absolute;' +
+    'width: 100%');
 
   // Set the iframe src to # in FF.  Otherwise when the frame's
   // load event fires in FF it clears out the content of the iframe.
-  if ('mozInnerScreenX' in window)  // detect a FF only property
+  if ('mozInnerScreenX' in window) // detect a FF only property
     this.iframe_.src = '#';
 
   div.appendChild(this.iframe_);
 
   this.iframe_.contentWindow.addEventListener('resize',
-                                              this.onResize_.bind(this));
+    this.onResize_.bind(this));
 
   var doc = this.document_ = this.iframe_.contentDocument;
   doc.body.style.cssText = (
-      'margin: 0px;' +
-      'padding: 0px;' +
-      'height: 100%;' +
-      'width: 100%;' +
-      'overflow: hidden;' +
-      'cursor: text;' +
-      '-webkit-user-select: none;' +
-      '-moz-user-select: none;');
+    'margin: 0px;' +
+    'padding: 0px;' +
+    'height: 100%;' +
+    'width: 100%;' +
+    'overflow: hidden;' +
+    'cursor: text;' +
+    '-webkit-user-select: none;' +
+    '-moz-user-select: none;');
 
   var style = doc.createElement('style');
   style.textContent = 'x-row {}';
@@ -9389,22 +9691,22 @@
   this.screen_.setAttribute('role', 'textbox');
   this.screen_.setAttribute('tabindex', '-1');
   this.screen_.style.cssText = (
-      'display: block;' +
-      'font-family: monospace;' +
-      'font-size: 15px;' +
-      'font-variant-ligatures: none;' +
-      'height: 100%;' +
-      'overflow-y: scroll; overflow-x: hidden;' +
-      'white-space: pre;' +
-      'width: 100%;' +
-      'outline: none !important');
+    'display: block;' +
+    'font-family: monospace;' +
+    'font-size: 15px;' +
+    'font-variant-ligatures: none;' +
+    'height: 100%;' +
+    'overflow-y: scroll; overflow-x: hidden;' +
+    'white-space: pre;' +
+    'width: 100%;' +
+    'outline: none !important');
 
   doc.body.appendChild(this.screen_);
 
   this.screen_.addEventListener('scroll', this.onScroll_.bind(this));
   this.screen_.addEventListener('mousewheel', this.onScrollWheel_.bind(this));
   this.screen_.addEventListener(
-      'DOMMouseScroll', this.onScrollWheel_.bind(this));
+    'DOMMouseScroll', this.onScrollWheel_.bind(this));
   this.screen_.addEventListener('copy', this.onCopy_.bind(this));
   this.screen_.addEventListener('paste', this.onPaste_.bind(this));
 
@@ -9413,19 +9715,19 @@
   // This is the main container for the fixed rows.
   this.rowNodes_ = doc.createElement('div');
   this.rowNodes_.style.cssText = (
-      'display: block;' +
-      'position: fixed;' +
-      'overflow: hidden;' +
-      '-webkit-user-select: text;' +
-      '-moz-user-select: text;');
+    'display: block;' +
+    'position: fixed;' +
+    'overflow: hidden;' +
+    '-webkit-user-select: text;' +
+    '-moz-user-select: text;');
   this.screen_.appendChild(this.rowNodes_);
 
   // Two nodes to hold offscreen text during the copy event.
   this.topSelectBag_ = doc.createElement('x-select-bag');
   this.topSelectBag_.style.cssText = (
-      'display: block;' +
-      'overflow: hidden;' +
-      'white-space: pre;');
+    'display: block;' +
+    'overflow: hidden;' +
+    'white-space: pre;');
 
   this.bottomSelectBag_ = this.topSelectBag_.cloneNode();
 
@@ -9462,10 +9764,10 @@
   this.svg_.setAttribute('xmlns', xmlns);
   this.svg_.setAttribute('version', '1.1');
   this.svg_.style.cssText = (
-      'position: absolute;' +
-      'top: 0;' +
-      'left: 0;' +
-      'visibility: hidden');
+    'position: absolute;' +
+    'top: 0;' +
+    'left: 0;' +
+    'visibility: hidden');
 
 
   // We send focus to this element just before a paste happens, so we can
@@ -9483,7 +9785,7 @@
 
   this.screen_.appendChild(this.pasteTarget_);
   this.pasteTarget_.addEventListener(
-      'textInput', this.handlePasteTargetTextInput_.bind(this));
+    'textInput', this.handlePasteTargetTextInput_.bind(this));
 
   this.resize();
 };
@@ -9500,7 +9802,8 @@
   this.screen_.style.fontFamily = fontFamily;
   if (opt_smoothing) {
     this.screen_.style.webkitFontSmoothing = opt_smoothing;
-  } else {
+  }
+  else {
     this.screen_.style.webkitFontSmoothing = '';
   }
 
@@ -9523,7 +9826,8 @@
 
     if (!this.userCssLink_.parentNode)
       this.document_.head.appendChild(this.userCssLink_);
-  } else if (this.userCssLink_.parentNode) {
+  }
+  else if (this.userCssLink_.parentNode) {
     this.document_.head.removeChild(this.userCssLink_);
   }
 };
@@ -9584,7 +9888,7 @@
  * This the widget width minus scrollbar width.
  */
 hterm.ScrollPort.prototype.getScreenWidth = function() {
-  return this.getScreenSize().width ;
+  return this.getScreenSize().width;
 };
 
 /**
@@ -9663,10 +9967,10 @@
     return;
 
   var self = this;
-  this.timeouts_.invalidate = setTimeout(function () {
-      delete self.timeouts_.invalidate;
-      self.invalidate();
-    }, 0);
+  this.timeouts_.invalidate = setTimeout(function() {
+    delete self.timeouts_.invalidate;
+    self.invalidate();
+  }, 0);
 };
 
 /**
@@ -9695,19 +9999,19 @@
   // Number of lines used to average the height of a single character.
   var numberOfLines = 100;
   var rulerSingleLineContents = ('XXXXXXXXXXXXXXXXXXXX' +
-                                 'XXXXXXXXXXXXXXXXXXXX' +
-                                 'XXXXXXXXXXXXXXXXXXXX' +
-                                 'XXXXXXXXXXXXXXXXXXXX' +
-                                 'XXXXXXXXXXXXXXXXXXXX');
+    'XXXXXXXXXXXXXXXXXXXX' +
+    'XXXXXXXXXXXXXXXXXXXX' +
+    'XXXXXXXXXXXXXXXXXXXX' +
+    'XXXXXXXXXXXXXXXXXXXX');
   if (!this.ruler_) {
     this.ruler_ = this.document_.createElement('div');
     this.ruler_.style.cssText = (
-        'position: absolute;' +
-        'top: 0;' +
-        'left: 0;' +
-        'visibility: hidden;' +
-        'height: auto !important;' +
-        'width: auto !important;');
+      'position: absolute;' +
+      'top: 0;' +
+      'left: 0;' +
+      'visibility: hidden;' +
+      'height: auto !important;' +
+      'width: auto !important;');
 
     // We need to put the text in a span to make the size calculation
     // work properly in Firefox
@@ -9731,7 +10035,7 @@
   var rulerSize = hterm.getClientSize(this.rulerSpan_);
 
   var size = new hterm.Size(rulerSize.width / rulerSingleLineContents.length,
-                            rulerSize.height / numberOfLines);
+    rulerSize.height / numberOfLines);
 
   this.ruler_.appendChild(this.rulerBaseline_);
   size.baseline = this.rulerBaseline_.offsetTop;
@@ -9766,8 +10070,8 @@
     // When we're debugging we add padding to the body so that the offscreen
     // elements are visible.
     this.document_.body.style.paddingTop =
-        this.document_.body.style.paddingBottom =
-        3 * this.characterSize.height + 'px';
+      this.document_.body.style.paddingBottom =
+      3 * this.characterSize.height + 'px';
   }
 };
 
@@ -9784,11 +10088,13 @@
 
   var self = this;
   this.publish(
-      'resize', { scrollPort: this },
-      function() {
-        self.scrollRowToBottom(self.rowProvider_.getRowCount());
-        self.scheduleRedraw();
-      });
+    'resize', {
+      scrollPort: this
+    },
+    function() {
+      self.scrollRowToBottom(self.rowProvider_.getRowCount());
+      self.scheduleRedraw();
+    });
 };
 
 /**
@@ -9803,7 +10109,7 @@
   // We don't want to show a partial row because it would be distracting
   // in a terminal, so we floor any fractional row count.
   this.visibleRowCount = lib.f.smartFloorDivide(
-      screenSize.height, this.characterSize.height);
+    screenSize.height, this.characterSize.height);
 
   // Then compute the height of our integral number of rows.
   var visibleRowsHeight = this.visibleRowCount * this.characterSize.height;
@@ -9835,10 +10141,10 @@
   // Resize the scroll area to appear as though it contains every row.
   this.lastRowCount_ = this.rowProvider_.getRowCount();
   this.scrollArea_.style.height = (this.characterSize.height *
-                                   this.lastRowCount_ +
-                                   this.visibleRowTopMargin +
-                                   this.visibleRowBottomMargin +
-                                   'px');
+    this.lastRowCount_ +
+    this.visibleRowTopMargin +
+    this.visibleRowBottomMargin +
+    'px');
 };
 
 /**
@@ -9852,10 +10158,10 @@
     return;
 
   var self = this;
-  this.timeouts_.redraw = setTimeout(function () {
-      delete self.timeouts_.redraw;
-      self.redraw_();
-    }, 0);
+  this.timeouts_.redraw = setTimeout(function() {
+    delete self.timeouts_.redraw;
+    self.redraw_();
+  }, 0);
 };
 
 /**
@@ -9907,7 +10213,7 @@
  */
 hterm.ScrollPort.prototype.drawTopFold_ = function(topRowIndex) {
   if (!this.selection.startRow ||
-      this.selection.startRow.rowIndex >= topRowIndex) {
+    this.selection.startRow.rowIndex >= topRowIndex) {
     // Selection is entirely below the top fold, just make sure the fold is
     // the first child.
     if (this.rowNodes_.firstChild != this.topFold_)
@@ -9917,26 +10223,27 @@
   }
 
   if (!this.selection.isMultiline ||
-      this.selection.endRow.rowIndex >= topRowIndex) {
+    this.selection.endRow.rowIndex >= topRowIndex) {
     // Only the startRow is above the fold.
     if (this.selection.startRow.nextSibling != this.topFold_)
       this.rowNodes_.insertBefore(this.topFold_,
-                                  this.selection.startRow.nextSibling);
-  } else {
+        this.selection.startRow.nextSibling);
+  }
+  else {
     // Both rows are above the fold.
     if (this.selection.endRow.nextSibling != this.topFold_) {
       this.rowNodes_.insertBefore(this.topFold_,
-                                  this.selection.endRow.nextSibling);
+        this.selection.endRow.nextSibling);
     }
 
     // Trim any intermediate lines.
     while (this.selection.startRow.nextSibling !=
-           this.selection.endRow) {
+      this.selection.endRow) {
       this.rowNodes_.removeChild(this.selection.startRow.nextSibling);
     }
   }
 
-  while(this.rowNodes_.firstChild != this.selection.startRow) {
+  while (this.rowNodes_.firstChild != this.selection.startRow) {
     this.rowNodes_.removeChild(this.rowNodes_.firstChild);
   }
 };
@@ -9956,7 +10263,7 @@
  */
 hterm.ScrollPort.prototype.drawBottomFold_ = function(bottomRowIndex) {
   if (!this.selection.endRow ||
-      this.selection.endRow.rowIndex <= bottomRowIndex) {
+    this.selection.endRow.rowIndex <= bottomRowIndex) {
     // Selection is entirely above the bottom fold, just make sure the fold is
     // the last child.
     if (this.rowNodes_.lastChild != this.bottomFold_)
@@ -9966,26 +10273,27 @@
   }
 
   if (!this.selection.isMultiline ||
-      this.selection.startRow.rowIndex <= bottomRowIndex) {
+    this.selection.startRow.rowIndex <= bottomRowIndex) {
     // Only the endRow is below the fold.
     if (this.bottomFold_.nextSibling != this.selection.endRow)
       this.rowNodes_.insertBefore(this.bottomFold_,
-                                  this.selection.endRow);
-  } else {
+        this.selection.endRow);
+  }
+  else {
     // Both rows are below the fold.
     if (this.bottomFold_.nextSibling != this.selection.startRow) {
       this.rowNodes_.insertBefore(this.bottomFold_,
-                                  this.selection.startRow);
+        this.selection.startRow);
     }
 
     // Trim any intermediate lines.
     while (this.selection.startRow.nextSibling !=
-           this.selection.endRow) {
+      this.selection.endRow) {
       this.rowNodes_.removeChild(this.selection.startRow.nextSibling);
     }
   }
 
-  while(this.rowNodes_.lastChild != this.selection.endRow) {
+  while (this.rowNodes_.lastChild != this.selection.endRow) {
     this.rowNodes_.removeChild(this.rowNodes_.lastChild);
   }
 };
@@ -10005,7 +10313,7 @@
  * adjusted around them.
  */
 hterm.ScrollPort.prototype.drawVisibleRows_ = function(
-    topRowIndex, bottomRowIndex) {
+  topRowIndex, bottomRowIndex) {
   var self = this;
 
   // Keep removing nodes, starting with currentNode, until we encounter
@@ -10033,7 +10341,7 @@
   var node = this.topFold_.nextSibling;
 
   var targetDrawCount = Math.min(this.visibleRowCount,
-                                 this.rowProvider_.getRowCount());
+    this.rowProvider_.getRowCount());
 
   for (var drawCount = 0; drawCount < targetDrawCount; drawCount++) {
     var rowIndex = topRowIndex + drawCount;
@@ -10150,7 +10458,8 @@
 
   if (this.previousRowNodeCache_ && rowIndex in this.previousRowNodeCache_) {
     node = this.previousRowNodeCache_[rowIndex];
-  } else {
+  }
+  else {
     node = this.rowProvider_.getRowNode(rowIndex);
   }
 
@@ -10174,7 +10483,8 @@
     firstRow = this.fetchRowNode_(0);
     this.rowNodes_.insertBefore(firstRow, this.topFold_);
     this.syncRowNodesDimensions_();
-  } else {
+  }
+  else {
     firstRow = this.topFold_.nextSibling;
   }
 
@@ -10188,7 +10498,8 @@
 
     lastRow = this.fetchRowNode_(lastRowIndex);
     this.rowNodes_.appendChild(lastRow);
-  } else {
+  }
+  else {
     lastRow = this.bottomFold_.previousSibling.rowIndex;
   }
 
@@ -10204,8 +10515,8 @@
  */
 hterm.ScrollPort.prototype.getScrollMax_ = function(e) {
   return (hterm.getClientHeight(this.scrollArea_) +
-          this.visibleRowTopMargin + this.visibleRowBottomMargin -
-          hterm.getClientHeight(this.screen_));
+    this.visibleRowTopMargin + this.visibleRowBottomMargin -
+    hterm.getClientHeight(this.screen_));
 };
 
 /**
@@ -10220,7 +10531,7 @@
     rowIndex + this.visibleRowCount >= this.lastRowCount_);
 
   var scrollTop = rowIndex * this.characterSize.height +
-      this.visibleRowTopMargin;
+    this.visibleRowTopMargin;
 
   var scrollMax = this.getScrollMax_();
   if (scrollTop > scrollMax)
@@ -10245,7 +10556,7 @@
     rowIndex + this.visibleRowCount >= this.lastRowCount_);
 
   var scrollTop = rowIndex * this.characterSize.height +
-      this.visibleRowTopMargin + this.visibleRowBottomMargin;
+    this.visibleRowTopMargin + this.visibleRowBottomMargin;
   scrollTop -= this.visibleRowCount * this.characterSize.height;
 
   if (scrollTop < 0)
@@ -10286,7 +10597,7 @@
 hterm.ScrollPort.prototype.onScroll_ = function(e) {
   var screenSize = this.getScreenSize();
   if (screenSize.width != this.lastScreenWidth_ ||
-      screenSize.height != this.lastScreenHeight_) {
+    screenSize.height != this.lastScreenHeight_) {
     // This event may also fire during a resize (but before the resize event!).
     // This happens when the browser moves the scrollbar as part of the resize.
     // In these cases, we want to ignore the scroll event and let onResize
@@ -10297,7 +10608,9 @@
   }
 
   this.redraw_();
-  this.publish('scroll', { scrollPort: this });
+  this.publish('scroll', {
+    scrollPort: this
+  });
 };
 
 /**
@@ -10365,7 +10678,7 @@
  * Clients may call event.preventDefault() if they want to keep the scrollport
  * from also handling the events.
  */
-hterm.ScrollPort.prototype.onCopy = function(e) { };
+hterm.ScrollPort.prototype.onCopy = function(e) {};
 
 /**
  * Handler for copy-to-clipboard events.
@@ -10385,7 +10698,7 @@
   this.selection.sync();
 
   if (!this.selection.startRow ||
-      this.selection.endRow.rowIndex - this.selection.startRow.rowIndex < 2) {
+    this.selection.endRow.rowIndex - this.selection.startRow.rowIndex < 2) {
     return;
   }
 
@@ -10399,15 +10712,16 @@
     if (this.selection.endRow.rowIndex < topRowIndex) {
       // Entire selection is above the top fold.
       endBackfillIndex = this.selection.endRow.rowIndex;
-    } else {
+    }
+    else {
       // Selection extends below the top fold.
       endBackfillIndex = this.topFold_.nextSibling.rowIndex;
     }
 
     this.topSelectBag_.textContent = this.rowProvider_.getRowsText(
-        this.selection.startRow.rowIndex + 1, endBackfillIndex);
+      this.selection.startRow.rowIndex + 1, endBackfillIndex);
     this.rowNodes_.insertBefore(this.topSelectBag_,
-                                this.selection.startRow.nextSibling);
+      this.selection.startRow.nextSibling);
     this.syncRowNodesDimensions_();
   }
 
@@ -10418,13 +10732,14 @@
     if (this.selection.startRow.rowIndex > bottomRowIndex) {
       // Entire selection is below the bottom fold.
       startBackfillIndex = this.selection.startRow.rowIndex + 1;
-    } else {
+    }
+    else {
       // Selection starts above the bottom fold.
       startBackfillIndex = this.bottomFold_.previousSibling.rowIndex + 1;
     }
 
     this.bottomSelectBag_.textContent = this.rowProvider_.getRowsText(
-        startBackfillIndex, this.selection.endRow.rowIndex);
+      startBackfillIndex, this.selection.endRow.rowIndex);
     this.rowNodes_.insertBefore(this.bottomSelectBag_, this.selection.endRow);
   }
 };
@@ -10439,7 +10754,7 @@
 
   var key = String.fromCharCode(e.which);
   var lowerKey = key.toLowerCase();
-  if ((e.ctrlKey || e.metaKey) && lowerKey == "v")
+  if ((e.ctrlKey || e.metaKey) && lowerKey == 'v')
     this.pasteTarget_.focus();
 };
 
@@ -10451,10 +10766,12 @@
 
   var self = this;
   setTimeout(function() {
-      self.publish('paste', { text: self.pasteTarget_.value });
-      self.pasteTarget_.value = '';
-      self.screen_.focus();
-    }, 0);
+    self.publish('paste', {
+      text: self.pasteTarget_.value
+    });
+    self.pasteTarget_.value = '';
+    self.screen_.focus();
+  }, 0);
 };
 
 /**
@@ -10487,9 +10804,9 @@
 'use strict';
 
 lib.rtdep('lib.colors', 'lib.PreferenceManager', 'lib.resource', 'lib.wc',
-          'lib.f', 'hterm.Keyboard', 'hterm.Options', 'hterm.PreferenceManager',
-          'hterm.Screen', 'hterm.ScrollPort', 'hterm.Size',
-          'hterm.TextAttributes', 'hterm.VT');
+  'lib.f', 'hterm.Keyboard', 'hterm.Options', 'hterm.PreferenceManager',
+  'hterm.Screen', 'hterm.ScrollPort', 'hterm.Size',
+  'hterm.TextAttributes', 'hterm.VT');
 
 /**
  * Constructor for the Terminal class.
@@ -10628,7 +10945,9 @@
   this.setDefaultTabStops();
 
   this.setProfile(opt_profileId || 'default',
-                  function() { this.onTerminalReady(); }.bind(this));
+    function() {
+      this.onTerminalReady();
+    }.bind(this));
 };
 
 /**
@@ -10647,7 +10966,7 @@
  * The terminal initialization is asynchronous, and shouldn't be used before
  * this method is called.
  */
-hterm.Terminal.prototype.onTerminalReady = function() { };
+hterm.Terminal.prototype.onTerminalReady = function() {};
 
 /**
  * Default tab with of 8 to match xterm.
@@ -10679,12 +10998,15 @@
       if (v == null) {
         if (navigator.language.toLowerCase() == 'en-us') {
           v = 'none';
-        } else {
+        }
+        else {
           v = 'right-alt';
         }
-      } else if (typeof v == 'string') {
+      }
+      else if (typeof v == 'string') {
         v = v.toLowerCase();
-      } else {
+      }
+      else {
         v = 'none';
       }
 
@@ -10713,8 +11035,9 @@
       var ary = v.match(/^lib-resource:(\S+)/);
       if (ary) {
         terminal.bellAudio_.setAttribute('src',
-                                         lib.resource.getDataUrl(ary[1]));
-      } else {
+          lib.resource.getDataUrl(ary[1]));
+      }
+      else {
         terminal.bellAudio_.setAttribute('src', v);
       }
     },
@@ -10722,7 +11045,7 @@
     'desktop-notification-bell': function(v) {
       if (v && Notification) {
         terminal.desktopNotificationBell_ =
-            Notification.permission === 'granted';
+          Notification.permission === 'granted';
         if (!terminal.desktopNotificationBell_) {
           // Note: We don't call Notification.requestPermission here because
           // Chrome requires the call be the result of a user action (such as an
@@ -10731,9 +11054,10 @@
           // A way of working around this would be to display a dialog in the
           // terminal with a "click-to-request-permission" button.
           console.warn('desktop-notification-bell is true but we do not have ' +
-                       'permission to display notifications.');
+            'permission to display notifications.');
         }
-      } else {
+      }
+      else {
         terminal.desktopNotificationBell_ = false;
       }
     },
@@ -10761,7 +11085,7 @@
     'character-map-overrides': function(v) {
       if (!(v == null || v instanceof Object)) {
         console.warn('Preference character-map-modifications is not an ' +
-                     'object: ' + v);
+          'object: ' + v);
         return;
       }
 
@@ -10779,16 +11103,18 @@
     },
 
     'cursor-blink-cycle': function(v) {
-        if (v instanceof Array &&
-            typeof v[0] == 'number' &&
-            typeof v[1] == 'number') {
-          terminal.cursorBlinkCycle_ = v;
-        } else if (typeof v == 'number') {
-          terminal.cursorBlinkCycle_ = [v, v];
-        } else {
-          // Fast blink indicates an error.
-          terminal.cursorBlinkCycle_ = [100, 100];
-        }
+      if (v instanceof Array &&
+        typeof v[0] == 'number' &&
+        typeof v[1] == 'number') {
+        terminal.cursorBlinkCycle_ = v;
+      }
+      else if (typeof v == 'number') {
+        terminal.cursorBlinkCycle_ = [v, v];
+      }
+      else {
+        // Fast blink indicates an error.
+        terminal.cursorBlinkCycle_ = [100, 100];
+      }
     },
 
     'cursor-color': function(v) {
@@ -10798,7 +11124,7 @@
     'color-palette-overrides': function(v) {
       if (!(v == null || v instanceof Object || v instanceof Array)) {
         console.warn('Preference color-palette-overrides is not an array or ' +
-                     'object: ' + v);
+          'object: ' + v);
         return;
       }
 
@@ -10911,7 +11237,8 @@
 
       try {
         terminal.keyboard.bindings.addBindings(v);
-      } catch (ex) {
+      }
+      catch (ex) {
         console.error('Error in keybindings preference: ' + ex);
       }
     },
@@ -10977,12 +11304,12 @@
     },
 
     'receive-encoding': function(v) {
-       if (!(/^(utf-8|raw)$/).test(v)) {
-         console.warn('Invalid value for "receive-encoding": ' + v);
-         v = 'utf-8';
-       }
+      if (!(/^(utf-8|raw)$/).test(v)) {
+        console.warn('Invalid value for "receive-encoding": ' + v);
+        v = 'utf-8';
+      }
 
-       terminal.vt.characterEncoding = v;
+      terminal.vt.characterEncoding = v;
     },
 
     'scroll-on-keystroke': function(v) {
@@ -11002,12 +11329,12 @@
     },
 
     'send-encoding': function(v) {
-       if (!(/^(utf-8|raw)$/).test(v)) {
-         console.warn('Invalid value for "send-encoding": ' + v);
-         v = 'utf-8';
-       }
+      if (!(/^(utf-8|raw)$/).test(v)) {
+        console.warn('Invalid value for "send-encoding": ' + v);
+        v = 'utf-8';
+      }
 
-       terminal.keyboard.characterEncoding = v;
+      terminal.keyboard.characterEncoding = v;
     },
 
     'shift-insert-paste': function(v) {
@@ -11088,9 +11415,9 @@
 hterm.Terminal.prototype.setBackgroundColor = function(color) {
   this.backgroundColor_ = lib.colors.normalizeCSS(color);
   this.primaryScreen_.textAttributes.setDefaults(
-      this.foregroundColor_, this.backgroundColor_);
+    this.foregroundColor_, this.backgroundColor_);
   this.alternateScreen_.textAttributes.setDefaults(
-      this.foregroundColor_, this.backgroundColor_);
+    this.foregroundColor_, this.backgroundColor_);
   this.scrollPort_.setBackgroundColor(color);
 };
 
@@ -11117,9 +11444,9 @@
 hterm.Terminal.prototype.setForegroundColor = function(color) {
   this.foregroundColor_ = lib.colors.normalizeCSS(color);
   this.primaryScreen_.textAttributes.setDefaults(
-      this.foregroundColor_, this.backgroundColor_);
+    this.foregroundColor_, this.backgroundColor_);
   this.alternateScreen_.textAttributes.setDefaults(
-      this.foregroundColor_, this.backgroundColor_);
+    this.foregroundColor_, this.backgroundColor_);
   this.scrollPort_.setForegroundColor(color);
 };
 
@@ -11148,17 +11475,17 @@
     environment = {};
 
   var self = this;
-  this.command = new commandClass(
-      { argString: argString || '',
-        io: this.io.push(),
-        environment: environment,
-        onExit: function(code) {
-          self.io.pop();
-          self.uninstallKeyboard();
-          if (self.prefs_.get('close-on-exit'))
-              window.close();
-        }
-      });
+  this.command = new commandClass({
+    argString: argString || '',
+    io: this.io.push(),
+    environment: environment,
+    onExit: function(code) {
+      self.io.pop();
+      self.uninstallKeyboard();
+      if (self.prefs_.get('close-on-exit'))
+        window.close();
+    }
+  });
 
   this.installKeyboard();
   this.command.run();
@@ -11181,14 +11508,14 @@
  */
 hterm.Terminal.prototype.installKeyboard = function() {
   this.keyboard.installKeyboard(this.scrollPort_.getDocument().body);
-}
+};
 
 /**
  * Uninstall the keyboard handler for this terminal.
  */
 hterm.Terminal.prototype.uninstallKeyboard = function() {
   this.keyboard.installKeyboard(null);
-}
+};
 
 /**
  * Set the font size for this terminal.
@@ -11206,7 +11533,7 @@
   this.scrollPort_.setFontSize(px);
   if (this.wcCssRule_) {
     this.wcCssRule_.style.width = this.scrollPort_.characterSize.width * 2 +
-        'px';
+      'px';
   }
 };
 
@@ -11233,7 +11560,7 @@
  */
 hterm.Terminal.prototype.syncFontFamily = function() {
   this.scrollPort_.setFontFamily(this.prefs_.get('font-family'),
-                                 this.prefs_.get('font-smoothing'));
+    this.prefs_.get('font-smoothing'));
   this.syncBoldSafeState();
 };
 
@@ -11251,7 +11578,8 @@
   var ary = navigator.userAgent.match(/\(X11;\s+(\S+)/);
   if (!ary || ary[2] == 'CrOS') {
     this.mousePasteButton = 2;
-  } else {
+  }
+  else {
     this.mousePasteButton = 3;
   }
 };
@@ -11274,8 +11602,8 @@
   var isBoldSafe = normalSize.equals(boldSize);
   if (!isBoldSafe) {
     console.warn('Bold characters disabled: Size of bold weight differs ' +
-                 'from normal.  Font family is: ' +
-                 this.scrollPort_.getFontFamily());
+      'from normal.  Font family is: ' +
+      this.scrollPort_.getFontFamily());
   }
 
   this.primaryScreen_.textAttributes.enableBold = isBoldSafe;
@@ -11287,8 +11615,8 @@
  */
 hterm.Terminal.prototype.syncBlinkState = function() {
   this.document_.documentElement.style.setProperty(
-      '--hterm-blink-node-duration',
-      this.prefs_.get('enable-blink') ? '0.7s' : '0');
+    '--hterm-blink-node-duration',
+    this.prefs_.get('enable-blink') ? '0.7s' : '0');
 };
 
 /**
@@ -11346,7 +11674,7 @@
   var column = lib.f.clamp(cursor.column, 0, this.screenSize.width - 1);
   this.screen_.setCursorPosition(row, column);
   if (cursor.column > column ||
-      cursor.column == column && cursor.overflow) {
+    cursor.column == column && cursor.overflow) {
     this.screen_.cursorPosition.overflow = true;
   }
 };
@@ -11366,7 +11694,7 @@
 hterm.Terminal.prototype.setCursorShape = function(shape) {
   this.cursorShape_ = shape;
   this.restyleCursor_();
-}
+};
 
 /**
  * Get the cursor shape
@@ -11375,7 +11703,7 @@
  */
 hterm.Terminal.prototype.getCursorShape = function() {
   return this.cursorShape_;
-}
+};
 
 /**
  * Set the width of the terminal, resizing the UI to match.
@@ -11389,8 +11717,8 @@
   }
 
   this.div_.style.width = Math.ceil(
-      this.scrollPort_.characterSize.width *
-      columnCount + this.scrollPort_.currentScrollbarWidthPx) + 'px';
+    this.scrollPort_.characterSize.width *
+    columnCount + this.scrollPort_.currentScrollbarWidthPx) + 'px';
   this.realizeSize_(columnCount, this.screenSize.height);
   this.scheduleSyncCursorPosition_();
 };
@@ -11407,7 +11735,7 @@
   }
 
   this.div_.style.height =
-      this.scrollPort_.characterSize.height * rowCount + 'px';
+    this.scrollPort_.characterSize.height * rowCount + 'px';
   this.realizeSize_(this.screenSize.width, rowCount);
   this.scheduleSyncCursorPosition_();
 };
@@ -11454,7 +11782,8 @@
   if (deltaColumns > 0) {
     if (this.defaultTabStops)
       this.setDefaultTabStops(this.screenSize.width - deltaColumns);
-  } else {
+  }
+  else {
     for (var i = this.tabStops_.length - 1; i >= 0; i--) {
       if (this.tabStops_[i] < columnCount)
         break;
@@ -11510,13 +11839,14 @@
     // We just removed rows from the top of the screen, we need to update
     // the cursor to match.
     cursor.row = Math.max(cursor.row - deltaRows, 0);
-  } else if (deltaRows > 0) {
+  }
+  else if (deltaRows > 0) {
     // Screen got larger.
 
     if (deltaRows <= this.scrollbackRows_.length) {
       var scrollbackCount = Math.min(deltaRows, this.scrollbackRows_.length);
       var rows = this.scrollbackRows_.splice(
-          this.scrollbackRows_.length - scrollbackCount, scrollbackCount);
+        this.scrollbackRows_.length - scrollbackCount, scrollbackCount);
       this.screen_.unshiftRows(rows);
       deltaRows -= scrollbackCount;
       cursor.row += scrollbackCount;
@@ -11755,7 +12085,7 @@
   this.scrollPort_.setBackgroundImage(this.prefs_.get('background-image'));
   this.scrollPort_.setBackgroundSize(this.prefs_.get('background-size'));
   this.scrollPort_.setBackgroundPosition(
-      this.prefs_.get('background-position'));
+    this.prefs_.get('background-position'));
   this.scrollPort_.setUserCss(this.prefs_.get('user-css'));
 
   this.div_.focus = this.focus.bind(this);
@@ -11765,11 +12095,13 @@
 
   this.setScrollbarVisible(this.prefs_.get('scrollbar-visible'));
   this.setScrollWheelMoveMultipler(
-      this.prefs_.get('scroll-wheel-move-multiplier'));
+    this.prefs_.get('scroll-wheel-move-multiplier'));
 
   this.document_ = this.scrollPort_.getDocument();
 
-  this.document_.body.oncontextmenu = function() { return false; };
+  this.document_.body.oncontextmenu = function() {
+    return false;
+  };
 
   var onMouse = this.onMouse_.bind(this);
   var screenNode = this.scrollPort_.getScreenNode();
@@ -11779,7 +12111,7 @@
   this.scrollPort_.onScrollWheel = onMouse;
 
   screenNode.addEventListener(
-      'focus', this.onFocusChange_.bind(this, true));
+    'focus', this.onFocusChange_.bind(this, true));
   // Listen for mousedown events on the screenNode as in FF the focus
   // events don't bubble.
   screenNode.addEventListener('mousedown', function() {
@@ -11787,35 +12119,35 @@
   }.bind(this));
 
   screenNode.addEventListener(
-      'blur', this.onFocusChange_.bind(this, false));
+    'blur', this.onFocusChange_.bind(this, false));
 
   var style = this.document_.createElement('style');
   style.textContent =
-      ('.cursor-node[focus="false"] {' +
-       '  box-sizing: border-box;' +
-       '  background-color: transparent !important;' +
-       '  border-width: 2px;' +
-       '  border-style: solid;' +
-       '}' +
-       '.wc-node {' +
-       '  display: inline-block;' +
-       '  text-align: center;' +
-       '  width: ' + this.scrollPort_.characterSize.width * 2 + 'px;' +
-       '}' +
-       ':root {' +
-       '  --hterm-blink-node-duration: 0.7s;' +
-       '}' +
-       '@keyframes blink {' +
-       '  from { opacity: 1.0; }' +
-       '  to { opacity: 0.0; }' +
-       '}' +
-       '.blink-node {' +
-       '  animation-name: blink;' +
-       '  animation-duration: var(--hterm-blink-node-duration);' +
-       '  animation-iteration-count: infinite;' +
-       '  animation-timing-function: ease-in-out;' +
-       '  animation-direction: alternate;' +
-       '}');
+    ('.cursor-node[focus="false"] {' +
+      '  box-sizing: border-box;' +
+      '  background-color: transparent !important;' +
+      '  border-width: 2px;' +
+      '  border-style: solid;' +
+      '}' +
+      '.wc-node {' +
+      '  display: inline-block;' +
+      '  text-align: center;' +
+      '  width: ' + this.scrollPort_.characterSize.width * 2 + 'px;' +
+      '}' +
+      ':root {' +
+      '  --hterm-blink-node-duration: 0.7s;' +
+      '}' +
+      '@keyframes blink {' +
+      '  from { opacity: 1.0; }' +
+      '  to { opacity: 0.0; }' +
+      '}' +
+      '.blink-node {' +
+      '  animation-name: blink;' +
+      '  animation-duration: var(--hterm-blink-node-duration);' +
+      '  animation-iteration-count: infinite;' +
+      '  animation-timing-function: ease-in-out;' +
+      '  animation-direction: alternate;' +
+      '}');
   this.document_.head.appendChild(style);
 
   var styleSheets = this.document_.styleSheets;
@@ -11825,13 +12157,13 @@
   this.cursorNode_ = this.document_.createElement('div');
   this.cursorNode_.className = 'cursor-node';
   this.cursorNode_.style.cssText =
-      ('position: absolute;' +
-       'top: -99px;' +
-       'display: block;' +
-       'width: ' + this.scrollPort_.characterSize.width + 'px;' +
-       'height: ' + this.scrollPort_.characterSize.height + 'px;' +
-       '-webkit-transition: opacity, background-color 100ms linear;' +
-       '-moz-transition: opacity, background-color 100ms linear;');
+    ('position: absolute;' +
+      'top: -99px;' +
+      'display: block;' +
+      'width: ' + this.scrollPort_.characterSize.width + 'px;' +
+      'height: ' + this.scrollPort_.characterSize.height + 'px;' +
+      '-webkit-transition: opacity, background-color 100ms linear;' +
+      '-moz-transition: opacity, background-color 100ms linear;');
 
   this.setCursorColor(this.prefs_.get('cursor-color'));
   this.setCursorBlink(!!this.prefs_.get('cursor-blink'));
@@ -11848,24 +12180,23 @@
   // It's a hack, but it's the cleanest way I could find.
   this.scrollBlockerNode_ = this.document_.createElement('div');
   this.scrollBlockerNode_.style.cssText =
-      ('position: absolute;' +
-       'top: -99px;' +
-       'display: block;' +
-       'width: 10px;' +
-       'height: 10px;');
+    ('position: absolute;' +
+      'top: -99px;' +
+      'display: block;' +
+      'width: 10px;' +
+      'height: 10px;');
   this.document_.body.appendChild(this.scrollBlockerNode_);
 
   this.scrollPort_.onScrollWheel = onMouse;
-  ['mousedown', 'mouseup', 'mousemove', 'click', 'dblclick',
-   ].forEach(function(event) {
-       this.scrollBlockerNode_.addEventListener(event, onMouse);
-       this.cursorNode_.addEventListener(event, onMouse);
-       this.document_.addEventListener(event, onMouse);
-     }.bind(this));
+  ['mousedown', 'mouseup', 'mousemove', 'click', 'dblclick',].forEach(function(event) {
+    this.scrollBlockerNode_.addEventListener(event, onMouse);
+    this.cursorNode_.addEventListener(event, onMouse);
+    this.document_.addEventListener(event, onMouse);
+  }.bind(this));
 
   this.cursorNode_.addEventListener('mousedown', function() {
-      setTimeout(this.focus.bind(this));
-    }.bind(this));
+    setTimeout(this.focus.bind(this));
+  }.bind(this));
 
   this.setReverseVideo(false);
 
@@ -12031,7 +12362,8 @@
   if (fromIndex < toIndex) {
     start = fromIndex;
     end = toIndex + count;
-  } else {
+  }
+  else {
     start = toIndex;
     end = fromIndex + count;
   }
@@ -12071,7 +12403,7 @@
  * The string is *not* parsed for escape codes.  Use the interpret() method if
  * that's what you're after.
  *
- * @param{string} str The string to print.
+ * @param {string} str The string to print.
  */
 hterm.Terminal.prototype.print = function(str) {
   var startOffset = 0;
@@ -12098,9 +12430,10 @@
       // last printed character should be the last of the string.
       // TODO: This will add to our problems with multibyte UTF-16 characters.
       substr = lib.wc.substr(str, startOffset, count - 1) +
-          lib.wc.substr(str, strWidth - 1);
+        lib.wc.substr(str, strWidth - 1);
       count = strWidth;
-    } else {
+    }
+    else {
       substr = lib.wc.substr(str, startOffset, count);
     }
 
@@ -12110,8 +12443,9 @@
         this.screen_.textAttributes.wcNode = true;
 
       if (this.options_.insertMode) {
-          this.screen_.insertString(tokens[i].str);
-      } else {
+        this.screen_.insertString(tokens[i].str);
+      }
+      else {
         this.screen_.overwriteString(tokens[i].str);
       }
       this.screen_.textAttributes.wcNode = false;
@@ -12147,7 +12481,8 @@
   if (scrollTop == 0 && scrollBottom == this.screenSize.height - 1) {
     this.vtScrollTop_ = null;
     this.vtScrollBottom_ = null;
-  } else {
+  }
+  else {
     this.vtScrollTop_ = scrollTop;
     this.vtScrollBottom_ = scrollBottom;
   }
@@ -12183,7 +12518,7 @@
     return this.vtScrollBottom_;
 
   return this.screenSize.height - 1;
-}
+};
 
 /**
  * Process a '\n' character.
@@ -12196,7 +12531,7 @@
  */
 hterm.Terminal.prototype.newLine = function() {
   var cursorAtEndOfScreen = (this.screen_.cursorPosition.row ==
-                             this.screen_.rowsArray.length - 1);
+    this.screen_.rowsArray.length - 1);
 
   if (this.vtScrollBottom_ != null) {
     // A VT Scroll region is active, we never append new rows.
@@ -12204,19 +12539,23 @@
       // We're at the end of the VT Scroll Region, perform a VT scroll.
       this.vtScrollUp(1);
       this.setAbsoluteCursorPosition(this.screen_.cursorPosition.row, 0);
-    } else if (cursorAtEndOfScreen) {
+    }
+    else if (cursorAtEndOfScreen) {
       // We're at the end of the screen, the only thing to do is put the
       // cursor to column 0.
       this.setAbsoluteCursorPosition(this.screen_.cursorPosition.row, 0);
-    } else {
+    }
+    else {
       // Anywhere else, advance the cursor row, and reset the column.
       this.setAbsoluteCursorPosition(this.screen_.cursorPosition.row + 1, 0);
     }
-  } else if (cursorAtEndOfScreen) {
+  }
+  else if (cursorAtEndOfScreen) {
     // We're at the end of the screen.  Append a new row to the terminal,
     // shifting the top row into the scrollback.
     this.appendRows_(1);
-  } else {
+  }
+  else {
     // Anywhere else in the screen just moves the cursor.
     this.setAbsoluteCursorPosition(this.screen_.cursorPosition.row + 1, 0);
   }
@@ -12237,7 +12576,8 @@
 hterm.Terminal.prototype.formFeed = function() {
   if (this.options_.autoCarriageReturn) {
     this.newLine();
-  } else {
+  }
+  else {
     this.lineFeed();
   }
 };
@@ -12253,7 +12593,8 @@
 
   if (currentRow == scrollTop) {
     this.insertLines(1);
-  } else {
+  }
+  else {
     this.setAbsoluteCursorRow(currentRow - 1);
   }
 };
@@ -12298,10 +12639,10 @@
   var count = opt_count ? Math.min(opt_count, maxCount) : maxCount;
 
   if (this.screen_.textAttributes.background ===
-      this.screen_.textAttributes.DEFAULT_COLOR) {
+    this.screen_.textAttributes.DEFAULT_COLOR) {
     var cursorRow = this.screen_.rowsArray[this.screen_.cursorPosition.row];
     if (hterm.TextAttributes.nodeWidth(cursorRow) <=
-        this.screen_.cursorPosition.column + count) {
+      this.screen_.cursorPosition.column + count) {
       this.screen_.deleteChars(count);
       this.clearCursorOverflow();
       return;
@@ -12578,7 +12919,8 @@
 hterm.Terminal.prototype.setCursorPosition = function(row, column) {
   if (this.options_.originMode) {
     this.setRelativeCursorPosition(row, column);
-  } else {
+  }
+  else {
     this.setAbsoluteCursorPosition(row, column);
   }
 };
@@ -12659,9 +13001,9 @@
 
   var self = this;
   this.timeouts_.redraw = setTimeout(function() {
-      delete self.timeouts_.redraw;
-      self.scrollPort_.redraw_();
-    }, 0);
+    delete self.timeouts_.redraw;
+    self.scrollPort_.redraw_();
+  }, 0);
 };
 
 /**
@@ -12679,9 +13021,9 @@
 
   var self = this;
   this.timeouts_.scrollDown = setTimeout(function() {
-      delete self.timeouts_.scrollDown;
-      self.scrollPort_.scrollRowToBottom(self.getRowCount());
-    }, 10);
+    delete self.timeouts_.scrollDown;
+    self.scrollPort_.scrollRowToBottom(self.getRowCount());
+  }, 10);
 };
 
 /**
@@ -12702,10 +13044,10 @@
   count = count || 1;
   var minHeight = (this.options_.originMode ? this.getVTScrollTop() : 0);
   var maxHeight = (this.options_.originMode ? this.getVTScrollBottom() :
-                   this.screenSize.height - 1);
+    this.screenSize.height - 1);
 
   var row = lib.f.clamp(this.screen_.cursorPosition.row + count,
-                        minHeight, maxHeight);
+    minHeight, maxHeight);
   this.setAbsoluteCursorRow(row);
 };
 
@@ -12749,7 +13091,8 @@
 
     this.setCursorPosition(Math.max(newRow, 0), newColumn);
 
-  } else {
+  }
+  else {
     var newColumn = Math.max(currentColumn - count, 0);
     this.setCursorColumn(newColumn);
   }
@@ -12767,7 +13110,7 @@
     return;
 
   var column = lib.f.clamp(this.screen_.cursorPosition.column + count,
-                           0, this.screenSize.width - 1);
+    0, this.screenSize.width - 1);
   this.setCursorColumn(column);
 };
 
@@ -12787,7 +13130,8 @@
   if (state) {
     this.scrollPort_.setForegroundColor(this.prefs_.get('background-color'));
     this.scrollPort_.setBackgroundColor(this.prefs_.get('foreground-color'));
-  } else {
+  }
+  else {
     this.scrollPort_.setForegroundColor(this.prefs_.get('foreground-color'));
     this.scrollPort_.setBackgroundColor(this.prefs_.get('background-color'));
   }
@@ -12800,12 +13144,12 @@
  */
 hterm.Terminal.prototype.ringBell = function() {
   this.cursorNode_.style.backgroundColor =
-      this.scrollPort_.getForegroundColor();
+    this.scrollPort_.getForegroundColor();
 
   var self = this;
   setTimeout(function() {
-      self.cursorNode_.style.backgroundColor = self.prefs_.get('cursor-color');
-    }, 200);
+    self.cursorNode_.style.backgroundColor = self.prefs_.get('cursor-color');
+  }, 200);
 
   // bellSquelchTimeout_ affects both audio and notification bells.
   if (this.bellSquelchTimeout_)
@@ -12814,19 +13158,23 @@
   if (this.bellAudio_.getAttribute('src')) {
     this.bellAudio_.play();
     this.bellSequelchTimeout_ = setTimeout(function() {
-        delete this.bellSquelchTimeout_;
-      }.bind(this), 500);
-  } else {
+      delete this.bellSquelchTimeout_;
+    }.bind(this), 500);
+  }
+  else {
     delete this.bellSquelchTimeout_;
   }
 
   if (this.desktopNotificationBell_ && !this.document_.hasFocus()) {
     var n = new Notification(
-        lib.f.replaceVars(hterm.desktopNotificationTitle,
-                          {'title': window.document.title || 'hterm'}));
+      lib.f.replaceVars(hterm.desktopNotificationTitle, {
+        'title': window.document.title || 'hterm'
+      }));
     this.bellNotificationList_.push(n);
     // TODO: Should we try to raise the window here?
-    n.onclick = function() { self.closeBellNotifications_(); };
+    n.onclick = function() {
+      self.closeBellNotifications_();
+    };
   }
 };
 
@@ -12923,7 +13271,7 @@
   this.screen_ = state ? this.alternateScreen_ : this.primaryScreen_;
 
   if (this.screen_.rowsArray.length &&
-      this.screen_.rowsArray[0].rowIndex != this.scrollbackRows_.length) {
+    this.screen_.rowsArray[0].rowIndex != this.scrollbackRows_.length) {
     // If the screen changed sizes while we were away, our rowIndexes may
     // be incorrect.
     var offset = this.scrollbackRows_.length;
@@ -12997,7 +13345,8 @@
       return;
 
     this.onCursorBlink_();
-  } else {
+  }
+  else {
     if (this.timeouts_.cursorBlink) {
       clearTimeout(this.timeouts_.cursorBlink);
       delete this.timeouts_.cursorBlink;
@@ -13013,7 +13362,7 @@
   var topRowIndex = this.scrollPort_.getTopRowIndex();
   var bottomRowIndex = this.scrollPort_.getBottomRowIndex(topRowIndex);
   var cursorRowIndex = this.scrollbackRows_.length +
-      this.screen_.cursorPosition.row;
+    this.screen_.cursorPosition.row;
 
   if (cursorRowIndex > bottomRowIndex) {
     // Cursor is scrolled off screen, move it outside of the visible area.
@@ -13022,22 +13371,22 @@
   }
 
   if (this.options_.cursorVisible &&
-      this.cursorNode_.style.display == 'none') {
+    this.cursorNode_.style.display == 'none') {
     // Re-display the terminal cursor if it was hidden by the mouse cursor.
     this.cursorNode_.style.display = '';
   }
 
 
   this.cursorNode_.style.top = this.scrollPort_.visibleRowTopMargin +
-      this.scrollPort_.characterSize.height * (cursorRowIndex - topRowIndex) +
-      'px';
+    this.scrollPort_.characterSize.height * (cursorRowIndex - topRowIndex) +
+    'px';
   this.cursorNode_.style.left = this.scrollPort_.characterSize.width *
-      this.screen_.cursorPosition.column + 'px';
+    this.screen_.cursorPosition.column + 'px';
 
   this.cursorNode_.setAttribute('title',
-                                '(' + this.screen_.cursorPosition.row +
-                                ', ' + this.screen_.cursorPosition.column +
-                                ')');
+    '(' + this.screen_.cursorPosition.row +
+    ', ' + this.screen_.cursorPosition.column +
+    ')');
 
   // Update the caret for a11y purposes.
   var selection = this.document_.getSelection();
@@ -13098,9 +13447,9 @@
 
   var self = this;
   this.timeouts_.syncCursor = setTimeout(function() {
-      self.syncCursorPosition_();
-      delete self.timeouts_.syncCursor;
-    }, 0);
+    self.syncCursorPosition_();
+    delete self.timeouts_.syncCursor;
+  }, 0);
 };
 
 /**
@@ -13118,19 +13467,19 @@
 
     this.zoomWarningNode_ = this.document_.createElement('div');
     this.zoomWarningNode_.style.cssText = (
-        'color: black;' +
-        'background-color: #ff2222;' +
-        'font-size: large;' +
-        'border-radius: 8px;' +
-        'opacity: 0.75;' +
-        'padding: 0.2em 0.5em 0.2em 0.5em;' +
-        'top: 0.5em;' +
-        'right: 1.2em;' +
-        'position: absolute;' +
-        '-webkit-text-size-adjust: none;' +
-        '-webkit-user-select: none;' +
-        '-moz-text-size-adjust: none;' +
-        '-moz-user-select: none;');
+      'color: black;' +
+      'background-color: #ff2222;' +
+      'font-size: large;' +
+      'border-radius: 8px;' +
+      'opacity: 0.75;' +
+      'padding: 0.2em 0.5em 0.2em 0.5em;' +
+      'top: 0.5em;' +
+      'right: 1.2em;' +
+      'position: absolute;' +
+      '-webkit-text-size-adjust: none;' +
+      '-webkit-user-select: none;' +
+      '-moz-text-size-adjust: none;' +
+      '-moz-user-select: none;');
 
     this.zoomWarningNode_.addEventListener('click', function(e) {
       this.parentNode.removeChild(this);
@@ -13138,15 +13487,15 @@
   }
 
   this.zoomWarningNode_.textContent = lib.MessageManager.replaceReferences(
-      hterm.zoomWarningMessage,
-      [parseInt(this.scrollPort_.characterSize.zoomFactor * 100)]);
+    hterm.zoomWarningMessage, [parseInt(this.scrollPort_.characterSize.zoomFactor * 100)]);
 
   this.zoomWarningNode_.style.fontFamily = this.prefs_.get('font-family');
 
   if (state) {
     if (!this.zoomWarningNode_.parentNode)
       this.div_.parentNode.appendChild(this.zoomWarningNode_);
-  } else if (this.zoomWarningNode_.parentNode) {
+  }
+  else if (this.zoomWarningNode_.parentNode) {
     this.zoomWarningNode_.parentNode.removeChild(this.zoomWarningNode_);
   }
 };
@@ -13171,15 +13520,15 @@
 
     this.overlayNode_ = this.document_.createElement('div');
     this.overlayNode_.style.cssText = (
-        'border-radius: 15px;' +
-        'font-size: xx-large;' +
-        'opacity: 0.75;' +
-        'padding: 0.2em 0.5em 0.2em 0.5em;' +
-        'position: absolute;' +
-        '-webkit-user-select: none;' +
-        '-webkit-transition: opacity 180ms ease-in;' +
-        '-moz-user-select: none;' +
-        '-moz-transition: opacity 180ms ease-in;');
+      'border-radius: 15px;' +
+      'font-size: xx-large;' +
+      'opacity: 0.75;' +
+      'padding: 0.2em 0.5em 0.2em 0.5em;' +
+      'position: absolute;' +
+      '-webkit-user-select: none;' +
+      '-webkit-transition: opacity 180ms ease-in;' +
+      '-moz-user-select: none;' +
+      '-moz-transition: opacity 180ms ease-in;');
 
     this.overlayNode_.addEventListener('mousedown', function(e) {
       e.preventDefault();
@@ -13201,9 +13550,9 @@
   var overlaySize = hterm.getClientSize(this.overlayNode_);
 
   this.overlayNode_.style.top =
-      (divSize.height - overlaySize.height) / 2 + 'px';
+    (divSize.height - overlaySize.height) / 2 + 'px';
   this.overlayNode_.style.left = (divSize.width - overlaySize.width -
-      this.scrollPort_.currentScrollbarWidthPx) / 2 + 'px';
+    this.scrollPort_.currentScrollbarWidthPx) / 2 + 'px';
 
   var self = this;
 
@@ -13214,14 +13563,14 @@
     return;
 
   this.overlayTimeout_ = setTimeout(function() {
-      self.overlayNode_.style.opacity = '0';
-      self.overlayTimeout_ = setTimeout(function() {
-          if (self.overlayNode_.parentNode)
-            self.overlayNode_.parentNode.removeChild(self.overlayNode_);
-          self.overlayTimeout_ = null;
-          self.overlayNode_.style.opacity = '0.75';
-        }, 200);
-    }, opt_timeout || 1500);
+    self.overlayNode_.style.opacity = '0';
+    self.overlayTimeout_ = setTimeout(function() {
+      if (self.overlayNode_.parentNode)
+        self.overlayNode_.parentNode.removeChild(self.overlayNode_);
+      self.overlayTimeout_ = null;
+      self.overlayNode_.style.opacity = '0.75';
+    }, 200);
+  }, opt_timeout || 1500);
 };
 
 /**
@@ -13245,10 +13594,10 @@
   var copySource = this.document_.createElement('pre');
   copySource.textContent = str;
   copySource.style.cssText = (
-      '-webkit-user-select: text;' +
-      '-moz-user-select: text;' +
-      'position: absolute;' +
-      'top: -99px');
+    '-webkit-user-select: text;' +
+    '-moz-user-select: text;' +
+    'position: absolute;' +
+    'top: -99px');
 
   this.document_.body.appendChild(copySource);
 
@@ -13275,7 +13624,7 @@
 /**
  * Returns the selected text, or null if no text is selected.
  *
- * @return {string|null}
+ * @return {?string}
  */
 hterm.Terminal.prototype.getSelectionText = function() {
   var selection = this.scrollPort_.selection;
@@ -13307,7 +13656,7 @@
 
   // End offset measures from the end of the line.
   var endOffset = (hterm.TextAttributes.nodeWidth(selection.endNode) -
-                   selection.endOffset);
+    selection.endOffset);
   node = selection.endNode;
 
   if (node.nodeName != 'X-ROW') {
@@ -13327,7 +13676,7 @@
   }
 
   var rv = this.getRowsText(selection.startRow.rowIndex,
-                            selection.endRow.rowIndex + 1);
+    selection.endRow.rowIndex + 1);
   return lib.wc.substring(rv, startOffset, lib.wc.strWidth(rv) - endOffset);
 };
 
@@ -13365,7 +13714,7 @@
 hterm.Terminal.prototype.openUrl = function(url) {
   var win = window.open(url, '_blank');
   win.focus();
-}
+};
 
 /**
  * Open the selected url.
@@ -13388,7 +13737,7 @@
     str = 'http://' + str;
 
   this.openUrl(str);
-}
+};
 
 
 /**
@@ -13413,15 +13762,15 @@
   }
 
   var reportMouseEvents = (!this.defeatMouseReports_ &&
-      this.vt.mouseReport != this.vt.MOUSE_REPORT_DISABLED);
+    this.vt.mouseReport != this.vt.MOUSE_REPORT_DISABLED);
 
   e.processedByTerminalHandler_ = true;
 
   // One based row/column stored on the mouse event.
   e.terminalRow = parseInt((e.clientY - this.scrollPort_.visibleRowTopMargin) /
-                           this.scrollPort_.characterSize.height) + 1;
+    this.scrollPort_.characterSize.height) + 1;
   e.terminalColumn = parseInt(e.clientX /
-                              this.scrollPort_.characterSize.width) + 1;
+    this.scrollPort_.characterSize.width) + 1;
 
   if (e.type == 'mousedown' && e.terminalColumn > this.screenSize.width) {
     // Mousedown in the scrollbar area.
@@ -13434,9 +13783,10 @@
     // cursor is over top.  This keeps the terminal cursor from interfering
     // with local text selection.
     if (e.terminalRow - 1 == this.screen_.cursorPosition.row &&
-        e.terminalColumn - 1 == this.screen_.cursorPosition.column) {
+      e.terminalColumn - 1 == this.screen_.cursorPosition.column) {
       this.cursorNode_.style.display = 'none';
-    } else if (this.cursorNode_.style.display == 'none') {
+    }
+    else if (this.cursorNode_.style.display == 'none') {
       this.cursorNode_.style.display = '';
     }
   }
@@ -13447,7 +13797,8 @@
       // alt-mousedown, then the mouse will act on the local selection.
       this.defeatMouseReports_ = true;
       this.setSelectionEnabled(true);
-    } else {
+    }
+    else {
       // Otherwise we defer ownership of the mouse to the VT.
       this.defeatMouseReports_ = false;
       this.document_.getSelection().collapseToEnd();
@@ -13468,7 +13819,7 @@
       // have expanded the selection text at the first click event.
       clearTimeout(this.timeouts_.openUrl);
       this.timeouts_.openUrl = setTimeout(this.openSelectedUrl_.bind(this),
-                                          500);
+        500);
       return;
     }
 
@@ -13476,18 +13827,19 @@
       this.paste();
 
     if (e.type == 'mouseup' && e.which == 1 && this.copyOnSelect &&
-        !this.document_.getSelection().isCollapsed) {
+      !this.document_.getSelection().isCollapsed) {
       this.copySelectionToClipboard(this.document_);
     }
 
     if ((e.type == 'mousemove' || e.type == 'mouseup') &&
-        this.scrollBlockerNode_.engaged) {
+      this.scrollBlockerNode_.engaged) {
       // Disengage the scroll-blocker after one of these events.
       this.scrollBlockerNode_.engaged = false;
       this.scrollBlockerNode_.style.top = '-99px';
     }
 
-  } else /* if (this.reportMouseEvents) */ {
+  }
+  else /* if (this.reportMouseEvents) */ {
     if (!this.scrollBlockerNode_.engaged) {
       if (e.type == 'mousedown') {
         // Move the scroll-blocker into place if we want to keep the scrollport
@@ -13495,7 +13847,8 @@
         this.scrollBlockerNode_.engaged = true;
         this.scrollBlockerNode_.style.top = (e.clientY - 5) + 'px';
         this.scrollBlockerNode_.style.left = (e.clientX - 5) + 'px';
-      } else if (e.type == 'mousemove') {
+      }
+      else if (e.type == 'mousemove') {
         // Oh.  This means that drag-scroll was disabled AFTER the mouse down,
         // in which case it's too late to engage the scroll-blocker.
         this.document_.getSelection().collapseToEnd();
@@ -13522,7 +13875,7 @@
  *
  * @param {Event} e The mouse event to handle.
  */
-hterm.Terminal.prototype.onMouse = function(e) { };
+hterm.Terminal.prototype.onMouse = function(e) {};
 
 /**
  * React when focus changes.
@@ -13579,9 +13932,9 @@
  */
 hterm.Terminal.prototype.onResize_ = function() {
   var columnCount = Math.floor(this.scrollPort_.getScreenWidth() /
-                               this.scrollPort_.characterSize.width) || 0;
+    this.scrollPort_.characterSize.width) || 0;
   var rowCount = lib.f.smartFloorDivide(this.scrollPort_.getScreenHeight(),
-                            this.scrollPort_.characterSize.height) || 0;
+    this.scrollPort_.characterSize.height) || 0;
 
   if (columnCount <= 0 || rowCount <= 0) {
     // We avoid these situations since they happen sometimes when the terminal
@@ -13593,7 +13946,7 @@
   }
 
   var isNewSize = (columnCount != this.screenSize.width ||
-                   rowCount != this.screenSize.height);
+    rowCount != this.screenSize.height);
 
   // We do this even if the size didn't change, just to be sure everything is
   // in sync.
@@ -13617,14 +13970,15 @@
   }
 
   if (this.cursorNode_.getAttribute('focus') == 'false' ||
-      this.cursorNode_.style.opacity == '0') {
+    this.cursorNode_.style.opacity == '0') {
     this.cursorNode_.style.opacity = '1';
     this.timeouts_.cursorBlink = setTimeout(this.myOnCursorBlink_,
-                                            this.cursorBlinkCycle_[0]);
-  } else {
+      this.cursorBlinkCycle_[0]);
+  }
+  else {
     this.cursorNode_.style.opacity = '0';
     this.timeouts_.cursorBlink = setTimeout(this.myOnCursorBlink_,
-                                            this.cursorBlinkCycle_[1]);
+      this.cursorBlinkCycle_[1]);
   }
 };
 
@@ -13659,8 +14013,8 @@
  */
 hterm.Terminal.prototype.closeBellNotifications_ = function() {
   this.bellNotificationList_.forEach(function(n) {
-      n.close();
-    });
+    n.close();
+  });
   this.bellNotificationList_.length = 0;
 };
 // SOURCE FILE: hterm/js/hterm_terminal_io.js
@@ -13847,9 +14201,9 @@
  * @param {string} string The string to print.
  */
 hterm.Terminal.IO.prototype.print =
-hterm.Terminal.IO.prototype.writeUTF16 = function(string) {
-  this.writeUTF8(lib.encodeUTF8(string));
-};
+  hterm.Terminal.IO.prototype.writeUTF16 = function(string) {
+    this.writeUTF8(lib.encodeUTF8(string));
+  };
 
 /**
  * Print a UTF-16 JavaScript string to the terminal followed by a newline.
@@ -13857,9 +14211,9 @@
  * @param {string} string The string to print.
  */
 hterm.Terminal.IO.prototype.println =
-hterm.Terminal.IO.prototype.writelnUTF16 = function(string) {
-  this.writelnUTF8(lib.encodeUTF8(string));
-};
+  hterm.Terminal.IO.prototype.writelnUTF16 = function(string) {
+    this.writelnUTF8(lib.encodeUTF8(string));
+  };
 // SOURCE FILE: hterm/js/hterm_text_attributes.js
 // Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
@@ -14009,17 +14363,17 @@
  */
 hterm.TextAttributes.prototype.isDefault = function() {
   return (this.foregroundSource == this.SRC_DEFAULT &&
-          this.backgroundSource == this.SRC_DEFAULT &&
-          !this.bold &&
-          !this.faint &&
-          !this.italic &&
-          !this.blink &&
-          !this.underline &&
-          !this.strikethrough &&
-          !this.inverse &&
-          !this.invisible &&
-          !this.wcNode &&
-          this.tileData == null);
+    this.backgroundSource == this.SRC_DEFAULT &&
+    !this.bold &&
+    !this.faint &&
+    !this.italic &&
+    !this.blink &&
+    !this.underline &&
+    !this.strikethrough &&
+    !this.inverse &&
+    !this.invisible &&
+    !this.wcNode &&
+    this.tileData == null);
 };
 
 /**
@@ -14120,14 +14474,14 @@
   // We don't want to put multiple characters in a wcNode or a tile.
   // See the comments in createContainer.
   return (!(this.wcNode || obj.wcNode) &&
-          !(this.tileData != null || obj.tileNode) &&
-          this.foreground == style.color &&
-          this.background == style.backgroundColor &&
-          (this.enableBold && this.bold) == !!style.fontWeight &&
-          this.blink == obj.blinkNode &&
-          this.italic == !!style.fontStyle &&
-          !!this.underline == !!obj.underline &&
-          !!this.strikethrough == !!obj.strikethrough);
+    !(this.tileData != null || obj.tileNode) &&
+    this.foreground == style.color &&
+    this.background == style.backgroundColor &&
+    (this.enableBold && this.bold) == !!style.fontWeight &&
+    this.blink == obj.blinkNode &&
+    this.italic == !!style.fontStyle &&
+    !!this.underline == !!obj.underline &&
+    !!this.strikethrough == !!obj.strikethrough);
 };
 
 hterm.TextAttributes.prototype.setDefaults = function(foreground, background) {
@@ -14174,7 +14528,7 @@
 
   if (this.enableBoldAsBright && this.bold) {
     if (foregroundSource != this.SRC_DEFAULT &&
-        foregroundSource != this.SRC_RGB) {
+      foregroundSource != this.SRC_RGB) {
       foregroundSource = getBrightIndex(foregroundSource);
     }
   }
@@ -14187,18 +14541,18 @@
   // Set fore/background colors unless already specified in rgb(r, g, b) form.
   if (foregroundSource != this.SRC_RGB) {
     this.foreground = ((foregroundSource == this.SRC_DEFAULT) ?
-                       defaultForeground : this.colorPalette[foregroundSource]);
+      defaultForeground : this.colorPalette[foregroundSource]);
   }
 
   if (this.faint && !this.invisible) {
     var colorToMakeFaint = ((this.foreground == this.DEFAULT_COLOR) ?
-                            this.defaultForeground : this.foreground);
+      this.defaultForeground : this.foreground);
     this.foreground = lib.colors.mix(colorToMakeFaint, 'rgb(0, 0, 0)', 0.3333);
   }
 
   if (backgroundSource != this.SRC_RGB) {
     this.background = ((backgroundSource == this.SRC_DEFAULT) ?
-                       defaultBackground : this.colorPalette[backgroundSource]);
+      defaultBackground : this.colorPalette[backgroundSource]);
   }
 };
 
@@ -14226,10 +14580,10 @@
   var style2 = obj2.style;
 
   return (style1.color == style2.color &&
-          style1.backgroundColor == style2.backgroundColor &&
-          style1.fontWeight == style2.fontWeight &&
-          style1.fontStyle == style2.fontStyle &&
-          style1.textDecoration == style2.textDecoration);
+    style1.backgroundColor == style2.backgroundColor &&
+    style1.fontWeight == style2.fontWeight &&
+    style1.fontStyle == style2.fontStyle &&
+    style1.textDecoration == style2.textDecoration);
 };
 
 /**
@@ -14241,7 +14595,7 @@
  * @return {boolean} True if the object is unstyled.
  */
 hterm.TextAttributes.containerIsDefault = function(obj) {
-  return typeof obj == 'string'  || obj.nodeType == 3;
+  return typeof obj == 'string' || obj.nodeType == 3;
 };
 
 /**
@@ -14254,10 +14608,11 @@
 hterm.TextAttributes.nodeWidth = function(node) {
   if (node.wcNode) {
     return lib.wc.strWidth(node.textContent);
-  } else {
+  }
+  else {
     return node.textContent.length;
   }
-}
+};
 
 /**
  * Static method to get the substr of a node's textContent.  The start index
@@ -14272,10 +14627,11 @@
 hterm.TextAttributes.nodeSubstr = function(node, start, width) {
   if (node.wcNode) {
     return lib.wc.substr(node.textContent, start, width);
-  } else {
+  }
+  else {
     return node.textContent.substr(start, width);
   }
-}
+};
 
 /**
  * Static method to get the substring based of a node's textContent.  The
@@ -14290,7 +14646,8 @@
 hterm.TextAttributes.nodeSubstring = function(node, start, end) {
   if (node.wcNode) {
     return lib.wc.substring(node.textContent, start, end);
-  } else {
+  }
+  else {
     return node.textContent.substring(start, end);
   }
 };
@@ -14307,18 +14664,25 @@
  */
 hterm.TextAttributes.splitWidecharString = function(str) {
   var rv = [];
-  var base = 0, length = 0;
+  var base = 0,
+    length = 0;
 
   for (var i = 0; i < str.length;) {
     var c = str.codePointAt(i);
     var increment = (c <= 0xffff) ? 1 : 2;
     if (c < 128 || lib.wc.charWidth(c) == 1) {
       length += increment;
-    } else {
+    }
+    else {
       if (length) {
-        rv.push({str: str.substr(base, length)});
+        rv.push({
+          str: str.substr(base, length)
+        });
       }
-      rv.push({str: str.substr(i, increment), wcNode: true});
+      rv.push({
+        str: str.substr(i, increment),
+        wcNode: true
+      });
       base = i + increment;
       length = 0;
     }
@@ -14326,7 +14690,9 @@
   }
 
   if (length)
-    rv.push({str: str.substr(base, length)});
+    rv.push({
+      str: str.substr(base, length)
+    });
 
   return rv;
 };
@@ -14338,7 +14704,7 @@
 'use strict';
 
 lib.rtdep('lib.colors', 'lib.f', 'lib.UTF8Decoder',
-          'hterm.VT.CharacterMap');
+  'hterm.VT.CharacterMap');
 
 /**
  * Constructor for the VT escape sequence interpreter.
@@ -14402,9 +14768,9 @@
   // This is used in parseUnknown_ to quickly scan a string for the next
   // control character.
   var cc1 = Object.keys(hterm.VT.CC1).map(
-      function(e) {
-        return '\\x' + lib.f.zpad(e.charCodeAt().toString(16), 2)
-      }).join('');
+    function(e) {
+      return '\\x' + lib.f.zpad(e.charCodeAt().toString(16), 2);
+    }).join('');
   this.cc1Pattern_ = new RegExp('[' + cc1 + ']');
 
   // Decoder to maintain UTF-8 decode state.
@@ -14719,7 +15085,7 @@
 
     case 'mouseup':
       // Mouse up has no indication of which button was released.
-      response = '\x1b[M\x23' + x + y;
+      response = '\x1b[M#' + x + y;
       break;
 
     case 'mousemove':
@@ -14768,7 +15134,7 @@
     this.parseState_.func.call(this, this.parseState_);
 
     if (this.parseState_.func == func && this.parseState_.pos == pos &&
-        this.parseState_.buf == buf) {
+      this.parseState_.buf == buf) {
       throw 'Parser did not alter the state!';
     }
   }
@@ -14855,16 +15221,18 @@
   if (ch >= '@' && ch <= '~') {
     // This is the final character.
     this.dispatch('CSI', this.leadingModifier_ + this.trailingModifier_ + ch,
-                  parseState);
+      parseState);
     parseState.resetParseFunction();
 
-  } else if (ch == ';') {
+  }
+  else if (ch == ';') {
     // Parameter delimiter.
     if (this.trailingModifier_) {
       // Parameter delimiter after the trailing modifier.  That's a paddlin'.
       parseState.resetParseFunction();
 
-    } else {
+    }
+    else {
       if (!args.length) {
         // They omitted the first param, we need to supply it.
         args.push('');
@@ -14873,33 +15241,40 @@
       args.push('');
     }
 
-  } else if (ch >= '0' && ch <= '9') {
+  }
+  else if (ch >= '0' && ch <= '9') {
     // Next byte in the current parameter.
 
     if (this.trailingModifier_) {
       // Numeric parameter after the trailing modifier.  That's a paddlin'.
       parseState.resetParseFunction();
-    } else {
+    }
+    else {
       if (!args.length) {
         args[0] = ch;
-      } else {
+      }
+      else {
         args[args.length - 1] += ch;
       }
     }
 
-  } else if (ch >= ' ' && ch <= '?' && ch != ':') {
+  }
+  else if (ch >= ' ' && ch <= '?' && ch != ':') {
     // Modifier character.
     if (!args.length) {
       this.leadingModifier_ += ch;
-    } else {
+    }
+    else {
       this.trailingModifier_ += ch;
     }
 
-  } else if (this.cc1Pattern_.test(ch)) {
+  }
+  else if (this.cc1Pattern_.test(ch)) {
     // Control character.
     this.dispatch('CC1', ch, parseState);
 
-  } else {
+  }
+  else {
     // Unexpected character in sequence, bail out.
     parseState.resetParseFunction();
   }
@@ -14951,7 +15326,7 @@
 
     if (abortReason) {
       console.log('parseUntilStringTerminator_: aborting: ' + abortReason,
-                  args[0]);
+        args[0]);
       parseState.reset(args[0]);
       return false;
     }
@@ -14970,7 +15345,7 @@
 
   parseState.resetParseFunction();
   parseState.advance(nextTerminator +
-                     (buf.substr(nextTerminator, 1) == '\x1b' ? 2 : 1));
+    (buf.substr(nextTerminator, 1) == '\x1b' ? 2 : 1));
 
   return true;
 };
@@ -15002,7 +15377,7 @@
     // (APC, '\x9f') from locking up the terminal waiting for its expected
     // (ST, '\x9c') or (BEL, '\x07').
     console.warn('Ignoring 8-bit control code: 0x' +
-                 code.charCodeAt(0).toString(16));
+      code.charCodeAt(0).toString(16));
     return;
   }
 
@@ -15025,9 +15400,11 @@
 hterm.VT.prototype.setANSIMode = function(code, state) {
   if (code == '4') {
     this.terminal.setInsertMode(state);
-  } else if (code == '20') {
+  }
+  else if (code == '20') {
     this.terminal.setAutoCarriageReturn(state);
-  } else if (this.warnUnimplemented) {
+  }
+  else if (this.warnUnimplemented) {
     console.warn('Unimplemented ANSI Mode: ' + code);
   }
 };
@@ -15101,11 +15478,11 @@
  */
 hterm.VT.prototype.setDECMode = function(code, state) {
   switch (code) {
-    case '1':  // DECCKM
+    case '1': // DECCKM
       this.terminal.keyboard.applicationCursor = state;
       break;
 
-    case '3':  // DECCOLM
+    case '3': // DECCOLM
       if (this.allowColumnWidthChanges_) {
         this.terminal.setWidth(state ? 132 : 80);
 
@@ -15114,96 +15491,98 @@
       }
       break;
 
-    case '5':  // DECSCNM
+    case '5': // DECSCNM
       this.terminal.setReverseVideo(state);
       break;
 
-    case '6':  // DECOM
+    case '6': // DECOM
       this.terminal.setOriginMode(state);
       break;
 
-    case '7':  // DECAWM
+    case '7': // DECAWM
       this.terminal.setWraparound(state);
       break;
 
-    case '12':  // att610
+    case '12': // att610
       if (this.enableDec12)
         this.terminal.setCursorBlink(state);
       break;
 
-    case '25':  // DECTCEM
+    case '25': // DECTCEM
       this.terminal.setCursorVisible(state);
       break;
 
-    case '40':  // no-spec
+    case '40': // no-spec
       this.terminal.allowColumnWidthChanges_ = state;
       break;
 
-    case '45':  // no-spec
+    case '45': // no-spec
       this.terminal.setReverseWraparound(state);
       break;
 
-    case '67':  // DECBKM
+    case '67': // DECBKM
       this.terminal.keyboard.backspaceSendsBackspace = state;
       break;
 
-    case '1000':  // Report on mouse clicks only.
+    case '1000': // Report on mouse clicks only.
       this.mouseReport = (
-          state ? this.MOUSE_REPORT_CLICK : this.MOUSE_REPORT_DISABLED);
+        state ? this.MOUSE_REPORT_CLICK : this.MOUSE_REPORT_DISABLED);
       break;
 
-    case '1002':  // Report on mouse clicks and drags
+    case '1002': // Report on mouse clicks and drags
       this.mouseReport = (
-          state ? this.MOUSE_REPORT_DRAG : this.MOUSE_REPORT_DISABLED);
+        state ? this.MOUSE_REPORT_DRAG : this.MOUSE_REPORT_DISABLED);
       break;
 
-    case '1010':  // rxvt
+    case '1010': // rxvt
       this.terminal.scrollOnOutput = state;
       break;
 
-    case '1011':  // rxvt
+    case '1011': // rxvt
       this.terminal.scrollOnKeystroke = state;
       break;
 
-    case '1036':  // no-spec
+    case '1036': // no-spec
       this.terminal.keyboard.metaSendsEscape = state;
       break;
 
-    case '1039':  // no-spec
+    case '1039': // no-spec
       if (state) {
         if (!this.terminal.keyboard.previousAltSendsWhat_) {
           this.terminal.keyboard.previousAltSendsWhat_ =
-              this.terminal.keyboard.altSendsWhat;
+            this.terminal.keyboard.altSendsWhat;
           this.terminal.keyboard.altSendsWhat = 'escape';
         }
-      } else if (this.terminal.keyboard.previousAltSendsWhat_) {
+      }
+      else if (this.terminal.keyboard.previousAltSendsWhat_) {
         this.terminal.keyboard.altSendsWhat =
-            this.terminal.keyboard.previousAltSendsWhat_;
+          this.terminal.keyboard.previousAltSendsWhat_;
         this.terminal.keyboard.previousAltSendsWhat_ = null;
       }
       break;
 
     case '47':
-    case '1047':  // no-spec
+    case '1047': // no-spec
       this.terminal.setAlternateMode(state);
       break;
 
-    case '1048':  // Save cursor as in DECSC.
+    case '1048': // Save cursor as in DECSC.
       this.savedState_.save();
 
-    case '1049':  // 1047 + 1048 + clear.
+    case '1049': // 1047 + 1048 + clear.
       if (state) {
         this.savedState_.save();
         this.terminal.setAlternateMode(state);
         this.terminal.clear();
-      } else {
+      }
+      else {
         this.terminal.setAlternateMode(state);
         this.savedState_.restore();
       }
 
       break;
 
-    case '2004':  // Bracketed paste mode.
+    case '2004': // Bracketed paste mode.
       this.terminal.setBracketedPaste(state);
       break;
 
@@ -15265,7 +15644,7 @@
  *
  * Silently ignored.
  */
-hterm.VT.CC1['\x00'] = function () {};
+hterm.VT.CC1['\x00'] = function() {};
 
 /**
  * Enquiry (ENQ).
@@ -15432,9 +15811,9 @@
  * Like newline, only keep the X position
  */
 hterm.VT.CC1['\x84'] =
-hterm.VT.ESC['D'] = function() {
-  this.terminal.lineFeed();
-};
+  hterm.VT.ESC['D'] = function() {
+    this.terminal.lineFeed();
+  };
 
 /**
  * Next Line (NEL).
@@ -15442,18 +15821,18 @@
  * Like newline, but doesn't add lines.
  */
 hterm.VT.CC1['\x85'] =
-hterm.VT.ESC['E'] = function() {
-  this.terminal.setCursorColumn(0);
-  this.terminal.cursorDown(1);
-};
+  hterm.VT.ESC['E'] = function() {
+    this.terminal.setCursorColumn(0);
+    this.terminal.cursorDown(1);
+  };
 
 /**
  * Horizontal Tabulation Set (HTS).
  */
 hterm.VT.CC1['\x88'] =
-hterm.VT.ESC['H'] = function() {
-  this.terminal.setTabStop(this.terminal.getCursorColumn());
-};
+  hterm.VT.ESC['H'] = function() {
+    this.terminal.setTabStop(this.terminal.getCursorColumn());
+  };
 
 /**
  * Reverse Index (RI).
@@ -15461,9 +15840,9 @@
  * Move up one line.
  */
 hterm.VT.CC1['\x8d'] =
-hterm.VT.ESC['M'] = function() {
-  this.terminal.reverseLineFeed();
-};
+  hterm.VT.ESC['M'] = function() {
+    this.terminal.reverseLineFeed();
+  };
 
 /**
  * Single Shift 2 (SS2).
@@ -15473,7 +15852,7 @@
  * Not currently implemented.
  */
 hterm.VT.CC1['\x8e'] =
-hterm.VT.ESC['N'] = hterm.VT.ignore;
+  hterm.VT.ESC['N'] = hterm.VT.ignore;
 
 /**
  * Single Shift 3 (SS3).
@@ -15483,7 +15862,7 @@
  * Not currently implemented.
  */
 hterm.VT.CC1['\x8f'] =
-hterm.VT.ESC['O'] = hterm.VT.ignore;
+  hterm.VT.ESC['O'] = hterm.VT.ignore;
 
 /**
  * Device Control String (DCS).
@@ -15494,10 +15873,10 @@
  * TODO(rginda): Consider implementing DECRQSS, the rest don't seem applicable.
  */
 hterm.VT.CC1['\x90'] =
-hterm.VT.ESC['P'] = function(parseState) {
-  parseState.resetArguments();
-  parseState.func = this.parseUntilStringTerminator_;
-};
+  hterm.VT.ESC['P'] = function(parseState) {
+    parseState.resetArguments();
+    parseState.func = this.parseUntilStringTerminator_;
+  };
 
 /**
  * Start of Protected Area (SPA).
@@ -15505,7 +15884,7 @@
  * Will not implement.
  */
 hterm.VT.CC1['\x96'] =
-hterm.VT.ESC['V'] = hterm.VT.ignore;
+  hterm.VT.ESC['V'] = hterm.VT.ignore;
 
 /**
  * End of Protected Area (EPA).
@@ -15513,7 +15892,7 @@
  * Will not implement.
  */
 hterm.VT.CC1['\x97'] =
-hterm.VT.ESC['W'] = hterm.VT.ignore;
+  hterm.VT.ESC['W'] = hterm.VT.ignore;
 
 /**
  * Start of String (SOS).
@@ -15521,7 +15900,7 @@
  * Will not implement.
  */
 hterm.VT.CC1['\x98'] =
-hterm.VT.ESC['X'] = hterm.VT.ignore;
+  hterm.VT.ESC['X'] = hterm.VT.ignore;
 
 /**
  * Single Character Introducer (SCI, also DECID).
@@ -15529,9 +15908,9 @@
  * Return Terminal ID.  Obsolete form of 'ESC [ c' (DA).
  */
 hterm.VT.CC1['\x9a'] =
-hterm.VT.ESC['Z'] = function() {
-  this.terminal.io.sendString('\x1b[?1;2c');
-};
+  hterm.VT.ESC['Z'] = function() {
+    this.terminal.io.sendString('\x1b[?1;2c');
+  };
 
 /**
  * Control Sequence Introducer (CSI).
@@ -15539,12 +15918,12 @@
  * The lead into most escape sequences.  See [CSI].
  */
 hterm.VT.CC1['\x9b'] =
-hterm.VT.ESC['['] = function(parseState) {
-  parseState.resetArguments();
-  this.leadingModifier_ = '';
-  this.trailingModifier_ = '';
-  parseState.func = this.parseCSI_;
-};
+  hterm.VT.ESC['['] = function(parseState) {
+    parseState.resetArguments();
+    this.leadingModifier_ = '';
+    this.trailingModifier_ = '';
+    parseState.func = this.parseCSI_;
+  };
 
 /**
  * String Terminator (ST).
@@ -15555,7 +15934,7 @@
  * sequences.  See the 'parseUntilStringTerminator_' method.
  */
 hterm.VT.CC1['\x9c'] =
-hterm.VT.ESC['\\'] = hterm.VT.ignore;
+  hterm.VT.ESC['\\'] = hterm.VT.ignore;
 
 /**
  * Operating System Command (OSC).
@@ -15563,43 +15942,44 @@
  * Commands relating to the operating system.
  */
 hterm.VT.CC1['\x9d'] =
-hterm.VT.ESC[']'] = function(parseState) {
-  parseState.resetArguments();
+  hterm.VT.ESC[']'] = function(parseState) {
+    parseState.resetArguments();
 
-  function parseOSC(parseState) {
-    if (!this.parseUntilStringTerminator_(parseState)) {
-      // The string sequence was too long.
-      return;
-    }
+    function parseOSC(parseState) {
+      if (!this.parseUntilStringTerminator_(parseState)) {
+        // The string sequence was too long.
+        return;
+      }
 
-    if (parseState.func == parseOSC) {
-      // We're not done parsing the string yet.
-      return;
-    }
+      if (parseState.func == parseOSC) {
+        // We're not done parsing the string yet.
+        return;
+      }
 
-    // We're done.
-    var ary = parseState.args[0].match(/^(\d+);(.*)$/);
-    if (ary) {
-      parseState.args[0] = ary[2];
-      this.dispatch('OSC', ary[1], parseState);
-    } else {
-      console.warn('Invalid OSC: ' + JSON.stringify(parseState.args[0]));
-    }
+      // We're done.
+      var ary = parseState.args[0].match(/^(\d+);(.*)$/);
+      if (ary) {
+        parseState.args[0] = ary[2];
+        this.dispatch('OSC', ary[1], parseState);
+      }
+      else {
+        console.warn('Invalid OSC: ' + JSON.stringify(parseState.args[0]));
+      }
+    };
+
+    parseState.func = parseOSC;
   };
 
-  parseState.func = parseOSC;
-};
-
 /**
  * Privacy Message (PM).
  *
  * Will not implement.
  */
 hterm.VT.CC1['\x9e'] =
-hterm.VT.ESC['^'] = function(parseState) {
-  parseState.resetArguments();
-  parseState.func = this.parseUntilStringTerminator_;
-};
+  hterm.VT.ESC['^'] = function(parseState) {
+    parseState.resetArguments();
+    parseState.func = this.parseUntilStringTerminator_;
+  };
 
 /**
  * Application Program Control (APC).
@@ -15607,10 +15987,10 @@
  * Will not implement.
  */
 hterm.VT.CC1['\x9f'] =
-hterm.VT.ESC['_'] = function(parseState) {
-  parseState.resetArguments();
-  parseState.func = this.parseUntilStringTerminator_;
-};
+  hterm.VT.ESC['_'] = function(parseState) {
+    parseState.resetArguments();
+    parseState.func = this.parseUntilStringTerminator_;
+  };
 
 /**
  * ESC \x20 - Unclear to me where these originated, possibly in xterm.
@@ -15625,7 +16005,7 @@
  *   ESC \x20 M - Set ANSI conformance level 2.
  *   ESC \x20 N - Set ANSI conformance level 3.
  */
-hterm.VT.ESC['\x20'] = function(parseState) {
+hterm.VT.ESC[' '] = function(parseState) {
   parseState.func = function(parseState) {
     var ch = parseState.consumeChar();
     if (this.warnUnimplemented)
@@ -15708,37 +16088,41 @@
  * TODO(rginda): Implement.
  */
 hterm.VT.ESC['('] =
-hterm.VT.ESC[')'] =
-hterm.VT.ESC['*'] =
-hterm.VT.ESC['+'] =
-hterm.VT.ESC['-'] =
-hterm.VT.ESC['.'] =
-hterm.VT.ESC['/'] = function(parseState, code) {
-  parseState.func = function(parseState) {
-    var ch = parseState.consumeChar();
-    if (ch == '\x1b') {
-      parseState.resetParseFunction();
-      parseState.func();
-      return;
-    }
-
-    if (ch in hterm.VT.CharacterMap.maps) {
-      if (code == '(') {
-        this.G0 = hterm.VT.CharacterMap.maps[ch];
-      } else if (code == ')' || code == '-') {
-        this.G1 = hterm.VT.CharacterMap.maps[ch];
-      } else if (code == '*' || code == '.') {
-        this.G2 = hterm.VT.CharacterMap.maps[ch];
-      } else if (code == '+' || code == '/') {
-        this.G3 = hterm.VT.CharacterMap.maps[ch];
+  hterm.VT.ESC[')'] =
+  hterm.VT.ESC['*'] =
+  hterm.VT.ESC['+'] =
+  hterm.VT.ESC['-'] =
+  hterm.VT.ESC['.'] =
+  hterm.VT.ESC['/'] = function(parseState, code) {
+    parseState.func = function(parseState) {
+      var ch = parseState.consumeChar();
+      if (ch == '\x1b') {
+        parseState.resetParseFunction();
+        parseState.func();
+        return;
       }
-    } else if (this.warnUnimplemented) {
-      console.log('Invalid character set for "' + code + '": ' + ch);
-    }
 
-    parseState.resetParseFunction();
+      if (ch in hterm.VT.CharacterMap.maps) {
+        if (code == '(') {
+          this.G0 = hterm.VT.CharacterMap.maps[ch];
+        }
+        else if (code == ')' || code == '-') {
+          this.G1 = hterm.VT.CharacterMap.maps[ch];
+        }
+        else if (code == '*' || code == '.') {
+          this.G2 = hterm.VT.CharacterMap.maps[ch];
+        }
+        else if (code == '+' || code == '/') {
+          this.G3 = hterm.VT.CharacterMap.maps[ch];
+        }
+      }
+      else if (this.warnUnimplemented) {
+        console.log('Invalid character set for "' + code + '": ' + ch);
+      }
+
+      parseState.resetParseFunction();
+    };
   };
-};
 
 /**
  * Back Index (DECBI).
@@ -15806,7 +16190,7 @@
  * Will not implement.
  */
 hterm.VT.ESC['l'] =
-hterm.VT.ESC['m'] = hterm.VT.ignore;
+  hterm.VT.ESC['m'] = hterm.VT.ignore;
 
 /**
  * Lock Shift 2 (LS2)
@@ -16032,7 +16416,7 @@
  */
 hterm.VT.CSI['H'] = function(parseState) {
   this.terminal.setCursorPosition(parseState.iarg(0, 1) - 1,
-                                  parseState.iarg(1, 1) - 1);
+    parseState.iarg(1, 1) - 1);
 };
 
 /**
@@ -16050,37 +16434,42 @@
  * Erase in Display (ED, DECSED).
  */
 hterm.VT.CSI['J'] =
-hterm.VT.CSI['?J'] = function(parseState, code) {
-  var arg = parseState.args[0];
+  hterm.VT.CSI['?J'] = function(parseState, code) {
+    var arg = parseState.args[0];
 
-  if (!arg || arg == '0') {
+    if (!arg || arg == '0') {
       this.terminal.eraseBelow();
-  } else if (arg == '1') {
-    this.terminal.eraseAbove();
-  } else if (arg == '2') {
-    this.terminal.clear();
-  } else if (arg == '3') {
-    // The xterm docs say this means "Erase saved lines", but we'll just clear
-    // the display since killing the scrollback seems rude.
-    this.terminal.clear();
-  }
-};
+    }
+    else if (arg == '1') {
+      this.terminal.eraseAbove();
+    }
+    else if (arg == '2') {
+      this.terminal.clear();
+    }
+    else if (arg == '3') {
+      // The xterm docs say this means "Erase saved lines", but we'll just clear
+      // the display since killing the scrollback seems rude.
+      this.terminal.clear();
+    }
+  };
 
 /**
  * Erase in line (EL, DECSEL).
  */
 hterm.VT.CSI['K'] =
-hterm.VT.CSI['?K'] = function(parseState, code) {
-  var arg = parseState.args[0];
+  hterm.VT.CSI['?K'] = function(parseState, code) {
+    var arg = parseState.args[0];
 
-  if (!arg || arg == '0') {
-    this.terminal.eraseToRight();
-  } else if (arg == '1'){
-    this.terminal.eraseToLeft();
-  } else if (arg == '2') {
-    this.terminal.eraseLine();
-  }
-};
+    if (!arg || arg == '0') {
+      this.terminal.eraseToRight();
+    }
+    else if (arg == '1') {
+      this.terminal.eraseToLeft();
+    }
+    else if (arg == '2') {
+      this.terminal.eraseLine();
+    }
+  };
 
 /**
  * Insert Lines (IL).
@@ -16217,7 +16606,8 @@
   if (!parseState.args[0] || parseState.args[0] == '0') {
     // Clear tab stop at cursor.
     this.terminal.clearTabStopAtCursor(false);
-  } else if (parseState.args[0] == '3') {
+  }
+  else if (parseState.args[0] == '3') {
     // Clear all tab stops.
     this.terminal.clearAllTabStops();
   }
@@ -16248,7 +16638,7 @@
  * These commands control the printer.  Will not implement.
  */
 hterm.VT.CSI['i'] =
-hterm.VT.CSI['?i'] = hterm.VT.ignore;
+  hterm.VT.CSI['?i'] = hterm.VT.ignore;
 
 /**
  * Reset Mode (RM).
@@ -16376,47 +16766,64 @@
     if (arg < 30) {
       if (arg == 0) {
         attrs.reset();
-      } else if (arg == 1) {
+      }
+      else if (arg == 1) {
         attrs.bold = true;
-      } else if (arg == 2) {
+      }
+      else if (arg == 2) {
         attrs.faint = true;
-      } else if (arg == 3) {
+      }
+      else if (arg == 3) {
         attrs.italic = true;
-      } else if (arg == 4) {
+      }
+      else if (arg == 4) {
         attrs.underline = true;
-      } else if (arg == 5) {
+      }
+      else if (arg == 5) {
         attrs.blink = true;
-      } else if (arg == 7) {  // Inverse.
+      }
+      else if (arg == 7) { // Inverse.
         attrs.inverse = true;
-      } else if (arg == 8) {  // Invisible.
+      }
+      else if (arg == 8) { // Invisible.
         attrs.invisible = true;
-      } else if (arg == 9) {
+      }
+      else if (arg == 9) {
         attrs.strikethrough = true;
-      } else if (arg == 22) {
+      }
+      else if (arg == 22) {
         attrs.bold = false;
         attrs.faint = false;
-      } else if (arg == 23) {
+      }
+      else if (arg == 23) {
         attrs.italic = false;
-      } else if (arg == 24) {
+      }
+      else if (arg == 24) {
         attrs.underline = false;
-      } else if (arg == 25) {
+      }
+      else if (arg == 25) {
         attrs.blink = false;
-      } else if (arg == 27) {
+      }
+      else if (arg == 27) {
         attrs.inverse = false;
-      } else if (arg == 28) {
+      }
+      else if (arg == 28) {
         attrs.invisible = false;
-      } else if (arg == 29) {
+      }
+      else if (arg == 29) {
         attrs.strikethrough = false;
       }
 
-    } else if (arg < 50) {
+    }
+    else if (arg < 50) {
       // Select fore/background color from bottom half of 16 color palette
       // or from the 256 color palette or alternative specify color in fully
       // qualified rgb(r, g, b) form.
       if (arg < 38) {
         attrs.foregroundSource = arg - 30;
 
-      } else if (arg == 38) {
+      }
+      else if (arg == 38) {
         // First check for true color definition
         var trueColor = getTrueColor(i);
         if (trueColor != null) {
@@ -16424,7 +16831,8 @@
           attrs.foreground = trueColor;
 
           i += 5;
-        } else {
+        }
+        else {
           // Check for 256 color
           var c = get256(i);
           if (c == null)
@@ -16438,13 +16846,16 @@
           attrs.foregroundSource = c;
         }
 
-      } else if (arg == 39) {
+      }
+      else if (arg == 39) {
         attrs.foregroundSource = attrs.SRC_DEFAULT;
 
-      } else if (arg < 48) {
+      }
+      else if (arg < 48) {
         attrs.backgroundSource = arg - 40;
 
-      } else if (arg == 48) {
+      }
+      else if (arg == 48) {
         // First check for true color definition
         var trueColor = getTrueColor(i);
         if (trueColor != null) {
@@ -16452,7 +16863,8 @@
           attrs.background = trueColor;
 
           i += 5;
-        } else {
+        }
+        else {
           // Check for 256 color
           var c = get256(i);
           if (c == null)
@@ -16465,20 +16877,23 @@
 
           attrs.backgroundSource = c;
         }
-      } else {
+      }
+      else {
         attrs.backgroundSource = attrs.SRC_DEFAULT;
       }
 
-    } else if (arg >= 90 && arg <= 97) {
+    }
+    else if (arg >= 90 && arg <= 97) {
       attrs.foregroundSource = arg - 90 + 8;
 
-    } else if (arg >= 100 && arg <= 107) {
+    }
+    else if (arg >= 100 && arg <= 107) {
       attrs.backgroundSource = arg - 100 + 8;
     }
   }
 
   attrs.setDefaults(this.terminal.getForegroundColor(),
-                    this.terminal.getBackgroundColor());
+    this.terminal.getBackgroundColor());
 };
 
 /**
@@ -16497,7 +16912,8 @@
 hterm.VT.CSI['n'] = function(parseState) {
   if (parseState.args[0] == '5') {
     this.terminal.io.sendString('\x1b0n');
-  } else if (parseState.args[0] == '6') {
+  }
+  else if (parseState.args[0] == '6') {
     var row = this.terminal.getCursorRow() + 1;
     var col = this.terminal.getCursorColumn() + 1;
     this.terminal.io.sendString('\x1b[' + row + ';' + col + 'R');
@@ -16529,13 +16945,17 @@
     var row = this.terminal.getCursorRow() + 1;
     var col = this.terminal.getCursorColumn() + 1;
     this.terminal.io.sendString('\x1b[' + row + ';' + col + 'R');
-  } else if (parseState.args[0] == '15') {
+  }
+  else if (parseState.args[0] == '15') {
     this.terminal.io.sendString('\x1b[?11n');
-  } else if (parseState.args[0] == '25') {
+  }
+  else if (parseState.args[0] == '25') {
     this.terminal.io.sendString('\x1b[?21n');
-  } else if (parseState.args[0] == '26') {
+  }
+  else if (parseState.args[0] == '26') {
     this.terminal.io.sendString('\x1b[?12;1;0;0n');
-  } else if (parseState.args[0] == '53') {
+  }
+  else if (parseState.args[0] == '53') {
     this.terminal.io.sendString('\x1b[?50n');
   }
 };
@@ -16601,16 +17021,20 @@
   if (arg == '0' || arg == '1') {
     this.terminal.setCursorShape(hterm.Terminal.cursorShape.BLOCK);
     this.terminal.setCursorBlink(true);
-  } else if (arg == '2') {
+  }
+  else if (arg == '2') {
     this.terminal.setCursorShape(hterm.Terminal.cursorShape.BLOCK);
     this.terminal.setCursorBlink(false);
-  } else if (arg == '3') {
+  }
+  else if (arg == '3') {
     this.terminal.setCursorShape(hterm.Terminal.cursorShape.UNDERLINE);
     this.terminal.setCursorBlink(true);
-  } else if (arg == '4') {
+  }
+  else if (arg == '4') {
     this.terminal.setCursorShape(hterm.Terminal.cursorShape.UNDERLINE);
     this.terminal.setCursorBlink(false);
-  } else {
+  }
+  else {
     console.warn('Unknown cursor style: ' + arg);
   }
 };
@@ -16627,7 +17051,7 @@
  */
 hterm.VT.CSI['r'] = function(parseState) {
   var args = parseState.args;
-  var scrollTop = args[0] ? parseInt(args[0], 10) -1 : null;
+  var scrollTop = args[0] ? parseInt(args[0], 10) - 1 : null;
   var scrollBottom = args[1] ? parseInt(args[1], 10) - 1 : null;
   this.terminal.setVTScrollRegion(scrollTop, scrollBottom);
   this.terminal.setCursorPosition(0, 0);
@@ -16753,7 +17177,8 @@
     if (parseState.args.length < 2)
       return;
     this.terminal.getTextAttributes().tileData = parseState.args[1];
-  } else if (arg == '1') {
+  }
+  else if (arg == '1') {
     // End a glyph.
     this.terminal.getTextAttributes().tileData = null;
   }
@@ -16844,8 +17269,8 @@
   this.glmap = glmap;
 
   var glkeys = Object.keys(this.glmap).map(function(key) {
-      return '\\x' + lib.f.zpad(key.charCodeAt(0).toString(16));
-    });
+    return '\\x' + lib.f.zpad(key.charCodeAt(0).toString(16));
+  });
 
   this.glre = new RegExp('[' + glkeys.join('') + ']', 'g');
 
@@ -16854,24 +17279,28 @@
   this.grmap = {};
 
   glkeys.forEach(function(glkey) {
-      var grkey = String.fromCharCode(glkey.charCodeAt(0) & 0x80);
-      this.grmap[grkey] = this.glmap[glkey];
-    }.bind(this));
+    var grkey = String.fromCharCode(glkey.charCodeAt(0) & 0x80);
+    this.grmap[grkey] = this.glmap[glkey];
+  }.bind(this));
 
   var grkeys = Object.keys(this.grmap).map(function(key) {
-      return '\\x' + lib.f.zpad(key.charCodeAt(0).toString(16), 2);
-    });
+    return '\\x' + lib.f.zpad(key.charCodeAt(0).toString(16), 2);
+  });
 
   this.grre = new RegExp('[' + grkeys.join('') + ']', 'g');
 
   this.GL = function(str) {
     return str.replace(this.glre,
-                       function(ch) { return this.glmap[ch] }.bind(this));
+      function(ch) {
+        return this.glmap[ch];
+      }.bind(this));
   }.bind(this);
 
   this.GR = function(str) {
     return str.replace(this.grre,
-                       function(ch) { return this.grmap[ch] }.bind(this));
+      function(ch) {
+        return this.grmap[ch];
+      }.bind(this));
   }.bind(this);
 };
 
@@ -16886,93 +17315,93 @@
  * http://vt100.net/docs/vt220-rm/table2-4.html
  */
 hterm.VT.CharacterMap.maps['0'] = new hterm.VT.CharacterMap(
-    'graphic', {
-      '\x60':'\u25c6',  // ` -> diamond
-      '\x61':'\u2592',  // a -> grey-box
-      '\x62':'\u2409',  // b -> h/t
-      '\x63':'\u240c',  // c -> f/f
-      '\x64':'\u240d',  // d -> c/r
-      '\x65':'\u240a',  // e -> l/f
-      '\x66':'\u00b0',  // f -> degree
-      '\x67':'\u00b1',  // g -> +/-
-      '\x68':'\u2424',  // h -> n/l
-      '\x69':'\u240b',  // i -> v/t
-      '\x6a':'\u2518',  // j -> bottom-right
-      '\x6b':'\u2510',  // k -> top-right
-      '\x6c':'\u250c',  // l -> top-left
-      '\x6d':'\u2514',  // m -> bottom-left
-      '\x6e':'\u253c',  // n -> line-cross
-      '\x6f':'\u23ba',  // o -> scan1
-      '\x70':'\u23bb',  // p -> scan3
-      '\x71':'\u2500',  // q -> scan5
-      '\x72':'\u23bc',  // r -> scan7
-      '\x73':'\u23bd',  // s -> scan9
-      '\x74':'\u251c',  // t -> left-tee
-      '\x75':'\u2524',  // u -> right-tee
-      '\x76':'\u2534',  // v -> bottom-tee
-      '\x77':'\u252c',  // w -> top-tee
-      '\x78':'\u2502',  // x -> vertical-line
-      '\x79':'\u2264',  // y -> less-equal
-      '\x7a':'\u2265',  // z -> greater-equal
-      '\x7b':'\u03c0',  // { -> pi
-      '\x7c':'\u2260',  // | -> not-equal
-      '\x7d':'\u00a3',  // } -> british-pound
-      '\x7e':'\u00b7',  // ~ -> dot
-    });
+  'graphic', {
+    '`': '◆', // ` -> diamond
+    'a': '▒', // a -> grey-box
+    'b': '␉', // b -> h/t
+    'c': '␌', // c -> f/f
+    'd': '␍', // d -> c/r
+    'e': '␊', // e -> l/f
+    'f': '°', // f -> degree
+    'g': '±', // g -> +/-
+    'h': '␤', // h -> n/l
+    'i': '␋', // i -> v/t
+    'j': '┘', // j -> bottom-right
+    'k': '┐', // k -> top-right
+    'l': '┌', // l -> top-left
+    'm': '└', // m -> bottom-left
+    'n': '┼', // n -> line-cross
+    'o': '⎺', // o -> scan1
+    'p': '⎻', // p -> scan3
+    'q': '─', // q -> scan5
+    'r': '⎼', // r -> scan7
+    's': '⎽', // s -> scan9
+    't': '├', // t -> left-tee
+    'u': '┤', // u -> right-tee
+    'v': '┴', // v -> bottom-tee
+    'w': '┬', // w -> top-tee
+    'x': '│', // x -> vertical-line
+    'y': '≤', // y -> less-equal
+    'z': '≥', // z -> greater-equal
+    '{': 'π', // { -> pi
+    '|': '≠', // | -> not-equal
+    '}': '£', // } -> british-pound
+    '~': '·', // ~ -> dot
+  });
 
 /**
  * British character map.
  * http://vt100.net/docs/vt220-rm/table2-5.html
  */
 hterm.VT.CharacterMap.maps['A'] = new hterm.VT.CharacterMap(
-    'british', {
-      '\x23': '\u00a3',  // # -> british-pound
-    });
+  'british', {
+    '#': '£', // # -> british-pound
+  });
 
 /**
  * US ASCII map, no changes.
  */
 hterm.VT.CharacterMap.maps['B'] = new hterm.VT.CharacterMap(
-    'us', null);
+  'us', null);
 
 /**
  * Dutch character map.
  * http://vt100.net/docs/vt220-rm/table2-6.html
  */
 hterm.VT.CharacterMap.maps['4'] = new hterm.VT.CharacterMap(
-    'dutch', {
-      '\x23': '\u00a3',  // # -> british-pound
+  'dutch', {
+    '#': '£', // # -> british-pound
 
-      '\x40': '\u00be',  // @ -> 3/4
+    '@': '¾', // @ -> 3/4
 
-      '\x5b': '\u0132',  // [ -> 'ij' ligature (xterm goes with \u00ff?)
-      '\x5c': '\u00bd',  // \ -> 1/2
-      '\x5d': '\u007c',  // ] -> vertical bar
+    '[': 'IJ', // [ -> 'ij' ligature (xterm goes with \u00ff?)
+    '\\': '½', // \ -> 1/2
+    ']': '|', // ] -> vertical bar
 
-      '\x7b': '\u00a8',  // { -> two dots
-      '\x7c': '\u0066',  // | -> f
-      '\x7d': '\u00bc',  // } -> 1/4
-      '\x7e': '\u00b4',  // ~ -> acute
-    });
+    '{': '¨', // { -> two dots
+    '|': 'f', // | -> f
+    '}': '¼', // } -> 1/4
+    '~': '´', // ~ -> acute
+  });
 
 /**
  * Finnish character map.
  * http://vt100.net/docs/vt220-rm/table2-7.html
  */
 hterm.VT.CharacterMap.maps['C'] =
-hterm.VT.CharacterMap.maps['5'] = new hterm.VT.CharacterMap(
+  hterm.VT.CharacterMap.maps['5'] = new hterm.VT.CharacterMap(
     'finnish', {
-      '\x5b': '\u00c4',  // [ -> 'A' umlaut
-      '\x5c': '\u00d6',  // \ -> 'O' umlaut
-      '\x5d': '\u00c5',  // ] -> 'A' ring
-      '\x5e': '\u00dc',  // ~ -> 'u' umlaut
+      '[': 'Ä', // [ -> 'A' umlaut
+      '\\': 'Ö', // \ -> 'O' umlaut
+      ']': 'Å', // ] -> 'A' ring
+      '^': 'Ü', // ~ -> 'u' umlaut
 
-      '\x60': '\u00e9',  // ` -> 'e' acute
+      '`': 'é', // ` -> 'e' acute
 
-      '\x7b': '\u00e4',  // { -> 'a' umlaut
-      '\x7c': '\u00f6',  // | -> 'o' umlaut
-      '\x7d': '\u00e5',  // } -> 'a' ring
-      '\x7e': '\u00fc',  // ~ -> 'u' umlaut
+      '{': 'ä', // { -> 'a' umlaut
+      '|': 'ö', // | -> 'o' umlaut
+      '}': 'å', // } -> 'a' ring
+      '~': 'ü', // ~ -> 'u' umlaut
     });
 
 /**
@@ -16980,102 +17409,102 @@
  * http://vt100.net/docs/vt220-rm/table2-8.html
  */
 hterm.VT.CharacterMap.maps['R'] = new hterm.VT.CharacterMap(
-    'french', {
-      '\x23': '\u00a3',  // # -> british-pound
+  'french', {
+    '#': '£', // # -> british-pound
 
-      '\x40': '\u00e0',  // @ -> 'a' grave
+    '@': 'à', // @ -> 'a' grave
 
-      '\x5b': '\u00b0',  // [ -> ring
-      '\x5c': '\u00e7',  // \ -> 'c' cedilla
-      '\x5d': '\u00a7',  // ] -> section symbol (double s)
+    '[': '°', // [ -> ring
+    '\\': 'ç', // \ -> 'c' cedilla
+    ']': '§', // ] -> section symbol (double s)
 
-      '\x7b': '\u00e9',  // { -> 'e' acute
-      '\x7c': '\u00f9',  // | -> 'u' grave
-      '\x7d': '\u00e8',  // } -> 'e' grave
-      '\x7e': '\u00a8',  // ~ -> umlaut
-    });
+    '{': 'é', // { -> 'e' acute
+    '|': 'ù', // | -> 'u' grave
+    '}': 'è', // } -> 'e' grave
+    '~': '¨', // ~ -> umlaut
+  });
 
 /**
  * French Canadian character map.
  * http://vt100.net/docs/vt220-rm/table2-9.html
  */
 hterm.VT.CharacterMap.maps['Q'] = new hterm.VT.CharacterMap(
-    'french canadian', {
-      '\x40': '\u00e0',  // @ -> 'a' grave
+  'french canadian', {
+    '@': 'à', // @ -> 'a' grave
 
-      '\x5b': '\u00e2',  // [ -> 'a' circumflex
-      '\x5c': '\u00e7',  // \ -> 'c' cedilla
-      '\x5d': '\u00ea',  // ] -> 'e' circumflex
-      '\x5e': '\u00ee',  // ^ -> 'i' circumflex
+    '[': 'â', // [ -> 'a' circumflex
+    '\\': 'ç', // \ -> 'c' cedilla
+    ']': 'ê', // ] -> 'e' circumflex
+    '^': 'î', // ^ -> 'i' circumflex
 
-      '\x60': '\u00f4',  // ` -> 'o' circumflex
+    '`': 'ô', // ` -> 'o' circumflex
 
-      '\x7b': '\u00e9',  // { -> 'e' acute
-      '\x7c': '\u00f9',  // | -> 'u' grave
-      '\x7d': '\u00e8',  // } -> 'e' grave
-      '\x7e': '\u00fb',  // ~ -> 'u' circumflex
-    });
+    '{': 'é', // { -> 'e' acute
+    '|': 'ù', // | -> 'u' grave
+    '}': 'è', // } -> 'e' grave
+    '~': 'û', // ~ -> 'u' circumflex
+  });
 
 /**
  * German character map.
  * http://vt100.net/docs/vt220-rm/table2-10.html
  */
 hterm.VT.CharacterMap.maps['K'] = new hterm.VT.CharacterMap(
-    'german', {
-      '\x40': '\u00a7',  // @ -> section symbol (double s)
+  'german', {
+    '@': '§', // @ -> section symbol (double s)
 
-      '\x5b': '\u00c4',  // [ -> 'A' umlaut
-      '\x5c': '\u00d6',  // \ -> 'O' umlaut
-      '\x5d': '\u00dc',  // ] -> 'U' umlaut
+    '[': 'Ä', // [ -> 'A' umlaut
+    '\\': 'Ö', // \ -> 'O' umlaut
+    ']': 'Ü', // ] -> 'U' umlaut
 
-      '\x7b': '\u00e4',  // { -> 'a' umlaut
-      '\x7c': '\u00f6',  // | -> 'o' umlaut
-      '\x7d': '\u00fc',  // } -> 'u' umlaut
-      '\x7e': '\u00df',  // ~ -> eszett
-    });
+    '{': 'ä', // { -> 'a' umlaut
+    '|': 'ö', // | -> 'o' umlaut
+    '}': 'ü', // } -> 'u' umlaut
+    '~': 'ß', // ~ -> eszett
+  });
 
 /**
  * Italian character map.
  * http://vt100.net/docs/vt220-rm/table2-11.html
  */
 hterm.VT.CharacterMap.maps['Y'] = new hterm.VT.CharacterMap(
-    'italian', {
-      '\x23': '\u00a3',  // # -> british-pound
+  'italian', {
+    '#': '£', // # -> british-pound
 
-      '\x40': '\u00a7',  // @ -> section symbol (double s)
+    '@': '§', // @ -> section symbol (double s)
 
-      '\x5b': '\u00b0',  // [ -> ring
-      '\x5c': '\u00e7',  // \ -> 'c' cedilla
-      '\x5d': '\u00e9',  // ] -> 'e' acute
+    '[': '°', // [ -> ring
+    '\\': 'ç', // \ -> 'c' cedilla
+    ']': 'é', // ] -> 'e' acute
 
-      '\x60': '\u00f9',  // ` -> 'u' grave
+    '`': 'ù', // ` -> 'u' grave
 
-      '\x7b': '\u00e0',  // { -> 'a' grave
-      '\x7c': '\u00f2',  // | -> 'o' grave
-      '\x7d': '\u00e8',  // } -> 'e' grave
-      '\x7e': '\u00ec',  // ~ -> 'i' grave
-    });
+    '{': 'à', // { -> 'a' grave
+    '|': 'ò', // | -> 'o' grave
+    '}': 'è', // } -> 'e' grave
+    '~': 'ì', // ~ -> 'i' grave
+  });
 
 /**
  * Norwegian/Danish character map.
  * http://vt100.net/docs/vt220-rm/table2-12.html
  */
 hterm.VT.CharacterMap.maps['E'] =
-hterm.VT.CharacterMap.maps['6'] = new hterm.VT.CharacterMap(
+  hterm.VT.CharacterMap.maps['6'] = new hterm.VT.CharacterMap(
     'norwegian/danish', {
-      '\x40': '\u00c4',  // @ -> 'A' umlaut
+      '@': 'Ä', // @ -> 'A' umlaut
 
-      '\x5b': '\u00c6',  // [ -> 'AE' ligature
-      '\x5c': '\u00d8',  // \ -> 'O' stroke
-      '\x5d': '\u00c5',  // ] -> 'A' ring
-      '\x5e': '\u00dc',  // ^ -> 'U' umlaut
+      '[': 'Æ', // [ -> 'AE' ligature
+      '\\': 'Ø', // \ -> 'O' stroke
+      ']': 'Å', // ] -> 'A' ring
+      '^': 'Ü', // ^ -> 'U' umlaut
 
-      '\x60': '\u00e4',  // ` -> 'a' umlaut
+      '`': 'ä', // ` -> 'a' umlaut
 
-      '\x7b': '\u00e6',  // { -> 'ae' ligature
-      '\x7c': '\u00f8',  // | -> 'o' stroke
-      '\x7d': '\u00e5',  // } -> 'a' ring
-      '\x7e': '\u00fc',  // ~ -> 'u' umlaut
+      '{': 'æ', // { -> 'ae' ligature
+      '|': 'ø', // | -> 'o' stroke
+      '}': 'å', // } -> 'a' ring
+      '~': 'ü', // ~ -> 'u' umlaut
     });
 
 /**
@@ -17083,40 +17512,40 @@
  * http://vt100.net/docs/vt220-rm/table2-13.html
  */
 hterm.VT.CharacterMap.maps['Z'] = new hterm.VT.CharacterMap(
-    'spanish', {
-      '\x23': '\u00a3',  // # -> british-pound
+  'spanish', {
+    '#': '£', // # -> british-pound
 
-      '\x40': '\u00a7',  // @ -> section symbol (double s)
+    '@': '§', // @ -> section symbol (double s)
 
-      '\x5b': '\u00a1',  // [ -> '!' inverted
-      '\x5c': '\u00d1',  // \ -> 'N' tilde
-      '\x5d': '\u00bf',  // ] -> '?' inverted
+    '[': '¡', // [ -> '!' inverted
+    '\\': 'Ñ', // \ -> 'N' tilde
+    ']': '¿', // ] -> '?' inverted
 
-      '\x7b': '\u00b0',  // { -> ring
-      '\x7c': '\u00f1',  // | -> 'n' tilde
-      '\x7d': '\u00e7',  // } -> 'c' cedilla
-    });
+    '{': '°', // { -> ring
+    '|': 'ñ', // | -> 'n' tilde
+    '}': 'ç', // } -> 'c' cedilla
+  });
 
 /**
  * Swedish character map.
  * http://vt100.net/docs/vt220-rm/table2-14.html
  */
 hterm.VT.CharacterMap.maps['7'] =
-hterm.VT.CharacterMap.maps['H'] = new hterm.VT.CharacterMap(
+  hterm.VT.CharacterMap.maps['H'] = new hterm.VT.CharacterMap(
     'swedish', {
-      '\x40': '\u00c9',  // @ -> 'E' acute
+      '@': 'É', // @ -> 'E' acute
 
-      '\x5b': '\u00c4',  // [ -> 'A' umlaut
-      '\x5c': '\u00d6',  // \ -> 'O' umlaut
-      '\x5d': '\u00c5',  // ] -> 'A' ring
-      '\x5e': '\u00dc',  // ^ -> 'U' umlaut
+      '[': 'Ä', // [ -> 'A' umlaut
+      '\\': 'Ö', // \ -> 'O' umlaut
+      ']': 'Å', // ] -> 'A' ring
+      '^': 'Ü', // ^ -> 'U' umlaut
 
-      '\x60': '\u00e9',  // ` -> 'e' acute
+      '`': 'é', // ` -> 'e' acute
 
-      '\x7b': '\u00e4',  // { -> 'a' umlaut
-      '\x7c': '\u00f6',  // | -> 'o' umlaut
-      '\x7d': '\u00e5',  // } -> 'a' ring
-      '\x7e': '\u00fc',  // ~ -> 'u' umlaut
+      '{': 'ä', // { -> 'a' umlaut
+      '|': 'ö', // | -> 'o' umlaut
+      '}': 'å', // } -> 'a' ring
+      '~': 'ü', // ~ -> 'u' umlaut
     });
 
 /**
@@ -17124,172 +17553,170 @@
  * http://vt100.net/docs/vt220-rm/table2-15.html
  */
 hterm.VT.CharacterMap.maps['='] = new hterm.VT.CharacterMap(
-    'swiss', {
-      '\x23': '\u00f9',  // # -> 'u' grave
+  'swiss', {
+    '#': 'ù', // # -> 'u' grave
 
-      '\x40': '\u00e0',  // @ -> 'a' grave
+    '@': 'à', // @ -> 'a' grave
 
-      '\x5b': '\u00e9',  // [ -> 'e' acute
-      '\x5c': '\u00e7',  // \ -> 'c' cedilla
-      '\x5d': '\u00ea',  // ] -> 'e' circumflex
-      '\x5e': '\u00ee',  // ^ -> 'i' circumflex
-      '\x5f': '\u00e8',  // _ -> 'e' grave
+    '[': 'é', // [ -> 'e' acute
+    '\\': 'ç', // \ -> 'c' cedilla
+    ']': 'ê', // ] -> 'e' circumflex
+    '^': 'î', // ^ -> 'i' circumflex
+    '_': 'è', // _ -> 'e' grave
 
-      '\x60': '\u00f4',  // ` -> 'o' circumflex
+    '`': 'ô', // ` -> 'o' circumflex
 
-      '\x7b': '\u00e4',  // { -> 'a' umlaut
-      '\x7c': '\u00f6',  // | -> 'o' umlaut
-      '\x7d': '\u00fc',  // } -> 'u' umlaut
-      '\x7e': '\u00fb',  // ~ -> 'u' circumflex
-    });
+    '{': 'ä', // { -> 'a' umlaut
+    '|': 'ö', // | -> 'o' umlaut
+    '}': 'ü', // } -> 'u' umlaut
+    '~': 'û', // ~ -> 'u' circumflex
+  });
 lib.resource.add('hterm/audio/bell', 'audio/ogg;base64',
-'T2dnUwACAAAAAAAAAADhqW5KAAAAAMFvEjYBHgF2b3JiaXMAAAAAAYC7AAAAAAAAAHcBAAAAAAC4' +
-'AU9nZ1MAAAAAAAAAAAAA4aluSgEAAAAAesI3EC3//////////////////8kDdm9yYmlzHQAAAFhp' +
-'cGguT3JnIGxpYlZvcmJpcyBJIDIwMDkwNzA5AAAAAAEFdm9yYmlzKUJDVgEACAAAADFMIMWA0JBV' +
-'AAAQAABgJCkOk2ZJKaWUoSh5mJRISSmllMUwiZiUicUYY4wxxhhjjDHGGGOMIDRkFQAABACAKAmO' +
-'o+ZJas45ZxgnjnKgOWlOOKcgB4pR4DkJwvUmY26mtKZrbs4pJQgNWQUAAAIAQEghhRRSSCGFFGKI' +
-'IYYYYoghhxxyyCGnnHIKKqigggoyyCCDTDLppJNOOumoo4466ii00EILLbTSSkwx1VZjrr0GXXxz' +
-'zjnnnHPOOeecc84JQkNWAQAgAAAEQgYZZBBCCCGFFFKIKaaYcgoyyIDQkFUAACAAgAAAAABHkRRJ' +
-'sRTLsRzN0SRP8ixREzXRM0VTVE1VVVVVdV1XdmXXdnXXdn1ZmIVbuH1ZuIVb2IVd94VhGIZhGIZh' +
-'GIZh+H3f933f930gNGQVACABAKAjOZbjKaIiGqLiOaIDhIasAgBkAAAEACAJkiIpkqNJpmZqrmmb' +
-'tmirtm3LsizLsgyEhqwCAAABAAQAAAAAAKBpmqZpmqZpmqZpmqZpmqZpmqZpmmZZlmVZlmVZlmVZ' +
-'lmVZlmVZlmVZlmVZlmVZlmVZlmVZlmVZlmVZQGjIKgBAAgBAx3Ecx3EkRVIkx3IsBwgNWQUAyAAA' +
-'CABAUizFcjRHczTHczzHczxHdETJlEzN9EwPCA1ZBQAAAgAIAAAAAABAMRzFcRzJ0SRPUi3TcjVX' +
-'cz3Xc03XdV1XVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVYHQkFUAAAQAACGdZpZq' +
-'gAgzkGEgNGQVAIAAAAAYoQhDDAgNWQUAAAQAAIih5CCa0JrzzTkOmuWgqRSb08GJVJsnuamYm3PO' +
-'OeecbM4Z45xzzinKmcWgmdCac85JDJqloJnQmnPOeRKbB62p0ppzzhnnnA7GGWGcc85p0poHqdlY' +
-'m3POWdCa5qi5FJtzzomUmye1uVSbc84555xzzjnnnHPOqV6czsE54Zxzzonam2u5CV2cc875ZJzu' +
-'zQnhnHPOOeecc84555xzzglCQ1YBAEAAAARh2BjGnYIgfY4GYhQhpiGTHnSPDpOgMcgppB6NjkZK' +
-'qYNQUhknpXSC0JBVAAAgAACEEFJIIYUUUkghhRRSSCGGGGKIIaeccgoqqKSSiirKKLPMMssss8wy' +
-'y6zDzjrrsMMQQwwxtNJKLDXVVmONteaec645SGultdZaK6WUUkoppSA0ZBUAAAIAQCBkkEEGGYUU' +
-'UkghhphyyimnoIIKCA1ZBQAAAgAIAAAA8CTPER3RER3RER3RER3RER3P8RxREiVREiXRMi1TMz1V' +
-'VFVXdm1Zl3Xbt4Vd2HXf133f141fF4ZlWZZlWZZlWZZlWZZlWZZlCUJDVgEAIAAAAEIIIYQUUkgh' +
-'hZRijDHHnINOQgmB0JBVAAAgAIAAAAAAR3EUx5EcyZEkS7IkTdIszfI0T/M00RNFUTRNUxVd0RV1' +
-'0xZlUzZd0zVl01Vl1XZl2bZlW7d9WbZ93/d93/d93/d93/d939d1IDRkFQAgAQCgIzmSIimSIjmO' +
-'40iSBISGrAIAZAAABACgKI7iOI4jSZIkWZImeZZniZqpmZ7pqaIKhIasAgAAAQAEAAAAAACgaIqn' +
-'mIqniIrniI4oiZZpiZqquaJsyq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7rukBo' +
-'yCoAQAIAQEdyJEdyJEVSJEVyJAcIDVkFAMgAAAgAwDEcQ1Ikx7IsTfM0T/M00RM90TM9VXRFFwgN' +
-'WQUAAAIACAAAAAAAwJAMS7EczdEkUVIt1VI11VItVVQ9VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV' +
-'VVVVVVVVVVVV1TRN0zSB0JCVAAAZAAAjQQYZhBCKcpBCbj1YCDHmJAWhOQahxBiEpxAzDDkNInSQ' +
-'QSc9uJI5wwzz4FIoFURMg40lN44gDcKmXEnlOAhCQ1YEAFEAAIAxyDHEGHLOScmgRM4xCZ2UyDkn' +
-'pZPSSSktlhgzKSWmEmPjnKPSScmklBhLip2kEmOJrQAAgAAHAIAAC6HQkBUBQBQAAGIMUgophZRS' +
-'zinmkFLKMeUcUko5p5xTzjkIHYTKMQadgxAppRxTzinHHITMQeWcg9BBKAAAIMABACDAQig0ZEUA' +
-'ECcA4HAkz5M0SxQlSxNFzxRl1xNN15U0zTQ1UVRVyxNV1VRV2xZNVbYlTRNNTfRUVRNFVRVV05ZN' +
-'VbVtzzRl2VRV3RZV1bZl2xZ+V5Z13zNNWRZV1dZNVbV115Z9X9ZtXZg0zTQ1UVRVTRRV1VRV2zZV' +
-'17Y1UXRVUVVlWVRVWXZlWfdVV9Z9SxRV1VNN2RVVVbZV2fVtVZZ94XRVXVdl2fdVWRZ+W9eF4fZ9' +
-'4RhV1dZN19V1VZZ9YdZlYbd13yhpmmlqoqiqmiiqqqmqtm2qrq1bouiqoqrKsmeqrqzKsq+rrmzr' +
-'miiqrqiqsiyqqiyrsqz7qizrtqiquq3KsrCbrqvrtu8LwyzrunCqrq6rsuz7qizruq3rxnHrujB8' +
-'pinLpqvquqm6um7runHMtm0co6rqvirLwrDKsu/rui+0dSFRVXXdlF3jV2VZ921fd55b94WybTu/' +
-'rfvKceu60vg5z28cubZtHLNuG7+t+8bzKz9hOI6lZ5q2baqqrZuqq+uybivDrOtCUVV9XZVl3zdd' +
-'WRdu3zeOW9eNoqrquirLvrDKsjHcxm8cuzAcXds2jlvXnbKtC31jyPcJz2vbxnH7OuP2daOvDAnH' +
-'jwAAgAEHAIAAE8pAoSErAoA4AQAGIecUUxAqxSB0EFLqIKRUMQYhc05KxRyUUEpqIZTUKsYgVI5J' +
-'yJyTEkpoKZTSUgehpVBKa6GU1lJrsabUYu0gpBZKaS2U0lpqqcbUWowRYxAy56RkzkkJpbQWSmkt' +
-'c05K56CkDkJKpaQUS0otVsxJyaCj0kFIqaQSU0mptVBKa6WkFktKMbYUW24x1hxKaS2kEltJKcYU' +
-'U20txpojxiBkzknJnJMSSmktlNJa5ZiUDkJKmYOSSkqtlZJSzJyT0kFIqYOOSkkptpJKTKGU1kpK' +
-'sYVSWmwx1pxSbDWU0lpJKcaSSmwtxlpbTLV1EFoLpbQWSmmttVZraq3GUEprJaUYS0qxtRZrbjHm' +
-'GkppraQSW0mpxRZbji3GmlNrNabWam4x5hpbbT3WmnNKrdbUUo0txppjbb3VmnvvIKQWSmktlNJi' +
-'ai3G1mKtoZTWSiqxlZJabDHm2lqMOZTSYkmpxZJSjC3GmltsuaaWamwx5ppSi7Xm2nNsNfbUWqwt' +
-'xppTS7XWWnOPufVWAADAgAMAQIAJZaDQkJUAQBQAAEGIUs5JaRByzDkqCULMOSepckxCKSlVzEEI' +
-'JbXOOSkpxdY5CCWlFksqLcVWaykptRZrLQAAoMABACDABk2JxQEKDVkJAEQBACDGIMQYhAYZpRiD' +
-'0BikFGMQIqUYc05KpRRjzknJGHMOQioZY85BKCmEUEoqKYUQSkklpQIAAAocAAACbNCUWByg0JAV' +
-'AUAUAABgDGIMMYYgdFQyKhGETEonqYEQWgutddZSa6XFzFpqrbTYQAithdYySyXG1FpmrcSYWisA' +
-'AOzAAQDswEIoNGQlAJAHAEAYoxRjzjlnEGLMOegcNAgx5hyEDirGnIMOQggVY85BCCGEzDkIIYQQ' +
-'QuYchBBCCKGDEEIIpZTSQQghhFJK6SCEEEIppXQQQgihlFIKAAAqcAAACLBRZHOCkaBCQ1YCAHkA' +
-'AIAxSjkHoZRGKcYglJJSoxRjEEpJqXIMQikpxVY5B6GUlFrsIJTSWmw1dhBKaS3GWkNKrcVYa64h' +
-'pdZirDXX1FqMteaaa0otxlprzbkAANwFBwCwAxtFNicYCSo0ZCUAkAcAgCCkFGOMMYYUYoox55xD' +
-'CCnFmHPOKaYYc84555RijDnnnHOMMeecc845xphzzjnnHHPOOeecc44555xzzjnnnHPOOeecc845' +
-'55xzzgkAACpwAAAIsFFkc4KRoEJDVgIAqQAAABFWYowxxhgbCDHGGGOMMUYSYowxxhhjbDHGGGOM' +
-'McaYYowxxhhjjDHGGGOMMcYYY4wxxhhjjDHGGGOMMcYYY4wxxhhjjDHGGGOMMcYYY4wxxhhjjDHG' +
-'GFtrrbXWWmuttdZaa6211lprrQBAvwoHAP8HG1ZHOCkaCyw0ZCUAEA4AABjDmHOOOQYdhIYp6KSE' +
-'DkIIoUNKOSglhFBKKSlzTkpKpaSUWkqZc1JSKiWlllLqIKTUWkottdZaByWl1lJqrbXWOgiltNRa' +
-'a6212EFIKaXWWostxlBKSq212GKMNYZSUmqtxdhirDGk0lJsLcYYY6yhlNZaazHGGGstKbXWYoy1' +
-'xlprSam11mKLNdZaCwDgbnAAgEiwcYaVpLPC0eBCQ1YCACEBAARCjDnnnHMQQgghUoox56CDEEII' +
-'IURKMeYcdBBCCCGEjDHnoIMQQgghhJAx5hx0EEIIIYQQOucchBBCCKGEUkrnHHQQQgghlFBC6SCE' +
-'EEIIoYRSSikdhBBCKKGEUkopJYQQQgmllFJKKaWEEEIIoYQSSimllBBCCKWUUkoppZQSQgghlFJK' +
-'KaWUUkIIoZRQSimllFJKCCGEUkoppZRSSgkhhFBKKaWUUkopIYQSSimllFJKKaUAAIADBwCAACPo' +
-'JKPKImw04cIDUGjISgCADAAAcdhq6ynWyCDFnISWS4SQchBiLhFSijlHsWVIGcUY1ZQxpRRTUmvo' +
-'nGKMUU+dY0oxw6yUVkookYLScqy1dswBAAAgCAAwECEzgUABFBjIAIADhAQpAKCwwNAxXAQE5BIy' +
-'CgwKx4Rz0mkDABCEyAyRiFgMEhOqgaJiOgBYXGDIB4AMjY20iwvoMsAFXdx1IIQgBCGIxQEUkICD' +
-'E2544g1PuMEJOkWlDgIAAAAA4AAAHgAAkg0gIiKaOY4Ojw+QEJERkhKTE5QAAAAAALABgA8AgCQF' +
-'iIiIZo6jw+MDJERkhKTE5AQlAAAAAAAAAAAACAgIAAAAAAAEAAAACAhPZ2dTAAQYOwAAAAAAAOGp' +
-'bkoCAAAAmc74DRgyNjM69TAzOTk74dnLubewsbagmZiNp4d0KbsExSY/I3XUTwJgkeZdn1HY4zoj' +
-'33/q9DFtv3Ui1/jmx7lCUtPt18/sYf9MkgAsAGRBd3gMGP4sU+qCPYBy9VrA3YqJosW3W2/ef1iO' +
-'/u3cg8ZG/57jU+pPmbGEJUgkfnaI39DbPqxddZphbMRmCc5rKlkUMkyx8iIoug5dJv1OYH9a59c+' +
-'3Gevqc7Z2XFdDjL/qHztRfjWEWxJ/aiGezjohu9HsCZdQBKbiH0VtU/3m85lDG2T/+xkZcYnX+E+' +
-'aqzv/xTgOoTFG+x7SNqQ4N+oAABSxuVXw77Jd5bmmTmuJakX7509HH0kGYKvARPpwfOSAPySPAc2' +
-'EkneDwB2HwAAJlQDYK5586N79GJCjx4+p6aDUd27XSvRyXLJkIC5YZ1jLv5lpOhZTz0s+DmnF1di' +
-'ptrnM6UDgIW11Xh8cHTd0/SmbgOAdxcyWwMAAGIrZ3fNSfZbzKiYrK4+tPqtnMVLOeWOG2kVvUY+' +
-'p2PJ/hkCl5aFRO4TLGYPZcIU3vYM1hohS4jHFlnyW/2T5J7kGsShXWT8N05V+3C/GPqJ1QdWisGP' +
-'xEzHqXISBPIinWDUt7IeJv/f5OtzBxpTzZZQ+CYEhHXfqG4aABQli72GJhN4oJv+hXcApAJSErAW' +
-'8G2raAX4NUcABnVt77CzZAB+LsHcVe+Q4h+QB1wh/ZrJTPxSBdI8mgTeAdTsQOoFUEng9BHcVPhx' +
-'SRRYkKWZJXOFYP6V4AEripJoEjXgA2wJRZHSExmJDm8F0A6gEXsg5a4ZsALItrMB7+fh7UKLvYWS' +
-'dtsDwFf1mzYzS1F82N1h2Oyt2e76B1QdS0SAsQigLPMOgJS9JRC7hFXA6kUsLFNKD5cA5cTRvgSq' +
-'Pc3Fl99xW3QTi/MHR8DEm6WnvaVQATwRqRKjywQ9BrrhugR2AKTsPQeQckrAOgDOhbTESyrXQ50C' +
-'kNpXdtWjW7W2/3UjeX3U95gIdalfRAoAmqUEiwp53hCdcCwlg47fcbfzlmQMAgaBkh7c+fcDgF+i' +
-'fwDXfzegLPcLYJsAAJQArTXjnh/uXGy3v1Hk3pV6/3t5ruW81f6prfbM2Q3WNVy98BwUtbCwhFhA' +
-'WuPev6Oe/4ZaFQUcgKrVs4defzh1TADA1DEh5b3VlDaECw5b+bPfkKos3tIAue3vJZOih3ga3l6O' +
-'3PSfIkrLv0PAS86PPdL7g8oc2KteNFKKzKRehOv2gJoFLBPXmaXvPBQILgJon0bbWBszrYZYYwE7' +
-'jl2j+vTdU7Vpk21LiU0QajPkywAAHqbUC0/YsYOdb4e6BOp7E0cCi04Ao/TgD8ZVAMid6h/A8IeB' +
-'Nkp6/xsAACZELEYIk+yvI6Qz1NN6lIftB/6IMWjWJNOqPTMedAmyaj6Es0QBklJpiSWWHnQ2CoYb' +
-'GWAmt+0gLQBFKCBnp2QUUQZ/1thtZDBJUpFWY82z34ocorB62oX7qB5y0oPAv/foxH25wVmgIHf2' +
-'xFOr8leZcBq1Kx3ZvCq9Bga639AxuHuPNL/71YCF4EywJpqHFAX6XF0sjVbuANnvvdLcrufYwOM/' +
-'iDa6iA468AYAAB6mNBMXcgTD8HSRqJ4vw8CjAlCEPACASlX/APwPOJKl9xQAAAPmnev2eWp33Xgy' +
-'w3Dvfz6myGk3oyP8YTKsCOvzAgALQi0o1c6Nzs2O2Pg2h4ACIJAgAGP0aNn5x0BDgVfH7u2TtyfD' +
-'cRIuYAyQhBF/lvSRAttgA6TPbWZA9gaUrZWAUEAA+Dx47Q3/r87HxUUqZmB0BmUuMlojFjHt1gDu' +
-'nnvuX8MImsjSq5WkzSzGS62OEIlOufWWezxWpv6FBgDgJVltfXFYtNAAnqU0xQoD0YLiXo5cF5QV' +
-'4CnY1tBLAkZCOABAhbk/AM+/AwSCCdlWAAAMcFjS7owb8GVDzveDiZvznbt2tF4bL5odN1YKl88T' +
-'AEABCZvufq9YCTBtMwVAQUEAwGtNltzSaHvADYC3TxLVjqiRA+OZAMhzcqEgRcAOwoCgvdTxsTHL' +
-'QEF6+oOb2+PAI8ciPQcXg7pOY+LjxQSv2fjmFuj34gGwz310/bGK6z3xgT887eomWULEaDd04wHe' +
-'tYxdjcgV2SxvSwn0VoZXJRqkRC5ASQ/muVoAUsX7AgAQMBNaVwAAlABRxT/1PmfqLqSRNDbhXb07' +
-'berpB3b94jpuWEZjBCD2OcdXFpCKEgCDfcFPMw8AAADUwT4lnUm50lmwrpMMhPQIKj6u0E8fr2vG' +
-'BngMNdIlrZsigjahljud6AFVg+tzXwUnXL3TJLpajaWKA4VAAAAMiFfqJgKAZ08XrtS3dxtQNYcp' +
-'PvYEG8ClvrQRJgBephwnNWJjtGqmp6VEPSvBe7EBiU3qgJbQAwD4Le8LAMDMhHbNAAAlgK+tFs5O' +
-'+YyJc9yCnJa3rxLPulGnxwsXV9Fsk2k4PisCAHC8FkwbGE9gJQAAoMnyksj0CdFMZLLgoz8M+Fxz' +
-'iwYBgIx+zHiCBAKAlBKNpF1sO9JpVcyEi9ar15YlHgrut5fPJnkdJ6vEwZPyAHQBIEDUrlMcBAAd' +
-'2KAS0Qq+JwRsE4AJZtMnAD6GnOYwYlOIZvtzUNdjreB7fiMkWI0CmBB6AIAKc38A9osEFlTSGECB' +
-'+cbeRDC0aRpLHqNPplcK/76Lxn2rpmqyXsYJWRi/FQAAAKBQk9MCAOibrQBQADCDsqpooPutd+05' +
-'Ce9g6iEdiYXgVmQAI4+4wskEBEiBloNQ6Ki0/KTQ0QjWfjxzi+AeuXKoMjEVfQOZzr0y941qLgM2' +
-'AExvbZOqcxZ6J6krlrj4y2j9AdgKDx6GnJsVLhbc42uq584+ouSdNBpoCiCVHrz+WzUA/DDtD8AT' +
-'gA3h0lMCAAzcFv+S+fSSNkeYWlTpb34mf2RfmqqJeMeklhHAfu7VoAEACgAApKRktL+KkQDWMwYC' +
-'UAAAAHCKsp80xhp91UjqQBw3x45cetqkjQEyu3G9B6N+R650Uq8OVig7wOm6Wun0ea4lKDPoabJs' +
-'6aLqgbhPzpv4KR4iODilw88ZpY7q1IOMcbASAOAVtmcCnobcrkG4KGS7/ZnskVWRNF9J0RUHKOnB' +
-'yy9WA8Dv6L4AAARMCQUA4GritfVM2lcZfH3Q3T/vZ47J2YHhcmBazjfdyuV25gLAzrc0cwAAAAAY' +
-'Ch6PdwAAAGyWjFW4yScjaWa2mGcofHxWxewKALglWBpLUvwwk+UOh5eNGyUOs1/EF+pZr+ud5Ozo' +
-'GwYdAABg2p52LiSgAY/ZVlOmilEgHn6G3OcwYjzI7vOj1t6xsx4S3lBY96EUQBF6AIBAmPYH4PoG' +
-'YCoJAADWe+OZJZi7/x76/yH7Lzf9M5XzRKnFPmveMsilQHwVAAAAAKB3LQD8PCIAAADga0QujBLy' +
-'wzeJ4a6Z/ERVBAUlAEDqvoM7BQBAuAguzFqILtmjH3Kd4wfKobnOhA3z85qWoRPm9hwoOHoDAAlC' +
-'bwDAA56FHAuXflHo3fe2ttG9XUDeA9YmYCBQ0oPr/1QC8IvuCwAAApbUAQCK22MmE3O78VAbHQT9' +
-'PIPNoT9zNc3l2Oe7TAVLANBufT8MAQAAAGzT4PS8AQAAoELGHb2uaCwwEv1EWhFriUkbAaAZ27/f' +
-'VZnTZXbWz3BwWpjUaMZKRj7dZ0J//gUeTdpVEwAAZOFsNxKAjQSgA+ABPoY8Jj5y2wje81jsXc/1' +
-'TOQWTDYZBmAkNDiqVwuA2NJ9AQAAEBKAt9Vrsfs/2N19MO91S9rd8EHTZHnzC5MYmfQEACy/FBcA' +
-'AADA5c4gi4z8RANs/m6FNXVo9DV46JG1BBDukqlw/Va5G7QbuGVSI+2aZaoLXJrdVj2zlC9Z5QEA' +
-'EFz/5QzgVZwAAAAA/oXcxyC6WfTu+09Ve/c766J4VTAGUFmA51+VANKi/QPoPwYgYAkA715OH4S0' +
-'s5KDHvj99MMq8TPFc3roKZnGOoT1bmIhVgc7XAMBAAAAAMAW1VbQw3gapzOpJd+Kd2fc4iSO62fJ' +
-'v9+movui1wUNPAj059N3OVxzk4gV73PmE8FIA2F5mRq37Evc76vLXfF4rD5UJJAw46hW6LZCb5sN' +
-'Ldx+kzMCAAB+hfy95+965ZCLP7B3/VlTHCvDEKtQhTm4KiCgAEAbrfbWTPssAAAAXpee1tVrozYY' +
-'n41wD1aeYtkKfswN5/SXPO0JDnhO/4laUortv/s412fybe/nONdncoCHnBVliu0CQGBWlPY/5Kwo' +
-'m2L/kruPM6Q7oz4tvDQy+bZ3HzOi+gNHA4DZEgA=' +
-''
+  'T2dnUwACAAAAAAAAAADhqW5KAAAAAMFvEjYBHgF2b3JiaXMAAAAAAYC7AAAAAAAAAHcBAAAAAAC4' +
+  'AU9nZ1MAAAAAAAAAAAAA4aluSgEAAAAAesI3EC3//////////////////8kDdm9yYmlzHQAAAFhp' +
+  'cGguT3JnIGxpYlZvcmJpcyBJIDIwMDkwNzA5AAAAAAEFdm9yYmlzKUJDVgEACAAAADFMIMWA0JBV' +
+  'AAAQAABgJCkOk2ZJKaWUoSh5mJRISSmllMUwiZiUicUYY4wxxhhjjDHGGGOMIDRkFQAABACAKAmO' +
+  'o+ZJas45ZxgnjnKgOWlOOKcgB4pR4DkJwvUmY26mtKZrbs4pJQgNWQUAAAIAQEghhRRSSCGFFGKI' +
+  'IYYYYoghhxxyyCGnnHIKKqigggoyyCCDTDLppJNOOumoo4466ii00EILLbTSSkwx1VZjrr0GXXxz' +
+  'zjnnnHPOOeecc84JQkNWAQAgAAAEQgYZZBBCCCGFFFKIKaaYcgoyyIDQkFUAACAAgAAAAABHkRRJ' +
+  'sRTLsRzN0SRP8ixREzXRM0VTVE1VVVVVdV1XdmXXdnXXdn1ZmIVbuH1ZuIVb2IVd94VhGIZhGIZh' +
+  'GIZh+H3f933f930gNGQVACABAKAjOZbjKaIiGqLiOaIDhIasAgBkAAAEACAJkiIpkqNJpmZqrmmb' +
+  'tmirtm3LsizLsgyEhqwCAAABAAQAAAAAAKBpmqZpmqZpmqZpmqZpmqZpmqZpmmZZlmVZlmVZlmVZ' +
+  'lmVZlmVZlmVZlmVZlmVZlmVZlmVZlmVZlmVZQGjIKgBAAgBAx3Ecx3EkRVIkx3IsBwgNWQUAyAAA' +
+  'CABAUizFcjRHczTHczzHczxHdETJlEzN9EwPCA1ZBQAAAgAIAAAAAABAMRzFcRzJ0SRPUi3TcjVX' +
+  'cz3Xc03XdV1XVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVYHQkFUAAAQAACGdZpZq' +
+  'gAgzkGEgNGQVAIAAAAAYoQhDDAgNWQUAAAQAAIih5CCa0JrzzTkOmuWgqRSb08GJVJsnuamYm3PO' +
+  'OeecbM4Z45xzzinKmcWgmdCac85JDJqloJnQmnPOeRKbB62p0ppzzhnnnA7GGWGcc85p0poHqdlY' +
+  'm3POWdCa5qi5FJtzzomUmye1uVSbc84555xzzjnnnHPOqV6czsE54Zxzzonam2u5CV2cc875ZJzu' +
+  'zQnhnHPOOeecc84555xzzglCQ1YBAEAAAARh2BjGnYIgfY4GYhQhpiGTHnSPDpOgMcgppB6NjkZK' +
+  'qYNQUhknpXSC0JBVAAAgAACEEFJIIYUUUkghhRRSSCGGGGKIIaeccgoqqKSSiirKKLPMMssss8wy' +
+  'y6zDzjrrsMMQQwwxtNJKLDXVVmONteaec645SGultdZaK6WUUkoppSA0ZBUAAAIAQCBkkEEGGYUU' +
+  'UkghhphyyimnoIIKCA1ZBQAAAgAIAAAA8CTPER3RER3RER3RER3RER3P8RxREiVREiXRMi1TMz1V' +
+  'VFVXdm1Zl3Xbt4Vd2HXf133f141fF4ZlWZZlWZZlWZZlWZZlWZZlCUJDVgEAIAAAAEIIIYQUUkgh' +
+  'hZRijDHHnINOQgmB0JBVAAAgAIAAAAAAR3EUx5EcyZEkS7IkTdIszfI0T/M00RNFUTRNUxVd0RV1' +
+  '0xZlUzZd0zVl01Vl1XZl2bZlW7d9WbZ93/d93/d93/d93/d939d1IDRkFQAgAQCgIzmSIimSIjmO' +
+  '40iSBISGrAIAZAAABACgKI7iOI4jSZIkWZImeZZniZqpmZ7pqaIKhIasAgAAAQAEAAAAAACgaIqn' +
+  'mIqniIrniI4oiZZpiZqquaJsyq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7rukBo' +
+  'yCoAQAIAQEdyJEdyJEVSJEVyJAcIDVkFAMgAAAgAwDEcQ1Ikx7IsTfM0T/M00RM90TM9VXRFFwgN' +
+  'WQUAAAIACAAAAAAAwJAMS7EczdEkUVIt1VI11VItVVQ9VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV' +
+  'VVVVVVVVVVVV1TRN0zSB0JCVAAAZAAAjQQYZhBCKcpBCbj1YCDHmJAWhOQahxBiEpxAzDDkNInSQ' +
+  'QSc9uJI5wwzz4FIoFURMg40lN44gDcKmXEnlOAhCQ1YEAFEAAIAxyDHEGHLOScmgRM4xCZ2UyDkn' +
+  'pZPSSSktlhgzKSWmEmPjnKPSScmklBhLip2kEmOJrQAAgAAHAIAAC6HQkBUBQBQAAGIMUgophZRS' +
+  'zinmkFLKMeUcUko5p5xTzjkIHYTKMQadgxAppRxTzinHHITMQeWcg9BBKAAAIMABACDAQig0ZEUA' +
+  'ECcA4HAkz5M0SxQlSxNFzxRl1xNN15U0zTQ1UVRVyxNV1VRV2xZNVbYlTRNNTfRUVRNFVRVV05ZN' +
+  'VbVtzzRl2VRV3RZV1bZl2xZ+V5Z13zNNWRZV1dZNVbV115Z9X9ZtXZg0zTQ1UVRVTRRV1VRV2zZV' +
+  '17Y1UXRVUVVlWVRVWXZlWfdVV9Z9SxRV1VNN2RVVVbZV2fVtVZZ94XRVXVdl2fdVWRZ+W9eF4fZ9' +
+  '4RhV1dZN19V1VZZ9YdZlYbd13yhpmmlqoqiqmiiqqqmqtm2qrq1bouiqoqrKsmeqrqzKsq+rrmzr' +
+  'miiqrqiqsiyqqiyrsqz7qizrtqiquq3KsrCbrqvrtu8LwyzrunCqrq6rsuz7qizruq3rxnHrujB8' +
+  'pinLpqvquqm6um7runHMtm0co6rqvirLwrDKsu/rui+0dSFRVXXdlF3jV2VZ921fd55b94WybTu/' +
+  'rfvKceu60vg5z28cubZtHLNuG7+t+8bzKz9hOI6lZ5q2baqqrZuqq+uybivDrOtCUVV9XZVl3zdd' +
+  'WRdu3zeOW9eNoqrquirLvrDKsjHcxm8cuzAcXds2jlvXnbKtC31jyPcJz2vbxnH7OuP2daOvDAnH' +
+  'jwAAgAEHAIAAE8pAoSErAoA4AQAGIecUUxAqxSB0EFLqIKRUMQYhc05KxRyUUEpqIZTUKsYgVI5J' +
+  'yJyTEkpoKZTSUgehpVBKa6GU1lJrsabUYu0gpBZKaS2U0lpqqcbUWowRYxAy56RkzkkJpbQWSmkt' +
+  'c05K56CkDkJKpaQUS0otVsxJyaCj0kFIqaQSU0mptVBKa6WkFktKMbYUW24x1hxKaS2kEltJKcYU' +
+  'U20txpojxiBkzknJnJMSSmktlNJa5ZiUDkJKmYOSSkqtlZJSzJyT0kFIqYOOSkkptpJKTKGU1kpK' +
+  'sYVSWmwx1pxSbDWU0lpJKcaSSmwtxlpbTLV1EFoLpbQWSmmttVZraq3GUEprJaUYS0qxtRZrbjHm' +
+  'GkppraQSW0mpxRZbji3GmlNrNabWam4x5hpbbT3WmnNKrdbUUo0txppjbb3VmnvvIKQWSmktlNJi' +
+  'ai3G1mKtoZTWSiqxlZJabDHm2lqMOZTSYkmpxZJSjC3GmltsuaaWamwx5ppSi7Xm2nNsNfbUWqwt' +
+  'xppTS7XWWnOPufVWAADAgAMAQIAJZaDQkJUAQBQAAEGIUs5JaRByzDkqCULMOSepckxCKSlVzEEI' +
+  'JbXOOSkpxdY5CCWlFksqLcVWaykptRZrLQAAoMABACDABk2JxQEKDVkJAEQBACDGIMQYhAYZpRiD' +
+  '0BikFGMQIqUYc05KpRRjzknJGHMOQioZY85BKCmEUEoqKYUQSkklpQIAAAocAAACbNCUWByg0JAV' +
+  'AUAUAABgDGIMMYYgdFQyKhGETEonqYEQWgutddZSa6XFzFpqrbTYQAithdYySyXG1FpmrcSYWisA' +
+  'AOzAAQDswEIoNGQlAJAHAEAYoxRjzjlnEGLMOegcNAgx5hyEDirGnIMOQggVY85BCCGEzDkIIYQQ' +
+  'QuYchBBCCKGDEEIIpZTSQQghhFJK6SCEEEIppXQQQgihlFIKAAAqcAAACLBRZHOCkaBCQ1YCAHkA' +
+  'AIAxSjkHoZRGKcYglJJSoxRjEEpJqXIMQikpxVY5B6GUlFrsIJTSWmw1dhBKaS3GWkNKrcVYa64h' +
+  'pdZirDXX1FqMteaaa0otxlprzbkAANwFBwCwAxtFNicYCSo0ZCUAkAcAgCCkFGOMMYYUYoox55xD' +
+  'CCnFmHPOKaYYc84555RijDnnnHOMMeecc845xphzzjnnHHPOOeecc44555xzzjnnnHPOOeecc845' +
+  '55xzzgkAACpwAAAIsFFkc4KRoEJDVgIAqQAAABFWYowxxhgbCDHGGGOMMUYSYowxxhhjbDHGGGOM' +
+  'McaYYowxxhhjjDHGGGOMMcYYY4wxxhhjjDHGGGOMMcYYY4wxxhhjjDHGGGOMMcYYY4wxxhhjjDHG' +
+  'GFtrrbXWWmuttdZaa6211lprrQBAvwoHAP8HG1ZHOCkaCyw0ZCUAEA4AABjDmHOOOQYdhIYp6KSE' +
+  'DkIIoUNKOSglhFBKKSlzTkpKpaSUWkqZc1JSKiWlllLqIKTUWkottdZaByWl1lJqrbXWOgiltNRa' +
+  'a6212EFIKaXWWostxlBKSq212GKMNYZSUmqtxdhirDGk0lJsLcYYY6yhlNZaazHGGGstKbXWYoy1' +
+  'xlprSam11mKLNdZaCwDgbnAAgEiwcYaVpLPC0eBCQ1YCACEBAARCjDnnnHMQQgghUoox56CDEEII' +
+  'IURKMeYcdBBCCCGEjDHnoIMQQgghhJAx5hx0EEIIIYQQOucchBBCCKGEUkrnHHQQQgghlFBC6SCE' +
+  'EEIIoYRSSikdhBBCKKGEUkopJYQQQgmllFJKKaWEEEIIoYQSSimllBBCCKWUUkoppZQSQgghlFJK' +
+  'KaWUUkIIoZRQSimllFJKCCGEUkoppZRSSgkhhFBKKaWUUkopIYQSSimllFJKKaUAAIADBwCAACPo' +
+  'JKPKImw04cIDUGjISgCADAAAcdhq6ynWyCDFnISWS4SQchBiLhFSijlHsWVIGcUY1ZQxpRRTUmvo' +
+  'nGKMUU+dY0oxw6yUVkookYLScqy1dswBAAAgCAAwECEzgUABFBjIAIADhAQpAKCwwNAxXAQE5BIy' +
+  'CgwKx4Rz0mkDABCEyAyRiFgMEhOqgaJiOgBYXGDIB4AMjY20iwvoMsAFXdx1IIQgBCGIxQEUkICD' +
+  'E2544g1PuMEJOkWlDgIAAAAA4AAAHgAAkg0gIiKaOY4Ojw+QEJERkhKTE5QAAAAAALABgA8AgCQF' +
+  'iIiIZo6jw+MDJERkhKTE5AQlAAAAAAAAAAAACAgIAAAAAAAEAAAACAhPZ2dTAAQYOwAAAAAAAOGp' +
+  'bkoCAAAAmc74DRgyNjM69TAzOTk74dnLubewsbagmZiNp4d0KbsExSY/I3XUTwJgkeZdn1HY4zoj' +
+  '33/q9DFtv3Ui1/jmx7lCUtPt18/sYf9MkgAsAGRBd3gMGP4sU+qCPYBy9VrA3YqJosW3W2/ef1iO' +
+  '/u3cg8ZG/57jU+pPmbGEJUgkfnaI39DbPqxddZphbMRmCc5rKlkUMkyx8iIoug5dJv1OYH9a59c+' +
+  '3Gevqc7Z2XFdDjL/qHztRfjWEWxJ/aiGezjohu9HsCZdQBKbiH0VtU/3m85lDG2T/+xkZcYnX+E+' +
+  'aqzv/xTgOoTFG+x7SNqQ4N+oAABSxuVXw77Jd5bmmTmuJakX7509HH0kGYKvARPpwfOSAPySPAc2' +
+  'EkneDwB2HwAAJlQDYK5586N79GJCjx4+p6aDUd27XSvRyXLJkIC5YZ1jLv5lpOhZTz0s+DmnF1di' +
+  'ptrnM6UDgIW11Xh8cHTd0/SmbgOAdxcyWwMAAGIrZ3fNSfZbzKiYrK4+tPqtnMVLOeWOG2kVvUY+' +
+  'p2PJ/hkCl5aFRO4TLGYPZcIU3vYM1hohS4jHFlnyW/2T5J7kGsShXWT8N05V+3C/GPqJ1QdWisGP' +
+  'xEzHqXISBPIinWDUt7IeJv/f5OtzBxpTzZZQ+CYEhHXfqG4aABQli72GJhN4oJv+hXcApAJSErAW' +
+  '8G2raAX4NUcABnVt77CzZAB+LsHcVe+Q4h+QB1wh/ZrJTPxSBdI8mgTeAdTsQOoFUEng9BHcVPhx' +
+  'SRRYkKWZJXOFYP6V4AEripJoEjXgA2wJRZHSExmJDm8F0A6gEXsg5a4ZsALItrMB7+fh7UKLvYWS' +
+  'dtsDwFf1mzYzS1F82N1h2Oyt2e76B1QdS0SAsQigLPMOgJS9JRC7hFXA6kUsLFNKD5cA5cTRvgSq' +
+  'Pc3Fl99xW3QTi/MHR8DEm6WnvaVQATwRqRKjywQ9BrrhugR2AKTsPQeQckrAOgDOhbTESyrXQ50C' +
+  'kNpXdtWjW7W2/3UjeX3U95gIdalfRAoAmqUEiwp53hCdcCwlg47fcbfzlmQMAgaBkh7c+fcDgF+i' +
+  'fwDXfzegLPcLYJsAAJQArTXjnh/uXGy3v1Hk3pV6/3t5ruW81f6prfbM2Q3WNVy98BwUtbCwhFhA' +
+  'WuPev6Oe/4ZaFQUcgKrVs4defzh1TADA1DEh5b3VlDaECw5b+bPfkKos3tIAue3vJZOih3ga3l6O' +
+  '3PSfIkrLv0PAS86PPdL7g8oc2KteNFKKzKRehOv2gJoFLBPXmaXvPBQILgJon0bbWBszrYZYYwE7' +
+  'jl2j+vTdU7Vpk21LiU0QajPkywAAHqbUC0/YsYOdb4e6BOp7E0cCi04Ao/TgD8ZVAMid6h/A8IeB' +
+  'Nkp6/xsAACZELEYIk+yvI6Qz1NN6lIftB/6IMWjWJNOqPTMedAmyaj6Es0QBklJpiSWWHnQ2CoYb' +
+  'GWAmt+0gLQBFKCBnp2QUUQZ/1thtZDBJUpFWY82z34ocorB62oX7qB5y0oPAv/foxH25wVmgIHf2' +
+  'xFOr8leZcBq1Kx3ZvCq9Bga639AxuHuPNL/71YCF4EywJpqHFAX6XF0sjVbuANnvvdLcrufYwOM/' +
+  'iDa6iA468AYAAB6mNBMXcgTD8HSRqJ4vw8CjAlCEPACASlX/APwPOJKl9xQAAAPmnev2eWp33Xgy' +
+  'w3Dvfz6myGk3oyP8YTKsCOvzAgALQi0o1c6Nzs2O2Pg2h4ACIJAgAGP0aNn5x0BDgVfH7u2TtyfD' +
+  'cRIuYAyQhBF/lvSRAttgA6TPbWZA9gaUrZWAUEAA+Dx47Q3/r87HxUUqZmB0BmUuMlojFjHt1gDu' +
+  'nnvuX8MImsjSq5WkzSzGS62OEIlOufWWezxWpv6FBgDgJVltfXFYtNAAnqU0xQoD0YLiXo5cF5QV' +
+  '4CnY1tBLAkZCOABAhbk/AM+/AwSCCdlWAAAMcFjS7owb8GVDzveDiZvznbt2tF4bL5odN1YKl88T' +
+  'AEABCZvufq9YCTBtMwVAQUEAwGtNltzSaHvADYC3TxLVjqiRA+OZAMhzcqEgRcAOwoCgvdTxsTHL' +
+  'QEF6+oOb2+PAI8ciPQcXg7pOY+LjxQSv2fjmFuj34gGwz310/bGK6z3xgT887eomWULEaDd04wHe' +
+  'tYxdjcgV2SxvSwn0VoZXJRqkRC5ASQ/muVoAUsX7AgAQMBNaVwAAlABRxT/1PmfqLqSRNDbhXb07' +
+  'berpB3b94jpuWEZjBCD2OcdXFpCKEgCDfcFPMw8AAADUwT4lnUm50lmwrpMMhPQIKj6u0E8fr2vG' +
+  'BngMNdIlrZsigjahljud6AFVg+tzXwUnXL3TJLpajaWKA4VAAAAMiFfqJgKAZ08XrtS3dxtQNYcp' +
+  'PvYEG8ClvrQRJgBephwnNWJjtGqmp6VEPSvBe7EBiU3qgJbQAwD4Le8LAMDMhHbNAAAlgK+tFs5O' +
+  '+YyJc9yCnJa3rxLPulGnxwsXV9Fsk2k4PisCAHC8FkwbGE9gJQAAoMnyksj0CdFMZLLgoz8M+Fxz' +
+  'iwYBgIx+zHiCBAKAlBKNpF1sO9JpVcyEi9ar15YlHgrut5fPJnkdJ6vEwZPyAHQBIEDUrlMcBAAd' +
+  '2KAS0Qq+JwRsE4AJZtMnAD6GnOYwYlOIZvtzUNdjreB7fiMkWI0CmBB6AIAKc38A9osEFlTSGECB' +
+  '+cbeRDC0aRpLHqNPplcK/76Lxn2rpmqyXsYJWRi/FQAAAKBQk9MCAOibrQBQADCDsqpooPutd+05' +
+  'Ce9g6iEdiYXgVmQAI4+4wskEBEiBloNQ6Ki0/KTQ0QjWfjxzi+AeuXKoMjEVfQOZzr0y941qLgM2' +
+  'AExvbZOqcxZ6J6krlrj4y2j9AdgKDx6GnJsVLhbc42uq584+ouSdNBpoCiCVHrz+WzUA/DDtD8AT' +
+  'gA3h0lMCAAzcFv+S+fSSNkeYWlTpb34mf2RfmqqJeMeklhHAfu7VoAEACgAApKRktL+KkQDWMwYC' +
+  'UAAAAHCKsp80xhp91UjqQBw3x45cetqkjQEyu3G9B6N+R650Uq8OVig7wOm6Wun0ea4lKDPoabJs' +
+  '6aLqgbhPzpv4KR4iODilw88ZpY7q1IOMcbASAOAVtmcCnobcrkG4KGS7/ZnskVWRNF9J0RUHKOnB' +
+  'yy9WA8Dv6L4AAARMCQUA4GritfVM2lcZfH3Q3T/vZ47J2YHhcmBazjfdyuV25gLAzrc0cwAAAAAY' +
+  'Ch6PdwAAAGyWjFW4yScjaWa2mGcofHxWxewKALglWBpLUvwwk+UOh5eNGyUOs1/EF+pZr+ud5Ozo' +
+  'GwYdAABg2p52LiSgAY/ZVlOmilEgHn6G3OcwYjzI7vOj1t6xsx4S3lBY96EUQBF6AIBAmPYH4PoG' +
+  'YCoJAADWe+OZJZi7/x76/yH7Lzf9M5XzRKnFPmveMsilQHwVAAAAAKB3LQD8PCIAAADga0QujBLy' +
+  'wzeJ4a6Z/ERVBAUlAEDqvoM7BQBAuAguzFqILtmjH3Kd4wfKobnOhA3z85qWoRPm9hwoOHoDAAlC' +
+  'bwDAA56FHAuXflHo3fe2ttG9XUDeA9YmYCBQ0oPr/1QC8IvuCwAAApbUAQCK22MmE3O78VAbHQT9' +
+  'PIPNoT9zNc3l2Oe7TAVLANBufT8MAQAAAGzT4PS8AQAAoELGHb2uaCwwEv1EWhFriUkbAaAZ27/f' +
+  'VZnTZXbWz3BwWpjUaMZKRj7dZ0J//gUeTdpVEwAAZOFsNxKAjQSgA+ABPoY8Jj5y2wje81jsXc/1' +
+  'TOQWTDYZBmAkNDiqVwuA2NJ9AQAAEBKAt9Vrsfs/2N19MO91S9rd8EHTZHnzC5MYmfQEACy/FBcA' +
+  'AADA5c4gi4z8RANs/m6FNXVo9DV46JG1BBDukqlw/Va5G7QbuGVSI+2aZaoLXJrdVj2zlC9Z5QEA' +
+  'EFz/5QzgVZwAAAAA/oXcxyC6WfTu+09Ve/c766J4VTAGUFmA51+VANKi/QPoPwYgYAkA715OH4S0' +
+  's5KDHvj99MMq8TPFc3roKZnGOoT1bmIhVgc7XAMBAAAAAMAW1VbQw3gapzOpJd+Kd2fc4iSO62fJ' +
+  'v9+movui1wUNPAj059N3OVxzk4gV73PmE8FIA2F5mRq37Evc76vLXfF4rD5UJJAw46hW6LZCb5sN' +
+  'Ldx+kzMCAAB+hfy95+965ZCLP7B3/VlTHCvDEKtQhTm4KiCgAEAbrfbWTPssAAAAXpee1tVrozYY' +
+  'n41wD1aeYtkKfswN5/SXPO0JDnhO/4laUortv/s412fybe/nONdncoCHnBVliu0CQGBWlPY/5Kwo' +
+  'm2L/kruPM6Q7oz4tvDQy+bZ3HzOi+gNHA4DZEgA=' +
+  ''
 );
 
 lib.resource.add('hterm/concat/date', 'text/plain',
-'Tue, 25 Apr 2017 15:12:45 +0000' +
-''
+  'Tue, 25 Apr 2017 15:12:45 +0000' +
+  ''
 );
 
 lib.resource.add('hterm/changelog/version', 'text/plain',
-'1.62' +
-''
+  '1.62' +
+  ''
 );
 
 lib.resource.add('hterm/changelog/date', 'text/plain',
-'2017-04-17' +
-''
+  '2017-04-17' +
+  ''
 );
 
 lib.resource.add('hterm/git/HEAD', 'text/plain',
-'git rev-parse HEAD' +
-''
+  'git rev-parse HEAD' +
+  ''
 );
-
-
diff --git a/app/vendors/hterm/hterm_all.min.js b/app/vendors/hterm/hterm_all.min.js
index 83d4a55..208526d 100644
--- a/app/vendors/hterm/hterm_all.min.js
+++ b/app/vendors/hterm/hterm_all.min.js
@@ -1,7 +1,4595 @@
-"use strict";if("undefined"!=typeof lib)throw new Error('Global "lib" object already exists.');var lib={};lib.runtimeDependencies_={},lib.initCallbacks_=[],lib.rtdep=function(e){var t;try{throw new Error}catch(r){var o=r.stack.split("\n");t=o.length>=3?o[2].replace(/^\s*at\s+/,""):o[1].replace(/^\s*global code@/,"")}for(var i=0;i<arguments.length;i++){var s=arguments[i];if(s instanceof Array)lib.rtdep.apply(lib,s);else{var n=this.runtimeDependencies_[s];n||(n=this.runtimeDependencies_[s]=[]),n.push(t)}}},lib.ensureRuntimeDependencies_=function(){var e=!0;for(var t in lib.runtimeDependencies_)for(var r=lib.runtimeDependencies_[t],o=t.split("."),i=window||self,s=0;s<o.length;s++){if(!(o[s]in i)){console.warn('Missing "'+t+'" is needed by',r),e=!1;break}i=i[o[s]]}if(!e)throw new Error("Failed runtime dependency check")},lib.registerInit=function(e,t){return lib.initCallbacks_.push([e,t]),t},lib.init=function(e,t){var r=lib.initCallbacks_,o=function(){if(r.length){var i=r.shift();t&&t("init: "+i[0]),i[1](lib.f.alarm(o))}else e()};if("function"!=typeof e)throw new Error("Missing or invalid argument: onInit");lib.ensureRuntimeDependencies_(),setTimeout(o,0)},lib.colors={},lib.colors.re_={hex16:/#([a-f0-9])([a-f0-9])([a-f0-9])/i,hex24:/#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/i,rgb:new RegExp("^/s*rgb/s*/(/s*(/d{1,3})/s*,/s*(/d{1,3})/s*,/s*(/d{1,3})/s*/)/s*$".replace(/\//g,"\\"),"i"),rgba:new RegExp("^/s*rgba/s*/(/s*(/d{1,3})/s*,/s*(/d{1,3})/s*,/s*(/d{1,3})/s*(?:,/s*(/d+(?:/./d+)?)/s*)/)/s*$".replace(/\//g,"\\"),"i"),rgbx:new RegExp("^/s*rgba?/s*/(/s*(/d{1,3})/s*,/s*(/d{1,3})/s*,/s*(/d{1,3})/s*(?:,/s*(/d+(?:/./d+)?)/s*)?/)/s*$".replace(/\//g,"\\"),"i"),x11rgb:/^\s*rgb:([a-f0-9]{1,4})\/([a-f0-9]{1,4})\/([a-f0-9]{1,4})\s*$/i,name:/[a-z][a-z0-9\s]+/},lib.colors.rgbToX11=function(e){function t(e){return e=(257*Math.min(e,255)).toString(16),lib.f.zpad(e,4)}var r=e.match(lib.colors.re_.rgbx);return r?"rgb:"+t(r[1])+"/"+t(r[2])+"/"+t(r[3]):null},lib.colors.x11HexToCSS=function(e){function t(e){return e=parseInt(e,16),2==r?e:1==r?e<<4:e>>4*(r-2)}if(!e.startsWith("#"))return null;if(e=e.substr(1),-1==[3,6,9,12].indexOf(e.length))return null;if(e.match(/[^a-f0-9]/i))return null;var r=e.length/3,o=e.substr(0,r),i=e.substr(r,r),s=e.substr(r+r,r);return lib.colors.arrayToRGBA([o,i,s].map(t))},lib.colors.x11ToCSS=function(e){function t(e){return 1==e.length?parseInt(e+e,16):2==e.length?parseInt(e,16):(3==e.length&&(e+=e.substr(2)),Math.round(parseInt(e,16)/257))}var r=e.match(lib.colors.re_.x11rgb);return r?(r.splice(0,1),lib.colors.arrayToRGBA(r.map(t))):e.startsWith("#")?lib.colors.x11HexToCSS(e):lib.colors.nameToRGB(e)},lib.colors.hexToRGB=function(e){function t(e){4==e.length&&(e=e.replace(r,function(e,t,r,o){return"#"+t+t+r+r+o+o}));var t=e.match(o);return t?"rgb("+parseInt(t[1],16)+", "+parseInt(t[2],16)+", "+parseInt(t[3],16)+")":null}var r=lib.colors.re_.hex16,o=lib.colors.re_.hex24;if(e instanceof Array)for(var i=0;i<e.length;i++)e[i]=t(e[i]);else e=t(e);return e},lib.colors.rgbToHex=function(e){function t(e){var t=lib.colors.crackRGB(e);return t?"#"+lib.f.zpad((parseInt(t[0])<<16|parseInt(t[1])<<8|parseInt(t[2])<<0).toString(16),6):null}if(e instanceof Array)for(var r=0;r<e.length;r++)e[r]=t(e[r]);else e=t(e);return e},lib.colors.normalizeCSS=function(e){return"#"==e.substr(0,1)?lib.colors.hexToRGB(e):lib.colors.re_.rgbx.test(e)?e:lib.colors.nameToRGB(e)},lib.colors.arrayToRGBA=function(e){var t=e.length>3?e[3]:1;return"rgba("+e[0]+", "+e[1]+", "+e[2]+", "+t+")"},lib.colors.setAlpha=function(e,t){var r=lib.colors.crackRGB(e);return r[3]=t,lib.colors.arrayToRGBA(r)},lib.colors.mix=function(e,t,r){for(var o=lib.colors.crackRGB(e),i=lib.colors.crackRGB(t),s=0;4>s;++s){var n=i[s]-o[s];o[s]=Math.round(parseInt(o[s])+n*r)}return lib.colors.arrayToRGBA(o)},lib.colors.crackRGB=function(e){if("rgba"==e.substr(0,4)){var t=e.match(lib.colors.re_.rgba);if(t)return t.shift(),t}else{var t=e.match(lib.colors.re_.rgb);if(t)return t.shift(),t.push(1),t}return console.error("Couldn't crack: "+e),null},lib.colors.nameToRGB=function(e){return e in lib.colors.colorNames?lib.colors.colorNames[e]:(e=e.toLowerCase(),e in lib.colors.colorNames?lib.colors.colorNames[e]:(e=e.replace(/\s+/g,""),e in lib.colors.colorNames?lib.colors.colorNames[e]:null))},lib.colors.stockColorPalette=lib.colors.hexToRGB(["#000000","#CC0000","#4E9A06","#C4A000","#3465A4","#75507B","#06989A","#D3D7CF","#555753","#EF2929","#00BA13","#FCE94F","#729FCF","#F200CB","#00B5BD","#EEEEEC","#000000","#00005F","#000087","#0000AF","#0000D7","#0000FF","#005F00","#005F5F","#005F87","#005FAF","#005FD7","#005FFF","#008700","#00875F","#008787","#0087AF","#0087D7","#0087FF","#00AF00","#00AF5F","#00AF87","#00AFAF","#00AFD7","#00AFFF","#00D700","#00D75F","#00D787","#00D7AF","#00D7D7","#00D7FF","#00FF00","#00FF5F","#00FF87","#00FFAF","#00FFD7","#00FFFF","#5F0000","#5F005F","#5F0087","#5F00AF","#5F00D7","#5F00FF","#5F5F00","#5F5F5F","#5F5F87","#5F5FAF","#5F5FD7","#5F5FFF","#5F8700","#5F875F","#5F8787","#5F87AF","#5F87D7","#5F87FF","#5FAF00","#5FAF5F","#5FAF87","#5FAFAF","#5FAFD7","#5FAFFF","#5FD700","#5FD75F","#5FD787","#5FD7AF","#5FD7D7","#5FD7FF","#5FFF00","#5FFF5F","#5FFF87","#5FFFAF","#5FFFD7","#5FFFFF","#870000","#87005F","#870087","#8700AF","#8700D7","#8700FF","#875F00","#875F5F","#875F87","#875FAF","#875FD7","#875FFF","#878700","#87875F","#878787","#8787AF","#8787D7","#8787FF","#87AF00","#87AF5F","#87AF87","#87AFAF","#87AFD7","#87AFFF","#87D700","#87D75F","#87D787","#87D7AF","#87D7D7","#87D7FF","#87FF00","#87FF5F","#87FF87","#87FFAF","#87FFD7","#87FFFF","#AF0000","#AF005F","#AF0087","#AF00AF","#AF00D7","#AF00FF","#AF5F00","#AF5F5F","#AF5F87","#AF5FAF","#AF5FD7","#AF5FFF","#AF8700","#AF875F","#AF8787","#AF87AF","#AF87D7","#AF87FF","#AFAF00","#AFAF5F","#AFAF87","#AFAFAF","#AFAFD7","#AFAFFF","#AFD700","#AFD75F","#AFD787","#AFD7AF","#AFD7D7","#AFD7FF","#AFFF00","#AFFF5F","#AFFF87","#AFFFAF","#AFFFD7","#AFFFFF","#D70000","#D7005F","#D70087","#D700AF","#D700D7","#D700FF","#D75F00","#D75F5F","#D75F87","#D75FAF","#D75FD7","#D75FFF","#D78700","#D7875F","#D78787","#D787AF","#D787D7","#D787FF","#D7AF00","#D7AF5F","#D7AF87","#D7AFAF","#D7AFD7","#D7AFFF","#D7D700","#D7D75F","#D7D787","#D7D7AF","#D7D7D7","#D7D7FF","#D7FF00","#D7FF5F","#D7FF87","#D7FFAF","#D7FFD7","#D7FFFF","#FF0000","#FF005F","#FF0087","#FF00AF","#FF00D7","#FF00FF","#FF5F00","#FF5F5F","#FF5F87","#FF5FAF","#FF5FD7","#FF5FFF","#FF8700","#FF875F","#FF8787","#FF87AF","#FF87D7","#FF87FF","#FFAF00","#FFAF5F","#FFAF87","#FFAFAF","#FFAFD7","#FFAFFF","#FFD700","#FFD75F","#FFD787","#FFD7AF","#FFD7D7","#FFD7FF","#FFFF00","#FFFF5F","#FFFF87","#FFFFAF","#FFFFD7","#FFFFFF","#080808","#121212","#1C1C1C","#262626","#303030","#3A3A3A","#444444","#4E4E4E","#585858","#626262","#6C6C6C","#767676","#808080","#8A8A8A","#949494","#9E9E9E","#A8A8A8","#B2B2B2","#BCBCBC","#C6C6C6","#D0D0D0","#DADADA","#E4E4E4","#EEEEEE"]),lib.colors.colorPalette=lib.colors.stockColorPalette,lib.colors.colorNames={aliceblue:"rgb(240, 248, 255)",antiquewhite:"rgb(250, 235, 215)",antiquewhite1:"rgb(255, 239, 219)",antiquewhite2:"rgb(238, 223, 204)",antiquewhite3:"rgb(205, 192, 176)",antiquewhite4:"rgb(139, 131, 120)",aquamarine:"rgb(127, 255, 212)",aquamarine1:"rgb(127, 255, 212)",aquamarine2:"rgb(118, 238, 198)",aquamarine3:"rgb(102, 205, 170)",aquamarine4:"rgb(69, 139, 116)",azure:"rgb(240, 255, 255)",azure1:"rgb(240, 255, 255)",azure2:"rgb(224, 238, 238)",azure3:"rgb(193, 205, 205)",azure4:"rgb(131, 139, 139)",beige:"rgb(245, 245, 220)",bisque:"rgb(255, 228, 196)",bisque1:"rgb(255, 228, 196)",bisque2:"rgb(238, 213, 183)",bisque3:"rgb(205, 183, 158)",bisque4:"rgb(139, 125, 107)",black:"rgb(0, 0, 0)",blanchedalmond:"rgb(255, 235, 205)",blue:"rgb(0, 0, 255)",blue1:"rgb(0, 0, 255)",blue2:"rgb(0, 0, 238)",blue3:"rgb(0, 0, 205)",blue4:"rgb(0, 0, 139)",blueviolet:"rgb(138, 43, 226)",brown:"rgb(165, 42, 42)",brown1:"rgb(255, 64, 64)",brown2:"rgb(238, 59, 59)",brown3:"rgb(205, 51, 51)",brown4:"rgb(139, 35, 35)",burlywood:"rgb(222, 184, 135)",burlywood1:"rgb(255, 211, 155)",burlywood2:"rgb(238, 197, 145)",burlywood3:"rgb(205, 170, 125)",burlywood4:"rgb(139, 115, 85)",cadetblue:"rgb(95, 158, 160)",cadetblue1:"rgb(152, 245, 255)",cadetblue2:"rgb(142, 229, 238)",cadetblue3:"rgb(122, 197, 205)",cadetblue4:"rgb(83, 134, 139)",chartreuse:"rgb(127, 255, 0)",chartreuse1:"rgb(127, 255, 0)",chartreuse2:"rgb(118, 238, 0)",chartreuse3:"rgb(102, 205, 0)",chartreuse4:"rgb(69, 139, 0)",chocolate:"rgb(210, 105, 30)",chocolate1:"rgb(255, 127, 36)",chocolate2:"rgb(238, 118, 33)",chocolate3:"rgb(205, 102, 29)",chocolate4:"rgb(139, 69, 19)",coral:"rgb(255, 127, 80)",coral1:"rgb(255, 114, 86)",coral2:"rgb(238, 106, 80)",coral3:"rgb(205, 91, 69)",coral4:"rgb(139, 62, 47)",cornflowerblue:"rgb(100, 149, 237)",cornsilk:"rgb(255, 248, 220)",cornsilk1:"rgb(255, 248, 220)",cornsilk2:"rgb(238, 232, 205)",cornsilk3:"rgb(205, 200, 177)",cornsilk4:"rgb(139, 136, 120)",cyan:"rgb(0, 255, 255)",cyan1:"rgb(0, 255, 255)",cyan2:"rgb(0, 238, 238)",cyan3:"rgb(0, 205, 205)",cyan4:"rgb(0, 139, 139)",darkblue:"rgb(0, 0, 139)",darkcyan:"rgb(0, 139, 139)",darkgoldenrod:"rgb(184, 134, 11)",darkgoldenrod1:"rgb(255, 185, 15)",darkgoldenrod2:"rgb(238, 173, 14)",darkgoldenrod3:"rgb(205, 149, 12)",darkgoldenrod4:"rgb(139, 101, 8)",darkgray:"rgb(169, 169, 169)",darkgreen:"rgb(0, 100, 0)",darkgrey:"rgb(169, 169, 169)",darkkhaki:"rgb(189, 183, 107)",darkmagenta:"rgb(139, 0, 139)",darkolivegreen:"rgb(85, 107, 47)",darkolivegreen1:"rgb(202, 255, 112)",darkolivegreen2:"rgb(188, 238, 104)",darkolivegreen3:"rgb(162, 205, 90)",darkolivegreen4:"rgb(110, 139, 61)",darkorange:"rgb(255, 140, 0)",darkorange1:"rgb(255, 127, 0)",darkorange2:"rgb(238, 118, 0)",darkorange3:"rgb(205, 102, 0)",darkorange4:"rgb(139, 69, 0)",darkorchid:"rgb(153, 50, 204)",darkorchid1:"rgb(191, 62, 255)",darkorchid2:"rgb(178, 58, 238)",darkorchid3:"rgb(154, 50, 205)",darkorchid4:"rgb(104, 34, 139)",darkred:"rgb(139, 0, 0)",darksalmon:"rgb(233, 150, 122)",darkseagreen:"rgb(143, 188, 143)",darkseagreen1:"rgb(193, 255, 193)",darkseagreen2:"rgb(180, 238, 180)",darkseagreen3:"rgb(155, 205, 155)",darkseagreen4:"rgb(105, 139, 105)",darkslateblue:"rgb(72, 61, 139)",darkslategray:"rgb(47, 79, 79)",darkslategray1:"rgb(151, 255, 255)",darkslategray2:"rgb(141, 238, 238)",darkslategray3:"rgb(121, 205, 205)",darkslategray4:"rgb(82, 139, 139)",darkslategrey:"rgb(47, 79, 79)",darkturquoise:"rgb(0, 206, 209)",darkviolet:"rgb(148, 0, 211)",debianred:"rgb(215, 7, 81)",deeppink:"rgb(255, 20, 147)",deeppink1:"rgb(255, 20, 147)",deeppink2:"rgb(238, 18, 137)",deeppink3:"rgb(205, 16, 118)",deeppink4:"rgb(139, 10, 80)",deepskyblue:"rgb(0, 191, 255)",deepskyblue1:"rgb(0, 191, 255)",deepskyblue2:"rgb(0, 178, 238)",deepskyblue3:"rgb(0, 154, 205)",deepskyblue4:"rgb(0, 104, 139)",dimgray:"rgb(105, 105, 105)",dimgrey:"rgb(105, 105, 105)",dodgerblue:"rgb(30, 144, 255)",dodgerblue1:"rgb(30, 144, 255)",dodgerblue2:"rgb(28, 134, 238)",dodgerblue3:"rgb(24, 116, 205)",dodgerblue4:"rgb(16, 78, 139)",firebrick:"rgb(178, 34, 34)",firebrick1:"rgb(255, 48, 48)",firebrick2:"rgb(238, 44, 44)",firebrick3:"rgb(205, 38, 38)",firebrick4:"rgb(139, 26, 26)",floralwhite:"rgb(255, 250, 240)",forestgreen:"rgb(34, 139, 34)",gainsboro:"rgb(220, 220, 220)",ghostwhite:"rgb(248, 248, 255)",gold:"rgb(255, 215, 0)",gold1:"rgb(255, 215, 0)",gold2:"rgb(238, 201, 0)",gold3:"rgb(205, 173, 0)",gold4:"rgb(139, 117, 0)",goldenrod:"rgb(218, 165, 32)",goldenrod1:"rgb(255, 193, 37)",goldenrod2:"rgb(238, 180, 34)",goldenrod3:"rgb(205, 155, 29)",goldenrod4:"rgb(139, 105, 20)",gray:"rgb(190, 190, 190)",gray0:"rgb(0, 0, 0)",gray1:"rgb(3, 3, 3)",gray10:"rgb(26, 26, 26)",gray100:"rgb(255, 255, 255)",gray11:"rgb(28, 28, 28)",gray12:"rgb(31, 31, 31)",gray13:"rgb(33, 33, 33)",gray14:"rgb(36, 36, 36)",gray15:"rgb(38, 38, 38)",gray16:"rgb(41, 41, 41)",gray17:"rgb(43, 43, 43)",gray18:"rgb(46, 46, 46)",gray19:"rgb(48, 48, 48)",gray2:"rgb(5, 5, 5)",gray20:"rgb(51, 51, 51)",gray21:"rgb(54, 54, 54)",gray22:"rgb(56, 56, 56)",gray23:"rgb(59, 59, 59)",gray24:"rgb(61, 61, 61)",gray25:"rgb(64, 64, 64)",gray26:"rgb(66, 66, 66)",gray27:"rgb(69, 69, 69)",gray28:"rgb(71, 71, 71)",gray29:"rgb(74, 74, 74)",gray3:"rgb(8, 8, 8)",gray30:"rgb(77, 77, 77)",gray31:"rgb(79, 79, 79)",gray32:"rgb(82, 82, 82)",gray33:"rgb(84, 84, 84)",gray34:"rgb(87, 87, 87)",gray35:"rgb(89, 89, 89)",gray36:"rgb(92, 92, 92)",gray37:"rgb(94, 94, 94)",gray38:"rgb(97, 97, 97)",gray39:"rgb(99, 99, 99)",gray4:"rgb(10, 10, 10)",gray40:"rgb(102, 102, 102)",gray41:"rgb(105, 105, 105)",gray42:"rgb(107, 107, 107)",gray43:"rgb(110, 110, 110)",gray44:"rgb(112, 112, 112)",gray45:"rgb(115, 115, 115)",gray46:"rgb(117, 117, 117)",gray47:"rgb(120, 120, 120)",gray48:"rgb(122, 122, 122)",gray49:"rgb(125, 125, 125)",gray5:"rgb(13, 13, 13)",gray50:"rgb(127, 127, 127)",gray51:"rgb(130, 130, 130)",gray52:"rgb(133, 133, 133)",gray53:"rgb(135, 135, 135)",gray54:"rgb(138, 138, 138)",gray55:"rgb(140, 140, 140)",gray56:"rgb(143, 143, 143)",gray57:"rgb(145, 145, 145)",gray58:"rgb(148, 148, 148)",gray59:"rgb(150, 150, 150)",gray6:"rgb(15, 15, 15)",gray60:"rgb(153, 153, 153)",gray61:"rgb(156, 156, 156)",gray62:"rgb(158, 158, 158)",gray63:"rgb(161, 161, 161)",gray64:"rgb(163, 163, 163)",gray65:"rgb(166, 166, 166)",gray66:"rgb(168, 168, 168)",gray67:"rgb(171, 171, 171)",gray68:"rgb(173, 173, 173)",gray69:"rgb(176, 176, 176)",gray7:"rgb(18, 18, 18)",gray70:"rgb(179, 179, 179)",gray71:"rgb(181, 181, 181)",gray72:"rgb(184, 184, 184)",gray73:"rgb(186, 186, 186)",gray74:"rgb(189, 189, 189)",gray75:"rgb(191, 191, 191)",gray76:"rgb(194, 194, 194)",gray77:"rgb(196, 196, 196)",gray78:"rgb(199, 199, 199)",gray79:"rgb(201, 201, 201)",gray8:"rgb(20, 20, 20)",gray80:"rgb(204, 204, 204)",gray81:"rgb(207, 207, 207)",gray82:"rgb(209, 209, 209)",gray83:"rgb(212, 212, 212)",gray84:"rgb(214, 214, 214)",gray85:"rgb(217, 217, 217)",gray86:"rgb(219, 219, 219)",gray87:"rgb(222, 222, 222)",gray88:"rgb(224, 224, 224)",gray89:"rgb(227, 227, 227)",gray9:"rgb(23, 23, 23)",gray90:"rgb(229, 229, 229)",gray91:"rgb(232, 232, 232)",gray92:"rgb(235, 235, 235)",gray93:"rgb(237, 237, 237)",gray94:"rgb(240, 240, 240)",gray95:"rgb(242, 242, 242)",gray96:"rgb(245, 245, 245)",gray97:"rgb(247, 247, 247)",gray98:"rgb(250, 250, 250)",gray99:"rgb(252, 252, 252)",green:"rgb(0, 255, 0)",green1:"rgb(0, 255, 0)",green2:"rgb(0, 238, 0)",green3:"rgb(0, 205, 0)",green4:"rgb(0, 139, 0)",greenyellow:"rgb(173, 255, 47)",grey:"rgb(190, 190, 190)",grey0:"rgb(0, 0, 0)",grey1:"rgb(3, 3, 3)",grey10:"rgb(26, 26, 26)",grey100:"rgb(255, 255, 255)",grey11:"rgb(28, 28, 28)",grey12:"rgb(31, 31, 31)",grey13:"rgb(33, 33, 33)",grey14:"rgb(36, 36, 36)",grey15:"rgb(38, 38, 38)",grey16:"rgb(41, 41, 41)",grey17:"rgb(43, 43, 43)",grey18:"rgb(46, 46, 46)",grey19:"rgb(48, 48, 48)",grey2:"rgb(5, 5, 5)",grey20:"rgb(51, 51, 51)",grey21:"rgb(54, 54, 54)",grey22:"rgb(56, 56, 56)",grey23:"rgb(59, 59, 59)",grey24:"rgb(61, 61, 61)",grey25:"rgb(64, 64, 64)",grey26:"rgb(66, 66, 66)",grey27:"rgb(69, 69, 69)",grey28:"rgb(71, 71, 71)",grey29:"rgb(74, 74, 74)",grey3:"rgb(8, 8, 8)",grey30:"rgb(77, 77, 77)",grey31:"rgb(79, 79, 79)",grey32:"rgb(82, 82, 82)",grey33:"rgb(84, 84, 84)",grey34:"rgb(87, 87, 87)",grey35:"rgb(89, 89, 89)",grey36:"rgb(92, 92, 92)",grey37:"rgb(94, 94, 94)",grey38:"rgb(97, 97, 97)",grey39:"rgb(99, 99, 99)",grey4:"rgb(10, 10, 10)",grey40:"rgb(102, 102, 102)",grey41:"rgb(105, 105, 105)",grey42:"rgb(107, 107, 107)",grey43:"rgb(110, 110, 110)",grey44:"rgb(112, 112, 112)",grey45:"rgb(115, 115, 115)",grey46:"rgb(117, 117, 117)",grey47:"rgb(120, 120, 120)",grey48:"rgb(122, 122, 122)",grey49:"rgb(125, 125, 125)",grey5:"rgb(13, 13, 13)",grey50:"rgb(127, 127, 127)",grey51:"rgb(130, 130, 130)",grey52:"rgb(133, 133, 133)",grey53:"rgb(135, 135, 135)",grey54:"rgb(138, 138, 138)",grey55:"rgb(140, 140, 140)",grey56:"rgb(143, 143, 143)",grey57:"rgb(145, 145, 145)",grey58:"rgb(148, 148, 148)",grey59:"rgb(150, 150, 150)",grey6:"rgb(15, 15, 15)",grey60:"rgb(153, 153, 153)",grey61:"rgb(156, 156, 156)",grey62:"rgb(158, 158, 158)",grey63:"rgb(161, 161, 161)",grey64:"rgb(163, 163, 163)",grey65:"rgb(166, 166, 166)",grey66:"rgb(168, 168, 168)",grey67:"rgb(171, 171, 171)",grey68:"rgb(173, 173, 173)",grey69:"rgb(176, 176, 176)",grey7:"rgb(18, 18, 18)",grey70:"rgb(179, 179, 179)",grey71:"rgb(181, 181, 181)",grey72:"rgb(184, 184, 184)",grey73:"rgb(186, 186, 186)",grey74:"rgb(189, 189, 189)",grey75:"rgb(191, 191, 191)",grey76:"rgb(194, 194, 194)",grey77:"rgb(196, 196, 196)",grey78:"rgb(199, 199, 199)",grey79:"rgb(201, 201, 201)",grey8:"rgb(20, 20, 20)",grey80:"rgb(204, 204, 204)",grey81:"rgb(207, 207, 207)",grey82:"rgb(209, 209, 209)",grey83:"rgb(212, 212, 212)",grey84:"rgb(214, 214, 214)",grey85:"rgb(217, 217, 217)",grey86:"rgb(219, 219, 219)",grey87:"rgb(222, 222, 222)",grey88:"rgb(224, 224, 224)",grey89:"rgb(227, 227, 227)",grey9:"rgb(23, 23, 23)",grey90:"rgb(229, 229, 229)",grey91:"rgb(232, 232, 232)",grey92:"rgb(235, 235, 235)",grey93:"rgb(237, 237, 237)",grey94:"rgb(240, 240, 240)",grey95:"rgb(242, 242, 242)",grey96:"rgb(245, 245, 245)",grey97:"rgb(247, 247, 247)",grey98:"rgb(250, 250, 250)",grey99:"rgb(252, 252, 252)",honeydew:"rgb(240, 255, 240)",honeydew1:"rgb(240, 255, 240)",honeydew2:"rgb(224, 238, 224)",honeydew3:"rgb(193, 205, 193)",honeydew4:"rgb(131, 139, 131)",hotpink:"rgb(255, 105, 180)",hotpink1:"rgb(255, 110, 180)",hotpink2:"rgb(238, 106, 167)",hotpink3:"rgb(205, 96, 144)",hotpink4:"rgb(139, 58, 98)",indianred:"rgb(205, 92, 92)",indianred1:"rgb(255, 106, 106)",indianred2:"rgb(238, 99, 99)",indianred3:"rgb(205, 85, 85)",indianred4:"rgb(139, 58, 58)",ivory:"rgb(255, 255, 240)",ivory1:"rgb(255, 255, 240)",ivory2:"rgb(238, 238, 224)",ivory3:"rgb(205, 205, 193)",ivory4:"rgb(139, 139, 131)",khaki:"rgb(240, 230, 140)",khaki1:"rgb(255, 246, 143)",khaki2:"rgb(238, 230, 133)",khaki3:"rgb(205, 198, 115)",khaki4:"rgb(139, 134, 78)",lavender:"rgb(230, 230, 250)",lavenderblush:"rgb(255, 240, 245)",lavenderblush1:"rgb(255, 240, 245)",lavenderblush2:"rgb(238, 224, 229)",lavenderblush3:"rgb(205, 193, 197)",lavenderblush4:"rgb(139, 131, 134)",lawngreen:"rgb(124, 252, 0)",lemonchiffon:"rgb(255, 250, 205)",lemonchiffon1:"rgb(255, 250, 205)",lemonchiffon2:"rgb(238, 233, 191)",lemonchiffon3:"rgb(205, 201, 165)",lemonchiffon4:"rgb(139, 137, 112)",lightblue:"rgb(173, 216, 230)",lightblue1:"rgb(191, 239, 255)",lightblue2:"rgb(178, 223, 238)",lightblue3:"rgb(154, 192, 205)",lightblue4:"rgb(104, 131, 139)",lightcoral:"rgb(240, 128, 128)",lightcyan:"rgb(224, 255, 255)",lightcyan1:"rgb(224, 255, 255)",lightcyan2:"rgb(209, 238, 238)",lightcyan3:"rgb(180, 205, 205)",lightcyan4:"rgb(122, 139, 139)",lightgoldenrod:"rgb(238, 221, 130)",lightgoldenrod1:"rgb(255, 236, 139)",lightgoldenrod2:"rgb(238, 220, 130)",lightgoldenrod3:"rgb(205, 190, 112)",lightgoldenrod4:"rgb(139, 129, 76)",lightgoldenrodyellow:"rgb(250, 250, 210)",lightgray:"rgb(211, 211, 211)",lightgreen:"rgb(144, 238, 144)",lightgrey:"rgb(211, 211, 211)",lightpink:"rgb(255, 182, 193)",lightpink1:"rgb(255, 174, 185)",lightpink2:"rgb(238, 162, 173)",lightpink3:"rgb(205, 140, 149)",lightpink4:"rgb(139, 95, 101)",lightsalmon:"rgb(255, 160, 122)",lightsalmon1:"rgb(255, 160, 122)",lightsalmon2:"rgb(238, 149, 114)",lightsalmon3:"rgb(205, 129, 98)",lightsalmon4:"rgb(139, 87, 66)",lightseagreen:"rgb(32, 178, 170)",lightskyblue:"rgb(135, 206, 250)",lightskyblue1:"rgb(176, 226, 255)",lightskyblue2:"rgb(164, 211, 238)",lightskyblue3:"rgb(141, 182, 205)",lightskyblue4:"rgb(96, 123, 139)",lightslateblue:"rgb(132, 112, 255)",lightslategray:"rgb(119, 136, 153)",lightslategrey:"rgb(119, 136, 153)",lightsteelblue:"rgb(176, 196, 222)",lightsteelblue1:"rgb(202, 225, 255)",lightsteelblue2:"rgb(188, 210, 238)",lightsteelblue3:"rgb(162, 181, 205)",lightsteelblue4:"rgb(110, 123, 139)",lightyellow:"rgb(255, 255, 224)",lightyellow1:"rgb(255, 255, 224)",lightyellow2:"rgb(238, 238, 209)",lightyellow3:"rgb(205, 205, 180)",lightyellow4:"rgb(139, 139, 122)",limegreen:"rgb(50, 205, 50)",linen:"rgb(250, 240, 230)",magenta:"rgb(255, 0, 255)",magenta1:"rgb(255, 0, 255)",magenta2:"rgb(238, 0, 238)",magenta3:"rgb(205, 0, 205)",magenta4:"rgb(139, 0, 139)",maroon:"rgb(176, 48, 96)",maroon1:"rgb(255, 52, 179)",maroon2:"rgb(238, 48, 167)",maroon3:"rgb(205, 41, 144)",maroon4:"rgb(139, 28, 98)",mediumaquamarine:"rgb(102, 205, 170)",mediumblue:"rgb(0, 0, 205)",mediumorchid:"rgb(186, 85, 211)",mediumorchid1:"rgb(224, 102, 255)",mediumorchid2:"rgb(209, 95, 238)",mediumorchid3:"rgb(180, 82, 205)",mediumorchid4:"rgb(122, 55, 139)",mediumpurple:"rgb(147, 112, 219)",mediumpurple1:"rgb(171, 130, 255)",mediumpurple2:"rgb(159, 121, 238)",mediumpurple3:"rgb(137, 104, 205)",mediumpurple4:"rgb(93, 71, 139)",mediumseagreen:"rgb(60, 179, 113)",mediumslateblue:"rgb(123, 104, 238)",mediumspringgreen:"rgb(0, 250, 154)",mediumturquoise:"rgb(72, 209, 204)",mediumvioletred:"rgb(199, 21, 133)",midnightblue:"rgb(25, 25, 112)",mintcream:"rgb(245, 255, 250)",mistyrose:"rgb(255, 228, 225)",mistyrose1:"rgb(255, 228, 225)",mistyrose2:"rgb(238, 213, 210)",mistyrose3:"rgb(205, 183, 181)",mistyrose4:"rgb(139, 125, 123)",moccasin:"rgb(255, 228, 181)",navajowhite:"rgb(255, 222, 173)",navajowhite1:"rgb(255, 222, 173)",navajowhite2:"rgb(238, 207, 161)",navajowhite3:"rgb(205, 179, 139)",navajowhite4:"rgb(139, 121, 94)",navy:"rgb(0, 0, 128)",navyblue:"rgb(0, 0, 128)",oldlace:"rgb(253, 245, 230)",olivedrab:"rgb(107, 142, 35)",olivedrab1:"rgb(192, 255, 62)",olivedrab2:"rgb(179, 238, 58)",olivedrab3:"rgb(154, 205, 50)",olivedrab4:"rgb(105, 139, 34)",orange:"rgb(255, 165, 0)",orange1:"rgb(255, 165, 0)",orange2:"rgb(238, 154, 0)",orange3:"rgb(205, 133, 0)",orange4:"rgb(139, 90, 0)",orangered:"rgb(255, 69, 0)",orangered1:"rgb(255, 69, 0)",orangered2:"rgb(238, 64, 0)",orangered3:"rgb(205, 55, 0)",orangered4:"rgb(139, 37, 0)",orchid:"rgb(218, 112, 214)",orchid1:"rgb(255, 131, 250)",orchid2:"rgb(238, 122, 233)",orchid3:"rgb(205, 105, 201)",orchid4:"rgb(139, 71, 137)",palegoldenrod:"rgb(238, 232, 170)",palegreen:"rgb(152, 251, 152)",palegreen1:"rgb(154, 255, 154)",palegreen2:"rgb(144, 238, 144)",palegreen3:"rgb(124, 205, 124)",palegreen4:"rgb(84, 139, 84)",paleturquoise:"rgb(175, 238, 238)",paleturquoise1:"rgb(187, 255, 255)",paleturquoise2:"rgb(174, 238, 238)",paleturquoise3:"rgb(150, 205, 205)",paleturquoise4:"rgb(102, 139, 139)",palevioletred:"rgb(219, 112, 147)",palevioletred1:"rgb(255, 130, 171)",palevioletred2:"rgb(238, 121, 159)",palevioletred3:"rgb(205, 104, 137)",palevioletred4:"rgb(139, 71, 93)",papayawhip:"rgb(255, 239, 213)",peachpuff:"rgb(255, 218, 185)",peachpuff1:"rgb(255, 218, 185)",peachpuff2:"rgb(238, 203, 173)",peachpuff3:"rgb(205, 175, 149)",peachpuff4:"rgb(139, 119, 101)",peru:"rgb(205, 133, 63)",pink:"rgb(255, 192, 203)",pink1:"rgb(255, 181, 197)",pink2:"rgb(238, 169, 184)",pink3:"rgb(205, 145, 158)",pink4:"rgb(139, 99, 108)",plum:"rgb(221, 160, 221)",plum1:"rgb(255, 187, 255)",plum2:"rgb(238, 174, 238)",plum3:"rgb(205, 150, 205)",plum4:"rgb(139, 102, 139)",powderblue:"rgb(176, 224, 230)",purple:"rgb(160, 32, 240)",purple1:"rgb(155, 48, 255)",purple2:"rgb(145, 44, 238)",purple3:"rgb(125, 38, 205)",purple4:"rgb(85, 26, 139)",red:"rgb(255, 0, 0)",red1:"rgb(255, 0, 0)",red2:"rgb(238, 0, 0)",red3:"rgb(205, 0, 0)",red4:"rgb(139, 0, 0)",rosybrown:"rgb(188, 143, 143)",rosybrown1:"rgb(255, 193, 193)",rosybrown2:"rgb(238, 180, 180)",rosybrown3:"rgb(205, 155, 155)",rosybrown4:"rgb(139, 105, 105)",royalblue:"rgb(65, 105, 225)",royalblue1:"rgb(72, 118, 255)",royalblue2:"rgb(67, 110, 238)",royalblue3:"rgb(58, 95, 205)",royalblue4:"rgb(39, 64, 139)",saddlebrown:"rgb(139, 69, 19)",salmon:"rgb(250, 128, 114)",salmon1:"rgb(255, 140, 105)",salmon2:"rgb(238, 130, 98)",salmon3:"rgb(205, 112, 84)",salmon4:"rgb(139, 76, 57)",sandybrown:"rgb(244, 164, 96)",seagreen:"rgb(46, 139, 87)",seagreen1:"rgb(84, 255, 159)",seagreen2:"rgb(78, 238, 148)",seagreen3:"rgb(67, 205, 128)",seagreen4:"rgb(46, 139, 87)",seashell:"rgb(255, 245, 238)",seashell1:"rgb(255, 245, 238)",seashell2:"rgb(238, 229, 222)",seashell3:"rgb(205, 197, 191)",seashell4:"rgb(139, 134, 130)",sienna:"rgb(160, 82, 45)",sienna1:"rgb(255, 130, 71)",sienna2:"rgb(238, 121, 66)",sienna3:"rgb(205, 104, 57)",sienna4:"rgb(139, 71, 38)",skyblue:"rgb(135, 206, 235)",skyblue1:"rgb(135, 206, 255)",skyblue2:"rgb(126, 192, 238)",skyblue3:"rgb(108, 166, 205)",skyblue4:"rgb(74, 112, 139)",slateblue:"rgb(106, 90, 205)",slateblue1:"rgb(131, 111, 255)",slateblue2:"rgb(122, 103, 238)",slateblue3:"rgb(105, 89, 205)",slateblue4:"rgb(71, 60, 139)",slategray:"rgb(112, 128, 144)",slategray1:"rgb(198, 226, 255)",slategray2:"rgb(185, 211, 238)",slategray3:"rgb(159, 182, 205)",slategray4:"rgb(108, 123, 139)",slategrey:"rgb(112, 128, 144)",snow:"rgb(255, 250, 250)",snow1:"rgb(255, 250, 250)",snow2:"rgb(238, 233, 233)",snow3:"rgb(205, 201, 201)",snow4:"rgb(139, 137, 137)",springgreen:"rgb(0, 255, 127)",springgreen1:"rgb(0, 255, 127)",springgreen2:"rgb(0, 238, 118)",springgreen3:"rgb(0, 205, 102)",springgreen4:"rgb(0, 139, 69)",steelblue:"rgb(70, 130, 180)",steelblue1:"rgb(99, 184, 255)",steelblue2:"rgb(92, 172, 238)",steelblue3:"rgb(79, 148, 205)",steelblue4:"rgb(54, 100, 139)",tan:"rgb(210, 180, 140)",tan1:"rgb(255, 165, 79)",tan2:"rgb(238, 154, 73)",tan3:"rgb(205, 133, 63)",tan4:"rgb(139, 90, 43)",thistle:"rgb(216, 191, 216)",thistle1:"rgb(255, 225, 255)",thistle2:"rgb(238, 210, 238)",thistle3:"rgb(205, 181, 205)",thistle4:"rgb(139, 123, 139)",tomato:"rgb(255, 99, 71)",tomato1:"rgb(255, 99, 71)",tomato2:"rgb(238, 92, 66)",tomato3:"rgb(205, 79, 57)",tomato4:"rgb(139, 54, 38)",turquoise:"rgb(64, 224, 208)",turquoise1:"rgb(0, 245, 255)",turquoise2:"rgb(0, 229, 238)",turquoise3:"rgb(0, 197, 205)",turquoise4:"rgb(0, 134, 139)",violet:"rgb(238, 130, 238)",violetred:"rgb(208, 32, 144)",violetred1:"rgb(255, 62, 150)",violetred2:"rgb(238, 58, 140)",violetred3:"rgb(205, 50, 120)",violetred4:"rgb(139, 34, 82)",wheat:"rgb(245, 222, 179)",wheat1:"rgb(255, 231, 186)",wheat2:"rgb(238, 216, 174)",wheat3:"rgb(205, 186, 150)",wheat4:"rgb(139, 126, 102)",white:"rgb(255, 255, 255)",whitesmoke:"rgb(245, 245, 245)",yellow:"rgb(255, 255, 0)",yellow1:"rgb(255, 255, 0)",yellow2:"rgb(238, 238, 0)",yellow3:"rgb(205, 205, 0)",yellow4:"rgb(139, 139, 0)",yellowgreen:"rgb(154, 205, 50)"},lib.f={},lib.f.replaceVars=function(e,t){return e.replace(/%([a-z]*)\(([^\)]+)\)/gi,function(e,r,o){if("undefined"==typeof t[o])throw"Unknown variable: "+o;var i=t[o];if(r in lib.f.replaceVars.functions)i=lib.f.replaceVars.functions[r](i);else if(r)throw"Unknown escape function: "+r;return i})},lib.f.replaceVars.functions={encodeURI:encodeURI,encodeURIComponent:encodeURIComponent,escapeHTML:function(e){var t={"<":"&lt;",">":"&gt;","&":"&amp;",'"':"&quot;","'":"&#39;"};return e.replace(/[<>&\"\']/g,function(e){return t[e]})}},lib.f.getAcceptLanguages=function(e){lib.f.getAcceptLanguages.chromeSupported()?chrome.i18n.getAcceptLanguages(e):setTimeout(function(){e([navigator.language.replace(/-/g,"_")])},0)},lib.f.getAcceptLanguages.chromeSupported=function(){return window.chrome&&chrome.i18n},lib.f.parseQuery=function(e){"?"==e.substr(0,1)&&(e=e.substr(1));for(var t={},r=e.split("&"),o=0;o<r.length;o++){var i=r[o].split("=");t[decodeURIComponent(i[0])]=decodeURIComponent(i[1])}return t},lib.f.getURL=function(e){return lib.f.getURL.chromeSupported()?chrome.runtime.getURL(e):e},lib.f.getURL.chromeSupported=function(){return window.chrome&&chrome.runtime&&chrome.runtime.getURL},lib.f.clamp=function(e,t,r){return t>e?t:e>r?r:e},lib.f.lpad=function(e,t,r){for(e=String(e),r=r||" ";e.length<t;)e=r+e;return e},lib.f.zpad=function(e,t){return lib.f.lpad(e,t,"0")},lib.f.getWhitespace=function(e){if(0>=e)return"";var t=this.getWhitespace;for(t.whitespace||(t.whitespace="          ");e>t.whitespace.length;)t.whitespace+=t.whitespace;return t.whitespace.substr(0,e)},lib.f.alarm=function(e,t){var r=t||5e3,o=lib.f.getStack(1);return function(){var t=setTimeout(function(){var i="string"==typeof e?i:e.name;i=i?": "+i:"",console.warn("lib.f.alarm: timeout expired: "+r/1e3+"s"+i),console.log(o),t=null},r),i=function(e){return function(){return t&&(clearTimeout(t),t=null),e.apply(null,arguments)}};return"string"==typeof e?i:i(e)}()},lib.f.getStack=function(e){var t,r=e?e+2:2;try{throw new Error}catch(o){t=o.stack.split("\n")}for(var i={},s=r;s<t.length;s++)i[s-r]=t[s].replace(/^\s*at\s+/,"");return i},lib.f.smartFloorDivide=function(e,t){var r=e/t,o=Math.ceil(r);return 1e-4>o-r?o:Math.floor(r)},lib.MessageManager=function(e){this.languages_=e.map(function(e){return e.replace(/-/g,"_")}),-1==this.languages_.indexOf("en")&&this.languages_.unshift("en"),this.messages={}},lib.MessageManager.prototype.addMessages=function(e){for(var t in e){var r=e[t];r.placeholders?this.messages[t]=r.message.replace(/\$([a-z][^\s\$]+)\$/gi,function(r,o){return e[t].placeholders[o.toLowerCase()].content}):this.messages[t]=r.message}},lib.MessageManager.prototype.findAndLoadMessages=function(e,t){function r(e){e?i=o.shift():s=o.shift(),o.length?n():t(i,s)}var o=this.languages_.concat(),i=[],s=[],n=function(){this.loadMessages(this.replaceReferences(e,o),r.bind(this,!0),r.bind(this,!1))}.bind(this);n()},lib.MessageManager.prototype.loadMessages=function(e,t,r){var o=new XMLHttpRequest;o.onloadend=function(){return 200!=o.status?void(r&&r(o.status)):(this.addMessages(JSON.parse(o.responseText)),void t())}.bind(this),o.open("GET",e),o.send()},lib.MessageManager.replaceReferences=function(e,t){return e.replace(/\$(\d+)/g,function(e,r){return t[r-1]})},lib.MessageManager.prototype.replaceReferences=lib.MessageManager.replaceReferences,lib.MessageManager.prototype.get=function(e,t,r){var o;if(e in this.messages)o=this.messages[e];else if(window.chrome.i18n&&(o=chrome.i18n.getMessage(e)),!o)return console.warn("Unknown message: "+e),"undefined"==typeof r?e:r;return t?(t instanceof Array||(t=[t]),this.replaceReferences(o,t)):o},lib.MessageManager.prototype.processI18nAttributes=function(e){function t(e){return e.replace(/-/g,"_").toUpperCase()}for(var r=e.querySelectorAll("[i18n]"),o=0;o<r.length;o++){var i=r[o],s=i.getAttribute("i18n");if(s){try{s=JSON.parse(s)}catch(n){throw console.error("Can't parse "+i.tagName+"#"+i.id+": "+s),n}for(var a in s){var l=s[a];"$"==l.substr(0,1)&&(l=t(i.getAttribute(l.substr(1))+"_"+a));var h=this.get(l);"_"==a?i.textContent=h:i.setAttribute(a,h)}}}},lib.PreferenceManager=function(e,t){this.storage=e,this.storageObserver_=this.onStorageChange_.bind(this),this.isActive_=!1,this.activate(),this.trace=!1;var r=t||"/";"/"!=r.substr(r.length-1)&&(r+="/"),this.prefix=r,this.prefRecords_={},this.globalObservers_=[],this.childFactories_={},this.childLists_={}},lib.PreferenceManager.prototype.DEFAULT_VALUE=new String("DEFAULT"),lib.PreferenceManager.Record=function(e,t){this.name=e,this.defaultValue=t,this.currentValue=this.DEFAULT_VALUE,this.observers=[]},lib.PreferenceManager.Record.prototype.DEFAULT_VALUE=lib.PreferenceManager.prototype.DEFAULT_VALUE,lib.PreferenceManager.Record.prototype.addObserver=function(e){this.observers.push(e)},lib.PreferenceManager.Record.prototype.removeObserver=function(e){var t=this.observers.indexOf(e);t>=0&&this.observers.splice(t,1)},lib.PreferenceManager.Record.prototype.get=function(){return this.currentValue===this.DEFAULT_VALUE?/^(string|number)$/.test(typeof this.defaultValue)?this.defaultValue:"object"==typeof this.defaultValue?JSON.parse(JSON.stringify(this.defaultValue)):this.defaultValue:this.currentValue},lib.PreferenceManager.prototype.deactivate=function(){if(!this.isActive_)throw new Error("Not activated");this.isActive_=!1,this.storage.removeObserver(this.storageObserver_)},lib.PreferenceManager.prototype.activate=function(){if(this.isActive_)throw new Error("Already activated");this.isActive_=!0,this.storage.addObserver(this.storageObserver_)},lib.PreferenceManager.prototype.readStorage=function(e){function t(){0==--r&&e&&e()}var r=0,o=Object.keys(this.prefRecords_).map(function(e){return this.prefix+e}.bind(this));this.trace&&console.log("Preferences read: "+this.prefix),
-this.storage.getItems(o,function(o){var i=this.prefix.length;for(var s in o){var n=o[s],a=s.substr(i),l=a in this.childLists_&&JSON.stringify(n)!=JSON.stringify(this.prefRecords_[a].currentValue);this.prefRecords_[a].currentValue=n,l&&(r++,this.syncChildList(a,t))}0==r&&e&&setTimeout(e)}.bind(this))},lib.PreferenceManager.prototype.definePreference=function(e,t,r){var o=this.prefRecords_[e];o?this.changeDefault(e,t):o=this.prefRecords_[e]=new lib.PreferenceManager.Record(e,t),r&&o.addObserver(r)},lib.PreferenceManager.prototype.definePreferences=function(e){for(var t=0;t<e.length;t++)this.definePreference(e[t][0],e[t][1],e[t][2])},lib.PreferenceManager.prototype.defineChildren=function(e,t){this.definePreference(e,[],this.onChildListChange_.bind(this,e)),this.childFactories_[e]=t,this.childLists_[e]={}},lib.PreferenceManager.prototype.addObservers=function(e,t){if(e&&"function"!=typeof e)throw new Error("Invalid param: globals");if(e&&this.globalObservers_.push(e),t)for(var r in t){if(!(r in this.prefRecords_))throw new Error("Unknown preference: "+r);this.prefRecords_[r].addObserver(t[r])}},lib.PreferenceManager.prototype.notifyAll=function(){for(var e in this.prefRecords_)this.notifyChange_(e)},lib.PreferenceManager.prototype.notifyChange_=function(e){var t=this.prefRecords_[e];if(!t)throw new Error("Unknown preference: "+e);for(var r=t.get(),o=0;o<this.globalObservers_.length;o++)this.globalObservers_[o](e,r);for(var o=0;o<t.observers.length;o++)t.observers[o](r,e,this)},lib.PreferenceManager.prototype.createChild=function(e,t,r){var o,i=this.get(e);if(r){if(o=r,-1!=i.indexOf(o))throw new Error("Duplicate child: "+e+": "+o)}else for(;!o||-1!=i.indexOf(o);)o=Math.floor(65535*Math.random()+1).toString(16),o=lib.f.zpad(o,4),t&&(o=t+":"+o);var s=this.childFactories_[e](this,o);return s.trace=this.trace,s.resetAll(),this.childLists_[e][o]=s,i.push(o),this.set(e,i),s},lib.PreferenceManager.prototype.removeChild=function(e,t){var r=this.getChild(e,t);r.resetAll();var o=this.get(e),i=o.indexOf(t);-1!=i&&(o.splice(i,1),this.set(e,o)),delete this.childLists_[e][t]},lib.PreferenceManager.prototype.getChild=function(e,t,r){if(!(e in this.childLists_))throw new Error("Unknown child list: "+e);var o=this.childLists_[e];if(!(t in o)){if("undefined"==typeof r)throw new Error('Unknown "'+e+'" child: '+t);return r}return o[t]},lib.PreferenceManager.diffChildLists=function(e,t){for(var r={added:{},removed:{},common:{}},o=0;o<e.length;o++)-1!=t.indexOf(e[o])?r.common[e[o]]=!0:r.added[e[o]]=!0;for(var o=0;o<t.length;o++)t[o]in r.added||t[o]in r.common||(r.removed[t[o]]=!0);return r},lib.PreferenceManager.prototype.syncChildList=function(e,t){function r(){0==--o&&t&&t()}for(var o=0,i=this.get(e),s=Object.keys(this.childLists_[e]),n=(lib.PreferenceManager.diffChildLists(i,s),0);n<i.length;n++){var a=i[n],l=s.indexOf(a);if(l>=0&&s.splice(l,1),!this.childLists_[e][a]){var h=this.childFactories_[e](this,a);if(!h){console.warn("Unable to restore child: "+e+": "+a);continue}h.trace=this.trace,this.childLists_[e][a]=h,o++,h.readStorage(r)}}for(var n=0;n<s.length;n++)delete this.childLists_[e][s[n]];!o&&t&&setTimeout(t)},lib.PreferenceManager.prototype.reset=function(e){var t=this.prefRecords_[e];if(!t)throw new Error("Unknown preference: "+e);this.storage.removeItem(this.prefix+e),t.currentValue!==this.DEFAULT_VALUE&&(t.currentValue=this.DEFAULT_VALUE,this.notifyChange_(e))},lib.PreferenceManager.prototype.resetAll=function(){var e=[];for(var t in this.childLists_){var r=this.childLists_[t];for(var o in r)r[o].resetAll()}for(var i in this.prefRecords_)this.prefRecords_[i].currentValue!==this.DEFAULT_VALUE&&(this.prefRecords_[i].currentValue=this.DEFAULT_VALUE,e.push(i));var s=Object.keys(this.prefRecords_).map(function(e){return this.prefix+e}.bind(this));this.storage.removeItems(s),e.forEach(this.notifyChange_.bind(this))},lib.PreferenceManager.prototype.diff=function(e,t){return typeof e==typeof t&&/^(undefined|boolean|number|string)$/.test(typeof e)?e!==t:!0},lib.PreferenceManager.prototype.changeDefault=function(e,t){var r=this.prefRecords_[e];if(!r)throw new Error("Unknown preference: "+e);if(this.diff(r.defaultValue,t)){if(r.currentValue!==this.DEFAULT_VALUE)return void(r.defaultValue=t);r.defaultValue=t,this.notifyChange_(e)}},lib.PreferenceManager.prototype.changeDefaults=function(e){for(var t in e)this.changeDefault(t,e[t])},lib.PreferenceManager.prototype.set=function(e,t){var r=this.prefRecords_[e];if(!r)throw new Error("Unknown preference: "+e);var o=r.get();this.diff(o,t)&&(this.diff(r.defaultValue,t)?(r.currentValue=t,this.storage.setItem(this.prefix+e,t)):(r.currentValue=this.DEFAULT_VALUE,this.storage.removeItem(this.prefix+e)),setTimeout(this.notifyChange_.bind(this,e),0))},lib.PreferenceManager.prototype.get=function(e){var t=this.prefRecords_[e];if(!t)throw new Error("Unknown preference: "+e);return t.get()},lib.PreferenceManager.prototype.exportAsJson=function(){var e={};for(var t in this.prefRecords_)if(t in this.childLists_){e[t]=[];for(var r=this.get(t),o=0;o<r.length;o++){var i=r[o];e[t].push({id:i,json:this.getChild(t,i).exportAsJson()})}}else{var s=this.prefRecords_[t];s.currentValue!=this.DEFAULT_VALUE&&(e[t]=s.currentValue)}return e},lib.PreferenceManager.prototype.importFromJson=function(e){for(var t in e)if(t in this.childLists_)for(var r=e[t],o=0;o<r.length;o++){var i=r[o].id,s=this.childLists_[t][i];s||(s=this.createChild(t,null,i)),s.importFromJson(r[o].json)}else this.set(t,e[t])},lib.PreferenceManager.prototype.onChildListChange_=function(e){this.syncChildList(e)},lib.PreferenceManager.prototype.onStorageChange_=function(e){for(var t in e)if(!this.prefix||0==t.lastIndexOf(this.prefix,0)){var r=t.substr(this.prefix.length);if(r in this.prefRecords_){var o=this.prefRecords_[r],i=e[t].newValue,s=o.currentValue;s===o.DEFAULT_VALUE&&(s=void 0),this.diff(s,i)&&("undefined"==typeof i?o.currentValue=o.DEFAULT_VALUE:o.currentValue=i,this.notifyChange_(r))}}},lib.resource={resources_:{}},lib.resource.add=function(e,t,r){lib.resource.resources_[e]={type:t,name:e,data:r}},lib.resource.get=function(e,t){if(!(e in lib.resource.resources_)){if("undefined"==typeof t)throw"Unknown resource: "+e;return t}return lib.resource.resources_[e]},lib.resource.getData=function(e,t){if(!(e in lib.resource.resources_)){if("undefined"==typeof t)throw"Unknown resource: "+e;return t}return lib.resource.resources_[e].data},lib.resource.getDataUrl=function(e,t){var r=lib.resource.get(e,t);return"data:"+r.type+","+r.data},lib.Storage=new Object,lib.Storage.Chrome=function(e){this.storage_=e,this.observers_=[],chrome.storage.onChanged.addListener(this.onChanged_.bind(this))},lib.Storage.Chrome.prototype.onChanged_=function(e,t){if(chrome.storage[t]==this.storage_)for(var r=0;r<this.observers_.length;r++)this.observers_[r](e)},lib.Storage.Chrome.prototype.addObserver=function(e){this.observers_.push(e)},lib.Storage.Chrome.prototype.removeObserver=function(e){var t=this.observers_.indexOf(e);-1!=t&&this.observers_.splice(t,1)},lib.Storage.Chrome.prototype.clear=function(e){this.storage_.clear(),e&&setTimeout(e,0)},lib.Storage.Chrome.prototype.getItem=function(e,t){this.storage_.get(e,t)},lib.Storage.Chrome.prototype.getItems=function(e,t){this.storage_.get(e,t)},lib.Storage.Chrome.prototype.setItem=function(e,t,r){var o={};o[e]=t,this.storage_.set(o,r)},lib.Storage.Chrome.prototype.setItems=function(e,t){this.storage_.set(e,t)},lib.Storage.Chrome.prototype.removeItem=function(e,t){this.storage_.remove(e,t)},lib.Storage.Chrome.prototype.removeItems=function(e,t){this.storage_.remove(e,t)},lib.Storage.Local=function(){this.observers_=[],this.storage_=window.localStorage,window.addEventListener("storage",this.onStorage_.bind(this))},lib.Storage.Local.prototype.onStorage_=function(e){if(e.storageArea==this.storage_){var t=e.oldValue?JSON.parse(e.oldValue):"",r=e.newValue?JSON.parse(e.newValue):"",o={};o[e.key]={oldValue:t,newValue:r};for(var i=0;i<this.observers_.length;i++)this.observers_[i](o)}},lib.Storage.Local.prototype.addObserver=function(e){this.observers_.push(e)},lib.Storage.Local.prototype.removeObserver=function(e){var t=this.observers_.indexOf(e);-1!=t&&this.observers_.splice(t,1)},lib.Storage.Local.prototype.clear=function(e){this.storage_.clear(),e&&setTimeout(e,0)},lib.Storage.Local.prototype.getItem=function(e,t){var r=this.storage_.getItem(e);if("string"==typeof r)try{r=JSON.parse(r)}catch(o){}setTimeout(t.bind(null,r),0)},lib.Storage.Local.prototype.getItems=function(e,t){for(var r={},o=e.length-1;o>=0;o--){var i=e[o],s=this.storage_.getItem(i);if("string"==typeof s)try{r[i]=JSON.parse(s)}catch(n){r[i]=s}else e.splice(o,1)}setTimeout(t.bind(null,r),0)},lib.Storage.Local.prototype.setItem=function(e,t,r){this.storage_.setItem(e,JSON.stringify(t)),r&&setTimeout(r,0)},lib.Storage.Local.prototype.setItems=function(e,t){for(var r in e)this.storage_.setItem(r,JSON.stringify(e[r]));t&&setTimeout(t,0)},lib.Storage.Local.prototype.removeItem=function(e,t){this.storage_.removeItem(e),t&&setTimeout(t,0)},lib.Storage.Local.prototype.removeItems=function(e,t){for(var r=0;r<e.length;r++)this.storage_.removeItem(e[r]);t&&setTimeout(t,0)},lib.Storage.Memory=function(){this.observers_=[],this.storage_={}},lib.Storage.Memory.prototype.addObserver=function(e){this.observers_.push(e)},lib.Storage.Memory.prototype.removeObserver=function(e){var t=this.observers_.indexOf(e);-1!=t&&this.observers_.splice(t,1)},lib.Storage.Memory.prototype.clear=function(e){var t={};for(var r in this.storage_)t[r]={oldValue:this.storage_[r],newValue:void 0};this.storage_={},setTimeout(function(){for(var e=0;e<this.observers_.length;e++)this.observers_[e](t)}.bind(this),0),e&&setTimeout(e,0)},lib.Storage.Memory.prototype.getItem=function(e,t){var r=this.storage_[e];if("string"==typeof r)try{r=JSON.parse(r)}catch(o){}setTimeout(t.bind(null,r),0)},lib.Storage.Memory.prototype.getItems=function(e,t){for(var r={},o=e.length-1;o>=0;o--){var i=e[o],s=this.storage_[i];if("string"==typeof s)try{r[i]=JSON.parse(s)}catch(n){r[i]=s}else e.splice(o,1)}setTimeout(t.bind(null,r),0)},lib.Storage.Memory.prototype.setItem=function(e,t,r){var o=this.storage_[e];this.storage_[e]=JSON.stringify(t);var i={};i[e]={oldValue:o,newValue:t},setTimeout(function(){for(var e=0;e<this.observers_.length;e++)this.observers_[e](i)}.bind(this),0),r&&setTimeout(r,0)},lib.Storage.Memory.prototype.setItems=function(e,t){var r={};for(var o in e)r[o]={oldValue:this.storage_[o],newValue:e[o]},this.storage_[o]=JSON.stringify(e[o]);setTimeout(function(){for(var e=0;e<this.observers_.length;e++)this.observers_[e](r)}.bind(this)),t&&setTimeout(t,0)},lib.Storage.Memory.prototype.removeItem=function(e,t){delete this.storage_[e],t&&setTimeout(t,0)},lib.Storage.Memory.prototype.removeItems=function(e,t){for(var r=0;r<e.length;r++)delete this.storage_[e[r]];t&&setTimeout(t,0)},lib.TestManager=function(e){this.log=e||new lib.TestManager.Log},lib.TestManager.prototype.createTestRun=function(e){return new lib.TestManager.TestRun(this,e)},lib.TestManager.prototype.onTestRunComplete=function(e){},lib.TestManager.prototype.testPreamble=function(e,t){},lib.TestManager.prototype.testPostamble=function(e,t){},lib.TestManager.Log=function(e){this.save=!1,this.data="",this.logFunction_=e||function(e){this.save&&(this.data+=e+"\n"),console.log(e)},this.pending_="",this.prefix_="",this.prefixStack_=[]},lib.TestManager.Log.prototype.pushPrefix=function(e){this.prefixStack_.push(e),this.prefix_=this.prefixStack_.join("")},lib.TestManager.Log.prototype.popPrefix=function(){this.prefixStack_.pop(),this.prefix_=this.prefixStack_.join("")},lib.TestManager.Log.prototype.print=function(e){this.pending_?this.pending_+=e:this.pending_=this.prefix_+e},lib.TestManager.Log.prototype.println=function(e){this.pending_&&this.flush(),this.logFunction_(this.prefix_+e)},lib.TestManager.Log.prototype.flush=function(){this.pending_&&(this.logFunction_(this.pending_),this.pending_="")},lib.TestManager.Suite=function(e){function t(t,r){this.testManager_=t,this.suiteName=e,this.setup(r)}return t.suiteName=e,t.addTest=lib.TestManager.Suite.addTest,t.disableTest=lib.TestManager.Suite.disableTest,t.getTest=lib.TestManager.Suite.getTest,t.getTestList=lib.TestManager.Suite.getTestList,t.testList_=[],t.testMap_={},t.prototype={__proto__:lib.TestManager.Suite.prototype},lib.TestManager.Suite.subclasses.push(t),t},lib.TestManager.Suite.subclasses=[],lib.TestManager.Suite.addTest=function(e,t){if(e in this.testMap_)throw"Duplicate test name: "+e;var r=new lib.TestManager.Test(this,e,t);this.testMap_[e]=r,this.testList_.push(r)},lib.TestManager.Suite.disableTest=function(e,t){if(e in this.testMap_)throw"Duplicate test name: "+e;var r=new lib.TestManager.Test(this,e,t);console.log("Disabled test: "+r.fullName)},lib.TestManager.Suite.getTest=function(e){return this.testMap_[e]},lib.TestManager.Suite.getTestList=function(){return this.testList_},lib.TestManager.Suite.prototype.setDefaults=function(e,t){for(var r in t)this[r]=r in e?e[r]:t[r]},lib.TestManager.Suite.prototype.setup=function(e){},lib.TestManager.Suite.prototype.preamble=function(e,t){},lib.TestManager.Suite.prototype.postamble=function(e,t){},lib.TestManager.Test=function(e,t,r){this.suiteClass=e,this.testName=t,this.fullName=e.suiteName+"["+t+"]",this.testFunction_=r},lib.TestManager.Test.prototype.run=function(e){try{this.testFunction_.apply(e.suite,[e,e.testRun.cx])}catch(t){if(t instanceof lib.TestManager.Result.TestComplete)return;e.println("Test raised an exception: "+t),t.stack&&(t.stack instanceof Array?e.println(t.stack.join("\n")):e.println(t.stack)),e.completeTest_(e.FAILED,!1)}},lib.TestManager.TestRun=function(e,t){this.testManager=e,this.log=e.log,this.cx=t||{},this.failures=[],this.passes=[],this.startDate=null,this.duration=null,this.currentResult=null,this.maxFailures=0,this.panic=!1,this.testQueue_=[]},lib.TestManager.TestRun.prototype.ALL_TESTS=new String("<all-tests>"),lib.TestManager.TestRun.prototype.selectTest=function(e){this.testQueue_.push(e)},lib.TestManager.TestRun.prototype.selectSuite=function(e,t){for(var r=t||this.ALL_TESTS,o=0,i=e.getTestList(),s=0;s<i.length;s++){var n=i[s];if(r!==this.ALL_TESTS)if(r instanceof RegExp){if(!r.test(n.testName))continue}else if(n.testName!=r)continue;this.selectTest(n),o++}return o},lib.TestManager.TestRun.prototype.selectPattern=function(e){for(var t=0,r=0;r<lib.TestManager.Suite.subclasses.length;r++)t+=this.selectSuite(lib.TestManager.Suite.subclasses[r],e);return t||this.log.println("No tests matched selection criteria: "+e),t},lib.TestManager.TestRun.prototype.onUncaughtException_=function(e,t,r){if(0==e.indexOf("Uncaught lib.TestManager.Result.TestComplete")||-1!=e.indexOf("status: passed"))return!0;if(this.currentResult&&e!="Uncaught "+this.currentResult.expectedErrorMessage_){var o="during";return this.currentResult.status!=this.currentResult.PENDING&&(o="after"),this.log.println("Uncaught exception "+o+" test case: "+this.currentResult.test.fullName),this.log.println(e+", "+t+":"+r),this.currentResult.completeTest_(this.currentResult.FAILED,!1),!1}},lib.TestManager.TestRun.prototype.onTestRunComplete_=function(e){return e?(this.duration=new Date-this.startDate,this.log.popPrefix(),this.log.println("} "+this.passes.length+" passed, "+this.failures.length+" failed, "+this.msToSeconds_(this.duration)),this.log.println(""),this.summarize(),window.onerror=null,void this.testManager.onTestRunComplete(this)):void setTimeout(this.onTestRunComplete_.bind(this),0,!0)},lib.TestManager.TestRun.prototype.onResultComplete=function(e){try{this.testManager.testPostamble(e,this.cx),e.suite.postamble(e,this.ctx)}catch(t){this.log.println("Unexpected exception in postamble: "+(t.stack?t.stack:t)),this.panic=!0}if(this.log.popPrefix(),this.log.print("} "+e.status+", "+this.msToSeconds_(e.duration)),this.log.flush(),e.status==e.FAILED)this.failures.push(e),this.currentSuite=null;else{if(e.status!=e.PASSED)return this.log.println("Unknown result status: "+e.test.fullName+": "+e.status),this.panic=!0;this.passes.push(e)}this.runNextTest_()},lib.TestManager.TestRun.prototype.onResultReComplete=function(e,t){this.log.println("Late complete for test: "+e.test.fullName+": "+t);var r=this.passes.indexOf(e);r>=0&&(this.passes.splice(r,1),this.failures.push(e))},lib.TestManager.TestRun.prototype.runNextTest_=function(){if(this.panic||!this.testQueue_.length)return this.onTestRunComplete_();if(this.maxFailures&&this.failures.length>=this.maxFailures)return this.log.println("Maximum failure count reached, aborting test run."),this.onTestRunComplete_();var e=this.testQueue_[0],t=this.currentResult?this.currentResult.suite:null;try{t&&t instanceof e.suiteClass||(this.log.println("Initializing suite: "+e.suiteClass.suiteName),t=new e.suiteClass(this.testManager,this.cx))}catch(r){return this.log.println("Exception during setup: "+(r.stack?r.stack:r)),this.panic=!0,void this.onTestRunComplete_()}try{this.log.print("Test: "+e.fullName+" {"),this.log.pushPrefix("  "),this.currentResult=new lib.TestManager.Result(this,t,e),this.testManager.testPreamble(this.currentResult,this.cx),t.preamble(this.currentResult,this.cx),this.testQueue_.shift()}catch(r){return this.log.println("Unexpected exception during test preamble: "+(r.stack?r.stack:r)),this.log.popPrefix(),this.log.println("}"),this.panic=!0,void this.onTestRunComplete_()}try{this.currentResult.run()}catch(r){this.log.println("Unexpected exception during test run: "+(r.stack?r.stack:r)),this.panic=!0}},lib.TestManager.TestRun.prototype.run=function(){this.log.println("Running "+this.testQueue_.length+" test(s) {"),this.log.pushPrefix("  "),window.onerror=this.onUncaughtException_.bind(this),this.startDate=new Date,this.runNextTest_()},lib.TestManager.TestRun.prototype.msToSeconds_=function(e){var t=(e/1e3).toFixed(2);return t+"s"},lib.TestManager.TestRun.prototype.summarize=function(){if(this.failures.length)for(var e=0;e<this.failures.length;e++)this.log.println("FAILED: "+this.failures[e].test.fullName);this.testQueue_.length&&this.log.println("Test run incomplete: "+this.testQueue_.length+" test(s) were not run.")},lib.TestManager.Result=function(e,t,r){this.testRun=e,this.suite=t,this.test=r,this.startDate=null,this.duration=null,this.status=this.PENDING,this.expectedErrorMessage_=null},lib.TestManager.Result.prototype.PENDING="pending",lib.TestManager.Result.prototype.FAILED="FAILED",lib.TestManager.Result.prototype.PASSED="passed",lib.TestManager.Result.TestComplete=function(e){this.result=e},lib.TestManager.Result.TestComplete.prototype.toString=function(){return"lib.TestManager.Result.TestComplete: "+this.result.test.fullName+", status: "+this.result.status},lib.TestManager.Result.prototype.run=function(){this.startDate=new Date,this.test.run(this),this.status!=this.PENDING||this.timeout_||(this.println("Test did not return a value and did not request more time."),this.completeTest_(this.FAILED,!1))},lib.TestManager.Result.prototype.expectErrorMessage=function(e){this.expectedErrorMessage_=e},lib.TestManager.Result.prototype.onTimeout_=function(){this.timeout_=null,this.status==this.PENDING&&(this.println("Test timed out."),this.completeTest_(this.FAILED,!1))},lib.TestManager.Result.prototype.requestTime=function(e){this.timeout_&&clearTimeout(this.timeout_),this.timeout_=setTimeout(this.onTimeout_.bind(this),e)},lib.TestManager.Result.prototype.completeTest_=function(e,t){if(this.status==this.PENDING?(this.duration=new Date-this.startDate,this.status=e,this.testRun.onResultComplete(this)):this.testRun.onResultReComplete(this,e),arguments.length<2||t)throw new lib.TestManager.Result.TestComplete(this)},lib.TestManager.Result.prototype.arrayEQ_=function(e,t){if(!e||!t)return!e&&!t;if(e.length!=t.length)return!1;for(var r=0;r<e.length;++r)if(e[r]!=t[r])return!1;return!0},lib.TestManager.Result.prototype.assertEQ=function(e,t,r){function o(e){if("number"==typeof e)return e;var t=String(e),r=t.split("\n").map(function(e){return JSON.stringify(e)});return r.length>1?"\n"+r.join("\n"):r.join("\n")}if(e!==t&&!(t instanceof Array&&this.arrayEQ_(e,t))){var i=r?"["+r+"]":"";this.fail("assertEQ"+i+": "+this.getCallerLocation_(1)+": "+o(e)+" !== "+o(t))}},lib.TestManager.Result.prototype.assert=function(e,t){if(e!==!0){var r=t?"["+t+"]":"";this.fail("assert"+r+": "+this.getCallerLocation_(1)+": "+String(e))}},lib.TestManager.Result.prototype.getCallerLocation_=function(e){try{throw new Error}catch(t){var r=t.stack.split("\n")[e+2],o=r.match(/([^\/]+:\d+):\d+\)?$/);return o?o[1]:"???"}},lib.TestManager.Result.prototype.println=function(e){this.testRun.log.println(e)},lib.TestManager.Result.prototype.fail=function(e){arguments.length&&this.println(e),this.completeTest_(this.FAILED,!0)},lib.TestManager.Result.prototype.pass=function(){this.completeTest_(this.PASSED,!0)},lib.UTF8Decoder=function(){this.bytesLeft=0,this.codePoint=0,this.lowerBound=0},lib.UTF8Decoder.prototype.decode=function(e){for(var t="",r=0;r<e.length;r++){var o=e.charCodeAt(r);if(0==this.bytesLeft)127>=o?t+=e.charAt(r):o>=192&&223>=o?(this.codePoint=o-192,this.bytesLeft=1,this.lowerBound=128):o>=224&&239>=o?(this.codePoint=o-224,this.bytesLeft=2,this.lowerBound=2048):o>=240&&247>=o?(this.codePoint=o-240,this.bytesLeft=3,this.lowerBound=65536):o>=248&&251>=o?(this.codePoint=o-248,this.bytesLeft=4,this.lowerBound=2097152):o>=252&&253>=o?(this.codePoint=o-252,this.bytesLeft=5,this.lowerBound=67108864):t+="�";else if(o>=128&&191>=o){if(this.bytesLeft--,this.codePoint=(this.codePoint<<6)+(o-128),0==this.bytesLeft){var i=this.codePoint;i<this.lowerBound||i>=55296&&57343>=i||i>1114111?t+="�":65536>i?t+=String.fromCharCode(i):(i-=65536,t+=String.fromCharCode(55296+(i>>>10&1023),56320+(1023&i)))}}else t+="�",this.bytesLeft=0,r--}return t},lib.decodeUTF8=function(e){return(new lib.UTF8Decoder).decode(e)},lib.encodeUTF8=function(e){for(var t="",r=0;r<e.length;r++){var o=e.charCodeAt(r);if(o>=56320&&57343>=o)o=65533;else if(o>=55296&&56319>=o)if(r+1<e.length){var i=e.charCodeAt(r+1);i>=56320&&57343>=i?(o=65536+((1023&o)<<10)+(1023&i),r++):o=65533}else o=65533;var s;if(127>=o)t+=e.charAt(r);else for(2047>=o?(t+=String.fromCharCode(192|o>>>6),s=1):65535>=o?(t+=String.fromCharCode(224|o>>>12),s=2):(t+=String.fromCharCode(240|o>>>18),s=3);s>0;)s--,t+=String.fromCharCode(128|o>>>6*s&63)}return t},String.prototype.codePointAt||!function(){var e=function(e){if(null==this)throw TypeError();var t=String(this),r=t.length,o=e?Number(e):0;if(o!=o&&(o=0),0>o||o>=r)return void 0;var i,s=t.charCodeAt(o);return s>=55296&&56319>=s&&r>o+1&&(i=t.charCodeAt(o+1),i>=56320&&57343>=i)?1024*(s-55296)+i-56320+65536:s};Object.defineProperty?Object.defineProperty(String.prototype,"codePointAt",{value:e,configurable:!0,writable:!0}):String.prototype.codePointAt=e}(),lib.wc={},lib.wc.nulWidth=0,lib.wc.controlWidth=0,lib.wc.regardCjkAmbiguous=!1,lib.wc.cjkAmbiguousWidth=2,lib.wc.combining=[[768,879],[1155,1158],[1160,1161],[1425,1469],[1471,1471],[1473,1474],[1476,1477],[1479,1479],[1536,1539],[1552,1557],[1611,1630],[1648,1648],[1750,1764],[1767,1768],[1770,1773],[1807,1807],[1809,1809],[1840,1866],[1958,1968],[2027,2035],[2305,2306],[2364,2364],[2369,2376],[2381,2381],[2385,2388],[2402,2403],[2433,2433],[2492,2492],[2497,2500],[2509,2509],[2530,2531],[2561,2562],[2620,2620],[2625,2626],[2631,2632],[2635,2637],[2672,2673],[2689,2690],[2748,2748],[2753,2757],[2759,2760],[2765,2765],[2786,2787],[2817,2817],[2876,2876],[2879,2879],[2881,2883],[2893,2893],[2902,2902],[2946,2946],[3008,3008],[3021,3021],[3134,3136],[3142,3144],[3146,3149],[3157,3158],[3260,3260],[3263,3263],[3270,3270],[3276,3277],[3298,3299],[3393,3395],[3405,3405],[3530,3530],[3538,3540],[3542,3542],[3633,3633],[3636,3642],[3655,3662],[3761,3761],[3764,3769],[3771,3772],[3784,3789],[3864,3865],[3893,3893],[3895,3895],[3897,3897],[3953,3966],[3968,3972],[3974,3975],[3984,3991],[3993,4028],[4038,4038],[4141,4144],[4146,4146],[4150,4151],[4153,4153],[4184,4185],[4448,4607],[4959,4959],[5906,5908],[5938,5940],[5970,5971],[6002,6003],[6068,6069],[6071,6077],[6086,6086],[6089,6099],[6109,6109],[6155,6157],[6313,6313],[6432,6434],[6439,6440],[6450,6450],[6457,6459],[6679,6680],[6912,6915],[6964,6964],[6966,6970],[6972,6972],[6978,6978],[7019,7027],[7616,7626],[7678,7679],[8203,8207],[8234,8238],[8288,8291],[8298,8303],[8400,8431],[12330,12335],[12441,12442],[43014,43014],[43019,43019],[43045,43046],[64286,64286],[65024,65039],[65056,65059],[65279,65279],[65529,65531],[68097,68099],[68101,68102],[68108,68111],[68152,68154],[68159,68159],[119143,119145],[119155,119170],[119173,119179],[119210,119213],[119362,119364],[917505,917505],[917536,917631],[917760,917999]],lib.wc.ambiguous=[[161,161],[164,164],[167,168],[170,170],[174,174],[176,180],[182,186],[188,191],[198,198],[208,208],[215,216],[222,225],[230,230],[232,234],[236,237],[240,240],[242,243],[247,250],[252,252],[254,254],[257,257],[273,273],[275,275],[283,283],[294,295],[299,299],[305,307],[312,312],[319,322],[324,324],[328,331],[333,333],[338,339],[358,359],[363,363],[462,462],[464,464],[466,466],[468,468],[470,470],[472,472],[474,474],[476,476],[593,593],[609,609],[708,708],[711,711],[713,715],[717,717],[720,720],[728,731],[733,733],[735,735],[913,929],[931,937],[945,961],[963,969],[1025,1025],[1040,1103],[1105,1105],[8208,8208],[8211,8214],[8216,8217],[8220,8221],[8224,8226],[8228,8231],[8240,8240],[8242,8243],[8245,8245],[8251,8251],[8254,8254],[8308,8308],[8319,8319],[8321,8324],[8364,8364],[8451,8451],[8453,8453],[8457,8457],[8467,8467],[8470,8470],[8481,8482],[8486,8486],[8491,8491],[8531,8532],[8539,8542],[8544,8555],[8560,8569],[8592,8601],[8632,8633],[8658,8658],[8660,8660],[8679,8679],[8704,8704],[8706,8707],[8711,8712],[8715,8715],[8719,8719],[8721,8721],[8725,8725],[8730,8730],[8733,8736],[8739,8739],[8741,8741],[8743,8748],[8750,8750],[8756,8759],[8764,8765],[8776,8776],[8780,8780],[8786,8786],[8800,8801],[8804,8807],[8810,8811],[8814,8815],[8834,8835],[8838,8839],[8853,8853],[8857,8857],[8869,8869],[8895,8895],[8978,8978],[9312,9449],[9451,9547],[9552,9587],[9600,9615],[9618,9621],[9632,9633],[9635,9641],[9650,9651],[9654,9655],[9660,9661],[9664,9665],[9670,9672],[9675,9675],[9678,9681],[9698,9701],[9711,9711],[9733,9734],[9737,9737],[9742,9743],[9748,9749],[9756,9756],[9758,9758],[9792,9792],[9794,9794],[9824,9825],[9827,9829],[9831,9834],[9836,9837],[9839,9839],[10045,10045],[10102,10111],[57344,63743],[65533,65533],[983040,1048573],[1048576,1114109]],lib.wc.isSpace=function(e){var t,r=0,o=lib.wc.combining.length-1;if(e<lib.wc.combining[0][0]||e>lib.wc.combining[o][1])return!1;for(;o>=r;)if(t=Math.floor((r+o)/2),e>lib.wc.combining[t][1])r=t+1;else{if(!(e<lib.wc.combining[t][0]))return!0;o=t-1}return!1},lib.wc.isCjkAmbiguous=function(e){var t,r=0,o=lib.wc.ambiguous.length-1;if(e<lib.wc.ambiguous[0][0]||e>lib.wc.ambiguous[o][1])return!1;for(;o>=r;)if(t=Math.floor((r+o)/2),e>lib.wc.ambiguous[t][1])r=t+1;else{if(!(e<lib.wc.ambiguous[t][0]))return!0;o=t-1}return!1},lib.wc.charWidth=function(e){return lib.wc.regardCjkAmbiguous?lib.wc.charWidthRegardAmbiguous(e):lib.wc.charWidthDisregardAmbiguous(e)},lib.wc.charWidthDisregardAmbiguous=function(e){return 0===e?lib.wc.nulWidth:32>e||e>=127&&160>e?lib.wc.controlWidth:127>e?1:lib.wc.isSpace(e)?0:1+(e>=4352&&(4447>=e||9001==e||9002==e||e>=11904&&42191>=e&&12351!=e||e>=44032&&55203>=e||e>=63744&&64255>=e||e>=65040&&65049>=e||e>=65072&&65135>=e||e>=65280&&65376>=e||e>=65504&&65510>=e||e>=131072&&196605>=e||e>=196608&&262141>=e))},lib.wc.charWidthRegardAmbiguous=function(e){return lib.wc.isCjkAmbiguous(e)?lib.wc.cjkAmbiguousWidth:lib.wc.charWidthDisregardAmbiguous(e)},lib.wc.strWidth=function(e){for(var t,r=0,o=0;o<e.length;){var i=e.codePointAt(o);if(t=lib.wc.charWidth(i),0>t)return-1;r+=t,o+=65535>=i?1:2}return r},lib.wc.substr=function(e,t,r){var o,i,s;for(o=0,s=0;o<e.length&&(s+=lib.wc.charWidth(e.charCodeAt(o)),!(s>t));o++);if(void 0!=r){for(i=o,s=0;i<e.length&&r>s;s+=lib.wc.charWidth(e.charCodeAt(i)),i++);return s>r&&i--,e.substring(o,i)}return e.substr(o)},lib.wc.substring=function(e,t,r){return lib.wc.substr(e,t,r-t)},lib.resource.add("libdot/changelog/version","text/plain","1.11"),lib.resource.add("libdot/changelog/date","text/plain","2017-04-17"),lib.rtdep("lib.Storage");var hterm={};hterm.windowType=null,hterm.zoomWarningMessage="ZOOM != 100%",hterm.notifyCopyMessage="✂",hterm.desktopNotificationTitle="♪ %(title) ♪",hterm.testDeps=["hterm.ScrollPort.Tests","hterm.Screen.Tests","hterm.Terminal.Tests","hterm.VT.Tests","hterm.VT.CannedTests"],lib.registerInit("hterm",function(e){function t(t){hterm.windowType=t.type,setTimeout(e,0)}function r(r){r&&window.chrome?chrome.windows.get(r.windowId,null,t):(hterm.windowType="normal",setTimeout(e,0))}if(!hterm.defaultStorage){var o=navigator.userAgent.match(/\sChrome\/(\d\d)/),i=o?parseInt(o[1]):-1;window.chrome&&chrome.storage&&chrome.storage.sync&&i>21?hterm.defaultStorage=new lib.Storage.Chrome(chrome.storage.sync):hterm.defaultStorage=new lib.Storage.Local}var s=!1;if(window.chrome&&chrome.runtime&&chrome.runtime.getManifest){var n=chrome.runtime.getManifest();s=n.app&&n.app.background}s?setTimeout(t.bind(null,{type:"popup"}),0):window.chrome&&chrome.tabs?chrome.tabs.getCurrent(r):setTimeout(t.bind(null,{type:"normal"}),0)}),hterm.getClientSize=function(e){return e.getBoundingClientRect()},hterm.getClientWidth=function(e){return e.getBoundingClientRect().width},hterm.getClientHeight=function(e){return e.getBoundingClientRect().height},hterm.copySelectionToClipboard=function(e){try{e.execCommand("copy")}catch(t){}},hterm.pasteFromClipboard=function(e){try{e.execCommand("paste")}catch(t){}},hterm.Size=function(e,t){this.width=e,this.height=t},hterm.Size.prototype.resize=function(e,t){this.width=e,this.height=t},hterm.Size.prototype.clone=function(){return new hterm.Size(this.width,this.height)},hterm.Size.prototype.setTo=function(e){this.width=e.width,this.height=e.height},hterm.Size.prototype.equals=function(e){return this.width==e.width&&this.height==e.height},hterm.Size.prototype.toString=function(){return"[hterm.Size: "+this.width+", "+this.height+"]"},hterm.RowCol=function(e,t,r){this.row=e,this.column=t,this.overflow=!!r},hterm.RowCol.prototype.move=function(e,t,r){this.row=e,this.column=t,this.overflow=!!r},hterm.RowCol.prototype.clone=function(){return new hterm.RowCol(this.row,this.column,this.overflow)},hterm.RowCol.prototype.setTo=function(e){this.row=e.row,this.column=e.column,this.overflow=e.overflow},hterm.RowCol.prototype.equals=function(e){return this.row==e.row&&this.column==e.column&&this.overflow==e.overflow},hterm.RowCol.prototype.toString=function(){return"[hterm.RowCol: "+this.row+", "+this.column+", "+this.overflow+"]"},lib.rtdep("lib.f"),hterm.Frame=function(e,t,r){this.terminal_=e,this.div_=e.div_,this.url=t,this.options=r||{},this.iframe_=null,this.container_=null,this.messageChannel_=null},hterm.Frame.prototype.onMessage_=function(e){return"ipc-init-ok"!=e.data.name?void console.log("Unknown message from frame:",e.data):(this.sendTerminalInfo_(),this.messageChannel_.port1.onmessage=this.onMessage.bind(this),void this.onLoad())},hterm.Frame.prototype.onMessage=function(){},hterm.Frame.prototype.onLoad_=function(){this.messageChannel_=new MessageChannel,this.messageChannel_.port1.onmessage=this.onMessage_.bind(this),this.messageChannel_.port1.start(),this.iframe_.contentWindow.postMessage({name:"ipc-init",argv:[{messagePort:this.messageChannel_.port2}]},this.url,[this.messageChannel_.port2])},hterm.Frame.prototype.onLoad=function(){},hterm.Frame.prototype.sendTerminalInfo_=function(){lib.f.getAcceptLanguages(function(e){this.postMessage("terminal-info",[{acceptLanguages:e,foregroundColor:this.terminal_.getForegroundColor(),backgroundColor:this.terminal_.getBackgroundColor(),cursorColor:this.terminal_.getCursorColor(),fontSize:this.terminal_.getFontSize(),fontFamily:this.terminal_.getFontFamily(),baseURL:lib.f.getURL("/")
-}])}.bind(this))},hterm.Frame.prototype.onCloseClicked_=function(){this.close()},hterm.Frame.prototype.close=function(){this.container_&&this.container_.parentNode&&(this.container_.parentNode.removeChild(this.container_),this.onClose())},hterm.Frame.prototype.onClose=function(){},hterm.Frame.prototype.postMessage=function(e,t){if(!this.messageChannel_)throw new Error("Message channel is not set up.");this.messageChannel_.port1.postMessage({name:e,argv:t})},hterm.Frame.prototype.show=function(){function e(e,r){return e in t.options?t.options[e]:r}var t=this,t=this;if(this.container_&&this.container_.parentNode)return void console.error("Frame already visible");var r="16px",o=hterm.getClientSize(this.div_),i=e("width",640),s=e("height",480),n=((o.width-i)/2,(o.height-s)/2,this.terminal_.document_),a=this.container_=n.createElement("div");a.style.cssText="position: absolute;display: -webkit-flex;-webkit-flex-direction: column;top: 10%;left: 4%;width: 90%;height: 80%;box-shadow: 0 0 2px "+this.terminal_.getForegroundColor()+";border: 2px "+this.terminal_.getForegroundColor()+" solid;";var l=n.createElement("div");l.style.cssText="display: -webkit-flex;-webkit-justify-content: flex-end;height: "+r+";background-color: "+this.terminal_.getForegroundColor()+";color: "+this.terminal_.getBackgroundColor()+";font-size: 16px;font-family: "+this.terminal_.getFontFamily(),a.appendChild(l);var h=this.iframe_=n.createElement("iframe");h.onload=this.onLoad_.bind(this),h.style.cssText="display: -webkit-flex;-webkit-flex: 1;width: 100%",h.setAttribute("src",this.url),h.setAttribute("seamless",!0),a.appendChild(h),this.div_.appendChild(a)},lib.rtdep("hterm.Keyboard.KeyMap"),hterm.Keyboard=function(e){this.terminal=e,this.keyboardElement_=null,this.handlers_=[["focusout",this.onFocusOut_.bind(this)],["keydown",this.onKeyDown_.bind(this)],["keypress",this.onKeyPress_.bind(this)],["keyup",this.onKeyUp_.bind(this)],["textInput",this.onTextInput_.bind(this)]],this.keyMap=new hterm.Keyboard.KeyMap(this),this.bindings=new hterm.Keyboard.Bindings(this),this.altGrMode="none",this.shiftInsertPaste=!0,this.homeKeysScroll=!1,this.pageKeysScroll=!1,this.ctrlPlusMinusZeroZoom=!0,this.ctrlCCopy=!1,this.ctrlVPaste=!1,this.applicationKeypad=!1,this.applicationCursor=!1,this.backspaceSendsBackspace=!1,this.characterEncoding="utf-8",this.metaSendsEscape=!0,this.passMetaV=!0,this.altSendsWhat="escape",this.altIsMeta=!1,this.altBackspaceIsMetaBackspace=!1,this.altKeyPressed=0,this.mediaKeysAreFKeys=!1,this.previousAltSendsWhat_=null},hterm.Keyboard.KeyActions={CANCEL:new String("CANCEL"),DEFAULT:new String("DEFAULT"),PASS:new String("PASS"),STRIP:new String("STRIP")},hterm.Keyboard.prototype.encode=function(e){return"utf-8"==this.characterEncoding?this.terminal.vt.encodeUTF8(e):e},hterm.Keyboard.prototype.installKeyboard=function(e){if(e!=this.keyboardElement_){e&&this.keyboardElement_&&this.installKeyboard(null);for(var t=0;t<this.handlers_.length;t++){var r=this.handlers_[t];e?e.addEventListener(r[0],r[1]):this.keyboardElement_.removeEventListener(r[0],r[1])}this.keyboardElement_=e}},hterm.Keyboard.prototype.uninstallKeyboard=function(){this.installKeyboard(null)},hterm.Keyboard.prototype.onTextInput_=function(e){e.data&&e.data.split("").forEach(this.terminal.onVTKeystroke.bind(this.terminal))},hterm.Keyboard.prototype.onKeyPress_=function(e){var t,r=String.fromCharCode(e.which),o=r.toLowerCase();if(!e.ctrlKey&&!e.metaKey||"c"!=o&&"v"!=o){if(e.altKey&&"browser-key"==this.altSendsWhat&&0==e.charCode){var i=String.fromCharCode(e.keyCode);e.shiftKey||(i=i.toLowerCase()),t=i.charCodeAt(0)+128}else e.charCode>=32&&(i=e.charCode);i&&this.terminal.onVTKeystroke(String.fromCharCode(i)),e.preventDefault(),e.stopPropagation()}},hterm.Keyboard.prototype.preventChromeAppNonCtrlShiftDefault_=function(e){window.chrome&&window.chrome.app&&window.chrome.app.window&&(e.ctrlKey&&e.shiftKey||e.preventDefault())},hterm.Keyboard.prototype.onFocusOut_=function(e){this.altKeyPressed=0},hterm.Keyboard.prototype.onKeyUp_=function(e){18==e.keyCode&&(this.altKeyPressed=this.altKeyPressed&~(1<<e.location-1)),27==e.keyCode&&this.preventChromeAppNonCtrlShiftDefault_(e)},hterm.Keyboard.prototype.onKeyDown_=function(e){function t(s){o=s;var a=r[s];return"function"==typeof a&&(a=a.apply(i.keyMap,[e,r])),a===n&&"normal"!=s&&(a=t("normal")),a}18==e.keyCode&&(this.altKeyPressed=this.altKeyPressed|1<<e.location-1),27==e.keyCode&&this.preventChromeAppNonCtrlShiftDefault_(e);var r=this.keyMap.keyDefs[e.keyCode];if(!r)return void console.warn("No definition for keyCode: "+e.keyCode);var o=null,i=this,s=hterm.Keyboard.KeyActions.CANCEL,n=hterm.Keyboard.KeyActions.DEFAULT,a=hterm.Keyboard.KeyActions.PASS,l=hterm.Keyboard.KeyActions.STRIP,h=e.ctrlKey,c=this.altIsMeta?!1:e.altKey,u=this.altIsMeta?e.altKey||e.metaKey:e.metaKey,g=!/^\[\w+\]$/.test(r.keyCap);switch(this.altGrMode){case"ctrl-alt":g&&h&&c&&(h=!1,c=!1);break;case"right-alt":g&&2&this.terminal.keyboard.altKeyPressed&&(h=!1,c=!1);break;case"left-alt":g&&1&this.terminal.keyboard.altKeyPressed&&(h=!1,c=!1)}var d;d=t(h?"control":c?"alt":u?"meta":"normal");var p=!e.maskShiftKey&&e.shiftKey,m={keyCode:e.keyCode,shift:e.shiftKey,ctrl:h,alt:c,meta:u},b=this.bindings.getBinding(m);if(b&&(p=h=c=u=!1,o="normal",d=b.action,"function"==typeof d&&(d=d.call(this,this.terminal,m))),c&&"browser-key"==this.altSendsWhat&&d==n&&(d=a),d!==a&&(d!==n||h||c||u)&&(d===l&&(c=h=!1,d=r.normal,"function"==typeof d&&(d=d.apply(this.keyMap,[e,r])),d==n&&2==r.keyCap.length&&(d=r.keyCap.substr(p?1:0,1))),e.preventDefault(),e.stopPropagation(),d!==s)){if(d!==n&&"string"!=typeof d)return void console.warn("Invalid action: "+JSON.stringify(d));if("control"==o?h=!1:"alt"==o?c=!1:"meta"==o&&(u=!1),"["==d.substr(0,2)&&(c||h||p)){var f;!p||c||h?!c||p||h?p&&c&&!h?f=";4":!h||p||c?p&&h&&!c?f=";6":c&&h&&!p?f=";7":p&&c&&h&&(f=";8"):f=";5":f=";3":f=";2",d=3==d.length?"[1"+f+d.substr(2,1):d.substr(0,d.length-1)+f+d.substr(d.length-1)}else{if(d===n&&(d=r.keyCap.substr(p?1:0,1),h)){var y=r.keyCap.substr(0,1),_=y.charCodeAt(0);_>=64&&95>=_&&(d=String.fromCharCode(_-64))}if(c&&"8-bit"==this.altSendsWhat&&1==d.length){var _=d.charCodeAt(0)+128;d=String.fromCharCode(_)}(c&&"escape"==this.altSendsWhat||u&&this.metaSendsEscape)&&(d=""+d)}this.terminal.onVTKeystroke(d)}},hterm.Keyboard.Bindings=function(){this.bindings_={}},hterm.Keyboard.Bindings.prototype.clear=function(){this.bindings_={}},hterm.Keyboard.Bindings.prototype.addBinding_=function(e,t){var r=null,o=this.bindings_[e.keyCode];if(o)for(var i=0;i<o.length;i++)if(o[i].keyPattern.matchKeyPattern(e)){r=o[i];break}r?r.action=t:(r={keyPattern:e,action:t},o?(this.bindings_[e.keyCode].push(r),o.sort(function(e,t){return hterm.Keyboard.KeyPattern.sortCompare(e.keyPattern,t.keyPattern)})):this.bindings_[e.keyCode]=[r])},hterm.Keyboard.Bindings.prototype.addBinding=function(e,t){if("string"!=typeof e)return void this.addBinding_(e,t);var r=new hterm.Parser;r.reset(e);var o;try{o=r.parseKeySequence()}catch(i){return void console.error(i)}if(!r.isComplete())return void console.error(r.error("Expected end of sequence: "+o));if("string"==typeof t){r.reset(t);try{t=r.parseKeyAction()}catch(i){return void console.error(i)}}return r.isComplete()?void this.addBinding_(new hterm.Keyboard.KeyPattern(o),t):void console.error(r.error("Expected end of sequence: "+o))},hterm.Keyboard.Bindings.prototype.addBindings=function(e){for(var t in e)this.addBinding(t,e[t])},hterm.Keyboard.Bindings.prototype.getBinding=function(e){var t=this.bindings_[e.keyCode];if(!t)return null;for(var r=0;r<t.length;r++){var o=t[r];if(o.keyPattern.matchKeyDown(e))return o}return null},lib.rtdep("hterm.Keyboard.KeyActions"),hterm.Keyboard.KeyMap=function(e){this.keyboard=e,this.keyDefs={},this.reset()},hterm.Keyboard.KeyMap.prototype.addKeyDef=function(e,t){e in this.keyDefs&&console.warn("Duplicate keyCode: "+e),this.keyDefs[e]=t},hterm.Keyboard.KeyMap.prototype.addKeyDefs=function(e){for(var t=0;t<arguments.length;t++)this.addKeyDef(arguments[t][0],{keyCap:arguments[t][1],normal:arguments[t][2],control:arguments[t][3],alt:arguments[t][4],meta:arguments[t][5]})},hterm.Keyboard.KeyMap.prototype.reset=function(){function e(e,t,r){return"function"==typeof e?e.apply(h,[t,r]):e}function t(t,r){return function(o,i){var s=o.shiftKey||o.ctrlKey||o.altKey||o.metaKey||!h.keyboard.applicationCursor?t:r;return e(s,o,i)}}function r(t,r){return function(o,i){var s=h.keyboard.backspaceSendsBackspace?r:t;return e(s,o,i)}}function o(t,r){return function(o,i){var s=o.shiftKey?r:t;return o.maskShiftKey=!0,e(s,o,i)}}function i(t,r){return function(o,i){var s=o.altKey?r:t;return e(s,o,i)}}function s(t,r){return function(o,i){var s=o.shiftKey||o.ctrlKey||o.altKey||o.metaKey?r:t;return e(s,o,i)}}function n(e){return String.fromCharCode(e.charCodeAt(0)-64)}function a(e){return function(t,r){return this[e](t,r)}}function l(t){return function(r,o){return h.keyboard.mediaKeysAreFKeys?e(t,r,o):166==r.keyCode||167==r.keyCode||168==r.keyCode?hterm.Keyboard.KeyActions.CANCEL:hterm.Keyboard.KeyActions.PASS}}this.keyDefs={};var h=this,c="",u="[",g="O",d=hterm.Keyboard.KeyActions.CANCEL,p=hterm.Keyboard.KeyActions.DEFAULT,m=hterm.Keyboard.KeyActions.PASS,b=hterm.Keyboard.KeyActions.STRIP;this.addKeyDefs([0,"[UNKNOWN]",m,m,m,m],[27,"[ESC]",c,p,p,p],[112,"[F1]",s(g+"P",u+"P"),p,u+"23~",p],[113,"[F2]",s(g+"Q",u+"Q"),p,u+"24~",p],[114,"[F3]",s(g+"R",u+"R"),p,u+"25~",p],[115,"[F4]",s(g+"S",u+"S"),p,u+"26~",p],[116,"[F5]",u+"15~",p,u+"28~",p],[117,"[F6]",u+"17~",p,u+"29~",p],[118,"[F7]",u+"18~",p,u+"31~",p],[119,"[F8]",u+"19~",p,u+"32~",p],[120,"[F9]",u+"20~",p,u+"33~",p],[121,"[F10]",u+"21~",p,u+"34~",p],[122,"[F11]",u+"23~",p,u+"42~",p],[123,"[F12]",u+"24~",p,u+"43~",p],[192,"`~",p,o(n("@"),n("^")),p,m],[49,"1!",p,a("onCtrlNum_"),a("onAltNum_"),a("onMetaNum_")],[50,"2@",p,a("onCtrlNum_"),a("onAltNum_"),a("onMetaNum_")],[51,"3#",p,a("onCtrlNum_"),a("onAltNum_"),a("onMetaNum_")],[52,"4$",p,a("onCtrlNum_"),a("onAltNum_"),a("onMetaNum_")],[53,"5%",p,a("onCtrlNum_"),a("onAltNum_"),a("onMetaNum_")],[54,"6^",p,a("onCtrlNum_"),a("onAltNum_"),a("onMetaNum_")],[55,"7&",p,a("onCtrlNum_"),a("onAltNum_"),a("onMetaNum_")],[56,"8*",p,a("onCtrlNum_"),a("onAltNum_"),a("onMetaNum_")],[57,"9(",p,a("onCtrlNum_"),a("onAltNum_"),a("onMetaNum_")],[48,"0)",p,a("onPlusMinusZero_"),a("onAltNum_"),a("onPlusMinusZero_")],[189,"-_",p,a("onPlusMinusZero_"),p,a("onPlusMinusZero_")],[187,"=+",p,a("onPlusMinusZero_"),p,a("onPlusMinusZero_")],[173,"-_",p,a("onPlusMinusZero_"),p,a("onPlusMinusZero_")],[61,"=+",p,a("onPlusMinusZero_"),p,a("onPlusMinusZero_")],[171,"+*",p,a("onPlusMinusZero_"),p,a("onPlusMinusZero_")],[8,"[BKSP]",r("","\b"),r("\b",""),p,p],[9,"[TAB]",o("	",u+"Z"),b,m,p],[81,"qQ",p,n("Q"),p,p],[87,"wW",p,n("W"),p,p],[69,"eE",p,n("E"),p,p],[82,"rR",p,n("R"),p,p],[84,"tT",p,n("T"),p,p],[89,"yY",p,n("Y"),p,p],[85,"uU",p,n("U"),p,p],[73,"iI",p,n("I"),p,p],[79,"oO",p,n("O"),p,p],[80,"pP",p,n("P"),p,p],[219,"[{",p,n("["),p,p],[221,"]}",p,n("]"),p,p],[220,"\\|",p,n("\\"),p,p],[20,"[CAPS]",m,m,m,p],[65,"aA",p,n("A"),p,p],[83,"sS",p,n("S"),p,p],[68,"dD",p,n("D"),p,p],[70,"fF",p,n("F"),p,p],[71,"gG",p,n("G"),p,p],[72,"hH",p,n("H"),p,p],[74,"jJ",p,o(n("J"),m),p,p],[75,"kK",p,o(n("K"),a("onClear_")),p,p],[76,"lL",p,o(n("L"),m),p,p],[186,";:",p,b,p,p],[222,"'\"",p,b,p,p],[13,"[ENTER]","\r",d,d,p],[16,"[SHIFT]",m,m,m,p],[90,"zZ",p,n("Z"),p,p],[88,"xX",p,n("X"),p,p],[67,"cC",p,a("onCtrlC_"),p,a("onMetaC_")],[86,"vV",p,a("onCtrlV_"),p,a("onMetaV_")],[66,"bB",p,o(n("B"),m),p,o(p,m)],[78,"nN",p,a("onCtrlN_"),p,a("onMetaN_")],[77,"mM",p,n("M"),p,p],[188,",<",p,i(b,m),p,p],[190,".>",p,i(b,m),p,p],[191,"/?",p,o(n("_"),n("?")),p,p],[17,"[CTRL]",m,m,m,m],[18,"[ALT]",m,m,m,m],[91,"[LAPL]",m,m,m,m],[32," ",p,n("@"),p,p],[92,"[RAPL]",m,m,m,m],[93,"[RMENU]",m,m,m,m],[42,"[PRTSCR]",m,m,m,m],[145,"[SCRLK]",m,m,m,m],[19,"[BREAK]",m,m,m,m],[45,"[INSERT]",a("onKeyInsert_"),p,p,p],[36,"[HOME]",a("onKeyHome_"),p,p,p],[33,"[PGUP]",a("onKeyPageUp_"),p,p,p],[46,"[DEL]",a("onKeyDel_"),p,p,p],[35,"[END]",a("onKeyEnd_"),p,p,p],[34,"[PGDOWN]",a("onKeyPageDown_"),p,p,p],[38,"[UP]",t(u+"A",g+"A"),p,p,p],[40,"[DOWN]",t(u+"B",g+"B"),p,p,p],[39,"[RIGHT]",t(u+"C",g+"C"),p,p,p],[37,"[LEFT]",t(u+"D",g+"D"),p,p,p],[144,"[NUMLOCK]",m,m,m,m],[96,"[KP0]",p,p,p,p],[97,"[KP1]",p,p,p,p],[98,"[KP2]",p,p,p,p],[99,"[KP3]",p,p,p,p],[100,"[KP4]",p,p,p,p],[101,"[KP5]",p,p,p,p],[102,"[KP6]",p,p,p,p],[103,"[KP7]",p,p,p,p],[104,"[KP8]",p,p,p,p],[105,"[KP9]",p,p,p,p],[107,"[KP+]",p,a("onPlusMinusZero_"),p,a("onPlusMinusZero_")],[109,"[KP-]",p,a("onPlusMinusZero_"),p,a("onPlusMinusZero_")],[106,"[KP*]",p,p,p,p],[111,"[KP/]",p,p,p,p],[110,"[KP.]",p,p,p,p],[166,"[BACK]",l(s(g+"P",u+"P")),p,u+"23~",p],[167,"[FWD]",l(s(g+"Q",u+"Q")),p,u+"24~",p],[168,"[RELOAD]",l(s(g+"R",u+"R")),p,u+"25~",p],[183,"[FSCR]",l(s(g+"S",u+"S")),p,u+"26~",p],[182,"[WINS]",l(u+"15~"),p,u+"28~",p],[216,"[BRIT-]",l(u+"17~"),p,u+"29~",p],[217,"[BRIT+]",l(u+"18~"),p,u+"31~",p])},hterm.Keyboard.KeyMap.prototype.onKeyInsert_=function(e){return this.keyboard.shiftInsertPaste&&e.shiftKey?hterm.Keyboard.KeyActions.PASS:"[2~"},hterm.Keyboard.KeyMap.prototype.onKeyHome_=function(e){return!this.keyboard.homeKeysScroll^e.shiftKey?e.altey||e.ctrlKey||e.shiftKey||!this.keyboard.applicationCursor?"":"OH":(this.keyboard.terminal.scrollHome(),hterm.Keyboard.KeyActions.CANCEL)},hterm.Keyboard.KeyMap.prototype.onKeyEnd_=function(e){return!this.keyboard.homeKeysScroll^e.shiftKey?e.altKey||e.ctrlKey||e.shiftKey||!this.keyboard.applicationCursor?"":"OF":(this.keyboard.terminal.scrollEnd(),hterm.Keyboard.KeyActions.CANCEL)},hterm.Keyboard.KeyMap.prototype.onKeyPageUp_=function(e){return!this.keyboard.pageKeysScroll^e.shiftKey?"[5~":(this.keyboard.terminal.scrollPageUp(),hterm.Keyboard.KeyActions.CANCEL)},hterm.Keyboard.KeyMap.prototype.onKeyDel_=function(e){return this.keyboard.altBackspaceIsMetaBackspace&&this.keyboard.altKeyPressed&&!e.altKey?"":"[3~"},hterm.Keyboard.KeyMap.prototype.onKeyPageDown_=function(e){return!this.keyboard.pageKeysScroll^e.shiftKey?"[6~":(this.keyboard.terminal.scrollPageDown(),hterm.Keyboard.KeyActions.CANCEL)},hterm.Keyboard.KeyMap.prototype.onClear_=function(e,t){return this.keyboard.terminal.wipeContents(),hterm.Keyboard.KeyActions.CANCEL},hterm.Keyboard.KeyMap.prototype.onCtrlNum_=function(e,t){function r(e){return String.fromCharCode(e.charCodeAt(0)-64)}if(this.keyboard.terminal.passCtrlNumber&&!e.shiftKey)return hterm.Keyboard.KeyActions.PASS;switch(t.keyCap.substr(0,1)){case"1":return"1";case"2":return r("@");case"3":return r("[");case"4":return r("\\");case"5":return r("]");case"6":return r("^");case"7":return r("_");case"8":return"";case"9":return"9"}},hterm.Keyboard.KeyMap.prototype.onAltNum_=function(e,t){return this.keyboard.terminal.passAltNumber&&!e.shiftKey?hterm.Keyboard.KeyActions.PASS:hterm.Keyboard.KeyActions.DEFAULT},hterm.Keyboard.KeyMap.prototype.onMetaNum_=function(e,t){return this.keyboard.terminal.passMetaNumber&&!e.shiftKey?hterm.Keyboard.KeyActions.PASS:hterm.Keyboard.KeyActions.DEFAULT},hterm.Keyboard.KeyMap.prototype.onCtrlC_=function(e,t){var r=this.keyboard.terminal.getDocument().getSelection();if(!r.isCollapsed){if(this.keyboard.ctrlCCopy&&!e.shiftKey)return this.keyboard.terminal.clearSelectionAfterCopy&&setTimeout(r.collapseToEnd.bind(r),50),hterm.Keyboard.KeyActions.PASS;if(!this.keyboard.ctrlCCopy&&e.shiftKey)return this.keyboard.terminal.clearSelectionAfterCopy&&setTimeout(r.collapseToEnd.bind(r),50),this.keyboard.terminal.copySelectionToClipboard(),hterm.Keyboard.KeyActions.CANCEL}return""},hterm.Keyboard.KeyMap.prototype.onCtrlN_=function(e,t){return e.shiftKey?(window.open(document.location.href,"","chrome=no,close=yes,resize=yes,scrollbars=yes,minimizable=yes,width="+window.innerWidth+",height="+window.innerHeight),hterm.Keyboard.KeyActions.CANCEL):""},hterm.Keyboard.KeyMap.prototype.onCtrlV_=function(e,t){return!e.shiftKey&&this.keyboard.ctrlVPaste||e.shiftKey&&!this.keyboard.ctrlVPaste?hterm.Keyboard.KeyActions.PASS:""},hterm.Keyboard.KeyMap.prototype.onMetaN_=function(e,t){return e.shiftKey?(window.open(document.location.href,"","chrome=no,close=yes,resize=yes,scrollbars=yes,minimizable=yes,width="+window.outerWidth+",height="+window.outerHeight),hterm.Keyboard.KeyActions.CANCEL):hterm.Keyboard.KeyActions.DEFAULT},hterm.Keyboard.KeyMap.prototype.onMetaC_=function(e,t){var r=this.keyboard.terminal.getDocument();return e.shiftKey||r.getSelection().isCollapsed?t.keyCap.substr(e.shiftKey?1:0,1):(this.keyboard.terminal.clearSelectionAfterCopy&&setTimeout(function(){r.getSelection().collapseToEnd()},50),hterm.Keyboard.KeyActions.PASS)},hterm.Keyboard.KeyMap.prototype.onMetaV_=function(e,t){return e.shiftKey?hterm.Keyboard.KeyActions.PASS:this.keyboard.passMetaV?hterm.Keyboard.KeyActions.PASS:hterm.Keyboard.KeyActions.DEFAULT},hterm.Keyboard.KeyMap.prototype.onPlusMinusZero_=function(e,t){if(!(this.keyboard.ctrlPlusMinusZeroZoom^e.shiftKey))return"-_"==t.keyCap?"":hterm.Keyboard.KeyActions.CANCEL;if(1!=this.keyboard.terminal.getZoomFactor())return hterm.Keyboard.KeyActions.PASS;var r=t.keyCap.substr(0,1);if("0"==r)this.keyboard.terminal.setFontSize(0);else{var o=this.keyboard.terminal.getFontSize();"-"==r||"[KP-]"==t.keyCap?o-=1:o+=1,this.keyboard.terminal.setFontSize(o)}return hterm.Keyboard.KeyActions.CANCEL},hterm.Keyboard.KeyPattern=function(e){this.wildcardCount=0,this.keyCode=e.keyCode,hterm.Keyboard.KeyPattern.modifiers.forEach(function(t){this[t]=e[t]||!1,"*"==this[t]&&this.wildcardCount++}.bind(this))},hterm.Keyboard.KeyPattern.modifiers=["shift","ctrl","alt","meta"],hterm.Keyboard.KeyPattern.sortCompare=function(e,t){return e.wildcardCount<t.wildcardCount?-1:e.wildcardCount>t.wildcardCount?1:0},hterm.Keyboard.KeyPattern.prototype.match_=function(e,t){if(this.keyCode!=e.keyCode)return!1;var r=!0;return hterm.Keyboard.KeyPattern.modifiers.forEach(function(o){var i=o in e?e[o]:!1;r&&(t||"*"!=this[o])&&this[o]!=i&&(r=!1)}.bind(this)),r},hterm.Keyboard.KeyPattern.prototype.matchKeyDown=function(e){return this.match_(e,!1)},hterm.Keyboard.KeyPattern.prototype.matchKeyPattern=function(e){return this.match_(e,!0)},hterm.Options=function(e){this.wraparound=e?e.wraparound:!0,this.reverseWraparound=e?e.reverseWraparound:!1,this.originMode=e?e.originMode:!1,this.autoCarriageReturn=e?e.autoCarriageReturn:!1,this.cursorVisible=e?e.cursorVisible:!1,this.cursorBlink=e?e.cursorBlink:!1,this.insertMode=e?e.insertMode:!1,this.reverseVideo=e?e.reverseVideo:!1,this.bracketedPaste=e?e.bracketedPaste:!1},lib.rtdep("hterm.Keyboard.KeyActions"),hterm.Parser=function(){this.source="",this.pos=0,this.ch=null},hterm.Parser.prototype.error=function(e){return new Error("Parse error at "+this.pos+": "+e)},hterm.Parser.prototype.isComplete=function(){return this.pos==this.source.length},hterm.Parser.prototype.reset=function(e,t){this.source=e,this.pos=t||0,this.ch=e.substr(0,1)},hterm.Parser.prototype.parseKeySequence=function(){var e={keyCode:null};for(var t in hterm.Parser.identifiers.modifierKeys)e[hterm.Parser.identifiers.modifierKeys[t]]=!1;for(;this.pos<this.source.length;){this.skipSpace();var r=this.parseToken();if("integer"==r.type)e.keyCode=r.value;else if("identifier"==r.type)if(r.value in hterm.Parser.identifiers.modifierKeys){var o=hterm.Parser.identifiers.modifierKeys[r.value];if(e[o]&&"*"!=e[o])throw this.error("Duplicate modifier: "+r.value);e[o]=!0}else{if(!(r.value in hterm.Parser.identifiers.keyCodes))throw this.error("Unknown key: "+r.value);e.keyCode=hterm.Parser.identifiers.keyCodes[r.value]}else{if("symbol"!=r.type)throw this.error("Expected integer or identifier");if("*"!=r.value)throw this.error("Unexpected symbol: "+r.value);for(var i in hterm.Parser.identifiers.modifierKeys){var s=hterm.Parser.identifiers.modifierKeys[i];e[s]||(e[s]="*")}}if(this.skipSpace(),"-"!=this.ch)break;if(null!=e.keyCode)throw this.error("Extra definition after target key");this.advance(1)}if(null==e.keyCode)throw this.error("Missing target key");return e},hterm.Parser.prototype.parseKeyAction=function(){this.skipSpace();var e=this.parseToken();if("string"==e.type)return e.value;if("identifier"==e.type){if(e.value in hterm.Parser.identifiers.actions)return hterm.Parser.identifiers.actions[e.value];throw this.error("Unknown key action: "+e.value)}throw this.error("Expected string or identifier")},hterm.Parser.prototype.peekString=function(){return"'"==this.ch||'"'==this.ch},hterm.Parser.prototype.peekIdentifier=function(){return this.ch.match(/[a-z_]/i)},hterm.Parser.prototype.peekInteger=function(){return this.ch.match(/[0-9]/)},hterm.Parser.prototype.parseToken=function(){if("*"==this.ch){var e={type:"symbol",value:this.ch};return this.advance(1),e}if(this.peekIdentifier())return{type:"identifier",value:this.parseIdentifier()};if(this.peekString())return{type:"string",value:this.parseString()};if(this.peekInteger())return{type:"integer",value:this.parseInteger()};throw this.error("Unexpected token")},hterm.Parser.prototype.parseIdentifier=function(){if(!this.peekIdentifier())throw this.error("Expected identifier");return this.parsePattern(/[a-z0-9_]+/gi)},hterm.Parser.prototype.parseInteger=function(){return"0"==this.ch&&this.pos<this.source.length-1&&"x"==this.source.substr(this.pos+1,1)?parseInt(this.parsePattern(/0x[0-9a-f]+/gi)):parseInt(this.parsePattern(/\d+/g))},hterm.Parser.prototype.parseString=function(){var e="",t=this.ch;if('"'!=t&&"'"!=t)throw this.error("String expected");this.advance(1);for(var r=new RegExp("[\\\\"+t+"]","g");this.pos<this.source.length;){if(r.lastIndex=this.pos,!r.exec(this.source))throw this.error("Unterminated string literal");if(e+=this.source.substring(this.pos,r.lastIndex-1),this.advance(r.lastIndex-this.pos-1),'"'!=t||"\\"!=this.ch)if("'"!=t||"\\"!=this.ch){if(this.ch==t)return this.advance(1),e}else e+=this.ch,this.advance(1);else this.advance(1),e+=this.parseEscape()}throw this.error("Unterminated string literal")},hterm.Parser.prototype.parseEscape=function(){var e={'"':'"',"'":"'","\\":"\\",a:"",b:"\b",e:"",f:"\f",n:"\n",r:"\r",t:"	",v:"",x:function(){var e=this.parsePattern(/[a-z0-9]{2}/gi);return String.fromCharCode(parseInt(e,16))},u:function(){var e=this.parsePattern(/[a-z0-9]{4}/gi);return String.fromCharCode(parseInt(e,16))}};if(!(this.ch in e))throw this.error("Unknown escape: "+this.ch);var t=e[this.ch];return this.advance(1),"function"==typeof t&&(t=t.call(this)),t},hterm.Parser.prototype.parsePattern=function(e){if(!e.global)throw this.error("Internal error: Span patterns must be global");e.lastIndex=this.pos;var t=e.exec(this.source);if(!t||e.lastIndex-t[0].length!=this.pos)throw this.error("Expected match for: "+e);return this.pos=e.lastIndex-1,this.advance(1),t[0]},hterm.Parser.prototype.advance=function(e){this.pos+=e,this.ch=this.source.substr(this.pos,1)},hterm.Parser.prototype.skipSpace=function(e){if(/\s/.test(this.ch)){var t=/\s+/gm;t.lastIndex=this.pos;var r=this.source;if(t.exec(r)&&(this.pos=t.lastIndex),this.ch=this.source.substr(this.pos,1),e&&-1==this.ch.indexOf(e))throw this.error("Expected one of "+e+", found: "+this.ch)}},hterm.Parser.identifiers={},hterm.Parser.identifiers.modifierKeys={Shift:"shift",Ctrl:"ctrl",Alt:"alt",Meta:"meta"},hterm.Parser.identifiers.keyCodes={ESC:27,F1:112,F2:113,F3:114,F4:115,F5:116,F6:117,F7:118,F8:119,F9:120,F10:121,F11:122,F12:123,ONE:49,TWO:50,THREE:51,FOUR:52,FIVE:53,SIX:54,SEVEN:55,EIGHT:56,NINE:57,ZERO:48,BACKSPACE:8,TAB:9,Q:81,W:87,E:69,R:82,T:84,Y:89,U:85,I:73,O:79,P:80,CAPSLOCK:20,A:65,S:83,D:68,F:70,G:71,H:72,J:74,K:75,L:76,ENTER:13,Z:90,X:88,C:67,V:86,B:66,N:78,M:77,SPACE:32,PRINT_SCREEN:42,SCROLL_LOCK:145,BREAK:19,INSERT:45,HOME:36,PGUP:33,DEL:46,END:35,PGDOWN:34,UP:38,DOWN:40,RIGHT:39,LEFT:37,NUMLOCK:144,KP0:96,KP1:97,KP2:98,KP3:99,KP4:100,KP5:101,KP6:102,KP7:103,KP8:104,KP9:105,KP_PLUS:107,KP_MINUS:109,KP_STAR:106,KP_DIVIDE:111,KP_DECIMAL:110,NAVIGATE_BACK:166,NAVIGATE_FORWARD:167,RELOAD:168,FULL_SCREEN:183,WINDOW_OVERVIEW:182,BRIGHTNESS_UP:216,BRIGHTNESS_DOWN:217},hterm.Parser.identifiers.actions={CANCEL:hterm.Keyboard.KeyActions.CANCEL,DEFAULT:hterm.Keyboard.KeyActions.DEFAULT,PASS:hterm.Keyboard.KeyActions.PASS,scrollPageUp:function(e){return e.scrollPageUp(),hterm.Keyboard.KeyActions.CANCEL},scrollPageDown:function(e){return e.scrollPageDown(),hterm.Keyboard.KeyActions.CANCEL},scrollToTop:function(e){return e.scrollEnd(),hterm.Keyboard.KeyActions.CANCEL},scrollToBottom:function(e){return e.scrollEnd(),hterm.Keyboard.KeyActions.CANCEL},clearScrollback:function(e){return e.wipeContents(),hterm.Keyboard.KeyActions.CANCEL}},lib.rtdep("lib.f","lib.Storage"),hterm.PreferenceManager=function(e){lib.PreferenceManager.call(this,hterm.defaultStorage,"/hterm/profiles/"+e);var t=hterm.PreferenceManager.defaultPreferences;Object.keys(t).forEach(function(e){this.definePreference(e,t[e][1])}.bind(this))},hterm.PreferenceManager.categories={},hterm.PreferenceManager.categories.Keyboard="Keyboard",hterm.PreferenceManager.categories.Appearance="Appearance",hterm.PreferenceManager.categories.CopyPaste="CopyPaste",hterm.PreferenceManager.categories.Sounds="Sounds",hterm.PreferenceManager.categories.Scrolling="Scrolling",hterm.PreferenceManager.categories.Encoding="Encoding",hterm.PreferenceManager.categories.Miscellaneous="Miscellaneous",hterm.PreferenceManager.categoryDefinitions=[{id:hterm.PreferenceManager.categories.Appearance,text:"Appearance (fonts, colors, images)"},{id:hterm.PreferenceManager.categories.CopyPaste,text:"Copy & Paste"},{id:hterm.PreferenceManager.categories.Encoding,text:"Encoding"},{id:hterm.PreferenceManager.categories.Keyboard,text:"Keyboard"},{id:hterm.PreferenceManager.categories.Scrolling,text:"Scrolling"},{id:hterm.PreferenceManager.categories.Sounds,text:"Sounds"},{id:hterm.PreferenceManager.categories.Miscellaneous,text:"Misc."}],hterm.PreferenceManager.defaultPreferences={"alt-gr-mode":[hterm.PreferenceManager.categories.Keyboard,null,[null,"none","ctrl-alt","left-alt","right-alt"],"Select an AltGr detection hack^Wheuristic.\n\n'null': Autodetect based on navigator.language:\n      'en-us' => 'none', else => 'right-alt'\n'none': Disable any AltGr related munging.\n'ctrl-alt': Assume Ctrl+Alt means AltGr.\n'left-alt': Assume left Alt means AltGr.\n'right-alt': Assume right Alt means AltGr.\n"],"alt-backspace-is-meta-backspace":[hterm.PreferenceManager.categories.Keyboard,!1,"bool","If set, undoes the Chrome OS Alt-Backspace->DEL remap, so that alt-backspace indeed is alt-backspace."],"alt-is-meta":[hterm.PreferenceManager.categories.Keyboard,!1,"bool","Set whether the alt key acts as a meta key or as a distinct alt key."],"alt-sends-what":[hterm.PreferenceManager.categories.Keyboard,"escape",["escape","8-bit","browser-key"],"Controls how the alt key is handled.\n\n  escape....... Send an ESC prefix.\n  8-bit........ Add 128 to the unshifted character as in xterm.\n  browser-key.. Wait for the keypress event and see what the browser \n                says.  (This won't work well on platforms where the \n                browser performs a default action for some alt sequences.)"],"audible-bell-sound":[hterm.PreferenceManager.categories.Sounds,"lib-resource:hterm/audio/bell","url","URL of the terminal bell sound.  Empty string for no audible bell."],"desktop-notification-bell":[hterm.PreferenceManager.categories.Sounds,!1,"bool",'If true, terminal bells in the background will create a Web Notification. https://www.w3.org/TR/notifications/\n\nDisplaying notifications requires permission from the user. When this option is set to true, hterm will attempt to ask the user for permission if necessary. Note browsers may not show this permission request if it did not originate from a user action.\n\nChrome extensions with the "notifications" permission have permission to display notifications.'],"background-color":[hterm.PreferenceManager.categories.Appearance,"rgb(16, 16, 16)","color","The background color for text with no other color attributes."],"background-image":[hterm.PreferenceManager.categories.Appearance,"","string","CSS value of the background image.  Empty string for no image.\n\nFor example:\n  url(https://goo.gl/anedTK)\n  linear-gradient(top bottom, blue, red)"],"background-size":[hterm.PreferenceManager.categories.Appearance,"","string","CSS value of the background image size.  Defaults to none."],"background-position":[hterm.PreferenceManager.categories.Appearance,"","string","CSS value of the background image position.\n\nFor example:\n  10% 10%\n  center"],"backspace-sends-backspace":[hterm.PreferenceManager.categories.Keyboard,!1,"bool","If true, the backspace should send BS ('\\x08', aka ^H).  Otherwise the backspace key should send '\\x7f'."],"character-map-overrides":[hterm.PreferenceManager.categories.Appearance,null,"value",'This is specified as an object. It is a sparse array, where each property is the character set code and the value is an object that is a sparse array itself. In that sparse array, each property is the received character and the value is the displayed character.\n\nFor example:\n  {"0":{"+":"\\u2192",",":"\\u2190","-":"\\u2191",".":"\\u2193", "0":"\\u2588"}}'],"close-on-exit":[hterm.PreferenceManager.categories.Miscellaneous,!0,"bool","Whether or not to close the window when the command exits."],"cursor-blink":[hterm.PreferenceManager.categories.Appearance,!1,"bool","Whether or not to blink the cursor by default."],"cursor-blink-cycle":[hterm.PreferenceManager.categories.Appearance,[1e3,500],"value","The cursor blink rate in milliseconds.\n\nA two element array, the first of which is how long the cursor should be on, second is how long it should be off."],"cursor-color":[hterm.PreferenceManager.categories.Appearance,"rgba(255, 0, 0, 0.5)","color","The color of the visible cursor."],"color-palette-overrides":[hterm.PreferenceManager.categories.Appearance,null,"value","Override colors in the default palette.\n\nThis can be specified as an array or an object.  If specified as an object it is assumed to be a sparse array, where each property is a numeric index into the color palette.\n\nValues can be specified as almost any css color value.  This includes #RGB, #RRGGBB, rgb(...), rgba(...), and any color names that are also part of the stock X11 rgb.txt file.\n\nYou can use 'null' to specify that the default value should be not be changed.  This is useful for skipping a small number of indices when the value is specified as an array."],"copy-on-select":[hterm.PreferenceManager.categories.CopyPaste,!0,"bool","Automatically copy mouse selection to the clipboard."],"use-default-window-copy":[hterm.PreferenceManager.categories.CopyPaste,!1,"bool","Whether to use the default window copy behavior"],"clear-selection-after-copy":[hterm.PreferenceManager.categories.CopyPaste,!0,"bool","Whether to clear the selection after copying."],"ctrl-plus-minus-zero-zoom":[hterm.PreferenceManager.categories.Keyboard,!0,"bool","If true, Ctrl-Plus/Minus/Zero controls zoom.\nIf false, Ctrl-Shift-Plus/Minus/Zero controls zoom, Ctrl-Minus sends ^_, Ctrl-Plus/Zero do nothing."],"ctrl-c-copy":[hterm.PreferenceManager.categories.Keyboard,!1,"bool","Ctrl+C copies if true, send ^C to host if false.\nCtrl+Shift+C sends ^C to host if true, copies if false."],"ctrl-v-paste":[hterm.PreferenceManager.categories.Keyboard,!1,"bool","Ctrl+V pastes if true, send ^V to host if false.\nCtrl+Shift+V sends ^V to host if true, pastes if false."],"east-asian-ambiguous-as-two-column":[hterm.PreferenceManager.categories.Keyboard,!1,"bool","Set whether East Asian Ambiguous characters have two column width."],"enable-8-bit-control":[hterm.PreferenceManager.categories.Keyboard,!1,"bool","True to enable 8-bit control characters, false to ignore them.\n\nWe'll respect the two-byte versions of these control characters regardless of this setting."],"enable-bold":[hterm.PreferenceManager.categories.Appearance,null,"tristate","True if we should use bold weight font for text with the bold/bright attribute.  False to use the normal weight font.  Null to autodetect."],
-"enable-bold-as-bright":[hterm.PreferenceManager.categories.Appearance,!0,"bool","True if we should use bright colors (8-15 on a 16 color palette) for any text with the bold attribute.  False otherwise."],"enable-blink":[hterm.PreferenceManager.categories.Appearance,!0,"bool","True if we should respect the blink attribute.  False to ignore it.  "],"enable-clipboard-notice":[hterm.PreferenceManager.categories.CopyPaste,!0,"bool","Show a message in the terminal when the host writes to the clipboard."],"enable-clipboard-write":[hterm.PreferenceManager.categories.CopyPaste,!0,"bool","Allow the host to write directly to the system clipboard."],"enable-dec12":[hterm.PreferenceManager.categories.Miscellaneous,!1,"bool","Respect the host's attempt to change the cursor blink status using DEC Private Mode 12."],environment:[hterm.PreferenceManager.categories.Miscellaneous,{TERM:"xterm-256color"},"value","The default environment variables, as an object."],"font-family":[hterm.PreferenceManager.categories.Appearance,'"DejaVu Sans Mono", "Everson Mono", FreeMono, "Menlo", "Terminal", monospace',"string","Default font family for the terminal text."],"font-size":[hterm.PreferenceManager.categories.Appearance,15,"int","The default font size in pixels."],"font-smoothing":[hterm.PreferenceManager.categories.Appearance,"antialiased","string","CSS font-smoothing property."],"foreground-color":[hterm.PreferenceManager.categories.Appearance,"rgb(240, 240, 240)","color","The foreground color for text with no other color attributes."],"home-keys-scroll":[hterm.PreferenceManager.categories.Keyboard,!1,"bool","If true, home/end will control the terminal scrollbar and shift home/end will send the VT keycodes.  If false then home/end sends VT codes and shift home/end scrolls."],keybindings:[hterm.PreferenceManager.categories.Keyboard,null,"value",'A map of key sequence to key actions.  Key sequences include zero or more modifier keys followed by a key code.  Key codes can be decimal or hexadecimal numbers, or a key identifier.  Key actions can be specified a string to send to the host, or an action identifier.  For a full list of key code and action identifiers, see https://goo.gl/8AoD09.\n\nSample keybindings:\n{ "Ctrl-Alt-K": "clearScrollback",\n  "Ctrl-Shift-L": "PASS",\n  "Ctrl-H": "\'HELLO\\n\'"\n}'],"max-string-sequence":[hterm.PreferenceManager.categories.Encoding,1e5,"int","Max length of a DCS, OSC, PM, or APS sequence before we give up and ignore the code."],"media-keys-are-fkeys":[hterm.PreferenceManager.categories.Keyboard,!1,"bool","If true, convert media keys to their Fkey equivalent. If false, let the browser handle the keys."],"meta-sends-escape":[hterm.PreferenceManager.categories.Keyboard,!0,"bool","Set whether the meta key sends a leading escape or not."],"mouse-paste-button":[hterm.PreferenceManager.categories.CopyPaste,null,[null,0,1,2,3,4,5,6],"Mouse paste button, or null to autodetect.\n\nFor autodetect, we'll try to enable middle button paste for non-X11 platforms.  On X11 we move it to button 3."],"page-keys-scroll":[hterm.PreferenceManager.categories.Keyboard,!1,"bool","If true, page up/down will control the terminal scrollbar and shift page up/down will send the VT keycodes.  If false then page up/down sends VT codes and shift page up/down scrolls."],"pass-alt-number":[hterm.PreferenceManager.categories.Keyboard,null,"tristate","Set whether we should pass Alt-1..9 to the browser.\n\nThis is handy when running hterm in a browser tab, so that you don't lose Chrome's \"switch to tab\" keyboard accelerators.  When not running in a tab it's better to send these keys to the host so they can be used in vim or emacs.\n\nIf true, Alt-1..9 will be handled by the browser.  If false, Alt-1..9 will be sent to the host.  If null, autodetect based on browser platform and window type."],"pass-ctrl-number":[hterm.PreferenceManager.categories.Keyboard,null,"tristate","Set whether we should pass Ctrl-1..9 to the browser.\n\nThis is handy when running hterm in a browser tab, so that you don't lose Chrome's \"switch to tab\" keyboard accelerators.  When not running in a tab it's better to send these keys to the host so they can be used in vim or emacs.\n\nIf true, Ctrl-1..9 will be handled by the browser.  If false, Ctrl-1..9 will be sent to the host.  If null, autodetect based on browser platform and window type."],"pass-meta-number":[hterm.PreferenceManager.categories.Keyboard,null,"tristate","Set whether we should pass Meta-1..9 to the browser.\n\nThis is handy when running hterm in a browser tab, so that you don't lose Chrome's \"switch to tab\" keyboard accelerators.  When not running in a tab it's better to send these keys to the host so they can be used in vim or emacs.\n\nIf true, Meta-1..9 will be handled by the browser.  If false, Meta-1..9 will be sent to the host.  If null, autodetect based on browser platform and window type."],"pass-meta-v":[hterm.PreferenceManager.categories.Keyboard,!0,"bool","Set whether meta-V gets passed to host."],"receive-encoding":[hterm.PreferenceManager.categories.Encoding,"utf-8",["utf-8","raw"],"Set the expected encoding for data received from the host.\n\nValid values are 'utf-8' and 'raw'."],"scroll-on-keystroke":[hterm.PreferenceManager.categories.Scrolling,!0,"bool","If true, scroll to the bottom on any keystroke."],"scroll-on-output":[hterm.PreferenceManager.categories.Scrolling,!1,"bool","If true, scroll to the bottom on terminal output."],"scrollbar-visible":[hterm.PreferenceManager.categories.Scrolling,!0,"bool","The vertical scrollbar mode."],"scroll-wheel-move-multiplier":[hterm.PreferenceManager.categories.Scrolling,1,"int","The multiplier for the pixel delta in mousewheel event caused by the scroll wheel. Alters how fast the page scrolls."],"send-encoding":[hterm.PreferenceManager.categories.Encoding,"utf-8",["utf-8","raw"],"Set the encoding for data sent to host."],"shift-insert-paste":[hterm.PreferenceManager.categories.Keyboard,!0,"bool","Shift + Insert pastes if true, sent to host if false."],"user-css":[hterm.PreferenceManager.categories.Appearance,"","url","URL of user stylesheet to include in the terminal document."]},hterm.PreferenceManager.prototype={__proto__:lib.PreferenceManager.prototype},hterm.PubSub=function(){this.observers_={}},hterm.PubSub.addBehavior=function(e){var t=new hterm.PubSub;for(var r in hterm.PubSub.prototype)e[r]=hterm.PubSub.prototype[r].bind(t)},hterm.PubSub.prototype.subscribe=function(e,t){e in this.observers_||(this.observers_[e]=[]),this.observers_[e].push(t)},hterm.PubSub.prototype.unsubscribe=function(e,t){var r=this.observers_[e];if(!r)throw"Invalid subject: "+e;var o=r.indexOf(t);if(0>o)throw"Not subscribed: "+e;r.splice(o,1)},hterm.PubSub.prototype.publish=function(e,t,r){function o(e){e<i.length-1&&setTimeout(o,0,e+1),i[e](t)}var i=this.observers_[e];i&&(i=[].concat(i)),r&&(i?i.push(r):i=[r]),i&&setTimeout(o,0,0)},lib.rtdep("lib.f","lib.wc","hterm.RowCol","hterm.Size","hterm.TextAttributes"),hterm.Screen=function(e){this.rowsArray=[],this.columnCount_=e||80,this.textAttributes=new hterm.TextAttributes(window.document),this.cursorPosition=new hterm.RowCol(0,0),this.cursorRowNode_=null,this.cursorNode_=null,this.cursorOffset_=null},hterm.Screen.prototype.getSize=function(){return new hterm.Size(this.columnCount_,this.rowsArray.length)},hterm.Screen.prototype.getHeight=function(){return this.rowsArray.length},hterm.Screen.prototype.getWidth=function(){return this.columnCount_},hterm.Screen.prototype.setColumnCount=function(e){this.columnCount_=e,this.cursorPosition.column>=e&&this.setCursorPosition(this.cursorPosition.row,e-1)},hterm.Screen.prototype.shiftRow=function(){return this.shiftRows(1)[0]},hterm.Screen.prototype.shiftRows=function(e){return this.rowsArray.splice(0,e)},hterm.Screen.prototype.unshiftRow=function(e){this.rowsArray.splice(0,0,e)},hterm.Screen.prototype.unshiftRows=function(e){this.rowsArray.unshift.apply(this.rowsArray,e)},hterm.Screen.prototype.popRow=function(){return this.popRows(1)[0]},hterm.Screen.prototype.popRows=function(e){return this.rowsArray.splice(this.rowsArray.length-e,e)},hterm.Screen.prototype.pushRow=function(e){this.rowsArray.push(e)},hterm.Screen.prototype.pushRows=function(e){e.push.apply(this.rowsArray,e)},hterm.Screen.prototype.insertRow=function(e,t){this.rowsArray.splice(e,0,t)},hterm.Screen.prototype.insertRows=function(e,t){for(var r=0;r<t.length;r++)this.rowsArray.splice(e+r,0,t[r])},hterm.Screen.prototype.removeRow=function(e){return this.rowsArray.splice(e,1)[0]},hterm.Screen.prototype.removeRows=function(e,t){return this.rowsArray.splice(e,t)},hterm.Screen.prototype.invalidateCursorPosition=function(){this.cursorPosition.move(0,0),this.cursorRowNode_=null,this.cursorNode_=null,this.cursorOffset_=null},hterm.Screen.prototype.clearCursorRow=function(){this.cursorRowNode_.innerHTML="",this.cursorRowNode_.removeAttribute("line-overflow"),this.cursorOffset_=0,this.cursorPosition.column=0,this.cursorPosition.overflow=!1;var e;e=this.textAttributes.isDefault()?"":lib.f.getWhitespace(this.columnCount_);var t=this.textAttributes.inverse;this.textAttributes.inverse=!1,this.textAttributes.syncColors();var r=this.textAttributes.createContainer(e);this.cursorRowNode_.appendChild(r),this.cursorNode_=r,this.textAttributes.inverse=t,this.textAttributes.syncColors()},hterm.Screen.prototype.commitLineOverflow=function(){this.cursorRowNode_.setAttribute("line-overflow",!0)},hterm.Screen.prototype.setCursorPosition=function(e,t){if(!this.rowsArray.length)return void console.warn("Attempt to set cursor position on empty screen.");e>=this.rowsArray.length?(console.error("Row out of bounds: "+e),e=this.rowsArray.length-1):0>e&&(console.error("Row out of bounds: "+e),e=0),t>=this.columnCount_?(console.error("Column out of bounds: "+t),t=this.columnCount_-1):0>t&&(console.error("Column out of bounds: "+t),t=0),this.cursorPosition.overflow=!1;var r=this.rowsArray[e],o=r.firstChild;o||(o=r.ownerDocument.createTextNode(""),r.appendChild(o));var i=0;for(r==this.cursorRowNode_?t>=this.cursorPosition.column-this.cursorOffset_&&(o=this.cursorNode_,i=this.cursorPosition.column-this.cursorOffset_):this.cursorRowNode_=r,this.cursorPosition.move(e,t);o;){var s=t-i,n=hterm.TextAttributes.nodeWidth(o);if(!o.nextSibling||n>s)return this.cursorNode_=o,void(this.cursorOffset_=s);i+=n,o=o.nextSibling}},hterm.Screen.prototype.syncSelectionCaret=function(e){try{e.collapse(this.cursorNode_,this.cursorOffset_)}catch(t){}},hterm.Screen.prototype.splitNode_=function(e,t){var r=e.cloneNode(!1),o=e.textContent;e.textContent=hterm.TextAttributes.nodeSubstr(e,0,t),r.textContent=lib.wc.substr(o,t),r.textContent&&e.parentNode.insertBefore(r,e.nextSibling),e.textContent||e.parentNode.removeChild(e)},hterm.Screen.prototype.maybeClipCurrentRow=function(){var e=hterm.TextAttributes.nodeWidth(this.cursorRowNode_);if(e<=this.columnCount_)return void(this.cursorPosition.column>=this.columnCount_&&(this.setCursorPosition(this.cursorPosition.row,this.columnCount_-1),this.cursorPosition.overflow=!0));var t=this.cursorPosition.column;this.setCursorPosition(this.cursorPosition.row,this.columnCount_-1),e=hterm.TextAttributes.nodeWidth(this.cursorNode_),this.cursorOffset_<e-1&&(this.cursorNode_.textContent=hterm.TextAttributes.nodeSubstr(this.cursorNode_,0,this.cursorOffset_+1));for(var r=this.cursorRowNode_,o=this.cursorNode_.nextSibling;o;)r.removeChild(o),o=this.cursorNode_.nextSibling;t<this.columnCount_?this.setCursorPosition(this.cursorPosition.row,t):this.cursorPosition.overflow=!0},hterm.Screen.prototype.insertString=function(e){var t=this.cursorNode_,r=t.textContent;this.cursorRowNode_.removeAttribute("line-overflow");var o=lib.wc.strWidth(e);this.cursorPosition.column+=o;var i=this.cursorOffset_,s=hterm.TextAttributes.nodeWidth(t)-i;if(0>s){var n=lib.f.getWhitespace(-s);if(this.textAttributes.underline||this.textAttributes.strikethrough||this.textAttributes.background||this.textAttributes.wcNode||null!=this.textAttributes.tileData)if(3!=t.nodeType&&(t.wcNode||t.tileNode||t.style.textDecoration||t.style.backgroundColor)){var a=t.ownerDocument.createTextNode(n);this.cursorRowNode_.insertBefore(a,t.nextSibling),this.cursorNode_=t=a,this.cursorOffset_=i=-s,r=n}else t.textContent=r+=n;else e=n+e;s=0}if(this.textAttributes.matchesContainer(t))return 0==s?t.textContent=r+e:0==i?t.textContent=e+r:t.textContent=hterm.TextAttributes.nodeSubstr(t,0,i)+e+hterm.TextAttributes.nodeSubstr(t,i),void(this.cursorOffset_+=o);if(0==i){var l=t.previousSibling;if(l&&this.textAttributes.matchesContainer(l))return l.textContent+=e,this.cursorNode_=l,void(this.cursorOffset_=lib.wc.strWidth(l.textContent));var h=this.textAttributes.createContainer(e);return this.cursorRowNode_.insertBefore(h,t),this.cursorNode_=h,void(this.cursorOffset_=o)}if(0==s){var c=t.nextSibling;if(c&&this.textAttributes.matchesContainer(c))return c.textContent=e+c.textContent,this.cursorNode_=c,void(this.cursorOffset_=lib.wc.strWidth(e));var h=this.textAttributes.createContainer(e);return this.cursorRowNode_.insertBefore(h,c),this.cursorNode_=h,void(this.cursorOffset_=hterm.TextAttributes.nodeWidth(h))}this.splitNode_(t,i);var h=this.textAttributes.createContainer(e);this.cursorRowNode_.insertBefore(h,t.nextSibling),this.cursorNode_=h,this.cursorOffset_=o},hterm.Screen.prototype.overwriteString=function(e){var t=this.columnCount_-this.cursorPosition.column;if(!t)return[e];var r=lib.wc.strWidth(e);return this.textAttributes.matchesContainer(this.cursorNode_)&&this.cursorNode_.textContent.substr(this.cursorOffset_)==e?(this.cursorOffset_+=r,void(this.cursorPosition.column+=r)):(this.deleteChars(Math.min(r,t)),void this.insertString(e))},hterm.Screen.prototype.deleteChars=function(e){var t=this.cursorNode_,r=this.cursorOffset_,o=this.cursorPosition.column;if(e=Math.min(e,this.columnCount_-o),!e)return 0;for(var i,s,n=e;t&&e;){if(i=hterm.TextAttributes.nodeWidth(t),t.textContent=hterm.TextAttributes.nodeSubstr(t,0,r)+hterm.TextAttributes.nodeSubstr(t,r+e),s=hterm.TextAttributes.nodeWidth(t),e-=i-s,i>r&&s&&i==s){var a=this.textAttributes.createContainer(" ");t.parentNode.insertBefore(a,t.nextSibling),t.textContent="",s=0,e-=1}var l=t.nextSibling;0==s&&t!=this.cursorNode_&&t.parentNode.removeChild(t),t=l,r=0}if(3!=this.cursorNode_.nodeType&&!this.cursorNode_.textContent){var h=this.cursorNode_;if(h.previousSibling)this.cursorNode_=h.previousSibling,this.cursorOffset_=hterm.TextAttributes.nodeWidth(h.previousSibling);else if(h.nextSibling)this.cursorNode_=h.nextSibling,this.cursorOffset_=0;else{var c=this.cursorRowNode_.ownerDocument.createTextNode("");this.cursorRowNode_.appendChild(c),this.cursorNode_=c,this.cursorOffset_=0}this.cursorRowNode_.removeChild(h)}return n},hterm.Screen.prototype.getLineStartRow_=function(e){for(;e.previousSibling&&e.previousSibling.hasAttribute("line-overflow");)e=e.previousSibling;return e},hterm.Screen.prototype.getLineText_=function(e){for(var t="";e&&(t+=e.textContent,e.hasAttribute("line-overflow"));)e=e.nextSibling;return t},hterm.Screen.prototype.getXRowAncestor_=function(e){for(;e&&"X-ROW"!==e.nodeName;)e=e.parentNode;return e},hterm.Screen.prototype.getPositionWithOverflow_=function(e,t,r){if(!t)return-1;var o=this.getXRowAncestor_(t);if(!o)return-1;for(var i=0;o!=e;){if(i+=hterm.TextAttributes.nodeWidth(e),!e.hasAttribute("line-overflow")||!e.nextSibling)return-1;e=e.nextSibling}return i+this.getPositionWithinRow_(e,t,r)},hterm.Screen.prototype.getPositionWithinRow_=function(e,t,r){if(t.parentNode!=e)return this.getPositionWithinRow_(t.parentNode,t,r)+this.getPositionWithinRow_(e,t.parentNode,0);for(var o=0,i=0;i<e.childNodes.length;i++){var s=e.childNodes[i];if(s==t)return o+r;o+=hterm.TextAttributes.nodeWidth(s)}return-1},hterm.Screen.prototype.getNodeAndOffsetWithOverflow_=function(e,t){for(;e&&t>hterm.TextAttributes.nodeWidth(e);){if(!e.hasAttribute("line-overflow")||!e.nextSibling)return-1;t-=hterm.TextAttributes.nodeWidth(e),e=e.nextSibling}return this.getNodeAndOffsetWithinRow_(e,t)},hterm.Screen.prototype.getNodeAndOffsetWithinRow_=function(e,t){for(var r=0;r<e.childNodes.length;r++){var o=e.childNodes[r],i=hterm.TextAttributes.nodeWidth(o);if(i>=t)return"SPAN"===o.nodeName?this.getNodeAndOffsetWithinRow_(o,t):[o,t];t-=i}return null},hterm.Screen.prototype.setRange_=function(e,t,r,o){var i=this.getNodeAndOffsetWithOverflow_(e,t);if(null!=i){var s=this.getNodeAndOffsetWithOverflow_(e,r);null!=s&&(o.setStart(i[0],i[1]),o.setEnd(s[0],s[1]))}},hterm.Screen.prototype.expandSelection=function(e){if(e){var t=e.getRangeAt(0);if(t&&!t.toString().match(/\s/)){var r=this.getLineStartRow_(this.getXRowAncestor_(t.startContainer));if(r){var o=this.getPositionWithOverflow_(r,t.startContainer,t.startOffset);if(-1!=o){var i=this.getPositionWithOverflow_(r,t.endContainer,t.endOffset);if(-1!=i){var s="[^\\s\\[\\](){}<>\"'\\^!@#$%&*,;:`]",n="[^\\s\\[\\](){}<>\"'\\^!@#$%&*,;:~.`]",a="[^\\s\\[\\](){}<>\"'\\^]*",l=this.getLineText_(r),h=lib.wc.substring(l,0,i),c=new RegExp(s+a+"$"),u=h.search(c);if(!(-1==u||u>o)){var g=lib.wc.substring(l,o,lib.wc.strWidth(l)),d=new RegExp("^"+a+n),p=g.match(d);if(p){var m=o+lib.wc.strWidth(p[0]);-1==m||i>m||(this.setRange_(r,u,m,t),e.addRange(t))}}}}}}}},lib.rtdep("lib.f","hterm.PubSub","hterm.Size"),hterm.ScrollPort=function(e){hterm.PubSub.addBehavior(this),this.rowProvider_=e,this.characterSize=new hterm.Size(10,10),this.ruler_=null,this.selection=new hterm.ScrollPort.Selection(this),this.currentRowNodeCache_=null,this.previousRowNodeCache_={},this.lastScreenWidth_=null,this.lastScreenHeight_=null,this.selectionEnabled_=!0,this.lastRowCount_=0,this.scrollWheelMultiplier_=1,this.isScrolledEnd=!0,this.xrowCssRule_=null,this.currentScrollbarWidthPx=16,this.ctrlVPaste=!1,this.div_=null,this.document_=null,this.timeouts_={},this.observers_={},this.DEBUG_=!1},hterm.ScrollPort.Selection=function(e){this.scrollPort_=e,this.startRow=null,this.endRow=null,this.isMultiline=null,this.isCollapsed=null},hterm.ScrollPort.Selection.prototype.findFirstChild=function(e,t){for(var r=e.firstChild;r;){if(-1!=t.indexOf(r))return r;if(r.childNodes.length){var o=this.findFirstChild(r,t);if(o)return o}r=r.nextSibling}return null},hterm.ScrollPort.Selection.prototype.sync=function(){function e(){r.startRow=i,r.startNode=o.anchorNode,r.startOffset=o.anchorOffset,r.endRow=s,r.endNode=o.focusNode,r.endOffset=o.focusOffset}function t(){r.startRow=s,r.startNode=o.focusNode,r.startOffset=o.focusOffset,r.endRow=i,r.endNode=o.anchorNode,r.endOffset=o.anchorOffset}var r=this,o=this.scrollPort_.getDocument().getSelection();if(this.startRow=null,this.endRow=null,this.isMultiline=null,this.isCollapsed=!o||o.isCollapsed,!this.isCollapsed){for(var i=o.anchorNode;i&&!("rowIndex"in i);)i=i.parentNode;if(!i)return void console.error("Selection anchor is not rooted in a row node: "+o.anchorNode.nodeName);for(var s=o.focusNode;s&&!("rowIndex"in s);)s=s.parentNode;if(!s)return void console.error("Selection focus is not rooted in a row node: "+o.focusNode.nodeName);if(i.rowIndex<s.rowIndex)e();else if(i.rowIndex>s.rowIndex)t();else if(o.focusNode==o.anchorNode)o.anchorOffset<o.focusOffset?e():t();else{var n=this.findFirstChild(i,[o.anchorNode,o.focusNode]);if(!n)throw new Error("Unexpected error syncing selection.");n==o.anchorNode?e():t()}this.isMultiline=i.rowIndex!=s.rowIndex}},hterm.ScrollPort.prototype.decorate=function(e){this.div_=e,this.iframe_=e.ownerDocument.createElement("iframe"),this.iframe_.style.cssText="border: 0;height: 100%;position: absolute;width: 100%","mozInnerScreenX"in window&&(this.iframe_.src="#"),e.appendChild(this.iframe_),this.iframe_.contentWindow.addEventListener("resize",this.onResize_.bind(this));var t=this.document_=this.iframe_.contentDocument;t.body.style.cssText="margin: 0px;padding: 0px;height: 100%;width: 100%;overflow: hidden;cursor: text;-webkit-user-select: none;-moz-user-select: none;";var r=t.createElement("style");r.textContent="x-row {}",t.head.appendChild(r),this.xrowCssRule_=t.styleSheets[0].cssRules[0],this.xrowCssRule_.style.display="block",this.userCssLink_=t.createElement("link"),this.userCssLink_.setAttribute("rel","stylesheet"),this.screen_=t.createElement("x-screen"),this.screen_.setAttribute("role","textbox"),this.screen_.setAttribute("tabindex","-1"),this.screen_.style.cssText="display: block;font-family: monospace;font-size: 15px;font-variant-ligatures: none;height: 100%;overflow-y: scroll; overflow-x: hidden;white-space: pre;width: 100%;outline: none !important",t.body.appendChild(this.screen_),this.screen_.addEventListener("scroll",this.onScroll_.bind(this)),this.screen_.addEventListener("mousewheel",this.onScrollWheel_.bind(this)),this.screen_.addEventListener("DOMMouseScroll",this.onScrollWheel_.bind(this)),this.screen_.addEventListener("copy",this.onCopy_.bind(this)),this.screen_.addEventListener("paste",this.onPaste_.bind(this)),t.body.addEventListener("keydown",this.onBodyKeyDown_.bind(this)),this.rowNodes_=t.createElement("div"),this.rowNodes_.style.cssText="display: block;position: fixed;overflow: hidden;-webkit-user-select: text;-moz-user-select: text;",this.screen_.appendChild(this.rowNodes_),this.topSelectBag_=t.createElement("x-select-bag"),this.topSelectBag_.style.cssText="display: block;overflow: hidden;white-space: pre;",this.bottomSelectBag_=this.topSelectBag_.cloneNode(),this.topFold_=t.createElement("x-fold"),this.topFold_.style.cssText="display: block;",this.rowNodes_.appendChild(this.topFold_),this.bottomFold_=this.topFold_.cloneNode(),this.rowNodes_.appendChild(this.bottomFold_),this.scrollArea_=t.createElement("div"),this.scrollArea_.style.cssText="visibility: hidden",this.screen_.appendChild(this.scrollArea_);var o="http://www.w3.org/2000/svg";this.svg_=this.div_.ownerDocument.createElementNS(o,"svg"),this.svg_.setAttribute("xmlns",o),this.svg_.setAttribute("version","1.1"),this.svg_.style.cssText="position: absolute;top: 0;left: 0;visibility: hidden",this.pasteTarget_=t.createElement("textarea"),this.pasteTarget_.setAttribute("tabindex","-1"),this.pasteTarget_.style.cssText="position: absolute;height: 1px;width: 1px;left: 0px; bottom: 0px;opacity: 0",this.pasteTarget_.contentEditable=!0,this.screen_.appendChild(this.pasteTarget_),this.pasteTarget_.addEventListener("textInput",this.handlePasteTargetTextInput_.bind(this)),this.resize()},hterm.ScrollPort.prototype.setFontFamily=function(e,t){this.screen_.style.fontFamily=e,t?this.screen_.style.webkitFontSmoothing=t:this.screen_.style.webkitFontSmoothing="",this.syncCharacterSize()},hterm.ScrollPort.prototype.getFontFamily=function(){return this.screen_.style.fontFamily},hterm.ScrollPort.prototype.setUserCss=function(e){e?(this.userCssLink_.setAttribute("href",e),this.userCssLink_.parentNode||this.document_.head.appendChild(this.userCssLink_)):this.userCssLink_.parentNode&&this.document_.head.removeChild(this.userCssLink_)},hterm.ScrollPort.prototype.focus=function(){this.iframe_.focus(),this.screen_.focus()},hterm.ScrollPort.prototype.getForegroundColor=function(){return this.screen_.style.color},hterm.ScrollPort.prototype.setForegroundColor=function(e){this.screen_.style.color=e},hterm.ScrollPort.prototype.getBackgroundColor=function(){return this.screen_.style.backgroundColor},hterm.ScrollPort.prototype.setBackgroundColor=function(e){this.screen_.style.backgroundColor=e},hterm.ScrollPort.prototype.setBackgroundImage=function(e){this.screen_.style.backgroundImage=e},hterm.ScrollPort.prototype.setBackgroundSize=function(e){this.screen_.style.backgroundSize=e},hterm.ScrollPort.prototype.setBackgroundPosition=function(e){this.screen_.style.backgroundPosition=e},hterm.ScrollPort.prototype.setCtrlVPaste=function(e){this.ctrlVPaste=e},hterm.ScrollPort.prototype.getScreenSize=function(){var e=hterm.getClientSize(this.screen_);return{height:e.height,width:e.width-this.currentScrollbarWidthPx}},hterm.ScrollPort.prototype.getScreenWidth=function(){return this.getScreenSize().width},hterm.ScrollPort.prototype.getScreenHeight=function(){return this.getScreenSize().height},hterm.ScrollPort.prototype.getDocument=function(){return this.document_},hterm.ScrollPort.prototype.getScreenNode=function(){return this.screen_},hterm.ScrollPort.prototype.resetCache=function(){this.currentRowNodeCache_=null,this.previousRowNodeCache_={}},hterm.ScrollPort.prototype.setRowProvider=function(e){this.resetCache(),this.rowProvider_=e,this.scheduleRedraw()},hterm.ScrollPort.prototype.invalidate=function(){for(var e=this.topFold_.nextSibling;e!=this.bottomFold_;){var t=e.nextSibling;e.parentElement.removeChild(e),e=t}this.previousRowNodeCache_=null;var r=this.getTopRowIndex(),o=this.getBottomRowIndex(r);this.drawVisibleRows_(r,o)},hterm.ScrollPort.prototype.scheduleInvalidate=function(){if(!this.timeouts_.invalidate){var e=this;this.timeouts_.invalidate=setTimeout(function(){delete e.timeouts_.invalidate,e.invalidate()},0)}},hterm.ScrollPort.prototype.setFontSize=function(e){this.screen_.style.fontSize=e+"px",this.syncCharacterSize()},hterm.ScrollPort.prototype.getFontSize=function(){return parseInt(this.screen_.style.fontSize)},hterm.ScrollPort.prototype.measureCharacterSize=function(e){var t=100,r="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";if(!this.ruler_){this.ruler_=this.document_.createElement("div"),this.ruler_.style.cssText="position: absolute;top: 0;left: 0;visibility: hidden;height: auto !important;width: auto !important;",this.rulerSpan_=this.document_.createElement("span");for(var o=""+r,i=0;t-1>i;++i)o+=String.fromCharCode(13)+r;this.rulerSpan_.innerHTML=o,this.ruler_.appendChild(this.rulerSpan_),this.rulerBaseline_=this.document_.createElement("span"),this.rulerBaseline_.style.fontSize="0px",this.rulerBaseline_.textContent="X"}this.rulerSpan_.style.fontWeight=e||"",this.rowNodes_.appendChild(this.ruler_);var s=hterm.getClientSize(this.rulerSpan_),n=new hterm.Size(s.width/r.length,s.height/t);return this.ruler_.appendChild(this.rulerBaseline_),n.baseline=this.rulerBaseline_.offsetTop,this.ruler_.removeChild(this.rulerBaseline_),this.rowNodes_.removeChild(this.ruler_),this.div_.ownerDocument.body.appendChild(this.svg_),n.zoomFactor=this.svg_.currentScale,this.div_.ownerDocument.body.removeChild(this.svg_),n},hterm.ScrollPort.prototype.syncCharacterSize=function(){this.characterSize=this.measureCharacterSize();var e=this.characterSize.height+"px";this.xrowCssRule_.style.height=e,this.topSelectBag_.style.height=e,this.bottomSelectBag_.style.height=e,this.resize(),this.DEBUG_&&(this.document_.body.style.paddingTop=this.document_.body.style.paddingBottom=3*this.characterSize.height+"px")},hterm.ScrollPort.prototype.resize=function(){this.currentScrollbarWidthPx=hterm.getClientWidth(this.screen_)-this.screen_.clientWidth,this.syncScrollHeight(),this.syncRowNodesDimensions_();var e=this;this.publish("resize",{scrollPort:this},function(){e.scrollRowToBottom(e.rowProvider_.getRowCount()),e.scheduleRedraw()})},hterm.ScrollPort.prototype.syncRowNodesDimensions_=function(){var e=this.getScreenSize();this.lastScreenWidth_=e.width,this.lastScreenHeight_=e.height,this.visibleRowCount=lib.f.smartFloorDivide(e.height,this.characterSize.height);var t=this.visibleRowCount*this.characterSize.height;this.visibleRowTopMargin=0,this.visibleRowBottomMargin=e.height-t,this.topFold_.style.marginBottom=this.visibleRowTopMargin+"px";for(var r=0,o=this.topFold_.previousSibling;o;)r+=hterm.getClientHeight(o),o=o.previousSibling;this.rowNodes_.style.width=e.width+"px",this.rowNodes_.style.height=t+r+"px",this.rowNodes_.style.left=this.screen_.offsetLeft+"px",this.rowNodes_.style.top=this.screen_.offsetTop-r+"px"},hterm.ScrollPort.prototype.syncScrollHeight=function(){this.lastRowCount_=this.rowProvider_.getRowCount(),this.scrollArea_.style.height=this.characterSize.height*this.lastRowCount_+this.visibleRowTopMargin+this.visibleRowBottomMargin+"px"},hterm.ScrollPort.prototype.scheduleRedraw=function(){if(!this.timeouts_.redraw){var e=this;this.timeouts_.redraw=setTimeout(function(){delete e.timeouts_.redraw,e.redraw_()},0)}},hterm.ScrollPort.prototype.redraw_=function(){this.resetSelectBags_(),this.selection.sync(),this.syncScrollHeight(),this.currentRowNodeCache_={};var e=this.getTopRowIndex(),t=this.getBottomRowIndex(e);this.drawTopFold_(e),this.drawBottomFold_(t),this.drawVisibleRows_(e,t),this.syncRowNodesDimensions_(),this.previousRowNodeCache_=this.currentRowNodeCache_,this.currentRowNodeCache_=null,this.isScrolledEnd=this.getTopRowIndex()+this.visibleRowCount>=this.lastRowCount_},hterm.ScrollPort.prototype.drawTopFold_=function(e){if(!this.selection.startRow||this.selection.startRow.rowIndex>=e)return void(this.rowNodes_.firstChild!=this.topFold_&&this.rowNodes_.insertBefore(this.topFold_,this.rowNodes_.firstChild));if(!this.selection.isMultiline||this.selection.endRow.rowIndex>=e)this.selection.startRow.nextSibling!=this.topFold_&&this.rowNodes_.insertBefore(this.topFold_,this.selection.startRow.nextSibling);else for(this.selection.endRow.nextSibling!=this.topFold_&&this.rowNodes_.insertBefore(this.topFold_,this.selection.endRow.nextSibling);this.selection.startRow.nextSibling!=this.selection.endRow;)this.rowNodes_.removeChild(this.selection.startRow.nextSibling);for(;this.rowNodes_.firstChild!=this.selection.startRow;)this.rowNodes_.removeChild(this.rowNodes_.firstChild)},hterm.ScrollPort.prototype.drawBottomFold_=function(e){if(!this.selection.endRow||this.selection.endRow.rowIndex<=e)return void(this.rowNodes_.lastChild!=this.bottomFold_&&this.rowNodes_.appendChild(this.bottomFold_));if(!this.selection.isMultiline||this.selection.startRow.rowIndex<=e)this.bottomFold_.nextSibling!=this.selection.endRow&&this.rowNodes_.insertBefore(this.bottomFold_,this.selection.endRow);else for(this.bottomFold_.nextSibling!=this.selection.startRow&&this.rowNodes_.insertBefore(this.bottomFold_,this.selection.startRow);this.selection.startRow.nextSibling!=this.selection.endRow;)this.rowNodes_.removeChild(this.selection.startRow.nextSibling);for(;this.rowNodes_.lastChild!=this.selection.endRow;)this.rowNodes_.removeChild(this.rowNodes_.lastChild)},hterm.ScrollPort.prototype.drawVisibleRows_=function(e,t){function r(e,t){for(;e!=t;){if(!e)throw"Did not encounter target node";if(e==o.bottomFold_)throw"Encountered bottom fold before target node";var r=e;e=e.nextSibling,r.parentNode.removeChild(r)}}for(var o=this,i=this.selection.startRow,s=this.selection.endRow,n=this.bottomFold_,a=this.topFold_.nextSibling,l=Math.min(this.visibleRowCount,this.rowProvider_.getRowCount()),h=0;l>h;h++){var c=e+h;if(a!=n)if(a.rowIndex!=c)if(i&&i.rowIndex==c)r(a,i),a=i.nextSibling;else if(s&&s.rowIndex==c)r(a,s),a=s.nextSibling;else if(a!=i&&a!=s){var u=this.fetchRowNode_(c);if(!u){console.log("Couldn't fetch row index: "+c);break}a!=u?(this.rowNodes_.insertBefore(u,a),!u.nextSibling,this.rowNodes_.removeChild(a),a=u.nextSibling):a=a.nextSibling}else{var u=this.fetchRowNode_(c);if(!u){console.log("Couldn't fetch row index: "+c);break}this.rowNodes_.insertBefore(u,a)}else a=a.nextSibling;else{var u=this.fetchRowNode_(c);if(!u){console.log("Couldn't fetch row index: "+c);break}this.rowNodes_.insertBefore(u,a)}}a!=this.bottomFold_&&r(a,n)},hterm.ScrollPort.prototype.resetSelectBags_=function(){this.topSelectBag_.parentNode&&(this.topSelectBag_.textContent="",this.topSelectBag_.parentNode.removeChild(this.topSelectBag_)),this.bottomSelectBag_.parentNode&&(this.bottomSelectBag_.textContent="",this.bottomSelectBag_.parentNode.removeChild(this.bottomSelectBag_))},hterm.ScrollPort.prototype.cacheRowNode_=function(e){this.currentRowNodeCache_[e.rowIndex]=e},hterm.ScrollPort.prototype.fetchRowNode_=function(e){var t;return t=this.previousRowNodeCache_&&e in this.previousRowNodeCache_?this.previousRowNodeCache_[e]:this.rowProvider_.getRowNode(e),this.currentRowNodeCache_&&this.cacheRowNode_(t),t},hterm.ScrollPort.prototype.selectAll=function(){var e;if(0!=this.topFold_.nextSibling.rowIndex){
-for(;this.topFold_.previousSibling;)this.rowNodes_.removeChild(this.topFold_.previousSibling);e=this.fetchRowNode_(0),this.rowNodes_.insertBefore(e,this.topFold_),this.syncRowNodesDimensions_()}else e=this.topFold_.nextSibling;var t,r=this.rowProvider_.getRowCount()-1;if(this.bottomFold_.previousSibling.rowIndex!=r){for(;this.bottomFold_.nextSibling;)this.rowNodes_.removeChild(this.bottomFold_.nextSibling);t=this.fetchRowNode_(r),this.rowNodes_.appendChild(t)}else t=this.bottomFold_.previousSibling.rowIndex;var o=this.document_.getSelection();o.collapse(e,0),o.extend(t,t.childNodes.length),this.selection.sync()},hterm.ScrollPort.prototype.getScrollMax_=function(e){return hterm.getClientHeight(this.scrollArea_)+this.visibleRowTopMargin+this.visibleRowBottomMargin-hterm.getClientHeight(this.screen_)},hterm.ScrollPort.prototype.scrollRowToTop=function(e){this.syncScrollHeight(),this.isScrolledEnd=e+this.visibleRowCount>=this.lastRowCount_;var t=e*this.characterSize.height+this.visibleRowTopMargin,r=this.getScrollMax_();t>r&&(t=r),this.screen_.scrollTop!=t&&(this.screen_.scrollTop=t,this.scheduleRedraw())},hterm.ScrollPort.prototype.scrollRowToBottom=function(e){this.syncScrollHeight(),this.isScrolledEnd=e+this.visibleRowCount>=this.lastRowCount_;var t=e*this.characterSize.height+this.visibleRowTopMargin+this.visibleRowBottomMargin;t-=this.visibleRowCount*this.characterSize.height,0>t&&(t=0),this.screen_.scrollTop!=t&&(this.screen_.scrollTop=t)},hterm.ScrollPort.prototype.getTopRowIndex=function(){return Math.round(this.screen_.scrollTop/this.characterSize.height)},hterm.ScrollPort.prototype.getBottomRowIndex=function(e){return e+this.visibleRowCount-1},hterm.ScrollPort.prototype.onScroll_=function(e){var t=this.getScreenSize();return t.width!=this.lastScreenWidth_||t.height!=this.lastScreenHeight_?void this.resize():(this.redraw_(),void this.publish("scroll",{scrollPort:this}))},hterm.ScrollPort.prototype.onScrollWheel=function(e){},hterm.ScrollPort.prototype.onScrollWheel_=function(e){if(this.onScrollWheel(e),!e.defaultPrevented){var t="DOMMouseScroll"==e.type?-1*e.detail:e.wheelDeltaY;t*=this.scrollWheelMultiplier_;var r=this.screen_.scrollTop-t;0>r&&(r=0);var o=this.getScrollMax_();r>o&&(r=o),r!=this.screen_.scrollTop&&(this.screen_.scrollTop=r,e.preventDefault())}},hterm.ScrollPort.prototype.onResize_=function(e){this.syncCharacterSize(),this.resize()},hterm.ScrollPort.prototype.onCopy=function(e){},hterm.ScrollPort.prototype.onCopy_=function(e){if(this.onCopy(e),!e.defaultPrevented&&(this.resetSelectBags_(),this.selection.sync(),this.selection.startRow&&!(this.selection.endRow.rowIndex-this.selection.startRow.rowIndex<2))){var t=this.getTopRowIndex(),r=this.getBottomRowIndex(t);if(this.selection.startRow.rowIndex<t){var o;o=this.selection.endRow.rowIndex<t?this.selection.endRow.rowIndex:this.topFold_.nextSibling.rowIndex,this.topSelectBag_.textContent=this.rowProvider_.getRowsText(this.selection.startRow.rowIndex+1,o),this.rowNodes_.insertBefore(this.topSelectBag_,this.selection.startRow.nextSibling),this.syncRowNodesDimensions_()}if(this.selection.endRow.rowIndex>r){var i;i=this.selection.startRow.rowIndex>r?this.selection.startRow.rowIndex+1:this.bottomFold_.previousSibling.rowIndex+1,this.bottomSelectBag_.textContent=this.rowProvider_.getRowsText(i,this.selection.endRow.rowIndex),this.rowNodes_.insertBefore(this.bottomSelectBag_,this.selection.endRow)}}},hterm.ScrollPort.prototype.onBodyKeyDown_=function(e){if(this.ctrlVPaste){var t=String.fromCharCode(e.which),r=t.toLowerCase();(e.ctrlKey||e.metaKey)&&"v"==r&&this.pasteTarget_.focus()}},hterm.ScrollPort.prototype.onPaste_=function(e){this.pasteTarget_.focus();var t=this;setTimeout(function(){t.publish("paste",{text:t.pasteTarget_.value}),t.pasteTarget_.value="",t.screen_.focus()},0)},hterm.ScrollPort.prototype.handlePasteTargetTextInput_=function(e){e.stopPropagation()},hterm.ScrollPort.prototype.setScrollbarVisible=function(e){this.screen_.style.overflowY=e?"scroll":"hidden"},hterm.ScrollPort.prototype.setScrollWheelMoveMultipler=function(e){this.scrollWheelMultiplier_=e},lib.rtdep("lib.colors","lib.PreferenceManager","lib.resource","lib.wc","lib.f","hterm.Keyboard","hterm.Options","hterm.PreferenceManager","hterm.Screen","hterm.ScrollPort","hterm.Size","hterm.TextAttributes","hterm.VT"),hterm.Terminal=function(e){this.profileId_=null,this.primaryScreen_=new hterm.Screen,this.alternateScreen_=new hterm.Screen,this.screen_=this.primaryScreen_,this.screenSize=new hterm.Size(0,0),this.scrollPort_=new hterm.ScrollPort(this),this.scrollPort_.subscribe("resize",this.onResize_.bind(this)),this.scrollPort_.subscribe("scroll",this.onScroll_.bind(this)),this.scrollPort_.subscribe("paste",this.onPaste_.bind(this)),this.scrollPort_.onCopy=this.onCopy_.bind(this),this.div_=null,this.document_=window.document,this.scrollbackRows_=[],this.tabStops_=[],this.defaultTabStops=!0,this.vtScrollTop_=null,this.vtScrollBottom_=null,this.cursorNode_=null,this.cursorShape_=hterm.Terminal.cursorShape.BLOCK,this.cursorColor_=null,this.cursorBlinkCycle_=[100,100],this.myOnCursorBlink_=this.onCursorBlink_.bind(this),this.backgroundColor_=null,this.foregroundColor_=null,this.scrollOnOutput_=null,this.scrollOnKeystroke_=null,this.defeatMouseReports_=!1,this.bellAudio_=this.document_.createElement("audio"),this.bellAudio_.setAttribute("preload","auto"),this.bellNotificationList_=[],this.desktopNotificationBell_=!1,this.savedOptions_={},this.options_=new hterm.Options,this.timeouts_={},this.vt=new hterm.VT(this),this.keyboard=new hterm.Keyboard(this),this.io=new hterm.Terminal.IO(this),this.enableMouseDragScroll=!0,this.copyOnSelect=null,this.mousePasteButton=null,this.useDefaultWindowCopy=!1,this.clearSelectionAfterCopy=!0,this.realizeSize_(80,24),this.setDefaultTabStops(),this.setProfile(e||"default",function(){this.onTerminalReady()}.bind(this))},hterm.Terminal.cursorShape={BLOCK:"BLOCK",BEAM:"BEAM",UNDERLINE:"UNDERLINE"},hterm.Terminal.prototype.onTerminalReady=function(){},hterm.Terminal.prototype.tabWidth=8,hterm.Terminal.prototype.setProfile=function(e,t){this.profileId_=e.replace(/\//g,"");var r=this;this.prefs_&&this.prefs_.deactivate(),this.prefs_=new hterm.PreferenceManager(this.profileId_),this.prefs_.addObservers(null,{"alt-gr-mode":function(e){e=null==e?"en-us"==navigator.language.toLowerCase()?"none":"right-alt":"string"==typeof e?e.toLowerCase():"none",/^(none|ctrl-alt|left-alt|right-alt)$/.test(e)||(e="none"),r.keyboard.altGrMode=e},"alt-backspace-is-meta-backspace":function(e){r.keyboard.altBackspaceIsMetaBackspace=e},"alt-is-meta":function(e){r.keyboard.altIsMeta=e},"alt-sends-what":function(e){/^(escape|8-bit|browser-key)$/.test(e)||(e="escape"),r.keyboard.altSendsWhat=e},"audible-bell-sound":function(e){var t=e.match(/^lib-resource:(\S+)/);t?r.bellAudio_.setAttribute("src",lib.resource.getDataUrl(t[1])):r.bellAudio_.setAttribute("src",e)},"desktop-notification-bell":function(e){e&&Notification?(r.desktopNotificationBell_="granted"===Notification.permission,r.desktopNotificationBell_||console.warn("desktop-notification-bell is true but we do not have permission to display notifications.")):r.desktopNotificationBell_=!1},"background-color":function(e){r.setBackgroundColor(e)},"background-image":function(e){r.scrollPort_.setBackgroundImage(e)},"background-size":function(e){r.scrollPort_.setBackgroundSize(e)},"background-position":function(e){r.scrollPort_.setBackgroundPosition(e)},"backspace-sends-backspace":function(e){r.keyboard.backspaceSendsBackspace=e},"character-map-overrides":function(e){if(!(null==e||e instanceof Object))return void console.warn("Preference character-map-modifications is not an object: "+e);for(var t in e){var r=hterm.VT.CharacterMap.maps[t].glmap;for(var o in e[t])r[o]=e[t][o];hterm.VT.CharacterMap.maps[t].reset(r)}},"cursor-blink":function(e){r.setCursorBlink(!!e)},"cursor-blink-cycle":function(e){e instanceof Array&&"number"==typeof e[0]&&"number"==typeof e[1]?r.cursorBlinkCycle_=e:"number"==typeof e?r.cursorBlinkCycle_=[e,e]:r.cursorBlinkCycle_=[100,100]},"cursor-color":function(e){r.setCursorColor(e)},"color-palette-overrides":function(e){if(!(null==e||e instanceof Object||e instanceof Array))return void console.warn("Preference color-palette-overrides is not an array or object: "+e);if(lib.colors.colorPalette=lib.colors.stockColorPalette.concat(),e)for(var t in e){var o=parseInt(t);if(isNaN(o)||0>o||o>255)console.log("Invalid value in palette: "+t+": "+e[t]);else if(e[o]){var i=lib.colors.normalizeCSS(e[o]);i&&(lib.colors.colorPalette[o]=i)}}r.primaryScreen_.textAttributes.resetColorPalette(),r.alternateScreen_.textAttributes.resetColorPalette()},"copy-on-select":function(e){r.copyOnSelect=!!e},"use-default-window-copy":function(e){r.useDefaultWindowCopy=!!e},"clear-selection-after-copy":function(e){r.clearSelectionAfterCopy=!!e},"ctrl-plus-minus-zero-zoom":function(e){r.keyboard.ctrlPlusMinusZeroZoom=e},"ctrl-c-copy":function(e){r.keyboard.ctrlCCopy=e},"ctrl-v-paste":function(e){r.keyboard.ctrlVPaste=e,r.scrollPort_.setCtrlVPaste(e)},"east-asian-ambiguous-as-two-column":function(e){lib.wc.regardCjkAmbiguous=e},"enable-8-bit-control":function(e){r.vt.enable8BitControl=!!e},"enable-bold":function(e){r.syncBoldSafeState()},"enable-bold-as-bright":function(e){r.primaryScreen_.textAttributes.enableBoldAsBright=!!e,r.alternateScreen_.textAttributes.enableBoldAsBright=!!e},"enable-blink":function(e){r.syncBlinkState()},"enable-clipboard-write":function(e){r.vt.enableClipboardWrite=!!e},"enable-dec12":function(e){r.vt.enableDec12=!!e},"font-family":function(e){r.syncFontFamily()},"font-size":function(e){r.setFontSize(e)},"font-smoothing":function(e){r.syncFontFamily()},"foreground-color":function(e){r.setForegroundColor(e)},"home-keys-scroll":function(e){r.keyboard.homeKeysScroll=e},keybindings:function(e){if(r.keyboard.bindings.clear(),e){if(!(e instanceof Object))return void console.error("Error in keybindings preference: Expected object");try{r.keyboard.bindings.addBindings(e)}catch(t){console.error("Error in keybindings preference: "+t)}}},"max-string-sequence":function(e){r.vt.maxStringSequence=e},"media-keys-are-fkeys":function(e){r.keyboard.mediaKeysAreFKeys=e},"meta-sends-escape":function(e){r.keyboard.metaSendsEscape=e},"mouse-paste-button":function(e){r.syncMousePasteButton()},"page-keys-scroll":function(e){r.keyboard.pageKeysScroll=e},"pass-alt-number":function(e){if(null==e){var t=window.navigator.userAgent.match(/Mac OS X/);e=!t&&"popup"!=hterm.windowType}r.passAltNumber=e},"pass-ctrl-number":function(e){if(null==e){var t=window.navigator.userAgent.match(/Mac OS X/);e=!t&&"popup"!=hterm.windowType}r.passCtrlNumber=e},"pass-meta-number":function(e){if(null==e){var t=window.navigator.userAgent.match(/Mac OS X/);e=t&&"popup"!=hterm.windowType}r.passMetaNumber=e},"pass-meta-v":function(e){r.keyboard.passMetaV=e},"receive-encoding":function(e){/^(utf-8|raw)$/.test(e)||(console.warn('Invalid value for "receive-encoding": '+e),e="utf-8"),r.vt.characterEncoding=e},"scroll-on-keystroke":function(e){r.scrollOnKeystroke_=e},"scroll-on-output":function(e){r.scrollOnOutput_=e},"scrollbar-visible":function(e){r.setScrollbarVisible(e)},"scroll-wheel-move-multiplier":function(e){r.setScrollWheelMoveMultipler(e)},"send-encoding":function(e){/^(utf-8|raw)$/.test(e)||(console.warn('Invalid value for "send-encoding": '+e),e="utf-8"),r.keyboard.characterEncoding=e},"shift-insert-paste":function(e){r.keyboard.shiftInsertPaste=e},"user-css":function(e){r.scrollPort_.setUserCss(e)}}),this.prefs_.readStorage(function(){this.prefs_.notifyAll(),t&&t()}.bind(this))},hterm.Terminal.prototype.getPrefs=function(){return this.prefs_},hterm.Terminal.prototype.setBracketedPaste=function(e){this.options_.bracketedPaste=e},hterm.Terminal.prototype.setCursorColor=function(e){this.cursorColor_=e,this.cursorNode_.style.backgroundColor=e,this.cursorNode_.style.borderColor=e},hterm.Terminal.prototype.getCursorColor=function(){return this.cursorColor_},hterm.Terminal.prototype.setSelectionEnabled=function(e){this.enableMouseDragScroll=e},hterm.Terminal.prototype.setBackgroundColor=function(e){this.backgroundColor_=lib.colors.normalizeCSS(e),this.primaryScreen_.textAttributes.setDefaults(this.foregroundColor_,this.backgroundColor_),this.alternateScreen_.textAttributes.setDefaults(this.foregroundColor_,this.backgroundColor_),this.scrollPort_.setBackgroundColor(e)},hterm.Terminal.prototype.getBackgroundColor=function(){return this.backgroundColor_},hterm.Terminal.prototype.setForegroundColor=function(e){this.foregroundColor_=lib.colors.normalizeCSS(e),this.primaryScreen_.textAttributes.setDefaults(this.foregroundColor_,this.backgroundColor_),this.alternateScreen_.textAttributes.setDefaults(this.foregroundColor_,this.backgroundColor_),this.scrollPort_.setForegroundColor(e)},hterm.Terminal.prototype.getForegroundColor=function(){return this.foregroundColor_},hterm.Terminal.prototype.runCommandClass=function(e,t){var r=this.prefs_.get("environment");("object"!=typeof r||null==r)&&(r={});var o=this;this.command=new e({argString:t||"",io:this.io.push(),environment:r,onExit:function(e){o.io.pop(),o.uninstallKeyboard(),o.prefs_.get("close-on-exit")&&window.close()}}),this.installKeyboard(),this.command.run()},hterm.Terminal.prototype.isPrimaryScreen=function(){return this.screen_==this.primaryScreen_},hterm.Terminal.prototype.installKeyboard=function(){this.keyboard.installKeyboard(this.scrollPort_.getDocument().body)},hterm.Terminal.prototype.uninstallKeyboard=function(){this.keyboard.installKeyboard(null)},hterm.Terminal.prototype.setFontSize=function(e){0===e&&(e=this.prefs_.get("font-size")),this.scrollPort_.setFontSize(e),this.wcCssRule_&&(this.wcCssRule_.style.width=2*this.scrollPort_.characterSize.width+"px")},hterm.Terminal.prototype.getFontSize=function(){return this.scrollPort_.getFontSize()},hterm.Terminal.prototype.getFontFamily=function(){return this.scrollPort_.getFontFamily()},hterm.Terminal.prototype.syncFontFamily=function(){this.scrollPort_.setFontFamily(this.prefs_.get("font-family"),this.prefs_.get("font-smoothing")),this.syncBoldSafeState()},hterm.Terminal.prototype.syncMousePasteButton=function(){var e=this.prefs_.get("mouse-paste-button");if("number"==typeof e)return void(this.mousePasteButton=e);var t=navigator.userAgent.match(/\(X11;\s+(\S+)/);t&&"CrOS"!=t[2]?this.mousePasteButton=3:this.mousePasteButton=2},hterm.Terminal.prototype.syncBoldSafeState=function(){var e=this.prefs_.get("enable-bold");if(null!==e)return this.primaryScreen_.textAttributes.enableBold=e,void(this.alternateScreen_.textAttributes.enableBold=e);var t=this.scrollPort_.measureCharacterSize(),r=this.scrollPort_.measureCharacterSize("bold"),o=t.equals(r);o||console.warn("Bold characters disabled: Size of bold weight differs from normal.  Font family is: "+this.scrollPort_.getFontFamily()),this.primaryScreen_.textAttributes.enableBold=o,this.alternateScreen_.textAttributes.enableBold=o},hterm.Terminal.prototype.syncBlinkState=function(){this.document_.documentElement.style.setProperty("--hterm-blink-node-duration",this.prefs_.get("enable-blink")?"0.7s":"0")},hterm.Terminal.prototype.saveCursor=function(){return this.screen_.cursorPosition.clone()},hterm.Terminal.prototype.getTextAttributes=function(){return this.screen_.textAttributes},hterm.Terminal.prototype.setTextAttributes=function(e){this.screen_.textAttributes=e},hterm.Terminal.prototype.getZoomFactor=function(){return this.scrollPort_.characterSize.zoomFactor},hterm.Terminal.prototype.setWindowTitle=function(e){window.document.title=e},hterm.Terminal.prototype.restoreCursor=function(e){var t=lib.f.clamp(e.row,0,this.screenSize.height-1),r=lib.f.clamp(e.column,0,this.screenSize.width-1);this.screen_.setCursorPosition(t,r),(e.column>r||e.column==r&&e.overflow)&&(this.screen_.cursorPosition.overflow=!0)},hterm.Terminal.prototype.clearCursorOverflow=function(){this.screen_.cursorPosition.overflow=!1},hterm.Terminal.prototype.setCursorShape=function(e){this.cursorShape_=e,this.restyleCursor_()},hterm.Terminal.prototype.getCursorShape=function(){return this.cursorShape_},hterm.Terminal.prototype.setWidth=function(e){return null==e?void(this.div_.style.width="100%"):(this.div_.style.width=Math.ceil(this.scrollPort_.characterSize.width*e+this.scrollPort_.currentScrollbarWidthPx)+"px",this.realizeSize_(e,this.screenSize.height),void this.scheduleSyncCursorPosition_())},hterm.Terminal.prototype.setHeight=function(e){return null==e?void(this.div_.style.height="100%"):(this.div_.style.height=this.scrollPort_.characterSize.height*e+"px",this.realizeSize_(this.screenSize.width,e),void this.scheduleSyncCursorPosition_())},hterm.Terminal.prototype.realizeSize_=function(e,t){e!=this.screenSize.width&&this.realizeWidth_(e),t!=this.screenSize.height&&this.realizeHeight_(t),this.io.onTerminalResize_(e,t)},hterm.Terminal.prototype.realizeWidth_=function(e){if(0>=e)throw new Error("Attempt to realize bad width: "+e);var t=e-this.screen_.getWidth();if(this.screenSize.width=e,this.screen_.setColumnCount(e),t>0)this.defaultTabStops&&this.setDefaultTabStops(this.screenSize.width-t);else for(var r=this.tabStops_.length-1;r>=0&&!(this.tabStops_[r]<e);r--)this.tabStops_.pop();this.screen_.setColumnCount(this.screenSize.width)},hterm.Terminal.prototype.realizeHeight_=function(e){if(0>=e)throw new Error("Attempt to realize bad height: "+e);var t=e-this.screen_.getHeight();this.screenSize.height=e;var r=this.saveCursor();if(0>t){for(t*=-1;t;){var o=this.getRowCount()-1;if(o-this.scrollbackRows_.length==r.row)break;if(this.getRowText(o))break;this.screen_.popRow(),t--}var i=this.screen_.shiftRows(t);this.scrollbackRows_.push.apply(this.scrollbackRows_,i),r.row=Math.max(r.row-t,0)}else if(t>0){if(t<=this.scrollbackRows_.length){var s=Math.min(t,this.scrollbackRows_.length),n=this.scrollbackRows_.splice(this.scrollbackRows_.length-s,s);this.screen_.unshiftRows(n),t-=s,r.row+=s}t&&this.appendRows_(t)}this.setVTScrollRegion(null,null),this.restoreCursor(r)},hterm.Terminal.prototype.scrollHome=function(){this.scrollPort_.scrollRowToTop(0)},hterm.Terminal.prototype.scrollEnd=function(){this.scrollPort_.scrollRowToBottom(this.getRowCount())},hterm.Terminal.prototype.scrollPageUp=function(){var e=this.scrollPort_.getTopRowIndex();this.scrollPort_.scrollRowToTop(e-this.screenSize.height+1)},hterm.Terminal.prototype.scrollPageDown=function(){var e=this.scrollPort_.getTopRowIndex();this.scrollPort_.scrollRowToTop(e+this.screenSize.height-1)},hterm.Terminal.prototype.wipeContents=function(){this.scrollbackRows_.length=0,this.scrollPort_.resetCache(),[this.primaryScreen_,this.alternateScreen_].forEach(function(e){var t=e.getHeight();t>0&&(this.renumberRows_(0,t),this.clearHome(e))}.bind(this)),this.syncCursorPosition_(),this.scrollPort_.invalidate()},hterm.Terminal.prototype.reset=function(){this.clearAllTabStops(),this.setDefaultTabStops(),this.clearHome(this.primaryScreen_),this.primaryScreen_.textAttributes.reset(),this.clearHome(this.alternateScreen_),this.alternateScreen_.textAttributes.reset(),this.setCursorBlink(!!this.prefs_.get("cursor-blink")),this.vt.reset(),this.softReset()},hterm.Terminal.prototype.softReset=function(){this.options_=new hterm.Options,this.options_.cursorBlink=!!this.timeouts_.cursorBlink,this.primaryScreen_.textAttributes.resetColorPalette(),this.alternateScreen_.textAttributes.resetColorPalette(),this.setVTScrollRegion(null,null),this.setCursorVisible(!0)},hterm.Terminal.prototype.forwardTabStop=function(){for(var e=this.screen_.cursorPosition.column,t=0;t<this.tabStops_.length;t++)if(this.tabStops_[t]>e)return void this.setCursorColumn(this.tabStops_[t]);var r=this.screen_.cursorPosition.overflow;this.setCursorColumn(this.screenSize.width-1),this.screen_.cursorPosition.overflow=r},hterm.Terminal.prototype.backwardTabStop=function(){for(var e=this.screen_.cursorPosition.column,t=this.tabStops_.length-1;t>=0;t--)if(this.tabStops_[t]<e)return void this.setCursorColumn(this.tabStops_[t]);this.setCursorColumn(1)},hterm.Terminal.prototype.setTabStop=function(e){for(var t=this.tabStops_.length-1;t>=0;t--){if(this.tabStops_[t]==e)return;if(this.tabStops_[t]<e)return void this.tabStops_.splice(t+1,0,e)}this.tabStops_.splice(0,0,e)},hterm.Terminal.prototype.clearTabStopAtCursor=function(){var e=this.screen_.cursorPosition.column,t=this.tabStops_.indexOf(e);-1!=t&&this.tabStops_.splice(t,1)},hterm.Terminal.prototype.clearAllTabStops=function(){this.tabStops_.length=0,this.defaultTabStops=!1},hterm.Terminal.prototype.setDefaultTabStops=function(e){var t=e||0,r=this.tabWidth;t=t-1-(t-1)%r+r;for(var o=t;o<this.screenSize.width;o+=r)this.setTabStop(o);this.defaultTabStops=!0},hterm.Terminal.prototype.interpret=function(e){this.vt.interpret(e),this.scheduleSyncCursorPosition_()},hterm.Terminal.prototype.decorate=function(e){this.div_=e,this.scrollPort_.decorate(e),this.scrollPort_.setBackgroundImage(this.prefs_.get("background-image")),this.scrollPort_.setBackgroundSize(this.prefs_.get("background-size")),this.scrollPort_.setBackgroundPosition(this.prefs_.get("background-position")),this.scrollPort_.setUserCss(this.prefs_.get("user-css")),this.div_.focus=this.focus.bind(this),this.setFontSize(this.prefs_.get("font-size")),this.syncFontFamily(),this.setScrollbarVisible(this.prefs_.get("scrollbar-visible")),this.setScrollWheelMoveMultipler(this.prefs_.get("scroll-wheel-move-multiplier")),this.document_=this.scrollPort_.getDocument(),this.document_.body.oncontextmenu=function(){return!1};var t=this.onMouse_.bind(this),r=this.scrollPort_.getScreenNode();r.addEventListener("mousedown",t),r.addEventListener("mouseup",t),r.addEventListener("mousemove",t),this.scrollPort_.onScrollWheel=t,r.addEventListener("focus",this.onFocusChange_.bind(this,!0)),r.addEventListener("mousedown",function(){setTimeout(this.onFocusChange_.bind(this,!0))}.bind(this)),r.addEventListener("blur",this.onFocusChange_.bind(this,!1));var o=this.document_.createElement("style");o.textContent='.cursor-node[focus="false"] {  box-sizing: border-box;  background-color: transparent !important;  border-width: 2px;  border-style: solid;}.wc-node {  display: inline-block;  text-align: center;  width: '+2*this.scrollPort_.characterSize.width+"px;}:root {  --hterm-blink-node-duration: 0.7s;}@keyframes blink {  from { opacity: 1.0; }  to { opacity: 0.0; }}.blink-node {  animation-name: blink;  animation-duration: var(--hterm-blink-node-duration);  animation-iteration-count: infinite;  animation-timing-function: ease-in-out;  animation-direction: alternate;}",this.document_.head.appendChild(o);var i=this.document_.styleSheets,s=i[i.length-1].cssRules;this.wcCssRule_=s[s.length-1],this.cursorNode_=this.document_.createElement("div"),this.cursorNode_.className="cursor-node",this.cursorNode_.style.cssText="position: absolute;top: -99px;display: block;width: "+this.scrollPort_.characterSize.width+"px;height: "+this.scrollPort_.characterSize.height+"px;-webkit-transition: opacity, background-color 100ms linear;-moz-transition: opacity, background-color 100ms linear;",this.setCursorColor(this.prefs_.get("cursor-color")),this.setCursorBlink(!!this.prefs_.get("cursor-blink")),this.restyleCursor_(),this.document_.body.appendChild(this.cursorNode_),this.scrollBlockerNode_=this.document_.createElement("div"),this.scrollBlockerNode_.style.cssText="position: absolute;top: -99px;display: block;width: 10px;height: 10px;",this.document_.body.appendChild(this.scrollBlockerNode_),this.scrollPort_.onScrollWheel=t,["mousedown","mouseup","mousemove","click","dblclick"].forEach(function(e){this.scrollBlockerNode_.addEventListener(e,t),this.cursorNode_.addEventListener(e,t),this.document_.addEventListener(e,t)}.bind(this)),this.cursorNode_.addEventListener("mousedown",function(){setTimeout(this.focus.bind(this))}.bind(this)),this.setReverseVideo(!1),this.scrollPort_.focus(),this.scrollPort_.scheduleRedraw()},hterm.Terminal.prototype.getDocument=function(){return this.document_},hterm.Terminal.prototype.focus=function(){this.scrollPort_.focus()},hterm.Terminal.prototype.getRowNode=function(e){if(e<this.scrollbackRows_.length)return this.scrollbackRows_[e];var t=e-this.scrollbackRows_.length;return this.screen_.rowsArray[t]},hterm.Terminal.prototype.getRowsText=function(e,t){for(var r=[],o=e;t>o;o++){var i=this.getRowNode(o);r.push(i.textContent),t-1>o&&!i.getAttribute("line-overflow")&&r.push("\n")}return r.join("")},hterm.Terminal.prototype.getRowText=function(e){var t=this.getRowNode(e);return t.textContent},hterm.Terminal.prototype.getRowCount=function(){return this.scrollbackRows_.length+this.screen_.rowsArray.length},hterm.Terminal.prototype.appendRows_=function(e){for(var t=this.screen_.rowsArray.length,r=this.scrollbackRows_.length+t,o=0;e>o;o++){var i=this.document_.createElement("x-row");i.appendChild(this.document_.createTextNode("")),i.rowIndex=r+o,this.screen_.pushRow(i)}var s=this.screen_.rowsArray.length-this.screenSize.height;if(s>0){var n=this.screen_.shiftRows(s);Array.prototype.push.apply(this.scrollbackRows_,n),this.scrollPort_.isScrolledEnd&&this.scheduleScrollDown_()}t>=this.screen_.rowsArray.length&&(t=this.screen_.rowsArray.length-1),this.setAbsoluteCursorPosition(t,0)},hterm.Terminal.prototype.moveRows_=function(e,t,r){var o=this.screen_.removeRows(e,t);this.screen_.insertRows(r,o);var i,s;r>e?(i=e,s=r+t):(i=r,s=e+t),this.renumberRows_(i,s),this.scrollPort_.scheduleInvalidate()},hterm.Terminal.prototype.renumberRows_=function(e,t,r){for(var o=r||this.screen_,i=this.scrollbackRows_.length,s=e;t>s;s++)o.rowsArray[s].rowIndex=i+s},hterm.Terminal.prototype.print=function(e){for(var t=0,r=lib.wc.strWidth(e);r>t;){this.options_.wraparound&&this.screen_.cursorPosition.overflow&&(this.screen_.commitLineOverflow(),this.newLine());var o,i=r-t,s=!1;this.screen_.cursorPosition.column+i>=this.screenSize.width&&(s=!0,i=this.screenSize.width-this.screen_.cursorPosition.column),s&&!this.options_.wraparound?(o=lib.wc.substr(e,t,i-1)+lib.wc.substr(e,r-1),i=r):o=lib.wc.substr(e,t,i);for(var n=hterm.TextAttributes.splitWidecharString(o),a=0;a<n.length;a++)n[a].wcNode&&(this.screen_.textAttributes.wcNode=!0),this.options_.insertMode?this.screen_.insertString(n[a].str):this.screen_.overwriteString(n[a].str),this.screen_.textAttributes.wcNode=!1;this.screen_.maybeClipCurrentRow(),t+=i}this.scheduleSyncCursorPosition_(),this.scrollOnOutput_&&this.scrollPort_.scrollRowToBottom(this.getRowCount())},hterm.Terminal.prototype.setVTScrollRegion=function(e,t){0==e&&t==this.screenSize.height-1?(this.vtScrollTop_=null,this.vtScrollBottom_=null):(this.vtScrollTop_=e,this.vtScrollBottom_=t)},hterm.Terminal.prototype.getVTScrollTop=function(){return null!=this.vtScrollTop_?this.vtScrollTop_:0},hterm.Terminal.prototype.getVTScrollBottom=function(){return null!=this.vtScrollBottom_?this.vtScrollBottom_:this.screenSize.height-1},hterm.Terminal.prototype.newLine=function(){var e=this.screen_.cursorPosition.row==this.screen_.rowsArray.length-1;null!=this.vtScrollBottom_?this.screen_.cursorPosition.row==this.vtScrollBottom_?(this.vtScrollUp(1),this.setAbsoluteCursorPosition(this.screen_.cursorPosition.row,0)):e?this.setAbsoluteCursorPosition(this.screen_.cursorPosition.row,0):this.setAbsoluteCursorPosition(this.screen_.cursorPosition.row+1,0):e?this.appendRows_(1):this.setAbsoluteCursorPosition(this.screen_.cursorPosition.row+1,0)},hterm.Terminal.prototype.lineFeed=function(){var e=this.screen_.cursorPosition.column;this.newLine(),this.setCursorColumn(e)},hterm.Terminal.prototype.formFeed=function(){this.options_.autoCarriageReturn?this.newLine():this.lineFeed()},hterm.Terminal.prototype.reverseLineFeed=function(){var e=this.getVTScrollTop(),t=this.screen_.cursorPosition.row;t==e?this.insertLines(1):this.setAbsoluteCursorRow(t-1)},hterm.Terminal.prototype.eraseToLeft=function(){var e=this.saveCursor();this.setCursorColumn(0),this.screen_.overwriteString(lib.f.getWhitespace(e.column+1)),this.restoreCursor(e)},hterm.Terminal.prototype.eraseToRight=function(e){if(!this.screen_.cursorPosition.overflow){var t=this.screenSize.width-this.screen_.cursorPosition.column,r=e?Math.min(e,t):t;if(this.screen_.textAttributes.background===this.screen_.textAttributes.DEFAULT_COLOR){var o=this.screen_.rowsArray[this.screen_.cursorPosition.row];if(hterm.TextAttributes.nodeWidth(o)<=this.screen_.cursorPosition.column+r)return this.screen_.deleteChars(r),void this.clearCursorOverflow()}var i=this.saveCursor();this.screen_.overwriteString(lib.f.getWhitespace(r)),this.restoreCursor(i),this.clearCursorOverflow()}},hterm.Terminal.prototype.eraseLine=function(){var e=this.saveCursor();this.screen_.clearCursorRow(),this.restoreCursor(e),this.clearCursorOverflow()},hterm.Terminal.prototype.eraseAbove=function(){var e=this.saveCursor();this.eraseToLeft();for(var t=0;t<e.row;t++)this.setAbsoluteCursorPosition(t,0),this.screen_.clearCursorRow();this.restoreCursor(e),this.clearCursorOverflow()},hterm.Terminal.prototype.eraseBelow=function(){var e=this.saveCursor();this.eraseToRight();for(var t=this.screenSize.height-1,r=e.row+1;t>=r;r++)this.setAbsoluteCursorPosition(r,0),this.screen_.clearCursorRow();this.restoreCursor(e),this.clearCursorOverflow()},hterm.Terminal.prototype.fill=function(e){var t=this.saveCursor();this.setAbsoluteCursorPosition(0,0);for(var r=0;r<this.screenSize.height;r++)for(var o=0;o<this.screenSize.width;o++)this.setAbsoluteCursorPosition(r,o),this.screen_.overwriteString(e);this.restoreCursor(t)},hterm.Terminal.prototype.clearHome=function(e){var t=e||this.screen_,r=t.getHeight();if(0!=r){for(var o=0;r>o;o++)t.setCursorPosition(o,0),t.clearCursorRow();t.setCursorPosition(0,0)}},hterm.Terminal.prototype.clear=function(e){var t=e||this.screen_,r=t.cursorPosition.clone();this.clearHome(t),t.setCursorPosition(r.row,r.column)},hterm.Terminal.prototype.insertLines=function(e){var t=this.screen_.cursorPosition.row,r=this.getVTScrollBottom();e=Math.min(e,r-t);var o=r-t-e+1;o&&this.moveRows_(t,o,t+e);for(var i=e-1;i>=0;i--)this.setAbsoluteCursorPosition(t+i,0),this.screen_.clearCursorRow()},hterm.Terminal.prototype.deleteLines=function(e){var t=this.saveCursor(),r=t.row,o=this.getVTScrollBottom(),i=o-r+1;e=Math.min(e,i);var s=o-e+1;e!=i&&this.moveRows_(r,e,s);for(var n=0;e>n;n++)this.setAbsoluteCursorPosition(s+n,0),this.screen_.clearCursorRow();this.restoreCursor(t),this.clearCursorOverflow()},hterm.Terminal.prototype.insertSpace=function(e){var t=this.saveCursor(),r=lib.f.getWhitespace(e||1);this.screen_.insertString(r),this.screen_.maybeClipCurrentRow(),this.restoreCursor(t),this.clearCursorOverflow()},hterm.Terminal.prototype.deleteChars=function(e){var t=this.screen_.deleteChars(e);if(t&&!this.screen_.textAttributes.isDefault()){var r=this.saveCursor();this.setCursorColumn(this.screenSize.width-t),this.screen_.insertString(lib.f.getWhitespace(t)),this.restoreCursor(r)}this.clearCursorOverflow()},hterm.Terminal.prototype.vtScrollUp=function(e){var t=this.saveCursor();this.setAbsoluteCursorRow(this.getVTScrollTop()),this.deleteLines(e),this.restoreCursor(t)},hterm.Terminal.prototype.vtScrollDown=function(e){var t=this.saveCursor();this.setAbsoluteCursorPosition(this.getVTScrollTop(),0),this.insertLines(e),this.restoreCursor(t)},hterm.Terminal.prototype.setCursorPosition=function(e,t){this.options_.originMode?this.setRelativeCursorPosition(e,t):this.setAbsoluteCursorPosition(e,t)},hterm.Terminal.prototype.setRelativeCursorPosition=function(e,t){var r=this.getVTScrollTop();e=lib.f.clamp(e+r,r,this.getVTScrollBottom()),t=lib.f.clamp(t,0,this.screenSize.width-1),this.screen_.setCursorPosition(e,t)},hterm.Terminal.prototype.setAbsoluteCursorPosition=function(e,t){e=lib.f.clamp(e,0,this.screenSize.height-1),t=lib.f.clamp(t,0,this.screenSize.width-1),this.screen_.setCursorPosition(e,t)},hterm.Terminal.prototype.setCursorColumn=function(e){this.setAbsoluteCursorPosition(this.screen_.cursorPosition.row,e)},hterm.Terminal.prototype.getCursorColumn=function(){
-return this.screen_.cursorPosition.column},hterm.Terminal.prototype.setAbsoluteCursorRow=function(e){this.setAbsoluteCursorPosition(e,this.screen_.cursorPosition.column)},hterm.Terminal.prototype.getCursorRow=function(){return this.screen_.cursorPosition.row},hterm.Terminal.prototype.scheduleRedraw_=function(){if(!this.timeouts_.redraw){var e=this;this.timeouts_.redraw=setTimeout(function(){delete e.timeouts_.redraw,e.scrollPort_.redraw_()},0)}},hterm.Terminal.prototype.scheduleScrollDown_=function(){if(!this.timeouts_.scrollDown){var e=this;this.timeouts_.scrollDown=setTimeout(function(){delete e.timeouts_.scrollDown,e.scrollPort_.scrollRowToBottom(e.getRowCount())},10)}},hterm.Terminal.prototype.cursorUp=function(e){return this.cursorDown(-(e||1))},hterm.Terminal.prototype.cursorDown=function(e){e=e||1;var t=this.options_.originMode?this.getVTScrollTop():0,r=this.options_.originMode?this.getVTScrollBottom():this.screenSize.height-1,o=lib.f.clamp(this.screen_.cursorPosition.row+e,t,r);this.setAbsoluteCursorRow(o)},hterm.Terminal.prototype.cursorLeft=function(e){if(e=e||1,!(1>e)){var t=this.screen_.cursorPosition.column;if(this.options_.reverseWraparound){if(this.screen_.cursorPosition.overflow&&(e--,this.clearCursorOverflow(),!e))return;var r=this.screen_.cursorPosition.row,o=t-e;0>o&&(r=r-Math.floor(e/this.screenSize.width)-1,0>r&&(r=this.screenSize.height+r%this.screenSize.height),o=this.screenSize.width+o%this.screenSize.width),this.setCursorPosition(Math.max(r,0),o)}else{var o=Math.max(t-e,0);this.setCursorColumn(o)}}},hterm.Terminal.prototype.cursorRight=function(e){if(e=e||1,!(1>e)){var t=lib.f.clamp(this.screen_.cursorPosition.column+e,0,this.screenSize.width-1);this.setCursorColumn(t)}},hterm.Terminal.prototype.setReverseVideo=function(e){this.options_.reverseVideo=e,e?(this.scrollPort_.setForegroundColor(this.prefs_.get("background-color")),this.scrollPort_.setBackgroundColor(this.prefs_.get("foreground-color"))):(this.scrollPort_.setForegroundColor(this.prefs_.get("foreground-color")),this.scrollPort_.setBackgroundColor(this.prefs_.get("background-color")))},hterm.Terminal.prototype.ringBell=function(){this.cursorNode_.style.backgroundColor=this.scrollPort_.getForegroundColor();var e=this;if(setTimeout(function(){e.cursorNode_.style.backgroundColor=e.prefs_.get("cursor-color")},200),!this.bellSquelchTimeout_&&(this.bellAudio_.getAttribute("src")?(this.bellAudio_.play(),this.bellSequelchTimeout_=setTimeout(function(){delete this.bellSquelchTimeout_}.bind(this),500)):delete this.bellSquelchTimeout_,this.desktopNotificationBell_&&!this.document_.hasFocus())){var t=new Notification(lib.f.replaceVars(hterm.desktopNotificationTitle,{title:window.document.title||"hterm"}));this.bellNotificationList_.push(t),t.onclick=function(){e.closeBellNotifications_()}}},hterm.Terminal.prototype.setOriginMode=function(e){this.options_.originMode=e,this.setCursorPosition(0,0)},hterm.Terminal.prototype.setInsertMode=function(e){this.options_.insertMode=e},hterm.Terminal.prototype.setAutoCarriageReturn=function(e){this.options_.autoCarriageReturn=e},hterm.Terminal.prototype.setWraparound=function(e){this.options_.wraparound=e},hterm.Terminal.prototype.setReverseWraparound=function(e){this.options_.reverseWraparound=e},hterm.Terminal.prototype.setAlternateMode=function(e){var t=this.saveCursor();if(this.screen_=e?this.alternateScreen_:this.primaryScreen_,this.screen_.rowsArray.length&&this.screen_.rowsArray[0].rowIndex!=this.scrollbackRows_.length)for(var r=this.scrollbackRows_.length,o=this.screen_.rowsArray,i=0;i<o.length;i++)o[i].rowIndex=r+i;this.realizeWidth_(this.screenSize.width),this.realizeHeight_(this.screenSize.height),this.scrollPort_.syncScrollHeight(),this.scrollPort_.invalidate(),this.restoreCursor(t),this.scrollPort_.resize()},hterm.Terminal.prototype.setCursorBlink=function(e){this.options_.cursorBlink=e,!e&&this.timeouts_.cursorBlink&&(clearTimeout(this.timeouts_.cursorBlink),delete this.timeouts_.cursorBlink),this.options_.cursorVisible&&this.setCursorVisible(!0)},hterm.Terminal.prototype.setCursorVisible=function(e){if(this.options_.cursorVisible=e,!e)return this.timeouts_.cursorBlink&&(clearTimeout(this.timeouts_.cursorBlink),delete this.timeouts_.cursorBlink),void(this.cursorNode_.style.opacity="0");if(this.syncCursorPosition_(),this.cursorNode_.style.opacity="1",this.options_.cursorBlink){if(this.timeouts_.cursorBlink)return;this.onCursorBlink_()}else this.timeouts_.cursorBlink&&(clearTimeout(this.timeouts_.cursorBlink),delete this.timeouts_.cursorBlink)},hterm.Terminal.prototype.syncCursorPosition_=function(){var e=this.scrollPort_.getTopRowIndex(),t=this.scrollPort_.getBottomRowIndex(e),r=this.scrollbackRows_.length+this.screen_.cursorPosition.row;if(r>t)return void(this.cursorNode_.style.top=-this.scrollPort_.characterSize.height+"px");this.options_.cursorVisible&&"none"==this.cursorNode_.style.display&&(this.cursorNode_.style.display=""),this.cursorNode_.style.top=this.scrollPort_.visibleRowTopMargin+this.scrollPort_.characterSize.height*(r-e)+"px",this.cursorNode_.style.left=this.scrollPort_.characterSize.width*this.screen_.cursorPosition.column+"px",this.cursorNode_.setAttribute("title","("+this.screen_.cursorPosition.row+", "+this.screen_.cursorPosition.column+")");var o=this.document_.getSelection();o&&o.isCollapsed&&this.screen_.syncSelectionCaret(o)},hterm.Terminal.prototype.restyleCursor_=function(){var e=this.cursorShape_;"false"==this.cursorNode_.getAttribute("focus")&&(e=hterm.Terminal.cursorShape.BLOCK);var t=this.cursorNode_.style;switch(t.width=this.scrollPort_.characterSize.width+"px",e){case hterm.Terminal.cursorShape.BEAM:t.height=this.scrollPort_.characterSize.height+"px",t.backgroundColor="transparent",t.borderBottomStyle=null,t.borderLeftStyle="solid";break;case hterm.Terminal.cursorShape.UNDERLINE:t.height=this.scrollPort_.characterSize.baseline+"px",t.backgroundColor="transparent",t.borderBottomStyle="solid",t.borderLeftStyle=null;break;default:t.height=this.scrollPort_.characterSize.height+"px",t.backgroundColor=this.cursorColor_,t.borderBottomStyle=null,t.borderLeftStyle=null}},hterm.Terminal.prototype.scheduleSyncCursorPosition_=function(){if(!this.timeouts_.syncCursor){var e=this;this.timeouts_.syncCursor=setTimeout(function(){e.syncCursorPosition_(),delete e.timeouts_.syncCursor},0)}},hterm.Terminal.prototype.showZoomWarning_=function(e){if(!this.zoomWarningNode_){if(!e)return;this.zoomWarningNode_=this.document_.createElement("div"),this.zoomWarningNode_.style.cssText="color: black;background-color: #ff2222;font-size: large;border-radius: 8px;opacity: 0.75;padding: 0.2em 0.5em 0.2em 0.5em;top: 0.5em;right: 1.2em;position: absolute;-webkit-text-size-adjust: none;-webkit-user-select: none;-moz-text-size-adjust: none;-moz-user-select: none;",this.zoomWarningNode_.addEventListener("click",function(e){this.parentNode.removeChild(this)})}this.zoomWarningNode_.textContent=lib.MessageManager.replaceReferences(hterm.zoomWarningMessage,[parseInt(100*this.scrollPort_.characterSize.zoomFactor)]),this.zoomWarningNode_.style.fontFamily=this.prefs_.get("font-family"),e?this.zoomWarningNode_.parentNode||this.div_.parentNode.appendChild(this.zoomWarningNode_):this.zoomWarningNode_.parentNode&&this.zoomWarningNode_.parentNode.removeChild(this.zoomWarningNode_)},hterm.Terminal.prototype.showOverlay=function(e,t){if(!this.overlayNode_){if(!this.div_)return;this.overlayNode_=this.document_.createElement("div"),this.overlayNode_.style.cssText="border-radius: 15px;font-size: xx-large;opacity: 0.75;padding: 0.2em 0.5em 0.2em 0.5em;position: absolute;-webkit-user-select: none;-webkit-transition: opacity 180ms ease-in;-moz-user-select: none;-moz-transition: opacity 180ms ease-in;",this.overlayNode_.addEventListener("mousedown",function(e){e.preventDefault(),e.stopPropagation()},!0)}this.overlayNode_.style.color=this.prefs_.get("background-color"),this.overlayNode_.style.backgroundColor=this.prefs_.get("foreground-color"),this.overlayNode_.style.fontFamily=this.prefs_.get("font-family"),this.overlayNode_.textContent=e,this.overlayNode_.style.opacity="0.75",this.overlayNode_.parentNode||this.div_.appendChild(this.overlayNode_);var r=hterm.getClientSize(this.div_),o=hterm.getClientSize(this.overlayNode_);this.overlayNode_.style.top=(r.height-o.height)/2+"px",this.overlayNode_.style.left=(r.width-o.width-this.scrollPort_.currentScrollbarWidthPx)/2+"px";var i=this;this.overlayTimeout_&&clearTimeout(this.overlayTimeout_),null!==t&&(this.overlayTimeout_=setTimeout(function(){i.overlayNode_.style.opacity="0",i.overlayTimeout_=setTimeout(function(){i.overlayNode_.parentNode&&i.overlayNode_.parentNode.removeChild(i.overlayNode_),i.overlayTimeout_=null,i.overlayNode_.style.opacity="0.75"},200)},t||1500))},hterm.Terminal.prototype.paste=function(){hterm.pasteFromClipboard(this.document_)},hterm.Terminal.prototype.copyStringToClipboard=function(e){this.prefs_.get("enable-clipboard-notice")&&setTimeout(this.showOverlay.bind(this,hterm.notifyCopyMessage,500),200);var t=this.document_.createElement("pre");t.textContent=e,t.style.cssText="-webkit-user-select: text;-moz-user-select: text;position: absolute;top: -99px",this.document_.body.appendChild(t);var r=this.document_.getSelection(),o=r.anchorNode,i=r.anchorOffset,s=r.focusNode,n=r.focusOffset;r.selectAllChildren(t),hterm.copySelectionToClipboard(this.document_),r.extend&&(r.collapse(o,i),r.extend(s,n)),t.parentNode.removeChild(t)},hterm.Terminal.prototype.getSelectionText=function(){var e=this.scrollPort_.selection;if(e.sync(),e.isCollapsed)return null;var t=e.startOffset,r=e.startNode;if("X-ROW"!=r.nodeName)for("#text"==r.nodeName&&"SPAN"==r.parentNode.nodeName&&(r=r.parentNode);r.previousSibling;)r=r.previousSibling,t+=hterm.TextAttributes.nodeWidth(r);var o=hterm.TextAttributes.nodeWidth(e.endNode)-e.endOffset;if(r=e.endNode,"X-ROW"!=r.nodeName)for("#text"==r.nodeName&&"SPAN"==r.parentNode.nodeName&&(r=r.parentNode);r.nextSibling;)r=r.nextSibling,o+=hterm.TextAttributes.nodeWidth(r);var i=this.getRowsText(e.startRow.rowIndex,e.endRow.rowIndex+1);return lib.wc.substring(i,t,lib.wc.strWidth(i)-o)},hterm.Terminal.prototype.copySelectionToClipboard=function(){var e=this.getSelectionText();null!=e&&this.copyStringToClipboard(e)},hterm.Terminal.prototype.overlaySize=function(){this.showOverlay(this.screenSize.width+"x"+this.screenSize.height)},hterm.Terminal.prototype.onVTKeystroke=function(e){this.scrollOnKeystroke_&&this.scrollPort_.scrollRowToBottom(this.getRowCount()),this.io.onVTKeystroke(this.keyboard.encode(e))},hterm.Terminal.prototype.openUrl=function(e){var t=window.open(e,"_blank");t.focus()},hterm.Terminal.prototype.openSelectedUrl_=function(){var e=this.getSelectionText();null==e&&(this.screen_.expandSelection(this.document_.getSelection()),e=this.getSelectionText()),e.length>2048||e.search(/[\s\[\](){}<>"'\\^`]/)>=0||(e.search("^[a-zA-Z][a-zA-Z0-9+.-]*://")<0&&(e="http://"+e),this.openUrl(e))},hterm.Terminal.prototype.onMouse_=function(e){if(!e.processedByTerminalHandler_){var t=!this.defeatMouseReports_&&this.vt.mouseReport!=this.vt.MOUSE_REPORT_DISABLED;if(e.processedByTerminalHandler_=!0,e.terminalRow=parseInt((e.clientY-this.scrollPort_.visibleRowTopMargin)/this.scrollPort_.characterSize.height)+1,e.terminalColumn=parseInt(e.clientX/this.scrollPort_.characterSize.width)+1,!("mousedown"==e.type&&e.terminalColumn>this.screenSize.width)){if(this.options_.cursorVisible&&!t&&(e.terminalRow-1==this.screen_.cursorPosition.row&&e.terminalColumn-1==this.screen_.cursorPosition.column?this.cursorNode_.style.display="none":"none"==this.cursorNode_.style.display&&(this.cursorNode_.style.display="")),"mousedown"==e.type&&(e.altKey||!t?(this.defeatMouseReports_=!0,this.setSelectionEnabled(!0)):(this.defeatMouseReports_=!1,this.document_.getSelection().collapseToEnd(),this.setSelectionEnabled(!1),e.preventDefault())),t)this.scrollBlockerNode_.engaged||("mousedown"==e.type?(this.scrollBlockerNode_.engaged=!0,this.scrollBlockerNode_.style.top=e.clientY-5+"px",this.scrollBlockerNode_.style.left=e.clientX-5+"px"):"mousemove"==e.type&&(this.document_.getSelection().collapseToEnd(),e.preventDefault())),this.onMouse(e);else{if("dblclick"==e.type&&this.copyOnSelect&&(this.screen_.expandSelection(this.document_.getSelection()),this.copySelectionToClipboard(this.document_)),"click"==e.type&&!e.shiftKey&&e.ctrlKey)return clearTimeout(this.timeouts_.openUrl),void(this.timeouts_.openUrl=setTimeout(this.openSelectedUrl_.bind(this),500));"mousedown"==e.type&&e.which==this.mousePasteButton&&this.paste(),"mouseup"==e.type&&1==e.which&&this.copyOnSelect&&!this.document_.getSelection().isCollapsed&&this.copySelectionToClipboard(this.document_),"mousemove"!=e.type&&"mouseup"!=e.type||!this.scrollBlockerNode_.engaged||(this.scrollBlockerNode_.engaged=!1,this.scrollBlockerNode_.style.top="-99px")}"mouseup"==e.type&&this.document_.getSelection().isCollapsed&&(this.defeatMouseReports_=!1)}}},hterm.Terminal.prototype.onMouse=function(e){},hterm.Terminal.prototype.onFocusChange_=function(e){this.cursorNode_.setAttribute("focus",e),this.restyleCursor_(),e===!0&&this.closeBellNotifications_()},hterm.Terminal.prototype.onScroll_=function(){this.scheduleSyncCursorPosition_()},hterm.Terminal.prototype.onPaste_=function(e){var t=e.text.replace(/\n/gm,"\r");t=this.keyboard.encode(t),this.options_.bracketedPaste&&(t="[200~"+t+"[201~"),this.io.sendString(t)},hterm.Terminal.prototype.onCopy_=function(e){this.useDefaultWindowCopy||(e.preventDefault(),setTimeout(this.copySelectionToClipboard.bind(this),0))},hterm.Terminal.prototype.onResize_=function(){var e=Math.floor(this.scrollPort_.getScreenWidth()/this.scrollPort_.characterSize.width)||0,t=lib.f.smartFloorDivide(this.scrollPort_.getScreenHeight(),this.scrollPort_.characterSize.height)||0;if(!(0>=e||0>=t)){var r=e!=this.screenSize.width||t!=this.screenSize.height;this.realizeSize_(e,t),this.showZoomWarning_(1!=this.scrollPort_.characterSize.zoomFactor),r&&this.overlaySize(),this.restyleCursor_(),this.scheduleSyncCursorPosition_()}},hterm.Terminal.prototype.onCursorBlink_=function(){return this.options_.cursorBlink?void("false"==this.cursorNode_.getAttribute("focus")||"0"==this.cursorNode_.style.opacity?(this.cursorNode_.style.opacity="1",this.timeouts_.cursorBlink=setTimeout(this.myOnCursorBlink_,this.cursorBlinkCycle_[0])):(this.cursorNode_.style.opacity="0",this.timeouts_.cursorBlink=setTimeout(this.myOnCursorBlink_,this.cursorBlinkCycle_[1]))):void delete this.timeouts_.cursorBlink},hterm.Terminal.prototype.setScrollbarVisible=function(e){this.scrollPort_.setScrollbarVisible(e)},hterm.Terminal.prototype.setScrollWheelMoveMultipler=function(e){this.scrollPort_.setScrollWheelMoveMultipler(e)},hterm.Terminal.prototype.closeBellNotifications_=function(){this.bellNotificationList_.forEach(function(e){e.close()}),this.bellNotificationList_.length=0},lib.rtdep("lib.encodeUTF8"),hterm.Terminal.IO=function(e){this.terminal_=e,this.previousIO_=null},hterm.Terminal.IO.prototype.showOverlay=function(e,t){this.terminal_.showOverlay(e,t)},hterm.Terminal.IO.prototype.createFrame=function(e,t){return new hterm.Frame(this.terminal_,e,t)},hterm.Terminal.IO.prototype.setTerminalProfile=function(e){this.terminal_.setProfile(e)},hterm.Terminal.IO.prototype.push=function(){var e=new hterm.Terminal.IO(this.terminal_);return e.keyboardCaptured_=this.keyboardCaptured_,e.columnCount=this.columnCount,e.rowCount=this.rowCount,e.previousIO_=this.terminal_.io,this.terminal_.io=e,e},hterm.Terminal.IO.prototype.pop=function(){this.terminal_.io=this.previousIO_},hterm.Terminal.IO.prototype.sendString=function(e){console.log("Unhandled sendString: "+e)},hterm.Terminal.IO.prototype.onVTKeystroke=function(e){console.log("Unobserverd VT keystroke: "+JSON.stringify(e))},hterm.Terminal.IO.prototype.onTerminalResize_=function(e,t){for(var r=this;r;)r.columnCount=e,r.rowCount=t,r=r.previousIO_;this.onTerminalResize(e,t)},hterm.Terminal.IO.prototype.onTerminalResize=function(e,t){},hterm.Terminal.IO.prototype.writeUTF8=function(e){if(this.terminal_.io!=this)throw"Attempt to print from inactive IO object.";this.terminal_.interpret(e)},hterm.Terminal.IO.prototype.writelnUTF8=function(e){if(this.terminal_.io!=this)throw"Attempt to print from inactive IO object.";this.terminal_.interpret(e+"\r\n")},hterm.Terminal.IO.prototype.print=hterm.Terminal.IO.prototype.writeUTF16=function(e){this.writeUTF8(lib.encodeUTF8(e))},hterm.Terminal.IO.prototype.println=hterm.Terminal.IO.prototype.writelnUTF16=function(e){this.writelnUTF8(lib.encodeUTF8(e))},lib.rtdep("lib.colors"),hterm.TextAttributes=function(e){this.document_=e,this.foregroundSource=this.SRC_DEFAULT,this.backgroundSource=this.SRC_DEFAULT,this.foreground=this.DEFAULT_COLOR,this.background=this.DEFAULT_COLOR,this.defaultForeground="rgb(255, 255, 255)",this.defaultBackground="rgb(0, 0, 0)",this.bold=!1,this.faint=!1,this.italic=!1,this.blink=!1,this.underline=!1,this.strikethrough=!1,this.inverse=!1,this.invisible=!1,this.wcNode=!1,this.tileData=null,this.colorPalette=null,this.resetColorPalette()},hterm.TextAttributes.prototype.enableBold=!0,hterm.TextAttributes.prototype.enableBoldAsBright=!0,hterm.TextAttributes.prototype.DEFAULT_COLOR=new String(""),hterm.TextAttributes.prototype.SRC_DEFAULT="default",hterm.TextAttributes.prototype.SRC_RGB="rgb",hterm.TextAttributes.prototype.setDocument=function(e){this.document_=e},hterm.TextAttributes.prototype.clone=function(){var e=new hterm.TextAttributes(null);for(var t in this)e[t]=this[t];return e.colorPalette=this.colorPalette.concat(),e},hterm.TextAttributes.prototype.reset=function(){this.foregroundSource=this.SRC_DEFAULT,this.backgroundSource=this.SRC_DEFAULT,this.foreground=this.DEFAULT_COLOR,this.background=this.DEFAULT_COLOR,this.bold=!1,this.faint=!1,this.italic=!1,this.blink=!1,this.underline=!1,this.strikethrough=!1,this.inverse=!1,this.invisible=!1,this.wcNode=!1},hterm.TextAttributes.prototype.resetColorPalette=function(){this.colorPalette=lib.colors.colorPalette.concat(),this.syncColors()},hterm.TextAttributes.prototype.isDefault=function(){return!(this.foregroundSource!=this.SRC_DEFAULT||this.backgroundSource!=this.SRC_DEFAULT||this.bold||this.faint||this.italic||this.blink||this.underline||this.strikethrough||this.inverse||this.invisible||this.wcNode||null!=this.tileData)},hterm.TextAttributes.prototype.createContainer=function(e){if(this.isDefault())return this.document_.createTextNode(e);var t=this.document_.createElement("span"),r=t.style,o=[];this.foreground!=this.DEFAULT_COLOR&&(r.color=this.foreground),this.background!=this.DEFAULT_COLOR&&(r.backgroundColor=this.background),this.enableBold&&this.bold&&(r.fontWeight="bold"),this.faint&&(t.faint=!0),this.italic&&(r.fontStyle="italic"),this.blink&&(o.push("blink-node"),t.blinkNode=!0);var i="";return this.underline&&(i+=" underline",t.underline=!0),this.strikethrough&&(i+=" line-through",t.strikethrough=!0),i&&(r.textDecoration=i),this.wcNode&&(o.push("wc-node"),t.wcNode=!0),null!=this.tileData&&(o.push("tile"),o.push("tile_"+this.tileData),t.tileNode=!0),e&&(t.textContent=e),o.length&&(t.className=o.join(" ")),t},hterm.TextAttributes.prototype.matchesContainer=function(e){if("string"==typeof e||3==e.nodeType)return this.isDefault();var t=e.style;return!(this.wcNode||e.wcNode||null!=this.tileData||e.tileNode||this.foreground!=t.color||this.background!=t.backgroundColor||(this.enableBold&&this.bold)!=!!t.fontWeight||this.blink!=e.blinkNode||this.italic!=!!t.fontStyle||!!this.underline!=!!e.underline||!!this.strikethrough!=!!e.strikethrough)},hterm.TextAttributes.prototype.setDefaults=function(e,t){this.defaultForeground=e,this.defaultBackground=t,this.syncColors()},hterm.TextAttributes.prototype.syncColors=function(){function e(e){return 8>e?e+8:e}var t=this.foregroundSource,r=this.backgroundSource,o=this.DEFAULT_COLOR,i=this.DEFAULT_COLOR;if(this.inverse&&(t=this.backgroundSource,r=this.foregroundSource,o=this.defaultBackground,i=this.defaultForeground),this.enableBoldAsBright&&this.bold&&t!=this.SRC_DEFAULT&&t!=this.SRC_RGB&&(t=e(t)),this.invisible&&(t=r,o=this.defaultBackground),t!=this.SRC_RGB&&(this.foreground=t==this.SRC_DEFAULT?o:this.colorPalette[t]),this.faint&&!this.invisible){var s=this.foreground==this.DEFAULT_COLOR?this.defaultForeground:this.foreground;this.foreground=lib.colors.mix(s,"rgb(0, 0, 0)",.3333)}r!=this.SRC_RGB&&(this.background=r==this.SRC_DEFAULT?i:this.colorPalette[r])},hterm.TextAttributes.containersMatch=function(e,t){if("string"==typeof e)return hterm.TextAttributes.containerIsDefault(t);if(e.nodeType!=t.nodeType)return!1;if(3==e.nodeType)return!0;var r=e.style,o=t.style;return r.color==o.color&&r.backgroundColor==o.backgroundColor&&r.fontWeight==o.fontWeight&&r.fontStyle==o.fontStyle&&r.textDecoration==o.textDecoration},hterm.TextAttributes.containerIsDefault=function(e){return"string"==typeof e||3==e.nodeType},hterm.TextAttributes.nodeWidth=function(e){return e.wcNode?lib.wc.strWidth(e.textContent):e.textContent.length},hterm.TextAttributes.nodeSubstr=function(e,t,r){return e.wcNode?lib.wc.substr(e.textContent,t,r):e.textContent.substr(t,r)},hterm.TextAttributes.nodeSubstring=function(e,t,r){return e.wcNode?lib.wc.substring(e.textContent,t,r):e.textContent.substring(t,r)},hterm.TextAttributes.splitWidecharString=function(e){for(var t=[],r=0,o=0,i=0;i<e.length;){var s=e.codePointAt(i),n=65535>=s?1:2;128>s||1==lib.wc.charWidth(s)?o+=n:(o&&t.push({str:e.substr(r,o)}),t.push({str:e.substr(i,n),wcNode:!0}),r=i+n,o=0),i+=n}return o&&t.push({str:e.substr(r,o)}),t},lib.rtdep("lib.colors","lib.f","lib.UTF8Decoder","hterm.VT.CharacterMap"),hterm.VT=function(e){this.terminal=e,e.onMouse=this.onTerminalMouse_.bind(this),this.mouseReport=this.MOUSE_REPORT_DISABLED,this.parseState_=new hterm.VT.ParseState(this.parseUnknown_),this.leadingModifier_="",this.trailingModifier_="",this.allowColumnWidthChanges_=!1,this.oscTimeLimit_=2e4;var t=Object.keys(hterm.VT.CC1).map(function(e){return"\\x"+lib.f.zpad(e.charCodeAt().toString(16),2)}).join("");this.cc1Pattern_=new RegExp("["+t+"]"),this.utf8Decoder_=new lib.UTF8Decoder,this.enable8BitControl=!1,this.enableClipboardWrite=!0,this.enableDec12=!1,this.characterEncoding="utf-8",this.maxStringSequence=1024,this.warnUnimplemented=!0,this.G0=hterm.VT.CharacterMap.maps.B,this.G1=hterm.VT.CharacterMap.maps[0],this.G2=hterm.VT.CharacterMap.maps.B,this.G3=hterm.VT.CharacterMap.maps.B,this.GL="G0",this.GR="G0",this.savedState_=new hterm.VT.CursorState(this)},hterm.VT.prototype.MOUSE_REPORT_DISABLED=0,hterm.VT.prototype.MOUSE_REPORT_CLICK=1,hterm.VT.prototype.MOUSE_REPORT_DRAG=3,hterm.VT.ParseState=function(e,t){this.defaultFunction=e,this.buf=t||null,this.pos=0,this.func=e,this.args=[]},hterm.VT.ParseState.prototype.reset=function(e){this.resetParseFunction(),this.resetBuf(e||""),this.resetArguments()},hterm.VT.ParseState.prototype.resetParseFunction=function(){this.func=this.defaultFunction},hterm.VT.ParseState.prototype.resetBuf=function(e){this.buf="string"==typeof e?e:null,this.pos=0},hterm.VT.ParseState.prototype.resetArguments=function(e){this.args.length=0,"undefined"!=typeof e&&(this.args[0]=e)},hterm.VT.ParseState.prototype.iarg=function(e,t){var r=this.args[e];if(r){var o=parseInt(r,10);return 0==o&&(o=t),o}return t},hterm.VT.ParseState.prototype.advance=function(e){this.pos+=e},hterm.VT.ParseState.prototype.peekRemainingBuf=function(){return this.buf.substr(this.pos)},hterm.VT.ParseState.prototype.peekChar=function(){return this.buf.substr(this.pos,1)},hterm.VT.ParseState.prototype.consumeChar=function(){return this.buf.substr(this.pos++,1)},hterm.VT.ParseState.prototype.isComplete=function(){return null==this.buf||this.buf.length<=this.pos},hterm.VT.CursorState=function(e){this.vt_=e,this.save()},hterm.VT.CursorState.prototype.save=function(){this.cursor=this.vt_.terminal.saveCursor(),this.textAttributes=this.vt_.terminal.getTextAttributes().clone(),this.GL=this.vt_.GL,this.GR=this.vt_.GR,this.G0=this.vt_.G0,this.G1=this.vt_.G1,this.G2=this.vt_.G2,this.G3=this.vt_.G3},hterm.VT.CursorState.prototype.restore=function(){this.vt_.terminal.restoreCursor(this.cursor),this.vt_.terminal.setTextAttributes(this.textAttributes.clone()),this.vt_.GL=this.GL,this.vt_.GR=this.GR,this.vt_.G0=this.G0,this.vt_.G1=this.G1,this.vt_.G2=this.G2,this.vt_.G3=this.G3},hterm.VT.prototype.reset=function(){this.G0=hterm.VT.CharacterMap.maps.B,this.G1=hterm.VT.CharacterMap.maps[0],this.G2=hterm.VT.CharacterMap.maps.B,this.G3=hterm.VT.CharacterMap.maps.B,this.GL="G0",this.GR="G0",this.savedState_=new hterm.VT.CursorState(this),this.mouseReport=this.MOUSE_REPORT_DISABLED},hterm.VT.prototype.onTerminalMouse_=function(e){if(this.mouseReport!=this.MOUSE_REPORT_DISABLED){var t,r=0;e.shiftKey&&(r|=4),(e.metaKey||this.terminal.keyboard.altIsMeta&&e.altKey)&&(r|=8),e.ctrlKey&&(r|=16);var o=String.fromCharCode(lib.f.clamp(e.terminalColumn+32,32,255)),i=String.fromCharCode(lib.f.clamp(e.terminalRow+32,32,255));switch(e.type){case"mousewheel":s=(e.wheelDeltaY>0?0:1)+96,s|=r,t=""+String.fromCharCode(s)+o+i,e.preventDefault();break;case"mousedown":var s=Math.min(e.which-1,2)+32;s|=r,t=""+String.fromCharCode(s)+o+i;break;case"mouseup":t="#"+o+i;break;case"mousemove":this.mouseReport==this.MOUSE_REPORT_DRAG&&e.which&&(s=32+Math.min(e.which-1,2),s+=32,s|=r,t=""+String.fromCharCode(s)+o+i);break;case"click":case"dblclick":break;default:console.error("Unknown mouse event: "+e.type,e)}t&&this.terminal.io.sendString(t)}},hterm.VT.prototype.interpret=function(e){for(this.parseState_.resetBuf(this.decode(e));!this.parseState_.isComplete();){var t=this.parseState_.func,r=this.parseState_.pos,e=this.parseState_.buf;if(this.parseState_.func.call(this,this.parseState_),this.parseState_.func==t&&this.parseState_.pos==r&&this.parseState_.buf==e)throw"Parser did not alter the state!"}},hterm.VT.prototype.decode=function(e){return"utf-8"==this.characterEncoding?this.decodeUTF8(e):e},hterm.VT.prototype.encodeUTF8=function(e){return lib.encodeUTF8(e)},hterm.VT.prototype.decodeUTF8=function(e){return this.utf8Decoder_.decode(e)},hterm.VT.prototype.parseUnknown_=function(e){function t(e){r[r.GL].GL&&(e=r[r.GL].GL(e)),r[r.GR].GR&&(e=r[r.GR].GR(e)),r.terminal.print(e)}var r=this,o=e.peekRemainingBuf(),i=o.search(this.cc1Pattern_);return 0==i?(this.dispatch("CC1",o.substr(0,1),e),void e.advance(1)):-1==i?(t(o),void e.reset()):(t(o.substr(0,i)),this.dispatch("CC1",o.substr(i,1),e),void e.advance(i+1))},hterm.VT.prototype.parseCSI_=function(e){var t=e.peekChar(),r=e.args;t>="@"&&"~">=t?(this.dispatch("CSI",this.leadingModifier_+this.trailingModifier_+t,e),e.resetParseFunction()):";"==t?this.trailingModifier_?e.resetParseFunction():(r.length||r.push(""),r.push("")):t>="0"&&"9">=t?this.trailingModifier_?e.resetParseFunction():r.length?r[r.length-1]+=t:r[0]=t:t>=" "&&"?">=t&&":"!=t?r.length?this.trailingModifier_+=t:this.leadingModifier_+=t:this.cc1Pattern_.test(t)?this.dispatch("CC1",t,e):e.resetParseFunction(),e.advance(1)},hterm.VT.prototype.parseUntilStringTerminator_=function(e){var t=e.peekRemainingBuf(),r=t.search(/(\x1b\\|\x07)/),o=e.args;if(o.length||(o[0]="",o[1]=new Date),-1==r){o[0]+=t;var i;return o[0].length>this.maxStringSequence&&(i="too long: "+o[0].length),-1!=o[0].indexOf("")&&(i="embedded escape: "+o[0].indexOf("")),new Date-o[1]>this.oscTimeLimit_&&(i="timeout expired: "+new Date-o[1]),i?(console.log("parseUntilStringTerminator_: aborting: "+i,o[0]),e.reset(o[0]),!1):(e.advance(t.length),!0)}return o[0].length+r>this.maxStringSequence?(e.reset(o[0]+t),!1):(o[0]+=t.substr(0,r),e.resetParseFunction(),e.advance(r+(""==t.substr(r,1)?2:1)),!0)},hterm.VT.prototype.dispatch=function(e,t,r){var o=hterm.VT[e][t];return o?o==hterm.VT.ignore?void(this.warnUnimplemented&&console.warn("Ignored "+e+" code: "+JSON.stringify(t))):"CC1"==e&&t>""&&!this.enable8BitControl?void console.warn("Ignoring 8-bit control code: 0x"+t.charCodeAt(0).toString(16)):void o.apply(this,[r,t]):void(this.warnUnimplemented&&console.warn("Unknown "+e+" code: "+JSON.stringify(t)))},hterm.VT.prototype.setANSIMode=function(e,t){"4"==e?this.terminal.setInsertMode(t):"20"==e?this.terminal.setAutoCarriageReturn(t):this.warnUnimplemented&&console.warn("Unimplemented ANSI Mode: "+e)},hterm.VT.prototype.setDECMode=function(e,t){switch(e){case"1":this.terminal.keyboard.applicationCursor=t;break;case"3":this.allowColumnWidthChanges_&&(this.terminal.setWidth(t?132:80),this.terminal.clearHome(),this.terminal.setVTScrollRegion(null,null));break;case"5":this.terminal.setReverseVideo(t);break;case"6":this.terminal.setOriginMode(t);break;case"7":this.terminal.setWraparound(t);break;case"12":this.enableDec12&&this.terminal.setCursorBlink(t);break;case"25":this.terminal.setCursorVisible(t);break;case"40":this.terminal.allowColumnWidthChanges_=t;break;case"45":this.terminal.setReverseWraparound(t);break;case"67":this.terminal.keyboard.backspaceSendsBackspace=t;break;case"1000":this.mouseReport=t?this.MOUSE_REPORT_CLICK:this.MOUSE_REPORT_DISABLED;break;case"1002":this.mouseReport=t?this.MOUSE_REPORT_DRAG:this.MOUSE_REPORT_DISABLED;break;case"1010":this.terminal.scrollOnOutput=t;break;case"1011":this.terminal.scrollOnKeystroke=t;break;case"1036":this.terminal.keyboard.metaSendsEscape=t;break;case"1039":t?this.terminal.keyboard.previousAltSendsWhat_||(this.terminal.keyboard.previousAltSendsWhat_=this.terminal.keyboard.altSendsWhat,this.terminal.keyboard.altSendsWhat="escape"):this.terminal.keyboard.previousAltSendsWhat_&&(this.terminal.keyboard.altSendsWhat=this.terminal.keyboard.previousAltSendsWhat_,this.terminal.keyboard.previousAltSendsWhat_=null);break;case"47":case"1047":this.terminal.setAlternateMode(t);break;case"1048":this.savedState_.save();case"1049":t?(this.savedState_.save(),this.terminal.setAlternateMode(t),this.terminal.clear()):(this.terminal.setAlternateMode(t),this.savedState_.restore());break;case"2004":this.terminal.setBracketedPaste(t);break;default:this.warnUnimplemented&&console.warn("Unimplemented DEC Private Mode: "+e)}},hterm.VT.ignore=function(){},hterm.VT.CC1={},hterm.VT.ESC={},hterm.VT.CSI={},hterm.VT.OSC={},hterm.VT.VT52={},hterm.VT.CC1["\x00"]=function(){},hterm.VT.CC1[""]=hterm.VT.ignore,hterm.VT.CC1[""]=function(){this.terminal.ringBell()},hterm.VT.CC1["\b"]=function(){this.terminal.cursorLeft(1)},hterm.VT.CC1["	"]=function(){this.terminal.forwardTabStop()},hterm.VT.CC1["\n"]=function(){this.terminal.formFeed()},hterm.VT.CC1[""]=hterm.VT.CC1["\n"],hterm.VT.CC1["\f"]=function(){this.terminal.formFeed()},hterm.VT.CC1["\r"]=function(){this.terminal.setCursorColumn(0)},hterm.VT.CC1[""]=function(){this.GL="G1"},hterm.VT.CC1[""]=function(){this.GL="G0"},hterm.VT.CC1[""]=hterm.VT.ignore,hterm.VT.CC1[""]=hterm.VT.ignore,hterm.VT.CC1[""]=function(e){"G1"==this.GL&&(this.GL="G0"),e.resetParseFunction(),this.terminal.print("?")},hterm.VT.CC1[""]=hterm.VT.CC1[""],hterm.VT.CC1[""]=function(e){function t(e){var r=e.consumeChar();""!=r&&(this.dispatch("ESC",r,e),e.func==t&&e.resetParseFunction())}e.func=t},hterm.VT.CC1[""]=hterm.VT.ignore,hterm.VT.CC1["„"]=hterm.VT.ESC.D=function(){this.terminal.lineFeed()},hterm.VT.CC1["…"]=hterm.VT.ESC.E=function(){this.terminal.setCursorColumn(0),this.terminal.cursorDown(1)},hterm.VT.CC1["ˆ"]=hterm.VT.ESC.H=function(){this.terminal.setTabStop(this.terminal.getCursorColumn())},hterm.VT.CC1[""]=hterm.VT.ESC.M=function(){this.terminal.reverseLineFeed()},hterm.VT.CC1["Ž"]=hterm.VT.ESC.N=hterm.VT.ignore,hterm.VT.CC1[""]=hterm.VT.ESC.O=hterm.VT.ignore,hterm.VT.CC1[""]=hterm.VT.ESC.P=function(e){e.resetArguments(),e.func=this.parseUntilStringTerminator_},hterm.VT.CC1["–"]=hterm.VT.ESC.V=hterm.VT.ignore,hterm.VT.CC1["—"]=hterm.VT.ESC.W=hterm.VT.ignore,hterm.VT.CC1["˜"]=hterm.VT.ESC.X=hterm.VT.ignore,hterm.VT.CC1["š"]=hterm.VT.ESC.Z=function(){this.terminal.io.sendString("[?1;2c")},hterm.VT.CC1["›"]=hterm.VT.ESC["["]=function(e){e.resetArguments(),this.leadingModifier_="",
-this.trailingModifier_="",e.func=this.parseCSI_},hterm.VT.CC1["œ"]=hterm.VT.ESC["\\"]=hterm.VT.ignore,hterm.VT.CC1[""]=hterm.VT.ESC["]"]=function(e){function t(e){if(this.parseUntilStringTerminator_(e)&&e.func!=t){var r=e.args[0].match(/^(\d+);(.*)$/);r?(e.args[0]=r[2],this.dispatch("OSC",r[1],e)):console.warn("Invalid OSC: "+JSON.stringify(e.args[0]))}}e.resetArguments(),e.func=t},hterm.VT.CC1["ž"]=hterm.VT.ESC["^"]=function(e){e.resetArguments(),e.func=this.parseUntilStringTerminator_},hterm.VT.CC1["Ÿ"]=hterm.VT.ESC._=function(e){e.resetArguments(),e.func=this.parseUntilStringTerminator_},hterm.VT.ESC[" "]=function(e){e.func=function(e){var t=e.consumeChar();this.warnUnimplemented&&console.warn("Unimplemented sequence: ESC 0x20 "+t),e.resetParseFunction()}},hterm.VT.ESC["#"]=function(e){e.func=function(e){var t=e.consumeChar();"8"==t&&this.terminal.fill("E"),e.resetParseFunction()}},hterm.VT.ESC["%"]=function(e){e.func=function(e){var t=e.consumeChar();"@"!=t&&"G"!=t&&this.warnUnimplemented&&console.warn("Unknown ESC % argument: "+JSON.stringify(t)),e.resetParseFunction()}},hterm.VT.ESC["("]=hterm.VT.ESC[")"]=hterm.VT.ESC["*"]=hterm.VT.ESC["+"]=hterm.VT.ESC["-"]=hterm.VT.ESC["."]=hterm.VT.ESC["/"]=function(e,t){e.func=function(e){var r=e.consumeChar();return""==r?(e.resetParseFunction(),void e.func()):(r in hterm.VT.CharacterMap.maps?"("==t?this.G0=hterm.VT.CharacterMap.maps[r]:")"==t||"-"==t?this.G1=hterm.VT.CharacterMap.maps[r]:"*"==t||"."==t?this.G2=hterm.VT.CharacterMap.maps[r]:("+"==t||"/"==t)&&(this.G3=hterm.VT.CharacterMap.maps[r]):this.warnUnimplemented&&console.log('Invalid character set for "'+t+'": '+r),void e.resetParseFunction())}},hterm.VT.ESC[6]=hterm.VT.ignore,hterm.VT.ESC[7]=function(){this.savedState_.save()},hterm.VT.ESC[8]=function(){this.savedState_.restore()},hterm.VT.ESC[9]=hterm.VT.ignore,hterm.VT.ESC["="]=function(){this.terminal.keyboard.applicationKeypad=!0},hterm.VT.ESC[">"]=function(){this.terminal.keyboard.applicationKeypad=!1},hterm.VT.ESC.F=hterm.VT.ignore,hterm.VT.ESC.c=function(){this.reset(),this.terminal.reset()},hterm.VT.ESC.l=hterm.VT.ESC.m=hterm.VT.ignore,hterm.VT.ESC.n=function(){this.GL="G2"},hterm.VT.ESC.o=function(){this.GL="G3"},hterm.VT.ESC["|"]=function(){this.GR="G3"},hterm.VT.ESC["}"]=function(){this.GR="G2"},hterm.VT.ESC["~"]=function(){this.GR="G1"},hterm.VT.OSC[0]=function(e){this.terminal.setWindowTitle(e.args[0])},hterm.VT.OSC[2]=hterm.VT.OSC[0],hterm.VT.OSC[4]=function(e){for(var t=e.args[0].split(";"),r=parseInt(t.length/2),o=this.terminal.getTextAttributes().colorPalette,i=[],s=0;r>s;++s){var n=parseInt(t[2*s]),a=t[2*s+1];n>=o.length||("?"!=a?(a=lib.colors.x11ToCSS(a),a&&(o[n]=a)):(a=lib.colors.rgbToX11(o[n]),a&&i.push(n+";"+a)))}i.length&&this.terminal.io.sendString("]4;"+i.join(";")+"")},hterm.VT.OSC[50]=function(e){var t=e.args[0].match(/CursorShape=(.)/i);if(!t)return void console.warn("Could not parse OSC 50 args: "+e.args[0]);switch(t[1]){case"1":this.terminal.setCursorShape(hterm.Terminal.cursorShape.BEAM);break;case"2":this.terminal.setCursorShape(hterm.Terminal.cursorShape.UNDERLINE);break;default:this.terminal.setCursorShape(hterm.Terminal.cursorShape.BLOCK)}},hterm.VT.OSC[52]=function(e){var t=e.args[0].match(/^[cps01234567]*;(.*)/);if(t){var r=window.atob(t[1]);r&&this.terminal.copyStringToClipboard(this.decode(r))}},hterm.VT.CSI["@"]=function(e){this.terminal.insertSpace(e.iarg(0,1))},hterm.VT.CSI.A=function(e){this.terminal.cursorUp(e.iarg(0,1))},hterm.VT.CSI.B=function(e){this.terminal.cursorDown(e.iarg(0,1))},hterm.VT.CSI.C=function(e){this.terminal.cursorRight(e.iarg(0,1))},hterm.VT.CSI.D=function(e){this.terminal.cursorLeft(e.iarg(0,1))},hterm.VT.CSI.E=function(e){this.terminal.cursorDown(e.iarg(0,1)),this.terminal.setCursorColumn(0)},hterm.VT.CSI.F=function(e){this.terminal.cursorUp(e.iarg(0,1)),this.terminal.setCursorColumn(0)},hterm.VT.CSI.G=function(e){this.terminal.setCursorColumn(e.iarg(0,1)-1)},hterm.VT.CSI.H=function(e){this.terminal.setCursorPosition(e.iarg(0,1)-1,e.iarg(1,1)-1)},hterm.VT.CSI.I=function(e){var t=e.iarg(0,1);t=lib.f.clamp(t,1,this.terminal.screenSize.width);for(var r=0;t>r;r++)this.terminal.forwardTabStop()},hterm.VT.CSI.J=hterm.VT.CSI["?J"]=function(e,t){var r=e.args[0];r&&"0"!=r?"1"==r?this.terminal.eraseAbove():"2"==r?this.terminal.clear():"3"==r&&this.terminal.clear():this.terminal.eraseBelow()},hterm.VT.CSI.K=hterm.VT.CSI["?K"]=function(e,t){var r=e.args[0];r&&"0"!=r?"1"==r?this.terminal.eraseToLeft():"2"==r&&this.terminal.eraseLine():this.terminal.eraseToRight()},hterm.VT.CSI.L=function(e){this.terminal.insertLines(e.iarg(0,1))},hterm.VT.CSI.M=function(e){this.terminal.deleteLines(e.iarg(0,1))},hterm.VT.CSI.P=function(e){this.terminal.deleteChars(e.iarg(0,1))},hterm.VT.CSI.S=function(e){this.terminal.vtScrollUp(e.iarg(0,1))},hterm.VT.CSI.T=function(e){e.args.length<=1&&this.terminal.vtScrollDown(e.iarg(0,1))},hterm.VT.CSI[">T"]=hterm.VT.ignore,hterm.VT.CSI.X=function(e){this.terminal.eraseToRight(e.iarg(0,1))},hterm.VT.CSI.Z=function(e){var t=e.iarg(0,1);t=lib.f.clamp(t,1,this.terminal.screenSize.width);for(var r=0;t>r;r++)this.terminal.backwardTabStop()},hterm.VT.CSI["`"]=function(e){this.terminal.setCursorColumn(e.iarg(0,1)-1)},hterm.VT.CSI.b=hterm.VT.ignore,hterm.VT.CSI.c=function(e){e.args[0]&&"0"!=e.args[0]||this.terminal.io.sendString("[?1;2c")},hterm.VT.CSI[">c"]=function(e){this.terminal.io.sendString("[>0;256;0c")},hterm.VT.CSI.d=function(e){this.terminal.setAbsoluteCursorRow(e.iarg(0,1)-1)},hterm.VT.CSI.f=hterm.VT.CSI.H,hterm.VT.CSI.g=function(e){e.args[0]&&"0"!=e.args[0]?"3"==e.args[0]&&this.terminal.clearAllTabStops():this.terminal.clearTabStopAtCursor(!1)},hterm.VT.CSI.h=function(e){for(var t=0;t<e.args.length;t++)this.setANSIMode(e.args[t],!0)},hterm.VT.CSI["?h"]=function(e){for(var t=0;t<e.args.length;t++)this.setDECMode(e.args[t],!0)},hterm.VT.CSI.i=hterm.VT.CSI["?i"]=hterm.VT.ignore,hterm.VT.CSI.l=function(e){for(var t=0;t<e.args.length;t++)this.setANSIMode(e.args[t],!1)},hterm.VT.CSI["?l"]=function(e){for(var t=0;t<e.args.length;t++)this.setDECMode(e.args[t],!1)},hterm.VT.CSI.m=function(e){function t(t){return e.args.length<t+2||"5"!=e.args[t+1]?null:e.iarg(t+2,0)}function r(t){if(e.args.length<t+5||"2"!=e.args[t+1])return null;var r=e.iarg(t+2,0),o=e.iarg(t+3,0),i=e.iarg(t+4,0);return"rgb("+r+" ,"+o+" ,"+i+")"}var o=this.terminal.getTextAttributes();if(!e.args.length)return void o.reset();for(var i=0;i<e.args.length;i++){var s=e.iarg(i,0);if(30>s)0==s?o.reset():1==s?o.bold=!0:2==s?o.faint=!0:3==s?o.italic=!0:4==s?o.underline=!0:5==s?o.blink=!0:7==s?o.inverse=!0:8==s?o.invisible=!0:9==s?o.strikethrough=!0:22==s?(o.bold=!1,o.faint=!1):23==s?o.italic=!1:24==s?o.underline=!1:25==s?o.blink=!1:27==s?o.inverse=!1:28==s?o.invisible=!1:29==s&&(o.strikethrough=!1);else if(50>s)if(38>s)o.foregroundSource=s-30;else if(38==s){var n=r(i);if(null!=n)o.foregroundSource=o.SRC_RGB,o.foreground=n,i+=5;else{var a=t(i);if(null==a)break;if(i+=2,a>=o.colorPalette.length)continue;o.foregroundSource=a}}else if(39==s)o.foregroundSource=o.SRC_DEFAULT;else if(48>s)o.backgroundSource=s-40;else if(48==s){var n=r(i);if(null!=n)o.backgroundSource=o.SRC_RGB,o.background=n,i+=5;else{var a=t(i);if(null==a)break;if(i+=2,a>=o.colorPalette.length)continue;o.backgroundSource=a}}else o.backgroundSource=o.SRC_DEFAULT;else s>=90&&97>=s?o.foregroundSource=s-90+8:s>=100&&107>=s&&(o.backgroundSource=s-100+8)}o.setDefaults(this.terminal.getForegroundColor(),this.terminal.getBackgroundColor())},hterm.VT.CSI[">m"]=hterm.VT.ignore,hterm.VT.CSI.n=function(e){if("5"==e.args[0])this.terminal.io.sendString("0n");else if("6"==e.args[0]){var t=this.terminal.getCursorRow()+1,r=this.terminal.getCursorColumn()+1;this.terminal.io.sendString("["+t+";"+r+"R")}},hterm.VT.CSI[">n"]=hterm.VT.ignore,hterm.VT.CSI["?n"]=function(e){if("6"==e.args[0]){var t=this.terminal.getCursorRow()+1,r=this.terminal.getCursorColumn()+1;this.terminal.io.sendString("["+t+";"+r+"R")}else"15"==e.args[0]?this.terminal.io.sendString("[?11n"):"25"==e.args[0]?this.terminal.io.sendString("[?21n"):"26"==e.args[0]?this.terminal.io.sendString("[?12;1;0;0n"):"53"==e.args[0]&&this.terminal.io.sendString("[?50n")},hterm.VT.CSI[">p"]=hterm.VT.ignore,hterm.VT.CSI["!p"]=function(){this.reset(),this.terminal.softReset()},hterm.VT.CSI.$p=hterm.VT.ignore,hterm.VT.CSI["?$p"]=hterm.VT.ignore,hterm.VT.CSI['"p']=hterm.VT.ignore,hterm.VT.CSI.q=hterm.VT.ignore,hterm.VT.CSI[" q"]=function(e){var t=e.args[0];"0"==t||"1"==t?(this.terminal.setCursorShape(hterm.Terminal.cursorShape.BLOCK),this.terminal.setCursorBlink(!0)):"2"==t?(this.terminal.setCursorShape(hterm.Terminal.cursorShape.BLOCK),this.terminal.setCursorBlink(!1)):"3"==t?(this.terminal.setCursorShape(hterm.Terminal.cursorShape.UNDERLINE),this.terminal.setCursorBlink(!0)):"4"==t?(this.terminal.setCursorShape(hterm.Terminal.cursorShape.UNDERLINE),this.terminal.setCursorBlink(!1)):console.warn("Unknown cursor style: "+t)},hterm.VT.CSI['"q']=hterm.VT.ignore,hterm.VT.CSI.r=function(e){var t=e.args,r=t[0]?parseInt(t[0],10)-1:null,o=t[1]?parseInt(t[1],10)-1:null;this.terminal.setVTScrollRegion(r,o),this.terminal.setCursorPosition(0,0)},hterm.VT.CSI["?r"]=hterm.VT.ignore,hterm.VT.CSI.$r=hterm.VT.ignore,hterm.VT.CSI.s=function(){this.savedState_.save()},hterm.VT.CSI["?s"]=hterm.VT.ignore,hterm.VT.CSI.t=hterm.VT.ignore,hterm.VT.CSI.$t=hterm.VT.ignore,hterm.VT.CSI[">t"]=hterm.VT.ignore,hterm.VT.CSI[" t"]=hterm.VT.ignore,hterm.VT.CSI.u=function(){this.savedState_.restore()},hterm.VT.CSI[" u"]=hterm.VT.ignore,hterm.VT.CSI.$v=hterm.VT.ignore,hterm.VT.CSI["'w"]=hterm.VT.ignore,hterm.VT.CSI.x=hterm.VT.ignore,hterm.VT.CSI["*x"]=hterm.VT.ignore,hterm.VT.CSI.$x=hterm.VT.ignore,hterm.VT.CSI.z=function(e){if(!(e.args.length<1)){var t=e.args[0];if("0"==t){if(e.args.length<2)return;this.terminal.getTextAttributes().tileData=e.args[1]}else"1"==t&&(this.terminal.getTextAttributes().tileData=null)}},hterm.VT.CSI["'z"]=hterm.VT.ignore,hterm.VT.CSI.$z=hterm.VT.ignore,hterm.VT.CSI["'{"]=hterm.VT.ignore,hterm.VT.CSI["'|"]=hterm.VT.ignore,hterm.VT.CSI[" }"]=hterm.VT.ignore,hterm.VT.CSI[" ~"]=hterm.VT.ignore,lib.rtdep("lib.f"),hterm.VT.CharacterMap=function(e,t){this.name=e,this.GL=null,this.GR=null,t&&this.reset(t)},hterm.VT.CharacterMap.prototype.reset=function(e){this.glmap=e;var t=Object.keys(this.glmap).map(function(e){return"\\x"+lib.f.zpad(e.charCodeAt(0).toString(16))});this.glre=new RegExp("["+t.join("")+"]","g"),this.grmap={},t.forEach(function(e){var t=String.fromCharCode(128&e.charCodeAt(0));this.grmap[t]=this.glmap[e]}.bind(this));var r=Object.keys(this.grmap).map(function(e){return"\\x"+lib.f.zpad(e.charCodeAt(0).toString(16),2)});this.grre=new RegExp("["+r.join("")+"]","g"),this.GL=function(e){return e.replace(this.glre,function(e){return this.glmap[e]}.bind(this))}.bind(this),this.GR=function(e){return e.replace(this.grre,function(e){return this.grmap[e]}.bind(this))}.bind(this)},hterm.VT.CharacterMap.maps={},hterm.VT.CharacterMap.maps[0]=new hterm.VT.CharacterMap("graphic",{"`":"◆",a:"▒",b:"␉",c:"␌",d:"␍",e:"␊",f:"°",g:"±",h:"␤",i:"␋",j:"┘",k:"┐",l:"┌",m:"└",n:"┼",o:"⎺",p:"⎻",q:"─",r:"⎼",s:"⎽",t:"├",u:"┤",v:"┴",w:"┬",x:"│",y:"≤",z:"≥","{":"π","|":"≠","}":"£","~":"·"}),hterm.VT.CharacterMap.maps.A=new hterm.VT.CharacterMap("british",{"#":"£"}),hterm.VT.CharacterMap.maps.B=new hterm.VT.CharacterMap("us",null),hterm.VT.CharacterMap.maps[4]=new hterm.VT.CharacterMap("dutch",{"#":"£","@":"¾","[":"IJ","\\":"½","]":"|","{":"¨","|":"f","}":"¼","~":"´"}),hterm.VT.CharacterMap.maps.C=hterm.VT.CharacterMap.maps[5]=new hterm.VT.CharacterMap("finnish",{"[":"Ä","\\":"Ö","]":"Å","^":"Ü","`":"é","{":"ä","|":"ö","}":"å","~":"ü"}),hterm.VT.CharacterMap.maps.R=new hterm.VT.CharacterMap("french",{"#":"£","@":"à","[":"°","\\":"ç","]":"§","{":"é","|":"ù","}":"è","~":"¨"}),hterm.VT.CharacterMap.maps.Q=new hterm.VT.CharacterMap("french canadian",{"@":"à","[":"â","\\":"ç","]":"ê","^":"î","`":"ô","{":"é","|":"ù","}":"è","~":"û"}),hterm.VT.CharacterMap.maps.K=new hterm.VT.CharacterMap("german",{"@":"§","[":"Ä","\\":"Ö","]":"Ü","{":"ä","|":"ö","}":"ü","~":"ß"}),hterm.VT.CharacterMap.maps.Y=new hterm.VT.CharacterMap("italian",{"#":"£","@":"§","[":"°","\\":"ç","]":"é","`":"ù","{":"à","|":"ò","}":"è","~":"ì"}),hterm.VT.CharacterMap.maps.E=hterm.VT.CharacterMap.maps[6]=new hterm.VT.CharacterMap("norwegian/danish",{"@":"Ä","[":"Æ","\\":"Ø","]":"Å","^":"Ü","`":"ä","{":"æ","|":"ø","}":"å","~":"ü"}),hterm.VT.CharacterMap.maps.Z=new hterm.VT.CharacterMap("spanish",{"#":"£","@":"§","[":"¡","\\":"Ñ","]":"¿","{":"°","|":"ñ","}":"ç"}),hterm.VT.CharacterMap.maps[7]=hterm.VT.CharacterMap.maps.H=new hterm.VT.CharacterMap("swedish",{"@":"É","[":"Ä","\\":"Ö","]":"Å","^":"Ü","`":"é","{":"ä","|":"ö","}":"å","~":"ü"}),hterm.VT.CharacterMap.maps["="]=new hterm.VT.CharacterMap("swiss",{"#":"ù","@":"à","[":"é","\\":"ç","]":"ê","^":"î",_:"è","`":"ô","{":"ä","|":"ö","}":"ü","~":"û"}),lib.resource.add("hterm/audio/bell","audio/ogg;base64","T2dnUwACAAAAAAAAAADhqW5KAAAAAMFvEjYBHgF2b3JiaXMAAAAAAYC7AAAAAAAAAHcBAAAAAAC4AU9nZ1MAAAAAAAAAAAAA4aluSgEAAAAAesI3EC3//////////////////8kDdm9yYmlzHQAAAFhpcGguT3JnIGxpYlZvcmJpcyBJIDIwMDkwNzA5AAAAAAEFdm9yYmlzKUJDVgEACAAAADFMIMWA0JBVAAAQAABgJCkOk2ZJKaWUoSh5mJRISSmllMUwiZiUicUYY4wxxhhjjDHGGGOMIDRkFQAABACAKAmOo+ZJas45ZxgnjnKgOWlOOKcgB4pR4DkJwvUmY26mtKZrbs4pJQgNWQUAAAIAQEghhRRSSCGFFGKIIYYYYoghhxxyyCGnnHIKKqigggoyyCCDTDLppJNOOumoo4466ii00EILLbTSSkwx1VZjrr0GXXxzzjnnnHPOOeecc84JQkNWAQAgAAAEQgYZZBBCCCGFFFKIKaaYcgoyyIDQkFUAACAAgAAAAABHkRRJsRTLsRzN0SRP8ixREzXRM0VTVE1VVVVVdV1XdmXXdnXXdn1ZmIVbuH1ZuIVb2IVd94VhGIZhGIZhGIZh+H3f933f930gNGQVACABAKAjOZbjKaIiGqLiOaIDhIasAgBkAAAEACAJkiIpkqNJpmZqrmmbtmirtm3LsizLsgyEhqwCAAABAAQAAAAAAKBpmqZpmqZpmqZpmqZpmqZpmqZpmmZZlmVZlmVZlmVZlmVZlmVZlmVZlmVZlmVZlmVZlmVZlmVZlmVZQGjIKgBAAgBAx3Ecx3EkRVIkx3IsBwgNWQUAyAAACABAUizFcjRHczTHczzHczxHdETJlEzN9EwPCA1ZBQAAAgAIAAAAAABAMRzFcRzJ0SRPUi3TcjVXcz3Xc03XdV1XVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVYHQkFUAAAQAACGdZpZqgAgzkGEgNGQVAIAAAAAYoQhDDAgNWQUAAAQAAIih5CCa0JrzzTkOmuWgqRSb08GJVJsnuamYm3POOeecbM4Z45xzzinKmcWgmdCac85JDJqloJnQmnPOeRKbB62p0ppzzhnnnA7GGWGcc85p0poHqdlYm3POWdCa5qi5FJtzzomUmye1uVSbc84555xzzjnnnHPOqV6czsE54Zxzzonam2u5CV2cc875ZJzuzQnhnHPOOeecc84555xzzglCQ1YBAEAAAARh2BjGnYIgfY4GYhQhpiGTHnSPDpOgMcgppB6NjkZKqYNQUhknpXSC0JBVAAAgAACEEFJIIYUUUkghhRRSSCGGGGKIIaeccgoqqKSSiirKKLPMMssss8wyy6zDzjrrsMMQQwwxtNJKLDXVVmONteaec645SGultdZaK6WUUkoppSA0ZBUAAAIAQCBkkEEGGYUUUkghhphyyimnoIIKCA1ZBQAAAgAIAAAA8CTPER3RER3RER3RER3RER3P8RxREiVREiXRMi1TMz1VVFVXdm1Zl3Xbt4Vd2HXf133f141fF4ZlWZZlWZZlWZZlWZZlWZZlCUJDVgEAIAAAAEIIIYQUUkghhZRijDHHnINOQgmB0JBVAAAgAIAAAAAAR3EUx5EcyZEkS7IkTdIszfI0T/M00RNFUTRNUxVd0RV10xZlUzZd0zVl01Vl1XZl2bZlW7d9WbZ93/d93/d93/d93/d939d1IDRkFQAgAQCgIzmSIimSIjmO40iSBISGrAIAZAAABACgKI7iOI4jSZIkWZImeZZniZqpmZ7pqaIKhIasAgAAAQAEAAAAAACgaIqnmIqniIrniI4oiZZpiZqquaJsyq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7rukBoyCoAQAIAQEdyJEdyJEVSJEVyJAcIDVkFAMgAAAgAwDEcQ1Ikx7IsTfM0T/M00RM90TM9VXRFFwgNWQUAAAIACAAAAAAAwJAMS7EczdEkUVIt1VI11VItVVQ9VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV1TRN0zSB0JCVAAAZAAAjQQYZhBCKcpBCbj1YCDHmJAWhOQahxBiEpxAzDDkNInSQQSc9uJI5wwzz4FIoFURMg40lN44gDcKmXEnlOAhCQ1YEAFEAAIAxyDHEGHLOScmgRM4xCZ2UyDknpZPSSSktlhgzKSWmEmPjnKPSScmklBhLip2kEmOJrQAAgAAHAIAAC6HQkBUBQBQAAGIMUgophZRSzinmkFLKMeUcUko5p5xTzjkIHYTKMQadgxAppRxTzinHHITMQeWcg9BBKAAAIMABACDAQig0ZEUAECcA4HAkz5M0SxQlSxNFzxRl1xNN15U0zTQ1UVRVyxNV1VRV2xZNVbYlTRNNTfRUVRNFVRVV05ZNVbVtzzRl2VRV3RZV1bZl2xZ+V5Z13zNNWRZV1dZNVbV115Z9X9ZtXZg0zTQ1UVRVTRRV1VRV2zZV17Y1UXRVUVVlWVRVWXZlWfdVV9Z9SxRV1VNN2RVVVbZV2fVtVZZ94XRVXVdl2fdVWRZ+W9eF4fZ94RhV1dZN19V1VZZ9YdZlYbd13yhpmmlqoqiqmiiqqqmqtm2qrq1bouiqoqrKsmeqrqzKsq+rrmzrmiiqrqiqsiyqqiyrsqz7qizrtqiquq3KsrCbrqvrtu8LwyzrunCqrq6rsuz7qizruq3rxnHrujB8pinLpqvquqm6um7runHMtm0co6rqvirLwrDKsu/rui+0dSFRVXXdlF3jV2VZ921fd55b94WybTu/rfvKceu60vg5z28cubZtHLNuG7+t+8bzKz9hOI6lZ5q2baqqrZuqq+uybivDrOtCUVV9XZVl3zddWRdu3zeOW9eNoqrquirLvrDKsjHcxm8cuzAcXds2jlvXnbKtC31jyPcJz2vbxnH7OuP2daOvDAnHjwAAgAEHAIAAE8pAoSErAoA4AQAGIecUUxAqxSB0EFLqIKRUMQYhc05KxRyUUEpqIZTUKsYgVI5JyJyTEkpoKZTSUgehpVBKa6GU1lJrsabUYu0gpBZKaS2U0lpqqcbUWowRYxAy56RkzkkJpbQWSmktc05K56CkDkJKpaQUS0otVsxJyaCj0kFIqaQSU0mptVBKa6WkFktKMbYUW24x1hxKaS2kEltJKcYUU20txpojxiBkzknJnJMSSmktlNJa5ZiUDkJKmYOSSkqtlZJSzJyT0kFIqYOOSkkptpJKTKGU1kpKsYVSWmwx1pxSbDWU0lpJKcaSSmwtxlpbTLV1EFoLpbQWSmmttVZraq3GUEprJaUYS0qxtRZrbjHmGkppraQSW0mpxRZbji3GmlNrNabWam4x5hpbbT3WmnNKrdbUUo0txppjbb3VmnvvIKQWSmktlNJiai3G1mKtoZTWSiqxlZJabDHm2lqMOZTSYkmpxZJSjC3GmltsuaaWamwx5ppSi7Xm2nNsNfbUWqwtxppTS7XWWnOPufVWAADAgAMAQIAJZaDQkJUAQBQAAEGIUs5JaRByzDkqCULMOSepckxCKSlVzEEIJbXOOSkpxdY5CCWlFksqLcVWaykptRZrLQAAoMABACDABk2JxQEKDVkJAEQBACDGIMQYhAYZpRiD0BikFGMQIqUYc05KpRRjzknJGHMOQioZY85BKCmEUEoqKYUQSkklpQIAAAocAAACbNCUWByg0JAVAUAUAABgDGIMMYYgdFQyKhGETEonqYEQWgutddZSa6XFzFpqrbTYQAithdYySyXG1FpmrcSYWisAAOzAAQDswEIoNGQlAJAHAEAYoxRjzjlnEGLMOegcNAgx5hyEDirGnIMOQggVY85BCCGEzDkIIYQQQuYchBBCCKGDEEIIpZTSQQghhFJK6SCEEEIppXQQQgihlFIKAAAqcAAACLBRZHOCkaBCQ1YCAHkAAIAxSjkHoZRGKcYglJJSoxRjEEpJqXIMQikpxVY5B6GUlFrsIJTSWmw1dhBKaS3GWkNKrcVYa64hpdZirDXX1FqMteaaa0otxlprzbkAANwFBwCwAxtFNicYCSo0ZCUAkAcAgCCkFGOMMYYUYoox55xDCCnFmHPOKaYYc84555RijDnnnHOMMeecc845xphzzjnnHHPOOeecc44555xzzjnnnHPOOeecc84555xzzgkAACpwAAAIsFFkc4KRoEJDVgIAqQAAABFWYowxxhgbCDHGGGOMMUYSYowxxhhjbDHGGGOMMcaYYowxxhhjjDHGGGOMMcYYY4wxxhhjjDHGGGOMMcYYY4wxxhhjjDHGGGOMMcYYY4wxxhhjjDHGGFtrrbXWWmuttdZaa6211lprrQBAvwoHAP8HG1ZHOCkaCyw0ZCUAEA4AABjDmHOOOQYdhIYp6KSEDkIIoUNKOSglhFBKKSlzTkpKpaSUWkqZc1JSKiWlllLqIKTUWkottdZaByWl1lJqrbXWOgiltNRaa6212EFIKaXWWostxlBKSq212GKMNYZSUmqtxdhirDGk0lJsLcYYY6yhlNZaazHGGGstKbXWYoy1xlprSam11mKLNdZaCwDgbnAAgEiwcYaVpLPC0eBCQ1YCACEBAARCjDnnnHMQQgghUoox56CDEEIIIURKMeYcdBBCCCGEjDHnoIMQQgghhJAx5hx0EEIIIYQQOucchBBCCKGEUkrnHHQQQgghlFBC6SCEEEIIoYRSSikdhBBCKKGEUkopJYQQQgmllFJKKaWEEEIIoYQSSimllBBCCKWUUkoppZQSQgghlFJKKaWUUkIIoZRQSimllFJKCCGEUkoppZRSSgkhhFBKKaWUUkopIYQSSimllFJKKaUAAIADBwCAACPoJKPKImw04cIDUGjISgCADAAAcdhq6ynWyCDFnISWS4SQchBiLhFSijlHsWVIGcUY1ZQxpRRTUmvonGKMUU+dY0oxw6yUVkookYLScqy1dswBAAAgCAAwECEzgUABFBjIAIADhAQpAKCwwNAxXAQE5BIyCgwKx4Rz0mkDABCEyAyRiFgMEhOqgaJiOgBYXGDIB4AMjY20iwvoMsAFXdx1IIQgBCGIxQEUkICDE2544g1PuMEJOkWlDgIAAAAA4AAAHgAAkg0gIiKaOY4Ojw+QEJERkhKTE5QAAAAAALABgA8AgCQFiIiIZo6jw+MDJERkhKTE5AQlAAAAAAAAAAAACAgIAAAAAAAEAAAACAhPZ2dTAAQYOwAAAAAAAOGpbkoCAAAAmc74DRgyNjM69TAzOTk74dnLubewsbagmZiNp4d0KbsExSY/I3XUTwJgkeZdn1HY4zoj33/q9DFtv3Ui1/jmx7lCUtPt18/sYf9MkgAsAGRBd3gMGP4sU+qCPYBy9VrA3YqJosW3W2/ef1iO/u3cg8ZG/57jU+pPmbGEJUgkfnaI39DbPqxddZphbMRmCc5rKlkUMkyx8iIoug5dJv1OYH9a59c+3Gevqc7Z2XFdDjL/qHztRfjWEWxJ/aiGezjohu9HsCZdQBKbiH0VtU/3m85lDG2T/+xkZcYnX+E+aqzv/xTgOoTFG+x7SNqQ4N+oAABSxuVXw77Jd5bmmTmuJakX7509HH0kGYKvARPpwfOSAPySPAc2EkneDwB2HwAAJlQDYK5586N79GJCjx4+p6aDUd27XSvRyXLJkIC5YZ1jLv5lpOhZTz0s+DmnF1diptrnM6UDgIW11Xh8cHTd0/SmbgOAdxcyWwMAAGIrZ3fNSfZbzKiYrK4+tPqtnMVLOeWOG2kVvUY+p2PJ/hkCl5aFRO4TLGYPZcIU3vYM1hohS4jHFlnyW/2T5J7kGsShXWT8N05V+3C/GPqJ1QdWisGPxEzHqXISBPIinWDUt7IeJv/f5OtzBxpTzZZQ+CYEhHXfqG4aABQli72GJhN4oJv+hXcApAJSErAW8G2raAX4NUcABnVt77CzZAB+LsHcVe+Q4h+QB1wh/ZrJTPxSBdI8mgTeAdTsQOoFUEng9BHcVPhxSRRYkKWZJXOFYP6V4AEripJoEjXgA2wJRZHSExmJDm8F0A6gEXsg5a4ZsALItrMB7+fh7UKLvYWSdtsDwFf1mzYzS1F82N1h2Oyt2e76B1QdS0SAsQigLPMOgJS9JRC7hFXA6kUsLFNKD5cA5cTRvgSqPc3Fl99xW3QTi/MHR8DEm6WnvaVQATwRqRKjywQ9BrrhugR2AKTsPQeQckrAOgDOhbTESyrXQ50CkNpXdtWjW7W2/3UjeX3U95gIdalfRAoAmqUEiwp53hCdcCwlg47fcbfzlmQMAgaBkh7c+fcDgF+ifwDXfzegLPcLYJsAAJQArTXjnh/uXGy3v1Hk3pV6/3t5ruW81f6prfbM2Q3WNVy98BwUtbCwhFhAWuPev6Oe/4ZaFQUcgKrVs4defzh1TADA1DEh5b3VlDaECw5b+bPfkKos3tIAue3vJZOih3ga3l6O3PSfIkrLv0PAS86PPdL7g8oc2KteNFKKzKRehOv2gJoFLBPXmaXvPBQILgJon0bbWBszrYZYYwE7jl2j+vTdU7Vpk21LiU0QajPkywAAHqbUC0/YsYOdb4e6BOp7E0cCi04Ao/TgD8ZVAMid6h/A8IeBNkp6/xsAACZELEYIk+yvI6Qz1NN6lIftB/6IMWjWJNOqPTMedAmyaj6Es0QBklJpiSWWHnQ2CoYbGWAmt+0gLQBFKCBnp2QUUQZ/1thtZDBJUpFWY82z34ocorB62oX7qB5y0oPAv/foxH25wVmgIHf2xFOr8leZcBq1Kx3ZvCq9Bga639AxuHuPNL/71YCF4EywJpqHFAX6XF0sjVbuANnvvdLcrufYwOM/iDa6iA468AYAAB6mNBMXcgTD8HSRqJ4vw8CjAlCEPACASlX/APwPOJKl9xQAAAPmnev2eWp33Xgyw3Dvfz6myGk3oyP8YTKsCOvzAgALQi0o1c6Nzs2O2Pg2h4ACIJAgAGP0aNn5x0BDgVfH7u2TtyfDcRIuYAyQhBF/lvSRAttgA6TPbWZA9gaUrZWAUEAA+Dx47Q3/r87HxUUqZmB0BmUuMlojFjHt1gDunnvuX8MImsjSq5WkzSzGS62OEIlOufWWezxWpv6FBgDgJVltfXFYtNAAnqU0xQoD0YLiXo5cF5QV4CnY1tBLAkZCOABAhbk/AM+/AwSCCdlWAAAMcFjS7owb8GVDzveDiZvznbt2tF4bL5odN1YKl88TAEABCZvufq9YCTBtMwVAQUEAwGtNltzSaHvADYC3TxLVjqiRA+OZAMhzcqEgRcAOwoCgvdTxsTHLQEF6+oOb2+PAI8ciPQcXg7pOY+LjxQSv2fjmFuj34gGwz310/bGK6z3xgT887eomWULEaDd04wHetYxdjcgV2SxvSwn0VoZXJRqkRC5ASQ/muVoAUsX7AgAQMBNaVwAAlABRxT/1PmfqLqSRNDbhXb07berpB3b94jpuWEZjBCD2OcdXFpCKEgCDfcFPMw8AAADUwT4lnUm50lmwrpMMhPQIKj6u0E8fr2vGBngMNdIlrZsigjahljud6AFVg+tzXwUnXL3TJLpajaWKA4VAAAAMiFfqJgKAZ08XrtS3dxtQNYcpPvYEG8ClvrQRJgBephwnNWJjtGqmp6VEPSvBe7EBiU3qgJbQAwD4Le8LAMDMhHbNAAAlgK+tFs5O+YyJc9yCnJa3rxLPulGnxwsXV9Fsk2k4PisCAHC8FkwbGE9gJQAAoMnyksj0CdFMZLLgoz8M+FxziwYBgIx+zHiCBAKAlBKNpF1sO9JpVcyEi9ar15YlHgrut5fPJnkdJ6vEwZPyAHQBIEDUrlMcBAAd2KAS0Qq+JwRsE4AJZtMnAD6GnOYwYlOIZvtzUNdjreB7fiMkWI0CmBB6AIAKc38A9osEFlTSGECB+cbeRDC0aRpLHqNPplcK/76Lxn2rpmqyXsYJWRi/FQAAAKBQk9MCAOibrQBQADCDsqpooPutd+05Ce9g6iEdiYXgVmQAI4+4wskEBEiBloNQ6Ki0/KTQ0QjWfjxzi+AeuXKoMjEVfQOZzr0y941qLgM2AExvbZOqcxZ6J6krlrj4y2j9AdgKDx6GnJsVLhbc42uq584+ouSdNBpoCiCVHrz+WzUA/DDtD8ATgA3h0lMCAAzcFv+S+fSSNkeYWlTpb34mf2RfmqqJeMeklhHAfu7VoAEACgAApKRktL+KkQDWMwYCUAAAAHCKsp80xhp91UjqQBw3x45cetqkjQEyu3G9B6N+R650Uq8OVig7wOm6Wun0ea4lKDPoabJs6aLqgbhPzpv4KR4iODilw88ZpY7q1IOMcbASAOAVtmcCnobcrkG4KGS7/ZnskVWRNF9J0RUHKOnByy9WA8Dv6L4AAARMCQUA4GritfVM2lcZfH3Q3T/vZ47J2YHhcmBazjfdyuV25gLAzrc0cwAAAAAYCh6PdwAAAGyWjFW4yScjaWa2mGcofHxWxewKALglWBpLUvwwk+UOh5eNGyUOs1/EF+pZr+ud5OzoGwYdAABg2p52LiSgAY/ZVlOmilEgHn6G3OcwYjzI7vOj1t6xsx4S3lBY96EUQBF6AIBAmPYH4PoGYCoJAADWe+OZJZi7/x76/yH7Lzf9M5XzRKnFPmveMsilQHwVAAAAAKB3LQD8PCIAAADga0QujBLywzeJ4a6Z/ERVBAUlAEDqvoM7BQBAuAguzFqILtmjH3Kd4wfKobnOhA3z85qWoRPm9hwoOHoDAAlCbwDAA56FHAuXflHo3fe2ttG9XUDeA9YmYCBQ0oPr/1QC8IvuCwAAApbUAQCK22MmE3O78VAbHQT9PIPNoT9zNc3l2Oe7TAVLANBufT8MAQAAAGzT4PS8AQAAoELGHb2uaCwwEv1EWhFriUkbAaAZ27/fVZnTZXbWz3BwWpjUaMZKRj7dZ0J//gUeTdpVEwAAZOFsNxKAjQSgA+ABPoY8Jj5y2wje81jsXc/1TOQWTDYZBmAkNDiqVwuA2NJ9AQAAEBKAt9Vrsfs/2N19MO91S9rd8EHTZHnzC5MYmfQEACy/FBcAAADA5c4gi4z8RANs/m6FNXVo9DV46JG1BBDukqlw/Va5G7QbuGVSI+2aZaoLXJrdVj2zlC9Z5QEAEFz/5QzgVZwAAAAA/oXcxyC6WfTu+09Ve/c766J4VTAGUFmA51+VANKi/QPoPwYgYAkA715OH4S0s5KDHvj99MMq8TPFc3roKZnGOoT1bmIhVgc7XAMBAAAAAMAW1VbQw3gapzOpJd+Kd2fc4iSO62fJv9+movui1wUNPAj059N3OVxzk4gV73PmE8FIA2F5mRq37Evc76vLXfF4rD5UJJAw46hW6LZCb5sNLdx+kzMCAAB+hfy95+965ZCLP7B3/VlTHCvDEKtQhTm4KiCgAEAbrfbWTPssAAAAXpee1tVrozYYn41wD1aeYtkKfswN5/SXPO0JDnhO/4laUortv/s412fybe/nONdncoCHnBVliu0CQGBWlPY/5Kwom2L/kruPM6Q7oz4tvDQy+bZ3HzOi+gNHA4DZEgA="),lib.resource.add("hterm/concat/date","text/plain","Tue, 25 Apr 2017 15:12:45 +0000"),lib.resource.add("hterm/changelog/version","text/plain","1.62"),lib.resource.add("hterm/changelog/date","text/plain","2017-04-17"),lib.resource.add("hterm/git/HEAD","text/plain","git rev-parse HEAD");
\ No newline at end of file
+'use strict';
+if ('undefined' != typeof lib) throw new Error('Global "lib" object already exists.');
+var lib = {};
+lib.runtimeDependencies_ = {}, lib.initCallbacks_ = [], lib.rtdep = function(e) {
+  var t;
+  try {
+    throw new Error;
+  }
+  catch (r) {
+    var o = r.stack.split('\n');
+    t = o.length >= 3 ? o[2].replace(/^\s*at\s+/, '') : o[1].replace(/^\s*global code@/, '');
+  }
+  for (var i = 0; i < arguments.length; i++) {
+    var s = arguments[i];
+    if (s instanceof Array) lib.rtdep.apply(lib, s);
+    else {
+      var n = this.runtimeDependencies_[s];
+      n || (n = this.runtimeDependencies_[s] = []), n.push(t);
+    }
+  }
+};, lib.ensureRuntimeDependencies_ = function() {
+  var e = !0;
+  for (var t in lib.runtimeDependencies_)
+    for (var r = lib.runtimeDependencies_[t], o = t.split('.'), i = window || self, s = 0; s < o.length; s++) {
+      if (!(o[s] in i)) {
+        console.warn('Missing "' + t + '" is needed by', r), e = !1;
+        break;
+      }
+      i = i[o[s]];
+    }
+  if (!e) throw new Error('Failed runtime dependency check');
+};, lib.registerInit = function(e, t) {
+  return lib.initCallbacks_.push([e, t]), t;
+};, lib.init = function(e, t) {
+  var r = lib.initCallbacks_,
+    o = function() {
+      if (r.length) {
+        var i = r.shift();
+        t && t('init: ' + i[0]), i[1](lib.f.alarm(o));
+      }
+      else e();
+    };
+  if ('function' != typeof e) throw new Error('Missing or invalid argument: onInit');
+  lib.ensureRuntimeDependencies_(), setTimeout(o, 0);
+};, lib.colors = {}, lib.colors.re_ = {
+  hex16: /#([a-f0-9])([a-f0-9])([a-f0-9])/i,
+  hex24: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/i,
+  rgb: new RegExp('^/s*rgb/s*/(/s*(/d{1,3})/s*,/s*(/d{1,3})/s*,/s*(/d{1,3})/s*/)/s*$'.replace(/\//g, '\\'), 'i'),
+  rgba: new RegExp('^/s*rgba/s*/(/s*(/d{1,3})/s*,/s*(/d{1,3})/s*,/s*(/d{1,3})/s*(?:,/s*(/d+(?:/./d+)?)/s*)/)/s*$'.replace(/\//g, '\\'), 'i'),
+  rgbx: new RegExp('^/s*rgba?/s*/(/s*(/d{1,3})/s*,/s*(/d{1,3})/s*,/s*(/d{1,3})/s*(?:,/s*(/d+(?:/./d+)?)/s*)?/)/s*$'.replace(/\//g, '\\'), 'i'),
+  x11rgb: /^\s*rgb:([a-f0-9]{1,4})\/([a-f0-9]{1,4})\/([a-f0-9]{1,4})\s*$/i,
+  name: /[a-z][a-z0-9\s]+/
+}, lib.colors.rgbToX11 = function(e) {
+  function t(e) {
+    return e = (257 * Math.min(e, 255)).toString(16), lib.f.zpad(e, 4);
+  }
+  var r = e.match(lib.colors.re_.rgbx);
+  return r ? 'rgb:' + t(r[1]) + '/' + t(r[2]) + '/' + t(r[3]) : null;
+};, lib.colors.x11HexToCSS = function(e) {
+  function t(e) {
+    return e = parseInt(e, 16), 2 == r ? e : 1 == r ? e << 4 : e >> 4 * (r - 2)
+  }
+  if (!e.startsWith('#')) return null;
+  if (e = e.substr(1), -1 == [3, 6, 9, 12].indexOf(e.length)) return null;
+  if (e.match(/[^a-f0-9]/i)) return null;
+  var r = e.length / 3,
+    o = e.substr(0, r),
+    i = e.substr(r, r),
+    s = e.substr(r + r, r);
+  return lib.colors.arrayToRGBA([o, i, s].map(t));
+};, lib.colors.x11ToCSS = function(e) {
+  function t(e) {
+    return 1 == e.length ? parseInt(e + e, 16) : 2 == e.length ? parseInt(e, 16) : (3 == e.length && (e += e.substr(2)), Math.round(parseInt(e, 16) / 257))
+  }
+  var r = e.match(lib.colors.re_.x11rgb);
+  return r ? (r.splice(0, 1), lib.colors.arrayToRGBA(r.map(t))) : e.startsWith('#') ? lib.colors.x11HexToCSS(e) : lib.colors.nameToRGB(e)
+};, lib.colors.hexToRGB = function(e) {
+  function t(e) {
+    4 == e.length && (e = e.replace(r, function(e, t, r, o) {
+      return '#' + t + t + r + r + o + o;
+    }));
+    var t = e.match(o);
+    return t ? 'rgb(' + parseInt(t[1], 16) + ', ' + parseInt(t[2], 16) + ', ' + parseInt(t[3], 16) + ')' : null;
+  }
+  var r = lib.colors.re_.hex16,
+    o = lib.colors.re_.hex24;
+  if (e instanceof Array)
+    for (var i = 0; i < e.length; i++) e[i] = t(e[i]);
+  else e = t(e);
+  return e;
+};, lib.colors.rgbToHex = function(e) {
+  function t(e) {
+    var t = lib.colors.crackRGB(e);
+    return t ? '#' + lib.f.zpad((parseInt(t[0]) << 16 | parseInt(t[1]) << 8 | parseInt(t[2]) << 0).toString(16), 6) : null;
+  }
+  if (e instanceof Array)
+    for (var r = 0; r < e.length; r++) e[r] = t(e[r]);
+  else e = t(e);
+  return e;
+};, lib.colors.normalizeCSS = function(e) {
+  return '#' == e.substr(0, 1) ? lib.colors.hexToRGB(e) : lib.colors.re_.rgbx.test(e) ? e : lib.colors.nameToRGB(e)
+};, lib.colors.arrayToRGBA = function(e) {
+  var t = e.length > 3 ? e[3] : 1;
+  return 'rgba(' + e[0] + ', ' + e[1] + ', ' + e[2] + ', ' + t + ')';
+};, lib.colors.setAlpha = function(e, t) {
+  var r = lib.colors.crackRGB(e);
+  return r[3] = t, lib.colors.arrayToRGBA(r);
+};, lib.colors.mix = function(e, t, r) {
+  for (var o = lib.colors.crackRGB(e), i = lib.colors.crackRGB(t), s = 0; 4 > s; ++s) {
+    var n = i[s] - o[s];
+    o[s] = Math.round(parseInt(o[s]) + n * r);
+  }
+  return lib.colors.arrayToRGBA(o);
+};, lib.colors.crackRGB = function(e) {
+  if ('rgba' == e.substr(0, 4)) {
+    var t = e.match(lib.colors.re_.rgba);
+    if (t) return t.shift(), t;
+  }
+  else {
+    var t = e.match(lib.colors.re_.rgb);
+    if (t) return t.shift(), t.push(1), t;
+  }
+  return console.error("Couldn't crack: " + e), null;
+};, lib.colors.nameToRGB = function(e) {
+  return e in lib.colors.colorNames ? lib.colors.colorNames[e] : (e = e.toLowerCase(), e in lib.colors.colorNames ? lib.colors.colorNames[e] : (e = e.replace(/\s+/g, ''), e in lib.colors.colorNames ? lib.colors.colorNames[e] : null));
+};, lib.colors.stockColorPalette = lib.colors.hexToRGB(['#000000', '#CC0000', '#4E9A06', '#C4A000', '#3465A4', '#75507B', '#06989A', '#D3D7CF', '#555753', '#EF2929', '#00BA13', '#FCE94F', '#729FCF', '#F200CB', '#00B5BD', '#EEEEEC', '#000000', '#00005F', '#000087', '#0000AF', '#0000D7', '#0000FF', '#005F00', '#005F5F', '#005F87', '#005FAF', '#005FD7', '#005FFF', '#008700', '#00875F', '#008787', '#0087AF', '#0087D7', '#0087FF', '#00AF00', '#00AF5F', '#00AF87', '#00AFAF', '#00AFD7', '#00AFFF', '#00D700', '#00D75F', '#00D787', '#00D7AF', '#00D7D7', '#00D7FF', '#00FF00', '#00FF5F', '#00FF87', '#00FFAF', '#00FFD7', '#00FFFF', '#5F0000', '#5F005F', '#5F0087', '#5F00AF', '#5F00D7', '#5F00FF', '#5F5F00', '#5F5F5F', '#5F5F87', '#5F5FAF', '#5F5FD7', '#5F5FFF', '#5F8700', '#5F875F', '#5F8787', '#5F87AF', '#5F87D7', '#5F87FF', '#5FAF00', '#5FAF5F', '#5FAF87', '#5FAFAF', '#5FAFD7', '#5FAFFF', '#5FD700', '#5FD75F', '#5FD787', '#5FD7AF', '#5FD7D7', '#5FD7FF', '#5FFF00', '#5FFF5F', '#5FFF87', '#5FFFAF', '#5FFFD7', '#5FFFFF', '#870000', '#87005F', '#870087', '#8700AF', '#8700D7', '#8700FF', '#875F00', '#875F5F', '#875F87', '#875FAF', '#875FD7', '#875FFF', '#878700', '#87875F', '#878787', '#8787AF', '#8787D7', '#8787FF', '#87AF00', '#87AF5F', '#87AF87', '#87AFAF', '#87AFD7', '#87AFFF', '#87D700', '#87D75F', '#87D787', '#87D7AF', '#87D7D7', '#87D7FF', '#87FF00', '#87FF5F', '#87FF87', '#87FFAF', '#87FFD7', '#87FFFF', '#AF0000', '#AF005F', '#AF0087', '#AF00AF', '#AF00D7', '#AF00FF', '#AF5F00', '#AF5F5F', '#AF5F87', '#AF5FAF', '#AF5FD7', '#AF5FFF', '#AF8700', '#AF875F', '#AF8787', '#AF87AF', '#AF87D7', '#AF87FF', '#AFAF00', '#AFAF5F', '#AFAF87', '#AFAFAF', '#AFAFD7', '#AFAFFF', '#AFD700', '#AFD75F', '#AFD787', '#AFD7AF', '#AFD7D7', '#AFD7FF', '#AFFF00', '#AFFF5F', '#AFFF87', '#AFFFAF', '#AFFFD7', '#AFFFFF', '#D70000', '#D7005F', '#D70087', '#D700AF', '#D700D7', '#D700FF', '#D75F00', '#D75F5F', '#D75F87', '#D75FAF', '#D75FD7', '#D75FFF', '#D78700', '#D7875F', '#D78787', '#D787AF', '#D787D7', '#D787FF', '#D7AF00', '#D7AF5F', '#D7AF87', '#D7AFAF', '#D7AFD7', '#D7AFFF', '#D7D700', '#D7D75F', '#D7D787', '#D7D7AF', '#D7D7D7', '#D7D7FF', '#D7FF00', '#D7FF5F', '#D7FF87', '#D7FFAF', '#D7FFD7', '#D7FFFF', '#FF0000', '#FF005F', '#FF0087', '#FF00AF', '#FF00D7', '#FF00FF', '#FF5F00', '#FF5F5F', '#FF5F87', '#FF5FAF', '#FF5FD7', '#FF5FFF', '#FF8700', '#FF875F', '#FF8787', '#FF87AF', '#FF87D7', '#FF87FF', '#FFAF00', '#FFAF5F', '#FFAF87', '#FFAFAF', '#FFAFD7', '#FFAFFF', '#FFD700', '#FFD75F', '#FFD787', '#FFD7AF', '#FFD7D7', '#FFD7FF', '#FFFF00', '#FFFF5F', '#FFFF87', '#FFFFAF', '#FFFFD7', '#FFFFFF', '#080808', '#121212', '#1C1C1C', '#262626', '#303030', '#3A3A3A', '#444444', '#4E4E4E', '#585858', '#626262', '#6C6C6C', '#767676', '#808080', '#8A8A8A', '#949494', '#9E9E9E', '#A8A8A8', '#B2B2B2', '#BCBCBC', '#C6C6C6', '#D0D0D0', '#DADADA', '#E4E4E4', '#EEEEEE']), lib.colors.colorPalette = lib.colors.stockColorPalette, lib.colors.colorNames = {
+  aliceblue: 'rgb(240, 248, 255)',
+  antiquewhite: 'rgb(250, 235, 215)',
+  antiquewhite1: 'rgb(255, 239, 219)',
+  antiquewhite2: 'rgb(238, 223, 204)',
+  antiquewhite3: 'rgb(205, 192, 176)',
+  antiquewhite4: 'rgb(139, 131, 120)',
+  aquamarine: 'rgb(127, 255, 212)',
+  aquamarine1: 'rgb(127, 255, 212)',
+  aquamarine2: 'rgb(118, 238, 198)',
+  aquamarine3: 'rgb(102, 205, 170)',
+  aquamarine4: 'rgb(69, 139, 116)',
+  azure: 'rgb(240, 255, 255)',
+  azure1: 'rgb(240, 255, 255)',
+  azure2: 'rgb(224, 238, 238)',
+  azure3: 'rgb(193, 205, 205)',
+  azure4: 'rgb(131, 139, 139)',
+  beige: 'rgb(245, 245, 220)',
+  bisque: 'rgb(255, 228, 196)',
+  bisque1: 'rgb(255, 228, 196)',
+  bisque2: 'rgb(238, 213, 183)',
+  bisque3: 'rgb(205, 183, 158)',
+  bisque4: 'rgb(139, 125, 107)',
+  black: 'rgb(0, 0, 0)',
+  blanchedalmond: 'rgb(255, 235, 205)',
+  blue: 'rgb(0, 0, 255)',
+  blue1: 'rgb(0, 0, 255)',
+  blue2: 'rgb(0, 0, 238)',
+  blue3: 'rgb(0, 0, 205)',
+  blue4: 'rgb(0, 0, 139)',
+  blueviolet: 'rgb(138, 43, 226)',
+  brown: 'rgb(165, 42, 42)',
+  brown1: 'rgb(255, 64, 64)',
+  brown2: 'rgb(238, 59, 59)',
+  brown3: 'rgb(205, 51, 51)',
+  brown4: 'rgb(139, 35, 35)',
+  burlywood: 'rgb(222, 184, 135)',
+  burlywood1: 'rgb(255, 211, 155)',
+  burlywood2: 'rgb(238, 197, 145)',
+  burlywood3: 'rgb(205, 170, 125)',
+  burlywood4: 'rgb(139, 115, 85)',
+  cadetblue: 'rgb(95, 158, 160)',
+  cadetblue1: 'rgb(152, 245, 255)',
+  cadetblue2: 'rgb(142, 229, 238)',
+  cadetblue3: 'rgb(122, 197, 205)',
+  cadetblue4: 'rgb(83, 134, 139)',
+  chartreuse: 'rgb(127, 255, 0)',
+  chartreuse1: 'rgb(127, 255, 0)',
+  chartreuse2: 'rgb(118, 238, 0)',
+  chartreuse3: 'rgb(102, 205, 0)',
+  chartreuse4: 'rgb(69, 139, 0)',
+  chocolate: 'rgb(210, 105, 30)',
+  chocolate1: 'rgb(255, 127, 36)',
+  chocolate2: 'rgb(238, 118, 33)',
+  chocolate3: 'rgb(205, 102, 29)',
+  chocolate4: 'rgb(139, 69, 19)',
+  coral: 'rgb(255, 127, 80)',
+  coral1: 'rgb(255, 114, 86)',
+  coral2: 'rgb(238, 106, 80)',
+  coral3: 'rgb(205, 91, 69)',
+  coral4: 'rgb(139, 62, 47)',
+  cornflowerblue: 'rgb(100, 149, 237)',
+  cornsilk: 'rgb(255, 248, 220)',
+  cornsilk1: 'rgb(255, 248, 220)',
+  cornsilk2: 'rgb(238, 232, 205)',
+  cornsilk3: 'rgb(205, 200, 177)',
+  cornsilk4: 'rgb(139, 136, 120)',
+  cyan: 'rgb(0, 255, 255)',
+  cyan1: 'rgb(0, 255, 255)',
+  cyan2: 'rgb(0, 238, 238)',
+  cyan3: 'rgb(0, 205, 205)',
+  cyan4: 'rgb(0, 139, 139)',
+  darkblue: 'rgb(0, 0, 139)',
+  darkcyan: 'rgb(0, 139, 139)',
+  darkgoldenrod: 'rgb(184, 134, 11)',
+  darkgoldenrod1: 'rgb(255, 185, 15)',
+  darkgoldenrod2: 'rgb(238, 173, 14)',
+  darkgoldenrod3: 'rgb(205, 149, 12)',
+  darkgoldenrod4: 'rgb(139, 101, 8)',
+  darkgray: 'rgb(169, 169, 169)',
+  darkgreen: 'rgb(0, 100, 0)',
+  darkgrey: 'rgb(169, 169, 169)',
+  darkkhaki: 'rgb(189, 183, 107)',
+  darkmagenta: 'rgb(139, 0, 139)',
+  darkolivegreen: 'rgb(85, 107, 47)',
+  darkolivegreen1: 'rgb(202, 255, 112)',
+  darkolivegreen2: 'rgb(188, 238, 104)',
+  darkolivegreen3: 'rgb(162, 205, 90)',
+  darkolivegreen4: 'rgb(110, 139, 61)',
+  darkorange: 'rgb(255, 140, 0)',
+  darkorange1: 'rgb(255, 127, 0)',
+  darkorange2: 'rgb(238, 118, 0)',
+  darkorange3: 'rgb(205, 102, 0)',
+  darkorange4: 'rgb(139, 69, 0)',
+  darkorchid: 'rgb(153, 50, 204)',
+  darkorchid1: 'rgb(191, 62, 255)',
+  darkorchid2: 'rgb(178, 58, 238)',
+  darkorchid3: 'rgb(154, 50, 205)',
+  darkorchid4: 'rgb(104, 34, 139)',
+  darkred: 'rgb(139, 0, 0)',
+  darksalmon: 'rgb(233, 150, 122)',
+  darkseagreen: 'rgb(143, 188, 143)',
+  darkseagreen1: 'rgb(193, 255, 193)',
+  darkseagreen2: 'rgb(180, 238, 180)',
+  darkseagreen3: 'rgb(155, 205, 155)',
+  darkseagreen4: 'rgb(105, 139, 105)',
+  darkslateblue: 'rgb(72, 61, 139)',
+  darkslategray: 'rgb(47, 79, 79)',
+  darkslategray1: 'rgb(151, 255, 255)',
+  darkslategray2: 'rgb(141, 238, 238)',
+  darkslategray3: 'rgb(121, 205, 205)',
+  darkslategray4: 'rgb(82, 139, 139)',
+  darkslategrey: 'rgb(47, 79, 79)',
+  darkturquoise: 'rgb(0, 206, 209)',
+  darkviolet: 'rgb(148, 0, 211)',
+  debianred: 'rgb(215, 7, 81)',
+  deeppink: 'rgb(255, 20, 147)',
+  deeppink1: 'rgb(255, 20, 147)',
+  deeppink2: 'rgb(238, 18, 137)',
+  deeppink3: 'rgb(205, 16, 118)',
+  deeppink4: 'rgb(139, 10, 80)',
+  deepskyblue: 'rgb(0, 191, 255)',
+  deepskyblue1: 'rgb(0, 191, 255)',
+  deepskyblue2: 'rgb(0, 178, 238)',
+  deepskyblue3: 'rgb(0, 154, 205)',
+  deepskyblue4: 'rgb(0, 104, 139)',
+  dimgray: 'rgb(105, 105, 105)',
+  dimgrey: 'rgb(105, 105, 105)',
+  dodgerblue: 'rgb(30, 144, 255)',
+  dodgerblue1: 'rgb(30, 144, 255)',
+  dodgerblue2: 'rgb(28, 134, 238)',
+  dodgerblue3: 'rgb(24, 116, 205)',
+  dodgerblue4: 'rgb(16, 78, 139)',
+  firebrick: 'rgb(178, 34, 34)',
+  firebrick1: 'rgb(255, 48, 48)',
+  firebrick2: 'rgb(238, 44, 44)',
+  firebrick3: 'rgb(205, 38, 38)',
+  firebrick4: 'rgb(139, 26, 26)',
+  floralwhite: 'rgb(255, 250, 240)',
+  forestgreen: 'rgb(34, 139, 34)',
+  gainsboro: 'rgb(220, 220, 220)',
+  ghostwhite: 'rgb(248, 248, 255)',
+  gold: 'rgb(255, 215, 0)',
+  gold1: 'rgb(255, 215, 0)',
+  gold2: 'rgb(238, 201, 0)',
+  gold3: 'rgb(205, 173, 0)',
+  gold4: 'rgb(139, 117, 0)',
+  goldenrod: 'rgb(218, 165, 32)',
+  goldenrod1: 'rgb(255, 193, 37)',
+  goldenrod2: 'rgb(238, 180, 34)',
+  goldenrod3: 'rgb(205, 155, 29)',
+  goldenrod4: 'rgb(139, 105, 20)',
+  gray: 'rgb(190, 190, 190)',
+  gray0: 'rgb(0, 0, 0)',
+  gray1: 'rgb(3, 3, 3)',
+  gray10: 'rgb(26, 26, 26)',
+  gray100: 'rgb(255, 255, 255)',
+  gray11: 'rgb(28, 28, 28)',
+  gray12: 'rgb(31, 31, 31)',
+  gray13: 'rgb(33, 33, 33)',
+  gray14: 'rgb(36, 36, 36)',
+  gray15: 'rgb(38, 38, 38)',
+  gray16: 'rgb(41, 41, 41)',
+  gray17: 'rgb(43, 43, 43)',
+  gray18: 'rgb(46, 46, 46)',
+  gray19: 'rgb(48, 48, 48)',
+  gray2: 'rgb(5, 5, 5)',
+  gray20: 'rgb(51, 51, 51)',
+  gray21: 'rgb(54, 54, 54)',
+  gray22: 'rgb(56, 56, 56)',
+  gray23: 'rgb(59, 59, 59)',
+  gray24: 'rgb(61, 61, 61)',
+  gray25: 'rgb(64, 64, 64)',
+  gray26: 'rgb(66, 66, 66)',
+  gray27: 'rgb(69, 69, 69)',
+  gray28: 'rgb(71, 71, 71)',
+  gray29: 'rgb(74, 74, 74)',
+  gray3: 'rgb(8, 8, 8)',
+  gray30: 'rgb(77, 77, 77)',
+  gray31: 'rgb(79, 79, 79)',
+  gray32: 'rgb(82, 82, 82)',
+  gray33: 'rgb(84, 84, 84)',
+  gray34: 'rgb(87, 87, 87)',
+  gray35: 'rgb(89, 89, 89)',
+  gray36: 'rgb(92, 92, 92)',
+  gray37: 'rgb(94, 94, 94)',
+  gray38: 'rgb(97, 97, 97)',
+  gray39: 'rgb(99, 99, 99)',
+  gray4: 'rgb(10, 10, 10)',
+  gray40: 'rgb(102, 102, 102)',
+  gray41: 'rgb(105, 105, 105)',
+  gray42: 'rgb(107, 107, 107)',
+  gray43: 'rgb(110, 110, 110)',
+  gray44: 'rgb(112, 112, 112)',
+  gray45: 'rgb(115, 115, 115)',
+  gray46: 'rgb(117, 117, 117)',
+  gray47: 'rgb(120, 120, 120)',
+  gray48: 'rgb(122, 122, 122)',
+  gray49: 'rgb(125, 125, 125)',
+  gray5: 'rgb(13, 13, 13)',
+  gray50: 'rgb(127, 127, 127)',
+  gray51: 'rgb(130, 130, 130)',
+  gray52: 'rgb(133, 133, 133)',
+  gray53: 'rgb(135, 135, 135)',
+  gray54: 'rgb(138, 138, 138)',
+  gray55: 'rgb(140, 140, 140)',
+  gray56: 'rgb(143, 143, 143)',
+  gray57: 'rgb(145, 145, 145)',
+  gray58: 'rgb(148, 148, 148)',
+  gray59: 'rgb(150, 150, 150)',
+  gray6: 'rgb(15, 15, 15)',
+  gray60: 'rgb(153, 153, 153)',
+  gray61: 'rgb(156, 156, 156)',
+  gray62: 'rgb(158, 158, 158)',
+  gray63: 'rgb(161, 161, 161)',
+  gray64: 'rgb(163, 163, 163)',
+  gray65: 'rgb(166, 166, 166)',
+  gray66: 'rgb(168, 168, 168)',
+  gray67: 'rgb(171, 171, 171)',
+  gray68: 'rgb(173, 173, 173)',
+  gray69: 'rgb(176, 176, 176)',
+  gray7: 'rgb(18, 18, 18)',
+  gray70: 'rgb(179, 179, 179)',
+  gray71: 'rgb(181, 181, 181)',
+  gray72: 'rgb(184, 184, 184)',
+  gray73: 'rgb(186, 186, 186)',
+  gray74: 'rgb(189, 189, 189)',
+  gray75: 'rgb(191, 191, 191)',
+  gray76: 'rgb(194, 194, 194)',
+  gray77: 'rgb(196, 196, 196)',
+  gray78: 'rgb(199, 199, 199)',
+  gray79: 'rgb(201, 201, 201)',
+  gray8: 'rgb(20, 20, 20)',
+  gray80: 'rgb(204, 204, 204)',
+  gray81: 'rgb(207, 207, 207)',
+  gray82: 'rgb(209, 209, 209)',
+  gray83: 'rgb(212, 212, 212)',
+  gray84: 'rgb(214, 214, 214)',
+  gray85: 'rgb(217, 217, 217)',
+  gray86: 'rgb(219, 219, 219)',
+  gray87: 'rgb(222, 222, 222)',
+  gray88: 'rgb(224, 224, 224)',
+  gray89: 'rgb(227, 227, 227)',
+  gray9: 'rgb(23, 23, 23)',
+  gray90: 'rgb(229, 229, 229)',
+  gray91: 'rgb(232, 232, 232)',
+  gray92: 'rgb(235, 235, 235)',
+  gray93: 'rgb(237, 237, 237)',
+  gray94: 'rgb(240, 240, 240)',
+  gray95: 'rgb(242, 242, 242)',
+  gray96: 'rgb(245, 245, 245)',
+  gray97: 'rgb(247, 247, 247)',
+  gray98: 'rgb(250, 250, 250)',
+  gray99: 'rgb(252, 252, 252)',
+  green: 'rgb(0, 255, 0)',
+  green1: 'rgb(0, 255, 0)',
+  green2: 'rgb(0, 238, 0)',
+  green3: 'rgb(0, 205, 0)',
+  green4: 'rgb(0, 139, 0)',
+  greenyellow: 'rgb(173, 255, 47)',
+  grey: 'rgb(190, 190, 190)',
+  grey0: 'rgb(0, 0, 0)',
+  grey1: 'rgb(3, 3, 3)',
+  grey10: 'rgb(26, 26, 26)',
+  grey100: 'rgb(255, 255, 255)',
+  grey11: 'rgb(28, 28, 28)',
+  grey12: 'rgb(31, 31, 31)',
+  grey13: 'rgb(33, 33, 33)',
+  grey14: 'rgb(36, 36, 36)',
+  grey15: 'rgb(38, 38, 38)',
+  grey16: 'rgb(41, 41, 41)',
+  grey17: 'rgb(43, 43, 43)',
+  grey18: 'rgb(46, 46, 46)',
+  grey19: 'rgb(48, 48, 48)',
+  grey2: 'rgb(5, 5, 5)',
+  grey20: 'rgb(51, 51, 51)',
+  grey21: 'rgb(54, 54, 54)',
+  grey22: 'rgb(56, 56, 56)',
+  grey23: 'rgb(59, 59, 59)',
+  grey24: 'rgb(61, 61, 61)',
+  grey25: 'rgb(64, 64, 64)',
+  grey26: 'rgb(66, 66, 66)',
+  grey27: 'rgb(69, 69, 69)',
+  grey28: 'rgb(71, 71, 71)',
+  grey29: 'rgb(74, 74, 74)',
+  grey3: 'rgb(8, 8, 8)',
+  grey30: 'rgb(77, 77, 77)',
+  grey31: 'rgb(79, 79, 79)',
+  grey32: 'rgb(82, 82, 82)',
+  grey33: 'rgb(84, 84, 84)',
+  grey34: 'rgb(87, 87, 87)',
+  grey35: 'rgb(89, 89, 89)',
+  grey36: 'rgb(92, 92, 92)',
+  grey37: 'rgb(94, 94, 94)',
+  grey38: 'rgb(97, 97, 97)',
+  grey39: 'rgb(99, 99, 99)',
+  grey4: 'rgb(10, 10, 10)',
+  grey40: 'rgb(102, 102, 102)',
+  grey41: 'rgb(105, 105, 105)',
+  grey42: 'rgb(107, 107, 107)',
+  grey43: 'rgb(110, 110, 110)',
+  grey44: 'rgb(112, 112, 112)',
+  grey45: 'rgb(115, 115, 115)',
+  grey46: 'rgb(117, 117, 117)',
+  grey47: 'rgb(120, 120, 120)',
+  grey48: 'rgb(122, 122, 122)',
+  grey49: 'rgb(125, 125, 125)',
+  grey5: 'rgb(13, 13, 13)',
+  grey50: 'rgb(127, 127, 127)',
+  grey51: 'rgb(130, 130, 130)',
+  grey52: 'rgb(133, 133, 133)',
+  grey53: 'rgb(135, 135, 135)',
+  grey54: 'rgb(138, 138, 138)',
+  grey55: 'rgb(140, 140, 140)',
+  grey56: 'rgb(143, 143, 143)',
+  grey57: 'rgb(145, 145, 145)',
+  grey58: 'rgb(148, 148, 148)',
+  grey59: 'rgb(150, 150, 150)',
+  grey6: 'rgb(15, 15, 15)',
+  grey60: 'rgb(153, 153, 153)',
+  grey61: 'rgb(156, 156, 156)',
+  grey62: 'rgb(158, 158, 158)',
+  grey63: 'rgb(161, 161, 161)',
+  grey64: 'rgb(163, 163, 163)',
+  grey65: 'rgb(166, 166, 166)',
+  grey66: 'rgb(168, 168, 168)',
+  grey67: 'rgb(171, 171, 171)',
+  grey68: 'rgb(173, 173, 173)',
+  grey69: 'rgb(176, 176, 176)',
+  grey7: 'rgb(18, 18, 18)',
+  grey70: 'rgb(179, 179, 179)',
+  grey71: 'rgb(181, 181, 181)',
+  grey72: 'rgb(184, 184, 184)',
+  grey73: 'rgb(186, 186, 186)',
+  grey74: 'rgb(189, 189, 189)',
+  grey75: 'rgb(191, 191, 191)',
+  grey76: 'rgb(194, 194, 194)',
+  grey77: 'rgb(196, 196, 196)',
+  grey78: 'rgb(199, 199, 199)',
+  grey79: 'rgb(201, 201, 201)',
+  grey8: 'rgb(20, 20, 20)',
+  grey80: 'rgb(204, 204, 204)',
+  grey81: 'rgb(207, 207, 207)',
+  grey82: 'rgb(209, 209, 209)',
+  grey83: 'rgb(212, 212, 212)',
+  grey84: 'rgb(214, 214, 214)',
+  grey85: 'rgb(217, 217, 217)',
+  grey86: 'rgb(219, 219, 219)',
+  grey87: 'rgb(222, 222, 222)',
+  grey88: 'rgb(224, 224, 224)',
+  grey89: 'rgb(227, 227, 227)',
+  grey9: 'rgb(23, 23, 23)',
+  grey90: 'rgb(229, 229, 229)',
+  grey91: 'rgb(232, 232, 232)',
+  grey92: 'rgb(235, 235, 235)',
+  grey93: 'rgb(237, 237, 237)',
+  grey94: 'rgb(240, 240, 240)',
+  grey95: 'rgb(242, 242, 242)',
+  grey96: 'rgb(245, 245, 245)',
+  grey97: 'rgb(247, 247, 247)',
+  grey98: 'rgb(250, 250, 250)',
+  grey99: 'rgb(252, 252, 252)',
+  honeydew: 'rgb(240, 255, 240)',
+  honeydew1: 'rgb(240, 255, 240)',
+  honeydew2: 'rgb(224, 238, 224)',
+  honeydew3: 'rgb(193, 205, 193)',
+  honeydew4: 'rgb(131, 139, 131)',
+  hotpink: 'rgb(255, 105, 180)',
+  hotpink1: 'rgb(255, 110, 180)',
+  hotpink2: 'rgb(238, 106, 167)',
+  hotpink3: 'rgb(205, 96, 144)',
+  hotpink4: 'rgb(139, 58, 98)',
+  indianred: 'rgb(205, 92, 92)',
+  indianred1: 'rgb(255, 106, 106)',
+  indianred2: 'rgb(238, 99, 99)',
+  indianred3: 'rgb(205, 85, 85)',
+  indianred4: 'rgb(139, 58, 58)',
+  ivory: 'rgb(255, 255, 240)',
+  ivory1: 'rgb(255, 255, 240)',
+  ivory2: 'rgb(238, 238, 224)',
+  ivory3: 'rgb(205, 205, 193)',
+  ivory4: 'rgb(139, 139, 131)',
+  khaki: 'rgb(240, 230, 140)',
+  khaki1: 'rgb(255, 246, 143)',
+  khaki2: 'rgb(238, 230, 133)',
+  khaki3: 'rgb(205, 198, 115)',
+  khaki4: 'rgb(139, 134, 78)',
+  lavender: 'rgb(230, 230, 250)',
+  lavenderblush: 'rgb(255, 240, 245)',
+  lavenderblush1: 'rgb(255, 240, 245)',
+  lavenderblush2: 'rgb(238, 224, 229)',
+  lavenderblush3: 'rgb(205, 193, 197)',
+  lavenderblush4: 'rgb(139, 131, 134)',
+  lawngreen: 'rgb(124, 252, 0)',
+  lemonchiffon: 'rgb(255, 250, 205)',
+  lemonchiffon1: 'rgb(255, 250, 205)',
+  lemonchiffon2: 'rgb(238, 233, 191)',
+  lemonchiffon3: 'rgb(205, 201, 165)',
+  lemonchiffon4: 'rgb(139, 137, 112)',
+  lightblue: 'rgb(173, 216, 230)',
+  lightblue1: 'rgb(191, 239, 255)',
+  lightblue2: 'rgb(178, 223, 238)',
+  lightblue3: 'rgb(154, 192, 205)',
+  lightblue4: 'rgb(104, 131, 139)',
+  lightcoral: 'rgb(240, 128, 128)',
+  lightcyan: 'rgb(224, 255, 255)',
+  lightcyan1: 'rgb(224, 255, 255)',
+  lightcyan2: 'rgb(209, 238, 238)',
+  lightcyan3: 'rgb(180, 205, 205)',
+  lightcyan4: 'rgb(122, 139, 139)',
+  lightgoldenrod: 'rgb(238, 221, 130)',
+  lightgoldenrod1: 'rgb(255, 236, 139)',
+  lightgoldenrod2: 'rgb(238, 220, 130)',
+  lightgoldenrod3: 'rgb(205, 190, 112)',
+  lightgoldenrod4: 'rgb(139, 129, 76)',
+  lightgoldenrodyellow: 'rgb(250, 250, 210)',
+  lightgray: 'rgb(211, 211, 211)',
+  lightgreen: 'rgb(144, 238, 144)',
+  lightgrey: 'rgb(211, 211, 211)',
+  lightpink: 'rgb(255, 182, 193)',
+  lightpink1: 'rgb(255, 174, 185)',
+  lightpink2: 'rgb(238, 162, 173)',
+  lightpink3: 'rgb(205, 140, 149)',
+  lightpink4: 'rgb(139, 95, 101)',
+  lightsalmon: 'rgb(255, 160, 122)',
+  lightsalmon1: 'rgb(255, 160, 122)',
+  lightsalmon2: 'rgb(238, 149, 114)',
+  lightsalmon3: 'rgb(205, 129, 98)',
+  lightsalmon4: 'rgb(139, 87, 66)',
+  lightseagreen: 'rgb(32, 178, 170)',
+  lightskyblue: 'rgb(135, 206, 250)',
+  lightskyblue1: 'rgb(176, 226, 255)',
+  lightskyblue2: 'rgb(164, 211, 238)',
+  lightskyblue3: 'rgb(141, 182, 205)',
+  lightskyblue4: 'rgb(96, 123, 139)',
+  lightslateblue: 'rgb(132, 112, 255)',
+  lightslategray: 'rgb(119, 136, 153)',
+  lightslategrey: 'rgb(119, 136, 153)',
+  lightsteelblue: 'rgb(176, 196, 222)',
+  lightsteelblue1: 'rgb(202, 225, 255)',
+  lightsteelblue2: 'rgb(188, 210, 238)',
+  lightsteelblue3: 'rgb(162, 181, 205)',
+  lightsteelblue4: 'rgb(110, 123, 139)',
+  lightyellow: 'rgb(255, 255, 224)',
+  lightyellow1: 'rgb(255, 255, 224)',
+  lightyellow2: 'rgb(238, 238, 209)',
+  lightyellow3: 'rgb(205, 205, 180)',
+  lightyellow4: 'rgb(139, 139, 122)',
+  limegreen: 'rgb(50, 205, 50)',
+  linen: 'rgb(250, 240, 230)',
+  magenta: 'rgb(255, 0, 255)',
+  magenta1: 'rgb(255, 0, 255)',
+  magenta2: 'rgb(238, 0, 238)',
+  magenta3: 'rgb(205, 0, 205)',
+  magenta4: 'rgb(139, 0, 139)',
+  maroon: 'rgb(176, 48, 96)',
+  maroon1: 'rgb(255, 52, 179)',
+  maroon2: 'rgb(238, 48, 167)',
+  maroon3: 'rgb(205, 41, 144)',
+  maroon4: 'rgb(139, 28, 98)',
+  mediumaquamarine: 'rgb(102, 205, 170)',
+  mediumblue: 'rgb(0, 0, 205)',
+  mediumorchid: 'rgb(186, 85, 211)',
+  mediumorchid1: 'rgb(224, 102, 255)',
+  mediumorchid2: 'rgb(209, 95, 238)',
+  mediumorchid3: 'rgb(180, 82, 205)',
+  mediumorchid4: 'rgb(122, 55, 139)',
+  mediumpurple: 'rgb(147, 112, 219)',
+  mediumpurple1: 'rgb(171, 130, 255)',
+  mediumpurple2: 'rgb(159, 121, 238)',
+  mediumpurple3: 'rgb(137, 104, 205)',
+  mediumpurple4: 'rgb(93, 71, 139)',
+  mediumseagreen: 'rgb(60, 179, 113)',
+  mediumslateblue: 'rgb(123, 104, 238)',
+  mediumspringgreen: 'rgb(0, 250, 154)',
+  mediumturquoise: 'rgb(72, 209, 204)',
+  mediumvioletred: 'rgb(199, 21, 133)',
+  midnightblue: 'rgb(25, 25, 112)',
+  mintcream: 'rgb(245, 255, 250)',
+  mistyrose: 'rgb(255, 228, 225)',
+  mistyrose1: 'rgb(255, 228, 225)',
+  mistyrose2: 'rgb(238, 213, 210)',
+  mistyrose3: 'rgb(205, 183, 181)',
+  mistyrose4: 'rgb(139, 125, 123)',
+  moccasin: 'rgb(255, 228, 181)',
+  navajowhite: 'rgb(255, 222, 173)',
+  navajowhite1: 'rgb(255, 222, 173)',
+  navajowhite2: 'rgb(238, 207, 161)',
+  navajowhite3: 'rgb(205, 179, 139)',
+  navajowhite4: 'rgb(139, 121, 94)',
+  navy: 'rgb(0, 0, 128)',
+  navyblue: 'rgb(0, 0, 128)',
+  oldlace: 'rgb(253, 245, 230)',
+  olivedrab: 'rgb(107, 142, 35)',
+  olivedrab1: 'rgb(192, 255, 62)',
+  olivedrab2: 'rgb(179, 238, 58)',
+  olivedrab3: 'rgb(154, 205, 50)',
+  olivedrab4: 'rgb(105, 139, 34)',
+  orange: 'rgb(255, 165, 0)',
+  orange1: 'rgb(255, 165, 0)',
+  orange2: 'rgb(238, 154, 0)',
+  orange3: 'rgb(205, 133, 0)',
+  orange4: 'rgb(139, 90, 0)',
+  orangered: 'rgb(255, 69, 0)',
+  orangered1: 'rgb(255, 69, 0)',
+  orangered2: 'rgb(238, 64, 0)',
+  orangered3: 'rgb(205, 55, 0)',
+  orangered4: 'rgb(139, 37, 0)',
+  orchid: 'rgb(218, 112, 214)',
+  orchid1: 'rgb(255, 131, 250)',
+  orchid2: 'rgb(238, 122, 233)',
+  orchid3: 'rgb(205, 105, 201)',
+  orchid4: 'rgb(139, 71, 137)',
+  palegoldenrod: 'rgb(238, 232, 170)',
+  palegreen: 'rgb(152, 251, 152)',
+  palegreen1: 'rgb(154, 255, 154)',
+  palegreen2: 'rgb(144, 238, 144)',
+  palegreen3: 'rgb(124, 205, 124)',
+  palegreen4: 'rgb(84, 139, 84)',
+  paleturquoise: 'rgb(175, 238, 238)',
+  paleturquoise1: 'rgb(187, 255, 255)',
+  paleturquoise2: 'rgb(174, 238, 238)',
+  paleturquoise3: 'rgb(150, 205, 205)',
+  paleturquoise4: 'rgb(102, 139, 139)',
+  palevioletred: 'rgb(219, 112, 147)',
+  palevioletred1: 'rgb(255, 130, 171)',
+  palevioletred2: 'rgb(238, 121, 159)',
+  palevioletred3: 'rgb(205, 104, 137)',
+  palevioletred4: 'rgb(139, 71, 93)',
+  papayawhip: 'rgb(255, 239, 213)',
+  peachpuff: 'rgb(255, 218, 185)',
+  peachpuff1: 'rgb(255, 218, 185)',
+  peachpuff2: 'rgb(238, 203, 173)',
+  peachpuff3: 'rgb(205, 175, 149)',
+  peachpuff4: 'rgb(139, 119, 101)',
+  peru: 'rgb(205, 133, 63)',
+  pink: 'rgb(255, 192, 203)',
+  pink1: 'rgb(255, 181, 197)',
+  pink2: 'rgb(238, 169, 184)',
+  pink3: 'rgb(205, 145, 158)',
+  pink4: 'rgb(139, 99, 108)',
+  plum: 'rgb(221, 160, 221)',
+  plum1: 'rgb(255, 187, 255)',
+  plum2: 'rgb(238, 174, 238)',
+  plum3: 'rgb(205, 150, 205)',
+  plum4: 'rgb(139, 102, 139)',
+  powderblue: 'rgb(176, 224, 230)',
+  purple: 'rgb(160, 32, 240)',
+  purple1: 'rgb(155, 48, 255)',
+  purple2: 'rgb(145, 44, 238)',
+  purple3: 'rgb(125, 38, 205)',
+  purple4: 'rgb(85, 26, 139)',
+  red: 'rgb(255, 0, 0)',
+  red1: 'rgb(255, 0, 0)',
+  red2: 'rgb(238, 0, 0)',
+  red3: 'rgb(205, 0, 0)',
+  red4: 'rgb(139, 0, 0)',
+  rosybrown: 'rgb(188, 143, 143)',
+  rosybrown1: 'rgb(255, 193, 193)',
+  rosybrown2: 'rgb(238, 180, 180)',
+  rosybrown3: 'rgb(205, 155, 155)',
+  rosybrown4: 'rgb(139, 105, 105)',
+  royalblue: 'rgb(65, 105, 225)',
+  royalblue1: 'rgb(72, 118, 255)',
+  royalblue2: 'rgb(67, 110, 238)',
+  royalblue3: 'rgb(58, 95, 205)',
+  royalblue4: 'rgb(39, 64, 139)',
+  saddlebrown: 'rgb(139, 69, 19)',
+  salmon: 'rgb(250, 128, 114)',
+  salmon1: 'rgb(255, 140, 105)',
+  salmon2: 'rgb(238, 130, 98)',
+  salmon3: 'rgb(205, 112, 84)',
+  salmon4: 'rgb(139, 76, 57)',
+  sandybrown: 'rgb(244, 164, 96)',
+  seagreen: 'rgb(46, 139, 87)',
+  seagreen1: 'rgb(84, 255, 159)',
+  seagreen2: 'rgb(78, 238, 148)',
+  seagreen3: 'rgb(67, 205, 128)',
+  seagreen4: 'rgb(46, 139, 87)',
+  seashell: 'rgb(255, 245, 238)',
+  seashell1: 'rgb(255, 245, 238)',
+  seashell2: 'rgb(238, 229, 222)',
+  seashell3: 'rgb(205, 197, 191)',
+  seashell4: 'rgb(139, 134, 130)',
+  sienna: 'rgb(160, 82, 45)',
+  sienna1: 'rgb(255, 130, 71)',
+  sienna2: 'rgb(238, 121, 66)',
+  sienna3: 'rgb(205, 104, 57)',
+  sienna4: 'rgb(139, 71, 38)',
+  skyblue: 'rgb(135, 206, 235)',
+  skyblue1: 'rgb(135, 206, 255)',
+  skyblue2: 'rgb(126, 192, 238)',
+  skyblue3: 'rgb(108, 166, 205)',
+  skyblue4: 'rgb(74, 112, 139)',
+  slateblue: 'rgb(106, 90, 205)',
+  slateblue1: 'rgb(131, 111, 255)',
+  slateblue2: 'rgb(122, 103, 238)',
+  slateblue3: 'rgb(105, 89, 205)',
+  slateblue4: 'rgb(71, 60, 139)',
+  slategray: 'rgb(112, 128, 144)',
+  slategray1: 'rgb(198, 226, 255)',
+  slategray2: 'rgb(185, 211, 238)',
+  slategray3: 'rgb(159, 182, 205)',
+  slategray4: 'rgb(108, 123, 139)',
+  slategrey: 'rgb(112, 128, 144)',
+  snow: 'rgb(255, 250, 250)',
+  snow1: 'rgb(255, 250, 250)',
+  snow2: 'rgb(238, 233, 233)',
+  snow3: 'rgb(205, 201, 201)',
+  snow4: 'rgb(139, 137, 137)',
+  springgreen: 'rgb(0, 255, 127)',
+  springgreen1: 'rgb(0, 255, 127)',
+  springgreen2: 'rgb(0, 238, 118)',
+  springgreen3: 'rgb(0, 205, 102)',
+  springgreen4: 'rgb(0, 139, 69)',
+  steelblue: 'rgb(70, 130, 180)',
+  steelblue1: 'rgb(99, 184, 255)',
+  steelblue2: 'rgb(92, 172, 238)',
+  steelblue3: 'rgb(79, 148, 205)',
+  steelblue4: 'rgb(54, 100, 139)',
+  tan: 'rgb(210, 180, 140)',
+  tan1: 'rgb(255, 165, 79)',
+  tan2: 'rgb(238, 154, 73)',
+  tan3: 'rgb(205, 133, 63)',
+  tan4: 'rgb(139, 90, 43)',
+  thistle: 'rgb(216, 191, 216)',
+  thistle1: 'rgb(255, 225, 255)',
+  thistle2: 'rgb(238, 210, 238)',
+  thistle3: 'rgb(205, 181, 205)',
+  thistle4: 'rgb(139, 123, 139)',
+  tomato: 'rgb(255, 99, 71)',
+  tomato1: 'rgb(255, 99, 71)',
+  tomato2: 'rgb(238, 92, 66)',
+  tomato3: 'rgb(205, 79, 57)',
+  tomato4: 'rgb(139, 54, 38)',
+  turquoise: 'rgb(64, 224, 208)',
+  turquoise1: 'rgb(0, 245, 255)',
+  turquoise2: 'rgb(0, 229, 238)',
+  turquoise3: 'rgb(0, 197, 205)',
+  turquoise4: 'rgb(0, 134, 139)',
+  violet: 'rgb(238, 130, 238)',
+  violetred: 'rgb(208, 32, 144)',
+  violetred1: 'rgb(255, 62, 150)',
+  violetred2: 'rgb(238, 58, 140)',
+  violetred3: 'rgb(205, 50, 120)',
+  violetred4: 'rgb(139, 34, 82)',
+  wheat: 'rgb(245, 222, 179)',
+  wheat1: 'rgb(255, 231, 186)',
+  wheat2: 'rgb(238, 216, 174)',
+  wheat3: 'rgb(205, 186, 150)',
+  wheat4: 'rgb(139, 126, 102)',
+  white: 'rgb(255, 255, 255)',
+  whitesmoke: 'rgb(245, 245, 245)',
+  yellow: 'rgb(255, 255, 0)',
+  yellow1: 'rgb(255, 255, 0)',
+  yellow2: 'rgb(238, 238, 0)',
+  yellow3: 'rgb(205, 205, 0)',
+  yellow4: 'rgb(139, 139, 0)',
+  yellowgreen: 'rgb(154, 205, 50)'
+}, lib.f = {}, lib.f.replaceVars = function(e, t) {
+  return e.replace(/%([a-z]*)\(([^\)]+)\)/gi, function(e, r, o) {
+    if ('undefined' == typeof t[o]) throw 'Unknown variable: ' + o;
+    var i = t[o];
+    if (r in lib.f.replaceVars.functions) i = lib.f.replaceVars.functions[r](i);
+    else if (r) throw 'Unknown escape function: ' + r;
+    return i;
+  });
+};, lib.f.replaceVars.functions = {
+  encodeURI: encodeURI,
+  encodeURIComponent: encodeURIComponent,
+  escapeHTML: function(e) {
+    var t = {
+      '<': '&lt;',
+      '>': '&gt;',
+      '&': '&amp;',
+      '"': '&quot;',
+      "'": '&#39;'
+    };
+    return e.replace(/[<>&\"\']/g, function(e) {
+      return t[e];
+    });
+  }
+}, lib.f.getAcceptLanguages = function(e) {
+  lib.f.getAcceptLanguages.chromeSupported() ? chrome.i18n.getAcceptLanguages(e) : setTimeout(function() {
+    e([navigator.language.replace(/-/g, '_')]);
+  }, 0);
+};, lib.f.getAcceptLanguages.chromeSupported = function() {
+  return window.chrome && chrome.i18n;
+};, lib.f.parseQuery = function(e) {
+  '?' == e.substr(0, 1) && (e = e.substr(1));
+  for (var t = {}, r = e.split('&'), o = 0; o < r.length; o++) {
+    var i = r[o].split('=');
+    t[decodeURIComponent(i[0])] = decodeURIComponent(i[1]);
+  }
+  return t;
+};, lib.f.getURL = function(e) {
+  return lib.f.getURL.chromeSupported() ? chrome.runtime.getURL(e) : e;
+};, lib.f.getURL.chromeSupported = function() {
+  return window.chrome && chrome.runtime && chrome.runtime.getURL;
+};, lib.f.clamp = function(e, t, r) {
+  return t > e ? t : e > r ? r : e
+};, lib.f.lpad = function(e, t, r) {
+  for (e = String(e), r = r || ' '; e.length < t;) e = r + e;
+  return e;
+};, lib.f.zpad = function(e, t) {
+  return lib.f.lpad(e, t, '0');
+};, lib.f.getWhitespace = function(e) {
+  if (0 >= e) return '';
+  var t = this.getWhitespace;
+  for (t.whitespace || (t.whitespace = '          '); e > t.whitespace.length;) t.whitespace += t.whitespace;
+  return t.whitespace.substr(0, e);
+};, lib.f.alarm = function(e, t) {
+  var r = t || 5e3,
+    o = lib.f.getStack(1);
+  return function() {
+    var t = setTimeout(function() {
+        var i = 'string' == typeof e ? i : e.name;
+        i = i ? ': ' + i : '', console.warn('lib.f.alarm: timeout expired: ' + r / 1e3 + 's' + i), console.log(o), t = null;
+      }, r),
+      i = function(e) {
+        return function() {
+          return t && (clearTimeout(t), t = null), e.apply(null, arguments);
+        }
+      };
+    return 'string' == typeof e ? i : i(e);
+  }();
+};, lib.f.getStack = function(e) {
+  var t, r = e ? e + 2 : 2;
+  try {
+    throw new Error;
+  }
+  catch (o) {
+    t = o.stack.split('\n');
+  }
+  for (var i = {}, s = r; s < t.length; s++) i[s - r] = t[s].replace(/^\s*at\s+/, '');
+  return i;
+};, lib.f.smartFloorDivide = function(e, t) {
+  var r = e / t,
+    o = Math.ceil(r);
+  return 1e-4 > o - r ? o : Math.floor(r);
+};, lib.MessageManager = function(e) {
+  this.languages_ = e.map(function(e) {
+    return e.replace(/-/g, '_');
+  }), -1 == this.languages_.indexOf('en') && this.languages_.unshift('en'), this.messages = {};
+};, lib.MessageManager.prototype.addMessages = function(e) {
+  for (var t in e) {
+    var r = e[t];
+    r.placeholders ? this.messages[t] = r.message.replace(/\$([a-z][^\s\$]+)\$/gi, function(r, o) {
+      return e[t].placeholders[o.toLowerCase()].content;
+    }) : this.messages[t] = r.message;
+  }
+};, lib.MessageManager.prototype.findAndLoadMessages = function(e, t) {
+  function r(e) {
+    e ? i = o.shift() : s = o.shift(), o.length ? n() : t(i, s);
+  }
+  var o = this.languages_.concat(),
+    i = [],
+    s = [],
+    n = function() {
+      this.loadMessages(this.replaceReferences(e, o), r.bind(this, !0), r.bind(this, !1));
+    }.bind(this);
+  n();
+};, lib.MessageManager.prototype.loadMessages = function(e, t, r) {
+  var o = new XMLHttpRequest;
+  o.onloadend = function() {
+    return 200 != o.status ? void(r && r(o.status)) : (this.addMessages(JSON.parse(o.responseText)), void t());
+  }.bind(this), o.open('GET', e), o.send();
+};, lib.MessageManager.replaceReferences = function(e, t) {
+  return e.replace(/\$(\d+)/g, function(e, r) {
+    return t[r - 1];
+  });
+};, lib.MessageManager.prototype.replaceReferences = lib.MessageManager.replaceReferences, lib.MessageManager.prototype.get = function(e, t, r) {
+  var o;
+  if (e in this.messages) o = this.messages[e];
+  else if (window.chrome.i18n && (o = chrome.i18n.getMessage(e)), !o) return console.warn('Unknown message: ' + e), 'undefined' == typeof r ? e : r;
+  return t ? (t instanceof Array || (t = [t]), this.replaceReferences(o, t)) : o;
+};, lib.MessageManager.prototype.processI18nAttributes = function(e) {
+  function t(e) {
+    return e.replace(/-/g, '_').toUpperCase();
+  }
+  for (var r = e.querySelectorAll('[i18n]'), o = 0; o < r.length; o++) {
+    var i = r[o],
+      s = i.getAttribute('i18n');
+    if (s) {
+      try {
+        s = JSON.parse(s);
+      }
+      catch (n) {
+        throw console.error("Can't parse " + i.tagName + '#' + i.id + ': ' + s), n;
+      }
+      for (var a in s) {
+        var l = s[a];
+        '$' == l.substr(0, 1) && (l = t(i.getAttribute(l.substr(1)) + '_' + a));
+        var h = this.get(l);
+        '_' == a ? i.textContent = h : i.setAttribute(a, h);
+      }
+    }
+  }
+};, lib.PreferenceManager = function(e, t) {
+  this.storage = e, this.storageObserver_ = this.onStorageChange_.bind(this), this.isActive_ = !1, this.activate(), this.trace = !1;
+  var r = t || '/';
+  '/' != r.substr(r.length - 1) && (r += '/'), this.prefix = r, this.prefRecords_ = {}, this.globalObservers_ = [], this.childFactories_ = {}, this.childLists_ = {};
+};, lib.PreferenceManager.prototype.DEFAULT_VALUE = new String('DEFAULT'), lib.PreferenceManager.Record = function(e, t) {
+  this.name = e, this.defaultValue = t, this.currentValue = this.DEFAULT_VALUE, this.observers = [];
+};, lib.PreferenceManager.Record.prototype.DEFAULT_VALUE = lib.PreferenceManager.prototype.DEFAULT_VALUE, lib.PreferenceManager.Record.prototype.addObserver = function(e) {
+  this.observers.push(e);
+};, lib.PreferenceManager.Record.prototype.removeObserver = function(e) {
+  var t = this.observers.indexOf(e);
+  t >= 0 && this.observers.splice(t, 1);
+};, lib.PreferenceManager.Record.prototype.get = function() {
+  return this.currentValue === this.DEFAULT_VALUE ? /^(string|number)$/.test(typeof this.defaultValue) ? this.defaultValue : 'object' == typeof this.defaultValue ? JSON.parse(JSON.stringify(this.defaultValue)) : this.defaultValue : this.currentValue
+};, lib.PreferenceManager.prototype.deactivate = function() {
+  if (!this.isActive_) throw new Error('Not activated');
+  this.isActive_ = !1, this.storage.removeObserver(this.storageObserver_);
+};, lib.PreferenceManager.prototype.activate = function() {
+  if (this.isActive_) throw new Error('Already activated');
+  this.isActive_ = !0, this.storage.addObserver(this.storageObserver_);
+};, lib.PreferenceManager.prototype.readStorage = function(e) {
+  function t() {
+    0 == --r && e && e();
+  }
+  var r = 0,
+    o = Object.keys(this.prefRecords_).map(function(e) {
+      return this.prefix + e;
+    }.bind(this));
+  this.trace && console.log('Preferences read: ' + this.prefix),
+    this.storage.getItems(o, function(o) {
+      var i = this.prefix.length;
+      for (var s in o) {
+        var n = o[s],
+          a = s.substr(i),
+          l = a in this.childLists_ && JSON.stringify(n) != JSON.stringify(this.prefRecords_[a].currentValue);
+        this.prefRecords_[a].currentValue = n, l && (r++, this.syncChildList(a, t));
+      }
+      0 == r && e && setTimeout(e);
+    }.bind(this));
+};, lib.PreferenceManager.prototype.definePreference = function(e, t, r) {
+  var o = this.prefRecords_[e];
+  o ? this.changeDefault(e, t) : o = this.prefRecords_[e] = new lib.PreferenceManager.Record(e, t), r && o.addObserver(r);
+};, lib.PreferenceManager.prototype.definePreferences = function(e) {
+  for (var t = 0; t < e.length; t++) this.definePreference(e[t][0], e[t][1], e[t][2]);
+};, lib.PreferenceManager.prototype.defineChildren = function(e, t) {
+  this.definePreference(e, [], this.onChildListChange_.bind(this, e)), this.childFactories_[e] = t, this.childLists_[e] = {};
+};, lib.PreferenceManager.prototype.addObservers = function(e, t) {
+  if (e && 'function' != typeof e) throw new Error('Invalid param: globals');
+  if (e && this.globalObservers_.push(e), t)
+    for (var r in t) {
+      if (!(r in this.prefRecords_)) throw new Error('Unknown preference: ' + r);
+      this.prefRecords_[r].addObserver(t[r]);
+    }
+};, lib.PreferenceManager.prototype.notifyAll = function() {
+  for (var e in this.prefRecords_) this.notifyChange_(e);
+};, lib.PreferenceManager.prototype.notifyChange_ = function(e) {
+  var t = this.prefRecords_[e];
+  if (!t) throw new Error('Unknown preference: ' + e);
+  for (var r = t.get(), o = 0; o < this.globalObservers_.length; o++) this.globalObservers_[o](e, r);
+  for (var o = 0; o < t.observers.length; o++) t.observers[o](r, e, this);
+};, lib.PreferenceManager.prototype.createChild = function(e, t, r) {
+  var o, i = this.get(e);
+  if (r) {
+    if (o = r, -1 != i.indexOf(o)) throw new Error('Duplicate child: ' + e + ': ' + o);
+  }
+  else
+    for (; !o || -1 != i.indexOf(o);) o = Math.floor(65535 * Math.random() + 1).toString(16), o = lib.f.zpad(o, 4), t && (o = t + ':' + o);
+  var s = this.childFactories_[e](this, o);
+  return s.trace = this.trace, s.resetAll(), this.childLists_[e][o] = s, i.push(o), this.set(e, i), s;
+};, lib.PreferenceManager.prototype.removeChild = function(e, t) {
+  var r = this.getChild(e, t);
+  r.resetAll();
+  var o = this.get(e),
+    i = o.indexOf(t); - 1 != i && (o.splice(i, 1), this.set(e, o)), delete this.childLists_[e][t];
+};, lib.PreferenceManager.prototype.getChild = function(e, t, r) {
+  if (!(e in this.childLists_)) throw new Error('Unknown child list: ' + e);
+  var o = this.childLists_[e];
+  if (!(t in o)) {
+    if ('undefined' == typeof r) throw new Error('Unknown "' + e + '" child: ' + t);
+    return r;
+  }
+  return o[t];
+};, lib.PreferenceManager.diffChildLists = function(e, t) {
+  for (var r = {
+      added: {},
+      removed: {},
+      common: {}
+    }, o = 0; o < e.length; o++) - 1 != t.indexOf(e[o]) ? r.common[e[o]] = !0 : r.added[e[o]] = !0;
+  for (var o = 0; o < t.length; o++) t[o] in r.added || t[o] in r.common || (r.removed[t[o]] = !0);
+  return r;
+};, lib.PreferenceManager.prototype.syncChildList = function(e, t) {
+  function r() {
+    0 == --o && t && t();
+  }
+  for (var o = 0, i = this.get(e), s = Object.keys(this.childLists_[e]), n = (lib.PreferenceManager.diffChildLists(i, s), 0); n < i.length; n++) {
+    var a = i[n],
+      l = s.indexOf(a);
+    if (l >= 0 && s.splice(l, 1), !this.childLists_[e][a]) {
+      var h = this.childFactories_[e](this, a);
+      if (!h) {
+        console.warn('Unable to restore child: ' + e + ': ' + a);
+        continue;
+      }
+      h.trace = this.trace, this.childLists_[e][a] = h, o++, h.readStorage(r);
+    }
+  }
+  for (var n = 0; n < s.length; n++) delete this.childLists_[e][s[n]];
+  !o && t && setTimeout(t);
+};, lib.PreferenceManager.prototype.reset = function(e) {
+  var t = this.prefRecords_[e];
+  if (!t) throw new Error('Unknown preference: ' + e);
+  this.storage.removeItem(this.prefix + e), t.currentValue !== this.DEFAULT_VALUE && (t.currentValue = this.DEFAULT_VALUE, this.notifyChange_(e));
+};, lib.PreferenceManager.prototype.resetAll = function() {
+  var e = [];
+  for (var t in this.childLists_) {
+    var r = this.childLists_[t];
+    for (var o in r) r[o].resetAll();
+  }
+  for (var i in this.prefRecords_) this.prefRecords_[i].currentValue !== this.DEFAULT_VALUE && (this.prefRecords_[i].currentValue = this.DEFAULT_VALUE, e.push(i));
+  var s = Object.keys(this.prefRecords_).map(function(e) {
+    return this.prefix + e;
+  }.bind(this));
+  this.storage.removeItems(s), e.forEach(this.notifyChange_.bind(this));
+};, lib.PreferenceManager.prototype.diff = function(e, t) {
+  return typeof e == typeof t && /^(undefined|boolean|number|string)$/.test(typeof e) ? e !== t : !0;
+};, lib.PreferenceManager.prototype.changeDefault = function(e, t) {
+  var r = this.prefRecords_[e];
+  if (!r) throw new Error('Unknown preference: ' + e);
+  if (this.diff(r.defaultValue, t)) {
+    if (r.currentValue !== this.DEFAULT_VALUE) return void(r.defaultValue = t);
+    r.defaultValue = t, this.notifyChange_(e);
+  }
+};, lib.PreferenceManager.prototype.changeDefaults = function(e) {
+  for (var t in e) this.changeDefault(t, e[t]);
+};, lib.PreferenceManager.prototype.set = function(e, t) {
+  var r = this.prefRecords_[e];
+  if (!r) throw new Error('Unknown preference: ' + e);
+  var o = r.get();
+  this.diff(o, t) && (this.diff(r.defaultValue, t) ? (r.currentValue = t, this.storage.setItem(this.prefix + e, t)) : (r.currentValue = this.DEFAULT_VALUE, this.storage.removeItem(this.prefix + e)), setTimeout(this.notifyChange_.bind(this, e), 0));
+};, lib.PreferenceManager.prototype.get = function(e) {
+  var t = this.prefRecords_[e];
+  if (!t) throw new Error('Unknown preference: ' + e);
+  return t.get();
+};, lib.PreferenceManager.prototype.exportAsJson = function() {
+  var e = {};
+  for (var t in this.prefRecords_)
+    if (t in this.childLists_) {
+      e[t] = [];
+      for (var r = this.get(t), o = 0; o < r.length; o++) {
+        var i = r[o];
+        e[t].push({
+          id: i,
+          json: this.getChild(t, i).exportAsJson()
+        });
+      }
+    }
+  else {
+    var s = this.prefRecords_[t];
+    s.currentValue != this.DEFAULT_VALUE && (e[t] = s.currentValue);
+  }
+  return e;
+};, lib.PreferenceManager.prototype.importFromJson = function(e) {
+  for (var t in e)
+    if (t in this.childLists_)
+      for (var r = e[t], o = 0; o < r.length; o++) {
+        var i = r[o].id,
+          s = this.childLists_[t][i];
+        s || (s = this.createChild(t, null, i)), s.importFromJson(r[o].json);
+      }
+  else this.set(t, e[t]);
+};, lib.PreferenceManager.prototype.onChildListChange_ = function(e) {
+  this.syncChildList(e);
+};, lib.PreferenceManager.prototype.onStorageChange_ = function(e) {
+  for (var t in e)
+    if (!this.prefix || 0 == t.lastIndexOf(this.prefix, 0)) {
+      var r = t.substr(this.prefix.length);
+      if (r in this.prefRecords_) {
+        var o = this.prefRecords_[r],
+          i = e[t].newValue,
+          s = o.currentValue;
+        s === o.DEFAULT_VALUE && (s = void 0), this.diff(s, i) && ('undefined' == typeof i ? o.currentValue = o.DEFAULT_VALUE : o.currentValue = i, this.notifyChange_(r));
+      }
+    }
+};, lib.resource = {
+  resources_: {}
+}, lib.resource.add = function(e, t, r) {
+  lib.resource.resources_[e] = {
+    type: t,
+    name: e,
+    data: r
+  };
+};, lib.resource.get = function(e, t) {
+  if (!(e in lib.resource.resources_)) {
+    if ('undefined' == typeof t) throw 'Unknown resource: ' + e;
+    return t;
+  }
+  return lib.resource.resources_[e];
+};, lib.resource.getData = function(e, t) {
+  if (!(e in lib.resource.resources_)) {
+    if ('undefined' == typeof t) throw 'Unknown resource: ' + e;
+    return t;
+  }
+  return lib.resource.resources_[e].data;
+};, lib.resource.getDataUrl = function(e, t) {
+  var r = lib.resource.get(e, t);
+  return 'data:' + r.type + ',' + r.data;
+};, lib.Storage = new Object, lib.Storage.Chrome = function(e) {
+  this.storage_ = e, this.observers_ = [], chrome.storage.onChanged.addListener(this.onChanged_.bind(this));
+};, lib.Storage.Chrome.prototype.onChanged_ = function(e, t) {
+  if (chrome.storage[t] == this.storage_)
+    for (var r = 0; r < this.observers_.length; r++) this.observers_[r](e);
+};, lib.Storage.Chrome.prototype.addObserver = function(e) {
+  this.observers_.push(e);
+};, lib.Storage.Chrome.prototype.removeObserver = function(e) {
+  var t = this.observers_.indexOf(e); - 1 != t && this.observers_.splice(t, 1);
+};, lib.Storage.Chrome.prototype.clear = function(e) {
+  this.storage_.clear(), e && setTimeout(e, 0);
+};, lib.Storage.Chrome.prototype.getItem = function(e, t) {
+  this.storage_.get(e, t);
+};, lib.Storage.Chrome.prototype.getItems = function(e, t) {
+  this.storage_.get(e, t);
+};, lib.Storage.Chrome.prototype.setItem = function(e, t, r) {
+  var o = {};
+  o[e] = t, this.storage_.set(o, r);
+};, lib.Storage.Chrome.prototype.setItems = function(e, t) {
+  this.storage_.set(e, t);
+};, lib.Storage.Chrome.prototype.removeItem = function(e, t) {
+  this.storage_.remove(e, t);
+};, lib.Storage.Chrome.prototype.removeItems = function(e, t) {
+  this.storage_.remove(e, t);
+};, lib.Storage.Local = function() {
+  this.observers_ = [], this.storage_ = window.localStorage, window.addEventListener('storage', this.onStorage_.bind(this));
+};, lib.Storage.Local.prototype.onStorage_ = function(e) {
+  if (e.storageArea == this.storage_) {
+    var t = e.oldValue ? JSON.parse(e.oldValue) : '',
+      r = e.newValue ? JSON.parse(e.newValue) : '',
+      o = {};
+    o[e.key] = {
+      oldValue: t,
+      newValue: r
+    };
+    for (var i = 0; i < this.observers_.length; i++) this.observers_[i](o);
+  }
+};, lib.Storage.Local.prototype.addObserver = function(e) {
+  this.observers_.push(e);
+};, lib.Storage.Local.prototype.removeObserver = function(e) {
+  var t = this.observers_.indexOf(e); - 1 != t && this.observers_.splice(t, 1);
+};, lib.Storage.Local.prototype.clear = function(e) {
+  this.storage_.clear(), e && setTimeout(e, 0);
+};, lib.Storage.Local.prototype.getItem = function(e, t) {
+  var r = this.storage_.getItem(e);
+  if ('string' == typeof r) try {
+    r = JSON.parse(r);
+  }
+  catch (o) {}
+  setTimeout(t.bind(null, r), 0);
+};, lib.Storage.Local.prototype.getItems = function(e, t) {
+  for (var r = {}, o = e.length - 1; o >= 0; o--) {
+    var i = e[o],
+      s = this.storage_.getItem(i);
+    if ('string' == typeof s) try {
+      r[i] = JSON.parse(s);
+    }
+    catch (n) {
+      r[i] = s;
+    }
+    else e.splice(o, 1);
+  }
+  setTimeout(t.bind(null, r), 0);
+};, lib.Storage.Local.prototype.setItem = function(e, t, r) {
+  this.storage_.setItem(e, JSON.stringify(t)), r && setTimeout(r, 0);
+};, lib.Storage.Local.prototype.setItems = function(e, t) {
+  for (var r in e) this.storage_.setItem(r, JSON.stringify(e[r]));
+  t && setTimeout(t, 0);
+};, lib.Storage.Local.prototype.removeItem = function(e, t) {
+  this.storage_.removeItem(e), t && setTimeout(t, 0);
+};, lib.Storage.Local.prototype.removeItems = function(e, t) {
+  for (var r = 0; r < e.length; r++) this.storage_.removeItem(e[r]);
+  t && setTimeout(t, 0);
+};, lib.Storage.Memory = function() {
+  this.observers_ = [], this.storage_ = {};
+};, lib.Storage.Memory.prototype.addObserver = function(e) {
+  this.observers_.push(e);
+};, lib.Storage.Memory.prototype.removeObserver = function(e) {
+  var t = this.observers_.indexOf(e); - 1 != t && this.observers_.splice(t, 1);
+};, lib.Storage.Memory.prototype.clear = function(e) {
+  var t = {};
+  for (var r in this.storage_) t[r] = {
+    oldValue: this.storage_[r],
+    newValue: void 0
+  };
+  this.storage_ = {}, setTimeout(function() {
+    for (var e = 0; e < this.observers_.length; e++) this.observers_[e](t);
+  }.bind(this), 0), e && setTimeout(e, 0);
+};, lib.Storage.Memory.prototype.getItem = function(e, t) {
+  var r = this.storage_[e];
+  if ('string' == typeof r) try {
+    r = JSON.parse(r);
+  }
+  catch (o) {}
+  setTimeout(t.bind(null, r), 0);
+};, lib.Storage.Memory.prototype.getItems = function(e, t) {
+  for (var r = {}, o = e.length - 1; o >= 0; o--) {
+    var i = e[o],
+      s = this.storage_[i];
+    if ('string' == typeof s) try {
+      r[i] = JSON.parse(s);
+    }
+    catch (n) {
+      r[i] = s;
+    }
+    else e.splice(o, 1);
+  }
+  setTimeout(t.bind(null, r), 0);
+};, lib.Storage.Memory.prototype.setItem = function(e, t, r) {
+  var o = this.storage_[e];
+  this.storage_[e] = JSON.stringify(t);
+  var i = {};
+  i[e] = {
+    oldValue: o,
+    newValue: t
+  }, setTimeout(function() {
+    for (var e = 0; e < this.observers_.length; e++) this.observers_[e](i);
+  }.bind(this), 0), r && setTimeout(r, 0);
+};, lib.Storage.Memory.prototype.setItems = function(e, t) {
+  var r = {};
+  for (var o in e) r[o] = {
+    oldValue: this.storage_[o],
+    newValue: e[o]
+  }, this.storage_[o] = JSON.stringify(e[o]);
+  setTimeout(function() {
+    for (var e = 0; e < this.observers_.length; e++) this.observers_[e](r);
+  }.bind(this)), t && setTimeout(t, 0);
+};, lib.Storage.Memory.prototype.removeItem = function(e, t) {
+  delete this.storage_[e], t && setTimeout(t, 0);
+};, lib.Storage.Memory.prototype.removeItems = function(e, t) {
+  for (var r = 0; r < e.length; r++) delete this.storage_[e[r]];
+  t && setTimeout(t, 0);
+};, lib.TestManager = function(e) {
+  this.log = e || new lib.TestManager.Log;
+};, lib.TestManager.prototype.createTestRun = function(e) {
+  return new lib.TestManager.TestRun(this, e);
+};, lib.TestManager.prototype.onTestRunComplete = function(e) {};, lib.TestManager.prototype.testPreamble = function(e, t) {};, lib.TestManager.prototype.testPostamble = function(e, t) {};, lib.TestManager.Log = function(e) {
+  this.save = !1, this.data = '', this.logFunction_ = e || function(e) {
+    this.save && (this.data += e + '\n'), console.log(e);
+  };, this.pending_ = '', this.prefix_ = '', this.prefixStack_ = [];
+};, lib.TestManager.Log.prototype.pushPrefix = function(e) {
+  this.prefixStack_.push(e), this.prefix_ = this.prefixStack_.join('');
+};, lib.TestManager.Log.prototype.popPrefix = function() {
+  this.prefixStack_.pop(), this.prefix_ = this.prefixStack_.join('');
+};, lib.TestManager.Log.prototype.print = function(e) {
+  this.pending_ ? this.pending_ += e : this.pending_ = this.prefix_ + e;
+};, lib.TestManager.Log.prototype.println = function(e) {
+  this.pending_ && this.flush(), this.logFunction_(this.prefix_ + e);
+};, lib.TestManager.Log.prototype.flush = function() {
+  this.pending_ && (this.logFunction_(this.pending_), this.pending_ = '');
+};, lib.TestManager.Suite = function(e) {
+  function t(t, r) {
+    this.testManager_ = t, this.suiteName = e, this.setup(r);
+  }
+  return t.suiteName = e, t.addTest = lib.TestManager.Suite.addTest, t.disableTest = lib.TestManager.Suite.disableTest, t.getTest = lib.TestManager.Suite.getTest, t.getTestList = lib.TestManager.Suite.getTestList, t.testList_ = [], t.testMap_ = {}, t.prototype = {
+    __proto__: lib.TestManager.Suite.prototype
+  }, lib.TestManager.Suite.subclasses.push(t), t;
+};, lib.TestManager.Suite.subclasses = [], lib.TestManager.Suite.addTest = function(e, t) {
+  if (e in this.testMap_) throw 'Duplicate test name: ' + e;
+  var r = new lib.TestManager.Test(this, e, t);
+  this.testMap_[e] = r, this.testList_.push(r);
+};, lib.TestManager.Suite.disableTest = function(e, t) {
+  if (e in this.testMap_) throw 'Duplicate test name: ' + e;
+  var r = new lib.TestManager.Test(this, e, t);
+  console.log('Disabled test: ' + r.fullName);
+};, lib.TestManager.Suite.getTest = function(e) {
+  return this.testMap_[e];
+};, lib.TestManager.Suite.getTestList = function() {
+  return this.testList_;
+};, lib.TestManager.Suite.prototype.setDefaults = function(e, t) {
+  for (var r in t) this[r] = r in e ? e[r] : t[r];
+};, lib.TestManager.Suite.prototype.setup = function(e) {};, lib.TestManager.Suite.prototype.preamble = function(e, t) {};, lib.TestManager.Suite.prototype.postamble = function(e, t) {};, lib.TestManager.Test = function(e, t, r) {
+  this.suiteClass = e, this.testName = t, this.fullName = e.suiteName + '[' + t + ']', this.testFunction_ = r;
+};, lib.TestManager.Test.prototype.run = function(e) {
+  try {
+    this.testFunction_.apply(e.suite, [e, e.testRun.cx]);
+  }
+  catch (t) {
+    if (t instanceof lib.TestManager.Result.TestComplete) return;
+    e.println('Test raised an exception: ' + t), t.stack && (t.stack instanceof Array ? e.println(t.stack.join('\n')) : e.println(t.stack)), e.completeTest_(e.FAILED, !1);
+  }
+};, lib.TestManager.TestRun = function(e, t) {
+  this.testManager = e, this.log = e.log, this.cx = t || {}, this.failures = [], this.passes = [], this.startDate = null, this.duration = null, this.currentResult = null, this.maxFailures = 0, this.panic = !1, this.testQueue_ = [];
+};, lib.TestManager.TestRun.prototype.ALL_TESTS = new String('<all-tests>'), lib.TestManager.TestRun.prototype.selectTest = function(e) {
+  this.testQueue_.push(e);
+};, lib.TestManager.TestRun.prototype.selectSuite = function(e, t) {
+  for (var r = t || this.ALL_TESTS, o = 0, i = e.getTestList(), s = 0; s < i.length; s++) {
+    var n = i[s];
+    if (r !== this.ALL_TESTS)
+      if (r instanceof RegExp) {
+        if (!r.test(n.testName)) continue;
+      }
+    else if (n.testName != r) continue;
+    this.selectTest(n), o++;
+  }
+  return o;
+};, lib.TestManager.TestRun.prototype.selectPattern = function(e) {
+  for (var t = 0, r = 0; r < lib.TestManager.Suite.subclasses.length; r++) t += this.selectSuite(lib.TestManager.Suite.subclasses[r], e);
+  return t || this.log.println('No tests matched selection criteria: ' + e), t;
+};, lib.TestManager.TestRun.prototype.onUncaughtException_ = function(e, t, r) {
+  if (0 == e.indexOf('Uncaught lib.TestManager.Result.TestComplete') || -1 != e.indexOf('status: passed')) return !0;
+  if (this.currentResult && e != 'Uncaught ' + this.currentResult.expectedErrorMessage_) {
+    var o = 'during';
+    return this.currentResult.status != this.currentResult.PENDING && (o = 'after'), this.log.println('Uncaught exception ' + o + ' test case: ' + this.currentResult.test.fullName), this.log.println(e + ', ' + t + ':' + r), this.currentResult.completeTest_(this.currentResult.FAILED, !1), !1;
+  }
+};, lib.TestManager.TestRun.prototype.onTestRunComplete_ = function(e) {
+  return e ? (this.duration = new Date - this.startDate, this.log.popPrefix(), this.log.println('} ' + this.passes.length + ' passed, ' + this.failures.length + ' failed, ' + this.msToSeconds_(this.duration)), this.log.println(''), this.summarize(), window.onerror = null, void this.testManager.onTestRunComplete(this)) : void setTimeout(this.onTestRunComplete_.bind(this), 0, !0);
+};, lib.TestManager.TestRun.prototype.onResultComplete = function(e) {
+  try {
+    this.testManager.testPostamble(e, this.cx), e.suite.postamble(e, this.ctx);
+  }
+  catch (t) {
+    this.log.println('Unexpected exception in postamble: ' + (t.stack ? t.stack : t)), this.panic = !0;
+  }
+  if (this.log.popPrefix(), this.log.print('} ' + e.status + ', ' + this.msToSeconds_(e.duration)), this.log.flush(), e.status == e.FAILED) this.failures.push(e), this.currentSuite = null;
+  else {
+    if (e.status != e.PASSED) return this.log.println('Unknown result status: ' + e.test.fullName + ': ' + e.status), this.panic = !0;
+    this.passes.push(e);
+  }
+  this.runNextTest_();
+};, lib.TestManager.TestRun.prototype.onResultReComplete = function(e, t) {
+  this.log.println('Late complete for test: ' + e.test.fullName + ': ' + t);
+  var r = this.passes.indexOf(e);
+  r >= 0 && (this.passes.splice(r, 1), this.failures.push(e));
+};, lib.TestManager.TestRun.prototype.runNextTest_ = function() {
+  if (this.panic || !this.testQueue_.length) return this.onTestRunComplete_();
+  if (this.maxFailures && this.failures.length >= this.maxFailures) return this.log.println('Maximum failure count reached, aborting test run.'), this.onTestRunComplete_();
+  var e = this.testQueue_[0],
+    t = this.currentResult ? this.currentResult.suite : null;
+  try {
+    t && t instanceof e.suiteClass || (this.log.println('Initializing suite: ' + e.suiteClass.suiteName), t = new e.suiteClass(this.testManager, this.cx));
+  }
+  catch (r) {
+    return this.log.println('Exception during setup: ' + (r.stack ? r.stack : r)), this.panic = !0, void this.onTestRunComplete_();
+  }
+  try {
+    this.log.print('Test: ' + e.fullName + ' {'), this.log.pushPrefix('  '), this.currentResult = new lib.TestManager.Result(this, t, e), this.testManager.testPreamble(this.currentResult, this.cx), t.preamble(this.currentResult, this.cx), this.testQueue_.shift();
+  }
+  catch (r) {
+    return this.log.println('Unexpected exception during test preamble: ' + (r.stack ? r.stack : r)), this.log.popPrefix(), this.log.println('}'), this.panic = !0, void this.onTestRunComplete_();
+  }
+  try {
+    this.currentResult.run();
+  }
+  catch (r) {
+    this.log.println('Unexpected exception during test run: ' + (r.stack ? r.stack : r)), this.panic = !0;
+  }
+};, lib.TestManager.TestRun.prototype.run = function() {
+  this.log.println('Running ' + this.testQueue_.length + ' test(s) {'), this.log.pushPrefix('  '), window.onerror = this.onUncaughtException_.bind(this), this.startDate = new Date, this.runNextTest_();
+};, lib.TestManager.TestRun.prototype.msToSeconds_ = function(e) {
+  var t = (e / 1e3).toFixed(2);
+  return t + 's';
+};, lib.TestManager.TestRun.prototype.summarize = function() {
+  if (this.failures.length)
+    for (var e = 0; e < this.failures.length; e++) this.log.println('FAILED: ' + this.failures[e].test.fullName);
+  this.testQueue_.length && this.log.println('Test run incomplete: ' + this.testQueue_.length + ' test(s) were not run.');
+};, lib.TestManager.Result = function(e, t, r) {
+  this.testRun = e, this.suite = t, this.test = r, this.startDate = null, this.duration = null, this.status = this.PENDING, this.expectedErrorMessage_ = null;
+};, lib.TestManager.Result.prototype.PENDING = 'pending', lib.TestManager.Result.prototype.FAILED = 'FAILED', lib.TestManager.Result.prototype.PASSED = 'passed', lib.TestManager.Result.TestComplete = function(e) {
+  this.result = e;
+};, lib.TestManager.Result.TestComplete.prototype.toString = function() {
+  return 'lib.TestManager.Result.TestComplete: ' + this.result.test.fullName + ', status: ' + this.result.status;
+};, lib.TestManager.Result.prototype.run = function() {
+  this.startDate = new Date, this.test.run(this), this.status != this.PENDING || this.timeout_ || (this.println('Test did not return a value and did not request more time.'), this.completeTest_(this.FAILED, !1));
+};, lib.TestManager.Result.prototype.expectErrorMessage = function(e) {
+  this.expectedErrorMessage_ = e;
+};, lib.TestManager.Result.prototype.onTimeout_ = function() {
+  this.timeout_ = null, this.status == this.PENDING && (this.println('Test timed out.'), this.completeTest_(this.FAILED, !1));
+};, lib.TestManager.Result.prototype.requestTime = function(e) {
+  this.timeout_ && clearTimeout(this.timeout_), this.timeout_ = setTimeout(this.onTimeout_.bind(this), e);
+};, lib.TestManager.Result.prototype.completeTest_ = function(e, t) {
+  if (this.status == this.PENDING ? (this.duration = new Date - this.startDate, this.status = e, this.testRun.onResultComplete(this)) : this.testRun.onResultReComplete(this, e), arguments.length < 2 || t) throw new lib.TestManager.Result.TestComplete(this);
+};, lib.TestManager.Result.prototype.arrayEQ_ = function(e, t) {
+  if (!e || !t) return !e && !t;
+  if (e.length != t.length) return !1;
+  for (var r = 0; r < e.length; ++r)
+    if (e[r] != t[r]) return !1;
+  return !0;
+};, lib.TestManager.Result.prototype.assertEQ = function(e, t, r) {
+  function o(e) {
+    if ('number' == typeof e) return e;
+    var t = String(e),
+      r = t.split('\n').map(function(e) {
+        return JSON.stringify(e);
+      });
+    return r.length > 1 ? '\n' + r.join('\n') : r.join('\n');
+  }
+  if (e !== t && !(t instanceof Array && this.arrayEQ_(e, t))) {
+    var i = r ? '[' + r + ']' : '';
+    this.fail('assertEQ' + i + ': ' + this.getCallerLocation_(1) + ': ' + o(e) + ' !== ' + o(t));
+  }
+};, lib.TestManager.Result.prototype.assert = function(e, t) {
+  if (e !== !0) {
+    var r = t ? '[' + t + ']' : '';
+    this.fail('assert' + r + ': ' + this.getCallerLocation_(1) + ': ' + String(e));
+  }
+};, lib.TestManager.Result.prototype.getCallerLocation_ = function(e) {
+  try {
+    throw new Error;
+  }
+  catch (t) {
+    var r = t.stack.split('\n')[e + 2],
+      o = r.match(/([^\/]+:\d+):\d+\)?$/);
+    return o ? o[1] : '???';
+  }
+};, lib.TestManager.Result.prototype.println = function(e) {
+  this.testRun.log.println(e);
+};, lib.TestManager.Result.prototype.fail = function(e) {
+  arguments.length && this.println(e), this.completeTest_(this.FAILED, !0);
+};, lib.TestManager.Result.prototype.pass = function() {
+  this.completeTest_(this.PASSED, !0);
+};, lib.UTF8Decoder = function() {
+  this.bytesLeft = 0, this.codePoint = 0, this.lowerBound = 0;
+};, lib.UTF8Decoder.prototype.decode = function(e) {
+  for (var t = '', r = 0; r < e.length; r++) {
+    var o = e.charCodeAt(r);
+    if (0 == this.bytesLeft) 127 >= o ? t += e.charAt(r) : o >= 192 && 223 >= o ? (this.codePoint = o - 192, this.bytesLeft = 1, this.lowerBound = 128) : o >= 224 && 239 >= o ? (this.codePoint = o - 224, this.bytesLeft = 2, this.lowerBound = 2048) : o >= 240 && 247 >= o ? (this.codePoint = o - 240, this.bytesLeft = 3, this.lowerBound = 65536) : o >= 248 && 251 >= o ? (this.codePoint = o - 248, this.bytesLeft = 4, this.lowerBound = 2097152) : o >= 252 && 253 >= o ? (this.codePoint = o - 252, this.bytesLeft = 5, this.lowerBound = 67108864) : t += '�';
+    else if (o >= 128 && 191 >= o) {
+      if (this.bytesLeft--, this.codePoint = (this.codePoint << 6) + (o - 128), 0 == this.bytesLeft) {
+        var i = this.codePoint;
+        i < this.lowerBound || i >= 55296 && 57343 >= i || i > 1114111 ? t += '�' : 65536 > i ? t += String.fromCharCode(i) : (i -= 65536, t += String.fromCharCode(55296 + (i >>> 10 & 1023), 56320 + (1023 & i)))
+      }
+    }
+    else t += '�', this.bytesLeft = 0, r--;
+  }
+  return t;
+};, lib.decodeUTF8 = function(e) {
+  return (new lib.UTF8Decoder).decode(e);
+};, lib.encodeUTF8 = function(e) {
+  for (var t = '', r = 0; r < e.length; r++) {
+    var o = e.charCodeAt(r);
+    if (o >= 56320 && 57343 >= o) o = 65533;
+    else if (o >= 55296 && 56319 >= o)
+      if (r + 1 < e.length) {
+        var i = e.charCodeAt(r + 1);
+        i >= 56320 && 57343 >= i ? (o = 65536 + ((1023 & o) << 10) + (1023 & i), r++) : o = 65533;
+      }
+    else o = 65533;
+    var s;
+    if (127 >= o) t += e.charAt(r);
+    else
+      for (2047 >= o ? (t += String.fromCharCode(192 | o >>> 6), s = 1) : 65535 >= o ? (t += String.fromCharCode(224 | o >>> 12), s = 2) : (t += String.fromCharCode(240 | o >>> 18), s = 3); s > 0;) s--, t += String.fromCharCode(128 | o >>> 6 * s & 63);
+  }
+  return t;
+};, String.prototype.codePointAt || ! function() {
+  var e = function(e) {
+    if (null == this) throw TypeError();
+    var t = String(this),
+      r = t.length,
+      o = e ? Number(e) : 0;
+    if (o != o && (o = 0), 0 > o || o >= r) return void 0;
+    var i, s = t.charCodeAt(o);
+    return s >= 55296 && 56319 >= s && r > o + 1 && (i = t.charCodeAt(o + 1), i >= 56320 && 57343 >= i) ? 1024 * (s - 55296) + i - 56320 + 65536 : s;
+  };
+  Object.defineProperty ? Object.defineProperty(String.prototype, 'codePointAt', {
+    value: e,
+    configurable: !0,
+    writable: !0
+  }) : String.prototype.codePointAt = e;
+}(), lib.wc = {}, lib.wc.nulWidth = 0, lib.wc.controlWidth = 0, lib.wc.regardCjkAmbiguous = !1, lib.wc.cjkAmbiguousWidth = 2, lib.wc.combining = [
+  [768, 879],
+  [1155, 1158],
+  [1160, 1161],
+  [1425, 1469],
+  [1471, 1471],
+  [1473, 1474],
+  [1476, 1477],
+  [1479, 1479],
+  [1536, 1539],
+  [1552, 1557],
+  [1611, 1630],
+  [1648, 1648],
+  [1750, 1764],
+  [1767, 1768],
+  [1770, 1773],
+  [1807, 1807],
+  [1809, 1809],
+  [1840, 1866],
+  [1958, 1968],
+  [2027, 2035],
+  [2305, 2306],
+  [2364, 2364],
+  [2369, 2376],
+  [2381, 2381],
+  [2385, 2388],
+  [2402, 2403],
+  [2433, 2433],
+  [2492, 2492],
+  [2497, 2500],
+  [2509, 2509],
+  [2530, 2531],
+  [2561, 2562],
+  [2620, 2620],
+  [2625, 2626],
+  [2631, 2632],
+  [2635, 2637],
+  [2672, 2673],
+  [2689, 2690],
+  [2748, 2748],
+  [2753, 2757],
+  [2759, 2760],
+  [2765, 2765],
+  [2786, 2787],
+  [2817, 2817],
+  [2876, 2876],
+  [2879, 2879],
+  [2881, 2883],
+  [2893, 2893],
+  [2902, 2902],
+  [2946, 2946],
+  [3008, 3008],
+  [3021, 3021],
+  [3134, 3136],
+  [3142, 3144],
+  [3146, 3149],
+  [3157, 3158],
+  [3260, 3260],
+  [3263, 3263],
+  [3270, 3270],
+  [3276, 3277],
+  [3298, 3299],
+  [3393, 3395],
+  [3405, 3405],
+  [3530, 3530],
+  [3538, 3540],
+  [3542, 3542],
+  [3633, 3633],
+  [3636, 3642],
+  [3655, 3662],
+  [3761, 3761],
+  [3764, 3769],
+  [3771, 3772],
+  [3784, 3789],
+  [3864, 3865],
+  [3893, 3893],
+  [3895, 3895],
+  [3897, 3897],
+  [3953, 3966],
+  [3968, 3972],
+  [3974, 3975],
+  [3984, 3991],
+  [3993, 4028],
+  [4038, 4038],
+  [4141, 4144],
+  [4146, 4146],
+  [4150, 4151],
+  [4153, 4153],
+  [4184, 4185],
+  [4448, 4607],
+  [4959, 4959],
+  [5906, 5908],
+  [5938, 5940],
+  [5970, 5971],
+  [6002, 6003],
+  [6068, 6069],
+  [6071, 6077],
+  [6086, 6086],
+  [6089, 6099],
+  [6109, 6109],
+  [6155, 6157],
+  [6313, 6313],
+  [6432, 6434],
+  [6439, 6440],
+  [6450, 6450],
+  [6457, 6459],
+  [6679, 6680],
+  [6912, 6915],
+  [6964, 6964],
+  [6966, 6970],
+  [6972, 6972],
+  [6978, 6978],
+  [7019, 7027],
+  [7616, 7626],
+  [7678, 7679],
+  [8203, 8207],
+  [8234, 8238],
+  [8288, 8291],
+  [8298, 8303],
+  [8400, 8431],
+  [12330, 12335],
+  [12441, 12442],
+  [43014, 43014],
+  [43019, 43019],
+  [43045, 43046],
+  [64286, 64286],
+  [65024, 65039],
+  [65056, 65059],
+  [65279, 65279],
+  [65529, 65531],
+  [68097, 68099],
+  [68101, 68102],
+  [68108, 68111],
+  [68152, 68154],
+  [68159, 68159],
+  [119143, 119145],
+  [119155, 119170],
+  [119173, 119179],
+  [119210, 119213],
+  [119362, 119364],
+  [917505, 917505],
+  [917536, 917631],
+  [917760, 917999]
+], lib.wc.ambiguous = [
+  [161, 161],
+  [164, 164],
+  [167, 168],
+  [170, 170],
+  [174, 174],
+  [176, 180],
+  [182, 186],
+  [188, 191],
+  [198, 198],
+  [208, 208],
+  [215, 216],
+  [222, 225],
+  [230, 230],
+  [232, 234],
+  [236, 237],
+  [240, 240],
+  [242, 243],
+  [247, 250],
+  [252, 252],
+  [254, 254],
+  [257, 257],
+  [273, 273],
+  [275, 275],
+  [283, 283],
+  [294, 295],
+  [299, 299],
+  [305, 307],
+  [312, 312],
+  [319, 322],
+  [324, 324],
+  [328, 331],
+  [333, 333],
+  [338, 339],
+  [358, 359],
+  [363, 363],
+  [462, 462],
+  [464, 464],
+  [466, 466],
+  [468, 468],
+  [470, 470],
+  [472, 472],
+  [474, 474],
+  [476, 476],
+  [593, 593],
+  [609, 609],
+  [708, 708],
+  [711, 711],
+  [713, 715],
+  [717, 717],
+  [720, 720],
+  [728, 731],
+  [733, 733],
+  [735, 735],
+  [913, 929],
+  [931, 937],
+  [945, 961],
+  [963, 969],
+  [1025, 1025],
+  [1040, 1103],
+  [1105, 1105],
+  [8208, 8208],
+  [8211, 8214],
+  [8216, 8217],
+  [8220, 8221],
+  [8224, 8226],
+  [8228, 8231],
+  [8240, 8240],
+  [8242, 8243],
+  [8245, 8245],
+  [8251, 8251],
+  [8254, 8254],
+  [8308, 8308],
+  [8319, 8319],
+  [8321, 8324],
+  [8364, 8364],
+  [8451, 8451],
+  [8453, 8453],
+  [8457, 8457],
+  [8467, 8467],
+  [8470, 8470],
+  [8481, 8482],
+  [8486, 8486],
+  [8491, 8491],
+  [8531, 8532],
+  [8539, 8542],
+  [8544, 8555],
+  [8560, 8569],
+  [8592, 8601],
+  [8632, 8633],
+  [8658, 8658],
+  [8660, 8660],
+  [8679, 8679],
+  [8704, 8704],
+  [8706, 8707],
+  [8711, 8712],
+  [8715, 8715],
+  [8719, 8719],
+  [8721, 8721],
+  [8725, 8725],
+  [8730, 8730],
+  [8733, 8736],
+  [8739, 8739],
+  [8741, 8741],
+  [8743, 8748],
+  [8750, 8750],
+  [8756, 8759],
+  [8764, 8765],
+  [8776, 8776],
+  [8780, 8780],
+  [8786, 8786],
+  [8800, 8801],
+  [8804, 8807],
+  [8810, 8811],
+  [8814, 8815],
+  [8834, 8835],
+  [8838, 8839],
+  [8853, 8853],
+  [8857, 8857],
+  [8869, 8869],
+  [8895, 8895],
+  [8978, 8978],
+  [9312, 9449],
+  [9451, 9547],
+  [9552, 9587],
+  [9600, 9615],
+  [9618, 9621],
+  [9632, 9633],
+  [9635, 9641],
+  [9650, 9651],
+  [9654, 9655],
+  [9660, 9661],
+  [9664, 9665],
+  [9670, 9672],
+  [9675, 9675],
+  [9678, 9681],
+  [9698, 9701],
+  [9711, 9711],
+  [9733, 9734],
+  [9737, 9737],
+  [9742, 9743],
+  [9748, 9749],
+  [9756, 9756],
+  [9758, 9758],
+  [9792, 9792],
+  [9794, 9794],
+  [9824, 9825],
+  [9827, 9829],
+  [9831, 9834],
+  [9836, 9837],
+  [9839, 9839],
+  [10045, 10045],
+  [10102, 10111],
+  [57344, 63743],
+  [65533, 65533],
+  [983040, 1048573],
+  [1048576, 1114109]
+], lib.wc.isSpace = function(e) {
+  var t, r = 0,
+    o = lib.wc.combining.length - 1;
+  if (e < lib.wc.combining[0][0] || e > lib.wc.combining[o][1]) return !1;
+  for (; o >= r;)
+    if (t = Math.floor((r + o) / 2), e > lib.wc.combining[t][1]) r = t + 1;
+    else {
+      if (!(e < lib.wc.combining[t][0])) return !0;
+      o = t - 1;
+    }
+  return !1;
+};, lib.wc.isCjkAmbiguous = function(e) {
+  var t, r = 0,
+    o = lib.wc.ambiguous.length - 1;
+  if (e < lib.wc.ambiguous[0][0] || e > lib.wc.ambiguous[o][1]) return !1;
+  for (; o >= r;)
+    if (t = Math.floor((r + o) / 2), e > lib.wc.ambiguous[t][1]) r = t + 1;
+    else {
+      if (!(e < lib.wc.ambiguous[t][0])) return !0;
+      o = t - 1;
+    }
+  return !1;
+};, lib.wc.charWidth = function(e) {
+  return lib.wc.regardCjkAmbiguous ? lib.wc.charWidthRegardAmbiguous(e) : lib.wc.charWidthDisregardAmbiguous(e);
+};, lib.wc.charWidthDisregardAmbiguous = function(e) {
+  return 0 === e ? lib.wc.nulWidth : 32 > e || e >= 127 && 160 > e ? lib.wc.controlWidth : 127 > e ? 1 : lib.wc.isSpace(e) ? 0 : 1 + (e >= 4352 && (4447 >= e || 9001 == e || 9002 == e || e >= 11904 && 42191 >= e && 12351 != e || e >= 44032 && 55203 >= e || e >= 63744 && 64255 >= e || e >= 65040 && 65049 >= e || e >= 65072 && 65135 >= e || e >= 65280 && 65376 >= e || e >= 65504 && 65510 >= e || e >= 131072 && 196605 >= e || e >= 196608 && 262141 >= e))
+};, lib.wc.charWidthRegardAmbiguous = function(e) {
+  return lib.wc.isCjkAmbiguous(e) ? lib.wc.cjkAmbiguousWidth : lib.wc.charWidthDisregardAmbiguous(e);
+};, lib.wc.strWidth = function(e) {
+  for (var t, r = 0, o = 0; o < e.length;) {
+    var i = e.codePointAt(o);
+    if (t = lib.wc.charWidth(i), 0 > t) return -1;
+    r += t, o += 65535 >= i ? 1 : 2;
+  }
+  return r;
+};, lib.wc.substr = function(e, t, r) {
+  var o, i, s;
+  for (o = 0, s = 0; o < e.length && (s += lib.wc.charWidth(e.charCodeAt(o)), !(s > t)); o++);
+  if (void 0 != r) {
+    for (i = o, s = 0; i < e.length && r > s; s += lib.wc.charWidth(e.charCodeAt(i)), i++);
+    return s > r && i--, e.substring(o, i);
+  }
+  return e.substr(o);
+};, lib.wc.substring = function(e, t, r) {
+  return lib.wc.substr(e, t, r - t);
+};, lib.resource.add('libdot/changelog/version', 'text/plain', '1.11'), lib.resource.add('libdot/changelog/date', 'text/plain', '2017-04-17'), lib.rtdep('lib.Storage');
+var hterm = {};
+hterm.windowType = null, hterm.zoomWarningMessage = 'ZOOM != 100%', hterm.notifyCopyMessage = '✂', hterm.desktopNotificationTitle = '♪ %(title) ♪', hterm.testDeps = ['hterm.ScrollPort.Tests', 'hterm.Screen.Tests', 'hterm.Terminal.Tests', 'hterm.VT.Tests', 'hterm.VT.CannedTests'], lib.registerInit('hterm', function(e) {
+  function t(t) {
+    hterm.windowType = t.type, setTimeout(e, 0);
+  }
+
+  function r(r) {
+    r && window.chrome ? chrome.windows.get(r.windowId, null, t) : (hterm.windowType = 'normal', setTimeout(e, 0));
+  }
+  if (!hterm.defaultStorage) {
+    var o = navigator.userAgent.match(/\sChrome\/(\d\d)/),
+      i = o ? parseInt(o[1]) : -1;
+    window.chrome && chrome.storage && chrome.storage.sync && i > 21 ? hterm.defaultStorage = new lib.Storage.Chrome(chrome.storage.sync) : hterm.defaultStorage = new lib.Storage.Local;
+  }
+  var s = !1;
+  if (window.chrome && chrome.runtime && chrome.runtime.getManifest) {
+    var n = chrome.runtime.getManifest();
+    s = n.app && n.app.background;
+  }
+  s ? setTimeout(t.bind(null, {
+    type: 'popup'
+  }), 0) : window.chrome && chrome.tabs ? chrome.tabs.getCurrent(r) : setTimeout(t.bind(null, {
+    type: 'normal'
+  }), 0)
+}), hterm.getClientSize = function(e) {
+  return e.getBoundingClientRect();
+};, hterm.getClientWidth = function(e) {
+  return e.getBoundingClientRect().width;
+};, hterm.getClientHeight = function(e) {
+  return e.getBoundingClientRect().height;
+};, hterm.copySelectionToClipboard = function(e) {
+  try {
+    e.execCommand('copy');
+  }
+  catch (t) {}
+};, hterm.pasteFromClipboard = function(e) {
+  try {
+    e.execCommand('paste');
+  }
+  catch (t) {}
+};, hterm.Size = function(e, t) {
+  this.width = e, this.height = t;
+};, hterm.Size.prototype.resize = function(e, t) {
+  this.width = e, this.height = t;
+};, hterm.Size.prototype.clone = function() {
+  return new hterm.Size(this.width, this.height);
+};, hterm.Size.prototype.setTo = function(e) {
+  this.width = e.width, this.height = e.height;
+};, hterm.Size.prototype.equals = function(e) {
+  return this.width == e.width && this.height == e.height;
+};, hterm.Size.prototype.toString = function() {
+  return '[hterm.Size: ' + this.width + ', ' + this.height + ']';
+};, hterm.RowCol = function(e, t, r) {
+  this.row = e, this.column = t, this.overflow = !!r;
+};, hterm.RowCol.prototype.move = function(e, t, r) {
+  this.row = e, this.column = t, this.overflow = !!r;
+};, hterm.RowCol.prototype.clone = function() {
+  return new hterm.RowCol(this.row, this.column, this.overflow);
+};, hterm.RowCol.prototype.setTo = function(e) {
+  this.row = e.row, this.column = e.column, this.overflow = e.overflow;
+};, hterm.RowCol.prototype.equals = function(e) {
+  return this.row == e.row && this.column == e.column && this.overflow == e.overflow;
+};, hterm.RowCol.prototype.toString = function() {
+  return '[hterm.RowCol: ' + this.row + ', ' + this.column + ', ' + this.overflow + ']';
+};, lib.rtdep('lib.f'), hterm.Frame = function(e, t, r) {
+  this.terminal_ = e, this.div_ = e.div_, this.url = t, this.options = r || {}, this.iframe_ = null, this.container_ = null, this.messageChannel_ = null;
+};, hterm.Frame.prototype.onMessage_ = function(e) {
+  return 'ipc-init-ok' != e.data.name ? void console.log('Unknown message from frame:', e.data) : (this.sendTerminalInfo_(), this.messageChannel_.port1.onmessage = this.onMessage.bind(this), void this.onLoad());
+};, hterm.Frame.prototype.onMessage = function() {};, hterm.Frame.prototype.onLoad_ = function() {
+  this.messageChannel_ = new MessageChannel, this.messageChannel_.port1.onmessage = this.onMessage_.bind(this), this.messageChannel_.port1.start(), this.iframe_.contentWindow.postMessage({
+    name: 'ipc-init',
+    argv: [{
+      messagePort: this.messageChannel_.port2
+    }]
+  }, this.url, [this.messageChannel_.port2]);
+};, hterm.Frame.prototype.onLoad = function() {};, hterm.Frame.prototype.sendTerminalInfo_ = function() {
+  lib.f.getAcceptLanguages(function(e) {
+    this.postMessage('terminal-info', [{
+      acceptLanguages: e,
+      foregroundColor: this.terminal_.getForegroundColor(),
+      backgroundColor: this.terminal_.getBackgroundColor(),
+      cursorColor: this.terminal_.getCursorColor(),
+      fontSize: this.terminal_.getFontSize(),
+      fontFamily: this.terminal_.getFontFamily(),
+      baseURL: lib.f.getURL('/')
+    }]);
+  }.bind(this));
+};, hterm.Frame.prototype.onCloseClicked_ = function() {
+  this.close();
+};, hterm.Frame.prototype.close = function() {
+  this.container_ && this.container_.parentNode && (this.container_.parentNode.removeChild(this.container_), this.onClose());
+};, hterm.Frame.prototype.onClose = function() {};, hterm.Frame.prototype.postMessage = function(e, t) {
+  if (!this.messageChannel_) throw new Error('Message channel is not set up.');
+  this.messageChannel_.port1.postMessage({
+    name: e,
+    argv: t
+  });
+};, hterm.Frame.prototype.show = function() {
+  function e(e, r) {
+    return e in t.options ? t.options[e] : r;
+  }
+  var t = this,
+    t = this;
+  if (this.container_ && this.container_.parentNode) return void console.error('Frame already visible');
+  var r = '16px',
+    o = hterm.getClientSize(this.div_),
+    i = e('width', 640),
+    s = e('height', 480),
+    n = ((o.width - i) / 2, (o.height - s) / 2, this.terminal_.document_),
+    a = this.container_ = n.createElement('div');
+  a.style.cssText = 'position: absolute;display: -webkit-flex;-webkit-flex-direction: column;top: 10%;left: 4%;width: 90%;height: 80%;box-shadow: 0 0 2px ' + this.terminal_.getForegroundColor() + ';border: 2px ' + this.terminal_.getForegroundColor() + ' solid;';
+  var l = n.createElement('div');
+  l.style.cssText = 'display: -webkit-flex;-webkit-justify-content: flex-end;height: ' + r + ';background-color: ' + this.terminal_.getForegroundColor() + ';color: ' + this.terminal_.getBackgroundColor() + ';font-size: 16px;font-family: ' + this.terminal_.getFontFamily(), a.appendChild(l);
+  var h = this.iframe_ = n.createElement('iframe');
+  h.onload = this.onLoad_.bind(this), h.style.cssText = 'display: -webkit-flex;-webkit-flex: 1;width: 100%', h.setAttribute('src', this.url), h.setAttribute('seamless', !0), a.appendChild(h), this.div_.appendChild(a);
+};, lib.rtdep('hterm.Keyboard.KeyMap'), hterm.Keyboard = function(e) {
+  this.terminal = e, this.keyboardElement_ = null, this.handlers_ = [
+    ['focusout', this.onFocusOut_.bind(this)],
+    ['keydown', this.onKeyDown_.bind(this)],
+    ['keypress', this.onKeyPress_.bind(this)],
+    ['keyup', this.onKeyUp_.bind(this)],
+    ['textInput', this.onTextInput_.bind(this)]
+  ], this.keyMap = new hterm.Keyboard.KeyMap(this), this.bindings = new hterm.Keyboard.Bindings(this), this.altGrMode = 'none', this.shiftInsertPaste = !0, this.homeKeysScroll = !1, this.pageKeysScroll = !1, this.ctrlPlusMinusZeroZoom = !0, this.ctrlCCopy = !1, this.ctrlVPaste = !1, this.applicationKeypad = !1, this.applicationCursor = !1, this.backspaceSendsBackspace = !1, this.characterEncoding = 'utf-8', this.metaSendsEscape = !0, this.passMetaV = !0, this.altSendsWhat = 'escape', this.altIsMeta = !1, this.altBackspaceIsMetaBackspace = !1, this.altKeyPressed = 0, this.mediaKeysAreFKeys = !1, this.previousAltSendsWhat_ = null;
+};, hterm.Keyboard.KeyActions = {
+  CANCEL: new String('CANCEL'),
+  DEFAULT: new String('DEFAULT'),
+  PASS: new String('PASS'),
+  STRIP: new String('STRIP')
+}, hterm.Keyboard.prototype.encode = function(e) {
+  return 'utf-8' == this.characterEncoding ? this.terminal.vt.encodeUTF8(e) : e;
+};, hterm.Keyboard.prototype.installKeyboard = function(e) {
+  if (e != this.keyboardElement_) {
+    e && this.keyboardElement_ && this.installKeyboard(null);
+    for (var t = 0; t < this.handlers_.length; t++) {
+      var r = this.handlers_[t];
+      e ? e.addEventListener(r[0], r[1]) : this.keyboardElement_.removeEventListener(r[0], r[1]);
+    }
+    this.keyboardElement_ = e;
+  }
+};, hterm.Keyboard.prototype.uninstallKeyboard = function() {
+  this.installKeyboard(null);
+};, hterm.Keyboard.prototype.onTextInput_ = function(e) {
+  e.data && e.data.split('').forEach(this.terminal.onVTKeystroke.bind(this.terminal));
+};, hterm.Keyboard.prototype.onKeyPress_ = function(e) {
+  var t, r = String.fromCharCode(e.which),
+    o = r.toLowerCase();
+  if (!e.ctrlKey && !e.metaKey || 'c' != o && 'v' != o) {
+    if (e.altKey && 'browser-key' == this.altSendsWhat && 0 == e.charCode) {
+      var i = String.fromCharCode(e.keyCode);
+      e.shiftKey || (i = i.toLowerCase()), t = i.charCodeAt(0) + 128;
+    }
+    else e.charCode >= 32 && (i = e.charCode);
+    i && this.terminal.onVTKeystroke(String.fromCharCode(i)), e.preventDefault(), e.stopPropagation();
+  }
+};, hterm.Keyboard.prototype.preventChromeAppNonCtrlShiftDefault_ = function(e) {
+  window.chrome && window.chrome.app && window.chrome.app.window && (e.ctrlKey && e.shiftKey || e.preventDefault());
+};, hterm.Keyboard.prototype.onFocusOut_ = function(e) {
+  this.altKeyPressed = 0;
+};, hterm.Keyboard.prototype.onKeyUp_ = function(e) {
+  18 == e.keyCode && (this.altKeyPressed = this.altKeyPressed & ~(1 << e.location - 1)), 27 == e.keyCode && this.preventChromeAppNonCtrlShiftDefault_(e);
+};, hterm.Keyboard.prototype.onKeyDown_ = function(e) {
+  function t(s) {
+    o = s;
+    var a = r[s];
+    return 'function' == typeof a && (a = a.apply(i.keyMap, [e, r])), a === n && 'normal' != s && (a = t('normal')), a;
+  }
+  18 == e.keyCode && (this.altKeyPressed = this.altKeyPressed | 1 << e.location - 1), 27 == e.keyCode && this.preventChromeAppNonCtrlShiftDefault_(e);
+  var r = this.keyMap.keyDefs[e.keyCode];
+  if (!r) return void console.warn('No definition for keyCode: ' + e.keyCode);
+  var o = null,
+    i = this,
+    s = hterm.Keyboard.KeyActions.CANCEL,
+    n = hterm.Keyboard.KeyActions.DEFAULT,
+    a = hterm.Keyboard.KeyActions.PASS,
+    l = hterm.Keyboard.KeyActions.STRIP,
+    h = e.ctrlKey,
+    c = this.altIsMeta ? !1 : e.altKey,
+    u = this.altIsMeta ? e.altKey || e.metaKey : e.metaKey,
+    g = !/^\[\w+\]$/.test(r.keyCap);
+  switch (this.altGrMode) {
+    case 'ctrl-alt':
+      g && h && c && (h = !1, c = !1);
+      break;
+    case 'right-alt':
+      g && 2 & this.terminal.keyboard.altKeyPressed && (h = !1, c = !1);
+      break;
+    case 'left-alt':
+      g && 1 & this.terminal.keyboard.altKeyPressed && (h = !1, c = !1);
+  }
+  var d;
+  d = t(h ? 'control' : c ? 'alt' : u ? 'meta' : 'normal');
+  var p = !e.maskShiftKey && e.shiftKey,
+    m = {
+      keyCode: e.keyCode,
+      shift: e.shiftKey,
+      ctrl: h,
+      alt: c,
+      meta: u
+    },
+    b = this.bindings.getBinding(m);
+  if (b && (p = h = c = u = !1, o = 'normal', d = b.action, 'function' == typeof d && (d = d.call(this, this.terminal, m))), c && 'browser-key' == this.altSendsWhat && d == n && (d = a), d !== a && (d !== n || h || c || u) && (d === l && (c = h = !1, d = r.normal, 'function' == typeof d && (d = d.apply(this.keyMap, [e, r])), d == n && 2 == r.keyCap.length && (d = r.keyCap.substr(p ? 1 : 0, 1))), e.preventDefault(), e.stopPropagation(), d !== s)) {
+    if (d !== n && 'string' != typeof d) return void console.warn('Invalid action: ' + JSON.stringify(d));
+    if ('control' == o ? h = !1 : 'alt' == o ? c = !1 : 'meta' == o && (u = !1), '[' == d.substr(0, 2) && (c || h || p)) {
+      var f;
+      !p || c || h ? !c || p || h ? p && c && !h ? f = ';4' : !h || p || c ? p && h && !c ? f = ';6' : c && h && !p ? f = ';7' : p && c && h && (f = ';8') : f = ';5' : f = ';3' : f = ';2', d = 3 == d.length ? '[1' + f + d.substr(2, 1) : d.substr(0, d.length - 1) + f + d.substr(d.length - 1);
+    }
+    else {
+      if (d === n && (d = r.keyCap.substr(p ? 1 : 0, 1), h)) {
+        var y = r.keyCap.substr(0, 1),
+          _ = y.charCodeAt(0);
+        _ >= 64 && 95 >= _ && (d = String.fromCharCode(_ - 64));
+      }
+      if (c && '8-bit' == this.altSendsWhat && 1 == d.length) {
+        var _ = d.charCodeAt(0) + 128;
+        d = String.fromCharCode(_);
+      }(c && 'escape' == this.altSendsWhat || u && this.metaSendsEscape) && (d = '' + d);
+    }
+    this.terminal.onVTKeystroke(d);
+  }
+};, hterm.Keyboard.Bindings = function() {
+  this.bindings_ = {};
+};, hterm.Keyboard.Bindings.prototype.clear = function() {
+  this.bindings_ = {};
+};, hterm.Keyboard.Bindings.prototype.addBinding_ = function(e, t) {
+  var r = null,
+    o = this.bindings_[e.keyCode];
+  if (o)
+    for (var i = 0; i < o.length; i++)
+      if (o[i].keyPattern.matchKeyPattern(e)) {
+        r = o[i];
+        break;
+      }
+  r ? r.action = t : (r = {
+    keyPattern: e,
+    action: t
+  }, o ? (this.bindings_[e.keyCode].push(r), o.sort(function(e, t) {
+    return hterm.Keyboard.KeyPattern.sortCompare(e.keyPattern, t.keyPattern);
+  })) : this.bindings_[e.keyCode] = [r]);
+};, hterm.Keyboard.Bindings.prototype.addBinding = function(e, t) {
+  if ('string' != typeof e) return void this.addBinding_(e, t);
+  var r = new hterm.Parser;
+  r.reset(e);
+  var o;
+  try {
+    o = r.parseKeySequence();
+  }
+  catch (i) {
+    return void console.error(i);
+  }
+  if (!r.isComplete()) return void console.error(r.error('Expected end of sequence: ' + o));
+  if ('string' == typeof t) {
+    r.reset(t);
+    try {
+      t = r.parseKeyAction();
+    }
+    catch (i) {
+      return void console.error(i);
+    }
+  }
+  return r.isComplete() ? void this.addBinding_(new hterm.Keyboard.KeyPattern(o), t) : void console.error(r.error('Expected end of sequence: ' + o));
+};, hterm.Keyboard.Bindings.prototype.addBindings = function(e) {
+  for (var t in e) this.addBinding(t, e[t]);
+};, hterm.Keyboard.Bindings.prototype.getBinding = function(e) {
+  var t = this.bindings_[e.keyCode];
+  if (!t) return null;
+  for (var r = 0; r < t.length; r++) {
+    var o = t[r];
+    if (o.keyPattern.matchKeyDown(e)) return o;
+  }
+  return null;
+};, lib.rtdep('hterm.Keyboard.KeyActions'), hterm.Keyboard.KeyMap = function(e) {
+  this.keyboard = e, this.keyDefs = {}, this.reset();
+};, hterm.Keyboard.KeyMap.prototype.addKeyDef = function(e, t) {
+  e in this.keyDefs && console.warn('Duplicate keyCode: ' + e), this.keyDefs[e] = t;
+};, hterm.Keyboard.KeyMap.prototype.addKeyDefs = function(e) {
+  for (var t = 0; t < arguments.length; t++) this.addKeyDef(arguments[t][0], {
+    keyCap: arguments[t][1],
+    normal: arguments[t][2],
+    control: arguments[t][3],
+    alt: arguments[t][4],
+    meta: arguments[t][5]
+  });
+};, hterm.Keyboard.KeyMap.prototype.reset = function() {
+  function e(e, t, r) {
+    return 'function' == typeof e ? e.apply(h, [t, r]) : e;
+  }
+
+  function t(t, r) {
+    return function(o, i) {
+      var s = o.shiftKey || o.ctrlKey || o.altKey || o.metaKey || !h.keyboard.applicationCursor ? t : r;
+      return e(s, o, i);
+    }
+  }
+
+  function r(t, r) {
+    return function(o, i) {
+      var s = h.keyboard.backspaceSendsBackspace ? r : t;
+      return e(s, o, i);
+    }
+  }
+
+  function o(t, r) {
+    return function(o, i) {
+      var s = o.shiftKey ? r : t;
+      return o.maskShiftKey = !0, e(s, o, i);
+    }
+  }
+
+  function i(t, r) {
+    return function(o, i) {
+      var s = o.altKey ? r : t;
+      return e(s, o, i);
+    }
+  }
+
+  function s(t, r) {
+    return function(o, i) {
+      var s = o.shiftKey || o.ctrlKey || o.altKey || o.metaKey ? r : t;
+      return e(s, o, i);
+    }
+  }
+
+  function n(e) {
+    return String.fromCharCode(e.charCodeAt(0) - 64);
+  }
+
+  function a(e) {
+    return function(t, r) {
+      return this[e](t, r);
+    }
+  }
+
+  function l(t) {
+    return function(r, o) {
+      return h.keyboard.mediaKeysAreFKeys ? e(t, r, o) : 166 == r.keyCode || 167 == r.keyCode || 168 == r.keyCode ? hterm.Keyboard.KeyActions.CANCEL : hterm.Keyboard.KeyActions.PASS
+    }
+  }
+  this.keyDefs = {};
+  var h = this,
+    c = '',
+    u = '[',
+    g = 'O',
+    d = hterm.Keyboard.KeyActions.CANCEL,
+    p = hterm.Keyboard.KeyActions.DEFAULT,
+    m = hterm.Keyboard.KeyActions.PASS,
+    b = hterm.Keyboard.KeyActions.STRIP;
+  this.addKeyDefs([0, '[UNKNOWN]', m, m, m, m], [27, '[ESC]', c, p, p, p], [112, '[F1]', s(g + 'P', u + 'P'), p, u + '23~', p], [113, '[F2]', s(g + 'Q', u + 'Q'), p, u + '24~', p], [114, '[F3]', s(g + 'R', u + 'R'), p, u + '25~', p], [115, '[F4]', s(g + 'S', u + 'S'), p, u + '26~', p], [116, '[F5]', u + '15~', p, u + '28~', p], [117, '[F6]', u + '17~', p, u + '29~', p], [118, '[F7]', u + '18~', p, u + '31~', p], [119, '[F8]', u + '19~', p, u + '32~', p], [120, '[F9]', u + '20~', p, u + '33~', p], [121, '[F10]', u + '21~', p, u + '34~', p], [122, '[F11]', u + '23~', p, u + '42~', p], [123, '[F12]', u + '24~', p, u + '43~', p], [192, '`~', p, o(n('@'), n('^')), p, m], [49, '1!', p, a('onCtrlNum_'), a('onAltNum_'), a('onMetaNum_')], [50, '2@', p, a('onCtrlNum_'), a('onAltNum_'), a('onMetaNum_')], [51, '3#', p, a('onCtrlNum_'), a('onAltNum_'), a('onMetaNum_')], [52, '4$', p, a('onCtrlNum_'), a('onAltNum_'), a('onMetaNum_')], [53, '5%', p, a('onCtrlNum_'), a('onAltNum_'), a('onMetaNum_')], [54, '6^', p, a('onCtrlNum_'), a('onAltNum_'), a('onMetaNum_')], [55, '7&', p, a('onCtrlNum_'), a('onAltNum_'), a('onMetaNum_')], [56, '8*', p, a('onCtrlNum_'), a('onAltNum_'), a('onMetaNum_')], [57, '9(', p, a('onCtrlNum_'), a('onAltNum_'), a('onMetaNum_')], [48, '0)', p, a('onPlusMinusZero_'), a('onAltNum_'), a('onPlusMinusZero_')], [189, '-_', p, a('onPlusMinusZero_'), p, a('onPlusMinusZero_')], [187, '=+', p, a('onPlusMinusZero_'), p, a('onPlusMinusZero_')], [173, '-_', p, a('onPlusMinusZero_'), p, a('onPlusMinusZero_')], [61, '=+', p, a('onPlusMinusZero_'), p, a('onPlusMinusZero_')], [171, '+*', p, a('onPlusMinusZero_'), p, a('onPlusMinusZero_')], [8, '[BKSP]', r('', '\b'), r('\b', ''), p, p], [9, '[TAB]', o('	', u + 'Z'), b, m, p], [81, 'qQ', p, n('Q'), p, p], [87, 'wW', p, n('W'), p, p], [69, 'eE', p, n('E'), p, p], [82, 'rR', p, n('R'), p, p], [84, 'tT', p, n('T'), p, p], [89, 'yY', p, n('Y'), p, p], [85, 'uU', p, n('U'), p, p], [73, 'iI', p, n('I'), p, p], [79, 'oO', p, n('O'), p, p], [80, 'pP', p, n('P'), p, p], [219, '[{', p, n('['), p, p], [221, ']}', p, n(']'), p, p], [220, '\\|', p, n('\\'), p, p], [20, '[CAPS]', m, m, m, p], [65, 'aA', p, n('A'), p, p], [83, 'sS', p, n('S'), p, p], [68, 'dD', p, n('D'), p, p], [70, 'fF', p, n('F'), p, p], [71, 'gG', p, n('G'), p, p], [72, 'hH', p, n('H'), p, p], [74, 'jJ', p, o(n('J'), m), p, p], [75, 'kK', p, o(n('K'), a('onClear_')), p, p], [76, 'lL', p, o(n('L'), m), p, p], [186, ';:', p, b, p, p], [222, "'\"", p, b, p, p], [13, '[ENTER]', '\r', d, d, p], [16, '[SHIFT]', m, m, m, p], [90, 'zZ', p, n('Z'), p, p], [88, 'xX', p, n('X'), p, p], [67, 'cC', p, a('onCtrlC_'), p, a('onMetaC_')], [86, 'vV', p, a('onCtrlV_'), p, a('onMetaV_')], [66, 'bB', p, o(n('B'), m), p, o(p, m)], [78, 'nN', p, a('onCtrlN_'), p, a('onMetaN_')], [77, 'mM', p, n('M'), p, p], [188, ',<', p, i(b, m), p, p], [190, '.>', p, i(b, m), p, p], [191, '/?', p, o(n('_'), n('?')), p, p], [17, '[CTRL]', m, m, m, m], [18, '[ALT]', m, m, m, m], [91, '[LAPL]', m, m, m, m], [32, ' ', p, n('@'), p, p], [92, '[RAPL]', m, m, m, m], [93, '[RMENU]', m, m, m, m], [42, '[PRTSCR]', m, m, m, m], [145, '[SCRLK]', m, m, m, m], [19, '[BREAK]', m, m, m, m], [45, '[INSERT]', a('onKeyInsert_'), p, p, p], [36, '[HOME]', a('onKeyHome_'), p, p, p], [33, '[PGUP]', a('onKeyPageUp_'), p, p, p], [46, '[DEL]', a('onKeyDel_'), p, p, p], [35, '[END]', a('onKeyEnd_'), p, p, p], [34, '[PGDOWN]', a('onKeyPageDown_'), p, p, p], [38, '[UP]', t(u + 'A', g + 'A'), p, p, p], [40, '[DOWN]', t(u + 'B', g + 'B'), p, p, p], [39, '[RIGHT]', t(u + 'C', g + 'C'), p, p, p], [37, '[LEFT]', t(u + 'D', g + 'D'), p, p, p], [144, '[NUMLOCK]', m, m, m, m], [96, '[KP0]', p, p, p, p], [97, '[KP1]', p, p, p, p], [98, '[KP2]', p, p, p, p], [99, '[KP3]', p, p, p, p], [100, '[KP4]', p, p, p, p], [101, '[KP5]', p, p, p, p], [102, '[KP6]', p, p, p, p], [103, '[KP7]', p, p, p, p], [104, '[KP8]', p, p, p, p], [105, '[KP9]', p, p, p, p], [107, '[KP+]', p, a('onPlusMinusZero_'), p, a('onPlusMinusZero_')], [109, '[KP-]', p, a('onPlusMinusZero_'), p, a('onPlusMinusZero_')], [106, '[KP*]', p, p, p, p], [111, '[KP/]', p, p, p, p], [110, '[KP.]', p, p, p, p], [166, '[BACK]', l(s(g + 'P', u + 'P')), p, u + '23~', p], [167, '[FWD]', l(s(g + 'Q', u + 'Q')), p, u + '24~', p], [168, '[RELOAD]', l(s(g + 'R', u + 'R')), p, u + '25~', p], [183, '[FSCR]', l(s(g + 'S', u + 'S')), p, u + '26~', p], [182, '[WINS]', l(u + '15~'), p, u + '28~', p], [216, '[BRIT-]', l(u + '17~'), p, u + '29~', p], [217, '[BRIT+]', l(u + '18~'), p, u + '31~', p]);
+};, hterm.Keyboard.KeyMap.prototype.onKeyInsert_ = function(e) {
+  return this.keyboard.shiftInsertPaste && e.shiftKey ? hterm.Keyboard.KeyActions.PASS : '[2~';
+};, hterm.Keyboard.KeyMap.prototype.onKeyHome_ = function(e) {
+  return !this.keyboard.homeKeysScroll ^ e.shiftKey ? e.altey || e.ctrlKey || e.shiftKey || !this.keyboard.applicationCursor ? '' : 'OH' : (this.keyboard.terminal.scrollHome(), hterm.Keyboard.KeyActions.CANCEL);
+};, hterm.Keyboard.KeyMap.prototype.onKeyEnd_ = function(e) {
+  return !this.keyboard.homeKeysScroll ^ e.shiftKey ? e.altKey || e.ctrlKey || e.shiftKey || !this.keyboard.applicationCursor ? '' : 'OF' : (this.keyboard.terminal.scrollEnd(), hterm.Keyboard.KeyActions.CANCEL);
+};, hterm.Keyboard.KeyMap.prototype.onKeyPageUp_ = function(e) {
+  return !this.keyboard.pageKeysScroll ^ e.shiftKey ? '[5~' : (this.keyboard.terminal.scrollPageUp(), hterm.Keyboard.KeyActions.CANCEL);
+};, hterm.Keyboard.KeyMap.prototype.onKeyDel_ = function(e) {
+  return this.keyboard.altBackspaceIsMetaBackspace && this.keyboard.altKeyPressed && !e.altKey ? '' : '[3~';
+};, hterm.Keyboard.KeyMap.prototype.onKeyPageDown_ = function(e) {
+  return !this.keyboard.pageKeysScroll ^ e.shiftKey ? '[6~' : (this.keyboard.terminal.scrollPageDown(), hterm.Keyboard.KeyActions.CANCEL);
+};, hterm.Keyboard.KeyMap.prototype.onClear_ = function(e, t) {
+  return this.keyboard.terminal.wipeContents(), hterm.Keyboard.KeyActions.CANCEL;
+};, hterm.Keyboard.KeyMap.prototype.onCtrlNum_ = function(e, t) {
+  function r(e) {
+    return String.fromCharCode(e.charCodeAt(0) - 64);
+  }
+  if (this.keyboard.terminal.passCtrlNumber && !e.shiftKey) return hterm.Keyboard.KeyActions.PASS;
+  switch (t.keyCap.substr(0, 1)) {
+    case '1':
+      return '1';
+    case '2':
+      return r('@');
+    case '3':
+      return r('[');
+    case '4':
+      return r('\\');
+    case '5':
+      return r(']');
+    case '6':
+      return r('^');
+    case '7':
+      return r('_');
+    case '8':
+      return '';
+    case '9':
+      return '9';
+  }
+};, hterm.Keyboard.KeyMap.prototype.onAltNum_ = function(e, t) {
+  return this.keyboard.terminal.passAltNumber && !e.shiftKey ? hterm.Keyboard.KeyActions.PASS : hterm.Keyboard.KeyActions.DEFAULT;
+};, hterm.Keyboard.KeyMap.prototype.onMetaNum_ = function(e, t) {
+  return this.keyboard.terminal.passMetaNumber && !e.shiftKey ? hterm.Keyboard.KeyActions.PASS : hterm.Keyboard.KeyActions.DEFAULT;
+};, hterm.Keyboard.KeyMap.prototype.onCtrlC_ = function(e, t) {
+  var r = this.keyboard.terminal.getDocument().getSelection();
+  if (!r.isCollapsed) {
+    if (this.keyboard.ctrlCCopy && !e.shiftKey) return this.keyboard.terminal.clearSelectionAfterCopy && setTimeout(r.collapseToEnd.bind(r), 50), hterm.Keyboard.KeyActions.PASS;
+    if (!this.keyboard.ctrlCCopy && e.shiftKey) return this.keyboard.terminal.clearSelectionAfterCopy && setTimeout(r.collapseToEnd.bind(r), 50), this.keyboard.terminal.copySelectionToClipboard(), hterm.Keyboard.KeyActions.CANCEL;
+  }
+  return '';
+};, hterm.Keyboard.KeyMap.prototype.onCtrlN_ = function(e, t) {
+  return e.shiftKey ? (window.open(document.location.href, '', 'chrome=no,close=yes,resize=yes,scrollbars=yes,minimizable=yes,width=' + window.innerWidth + ',height=' + window.innerHeight), hterm.Keyboard.KeyActions.CANCEL) : '';
+};, hterm.Keyboard.KeyMap.prototype.onCtrlV_ = function(e, t) {
+  return !e.shiftKey && this.keyboard.ctrlVPaste || e.shiftKey && !this.keyboard.ctrlVPaste ? hterm.Keyboard.KeyActions.PASS : '';
+};, hterm.Keyboard.KeyMap.prototype.onMetaN_ = function(e, t) {
+  return e.shiftKey ? (window.open(document.location.href, '', 'chrome=no,close=yes,resize=yes,scrollbars=yes,minimizable=yes,width=' + window.outerWidth + ',height=' + window.outerHeight), hterm.Keyboard.KeyActions.CANCEL) : hterm.Keyboard.KeyActions.DEFAULT;
+};, hterm.Keyboard.KeyMap.prototype.onMetaC_ = function(e, t) {
+  var r = this.keyboard.terminal.getDocument();
+  return e.shiftKey || r.getSelection().isCollapsed ? t.keyCap.substr(e.shiftKey ? 1 : 0, 1) : (this.keyboard.terminal.clearSelectionAfterCopy && setTimeout(function() {
+    r.getSelection().collapseToEnd();
+  }, 50), hterm.Keyboard.KeyActions.PASS);
+};, hterm.Keyboard.KeyMap.prototype.onMetaV_ = function(e, t) {
+  return e.shiftKey ? hterm.Keyboard.KeyActions.PASS : this.keyboard.passMetaV ? hterm.Keyboard.KeyActions.PASS : hterm.Keyboard.KeyActions.DEFAULT
+};, hterm.Keyboard.KeyMap.prototype.onPlusMinusZero_ = function(e, t) {
+  if (!(this.keyboard.ctrlPlusMinusZeroZoom ^ e.shiftKey)) return '-_' == t.keyCap ? '' : hterm.Keyboard.KeyActions.CANCEL;
+  if (1 != this.keyboard.terminal.getZoomFactor()) return hterm.Keyboard.KeyActions.PASS;
+  var r = t.keyCap.substr(0, 1);
+  if ('0' == r) this.keyboard.terminal.setFontSize(0);
+  else {
+    var o = this.keyboard.terminal.getFontSize();
+    '-' == r || '[KP-]' == t.keyCap ? o -= 1 : o += 1, this.keyboard.terminal.setFontSize(o);
+  }
+  return hterm.Keyboard.KeyActions.CANCEL;
+};, hterm.Keyboard.KeyPattern = function(e) {
+  this.wildcardCount = 0, this.keyCode = e.keyCode, hterm.Keyboard.KeyPattern.modifiers.forEach(function(t) {
+    this[t] = e[t] || !1, '*' == this[t] && this.wildcardCount++;
+  }.bind(this));
+};, hterm.Keyboard.KeyPattern.modifiers = ['shift', 'ctrl', 'alt', 'meta'], hterm.Keyboard.KeyPattern.sortCompare = function(e, t) {
+  return e.wildcardCount < t.wildcardCount ? -1 : e.wildcardCount > t.wildcardCount ? 1 : 0
+};, hterm.Keyboard.KeyPattern.prototype.match_ = function(e, t) {
+  if (this.keyCode != e.keyCode) return !1;
+  var r = !0;
+  return hterm.Keyboard.KeyPattern.modifiers.forEach(function(o) {
+    var i = o in e ? e[o] : !1;
+    r && (t || '*' != this[o]) && this[o] != i && (r = !1);
+  }.bind(this)), r;
+};, hterm.Keyboard.KeyPattern.prototype.matchKeyDown = function(e) {
+  return this.match_(e, !1);
+};, hterm.Keyboard.KeyPattern.prototype.matchKeyPattern = function(e) {
+  return this.match_(e, !0);
+};, hterm.Options = function(e) {
+  this.wraparound = e ? e.wraparound : !0, this.reverseWraparound = e ? e.reverseWraparound : !1, this.originMode = e ? e.originMode : !1, this.autoCarriageReturn = e ? e.autoCarriageReturn : !1, this.cursorVisible = e ? e.cursorVisible : !1, this.cursorBlink = e ? e.cursorBlink : !1, this.insertMode = e ? e.insertMode : !1, this.reverseVideo = e ? e.reverseVideo : !1, this.bracketedPaste = e ? e.bracketedPaste : !1;
+};, lib.rtdep('hterm.Keyboard.KeyActions'), hterm.Parser = function() {
+  this.source = '', this.pos = 0, this.ch = null;
+};, hterm.Parser.prototype.error = function(e) {
+  return new Error('Parse error at ' + this.pos + ': ' + e);
+};, hterm.Parser.prototype.isComplete = function() {
+  return this.pos == this.source.length;
+};, hterm.Parser.prototype.reset = function(e, t) {
+  this.source = e, this.pos = t || 0, this.ch = e.substr(0, 1);
+};, hterm.Parser.prototype.parseKeySequence = function() {
+  var e = {
+    keyCode: null
+  };
+  for (var t in hterm.Parser.identifiers.modifierKeys) e[hterm.Parser.identifiers.modifierKeys[t]] = !1;
+  for (; this.pos < this.source.length;) {
+    this.skipSpace();
+    var r = this.parseToken();
+    if ('integer' == r.type) e.keyCode = r.value;
+    else if ('identifier' == r.type)
+      if (r.value in hterm.Parser.identifiers.modifierKeys) {
+        var o = hterm.Parser.identifiers.modifierKeys[r.value];
+        if (e[o] && '*' != e[o]) throw this.error('Duplicate modifier: ' + r.value);
+        e[o] = !0;
+      }
+    else {
+      if (!(r.value in hterm.Parser.identifiers.keyCodes)) throw this.error('Unknown key: ' + r.value);
+      e.keyCode = hterm.Parser.identifiers.keyCodes[r.value];
+    }
+    else {
+      if ('symbol' != r.type) throw this.error('Expected integer or identifier');
+      if ('*' != r.value) throw this.error('Unexpected symbol: ' + r.value);
+      for (var i in hterm.Parser.identifiers.modifierKeys) {
+        var s = hterm.Parser.identifiers.modifierKeys[i];
+        e[s] || (e[s] = '*');
+      }
+    }
+    if (this.skipSpace(), '-' != this.ch) break;
+    if (null != e.keyCode) throw this.error('Extra definition after target key');
+    this.advance(1);
+  }
+  if (null == e.keyCode) throw this.error('Missing target key');
+  return e;
+};, hterm.Parser.prototype.parseKeyAction = function() {
+  this.skipSpace();
+  var e = this.parseToken();
+  if ('string' == e.type) return e.value;
+  if ('identifier' == e.type) {
+    if (e.value in hterm.Parser.identifiers.actions) return hterm.Parser.identifiers.actions[e.value];
+    throw this.error('Unknown key action: ' + e.value);
+  }
+  throw this.error('Expected string or identifier');
+};, hterm.Parser.prototype.peekString = function() {
+  return "'" == this.ch || '"' == this.ch;
+};, hterm.Parser.prototype.peekIdentifier = function() {
+  return this.ch.match(/[a-z_]/i);
+};, hterm.Parser.prototype.peekInteger = function() {
+  return this.ch.match(/[0-9]/);
+};, hterm.Parser.prototype.parseToken = function() {
+  if ('*' == this.ch) {
+    var e = {
+      type: 'symbol',
+      value: this.ch
+    };
+    return this.advance(1), e;
+  }
+  if (this.peekIdentifier()) return {
+    type: 'identifier',
+    value: this.parseIdentifier()
+  };
+  if (this.peekString()) return {
+    type: 'string',
+    value: this.parseString()
+  };
+  if (this.peekInteger()) return {
+    type: 'integer',
+    value: this.parseInteger()
+  };
+  throw this.error('Unexpected token');
+};, hterm.Parser.prototype.parseIdentifier = function() {
+  if (!this.peekIdentifier()) throw this.error('Expected identifier');
+  return this.parsePattern(/[a-z0-9_]+/gi);
+};, hterm.Parser.prototype.parseInteger = function() {
+  return '0' == this.ch && this.pos < this.source.length - 1 && 'x' == this.source.substr(this.pos + 1, 1) ? parseInt(this.parsePattern(/0x[0-9a-f]+/gi)) : parseInt(this.parsePattern(/\d+/g));
+};, hterm.Parser.prototype.parseString = function() {
+  var e = '',
+    t = this.ch;
+  if ('"' != t && "'" != t) throw this.error('String expected');
+  this.advance(1);
+  for (var r = new RegExp('[\\\\' + t + ']', 'g'); this.pos < this.source.length;) {
+    if (r.lastIndex = this.pos, !r.exec(this.source)) throw this.error('Unterminated string literal');
+    if (e += this.source.substring(this.pos, r.lastIndex - 1), this.advance(r.lastIndex - this.pos - 1), '"' != t || '\\' != this.ch)
+      if ("'" != t || '\\' != this.ch) {
+        if (this.ch == t) return this.advance(1), e;
+      }
+    else e += this.ch, this.advance(1);
+    else this.advance(1), e += this.parseEscape();
+  }
+  throw this.error('Unterminated string literal');
+};, hterm.Parser.prototype.parseEscape = function() {
+  var e = {
+    '"': '"',
+    "'": "'",
+    '\\': '\\',
+    a: '',
+    b: '\b',
+    e: '',
+    f: '\f',
+    n: '\n',
+    r: '\r',
+    t: '	',
+    v: '',
+    x: function() {
+      var e = this.parsePattern(/[a-z0-9]{2}/gi);
+      return String.fromCharCode(parseInt(e, 16));
+    },
+    u: function() {
+      var e = this.parsePattern(/[a-z0-9]{4}/gi);
+      return String.fromCharCode(parseInt(e, 16));
+    }
+  };
+  if (!(this.ch in e)) throw this.error('Unknown escape: ' + this.ch);
+  var t = e[this.ch];
+  return this.advance(1), 'function' == typeof t && (t = t.call(this)), t;
+};, hterm.Parser.prototype.parsePattern = function(e) {
+  if (!e.global) throw this.error('Internal error: Span patterns must be global');
+  e.lastIndex = this.pos;
+  var t = e.exec(this.source);
+  if (!t || e.lastIndex - t[0].length != this.pos) throw this.error('Expected match for: ' + e);
+  return this.pos = e.lastIndex - 1, this.advance(1), t[0];
+};, hterm.Parser.prototype.advance = function(e) {
+  this.pos += e, this.ch = this.source.substr(this.pos, 1);
+};, hterm.Parser.prototype.skipSpace = function(e) {
+  if (/\s/.test(this.ch)) {
+    var t = /\s+/gm;
+    t.lastIndex = this.pos;
+    var r = this.source;
+    if (t.exec(r) && (this.pos = t.lastIndex), this.ch = this.source.substr(this.pos, 1), e && -1 == this.ch.indexOf(e)) throw this.error('Expected one of ' + e + ', found: ' + this.ch);
+  }
+};, hterm.Parser.identifiers = {}, hterm.Parser.identifiers.modifierKeys = {
+  Shift: 'shift',
+  Ctrl: 'ctrl',
+  Alt: 'alt',
+  Meta: 'meta'
+}, hterm.Parser.identifiers.keyCodes = {
+  ESC: 27,
+  F1: 112,
+  F2: 113,
+  F3: 114,
+  F4: 115,
+  F5: 116,
+  F6: 117,
+  F7: 118,
+  F8: 119,
+  F9: 120,
+  F10: 121,
+  F11: 122,
+  F12: 123,
+  ONE: 49,
+  TWO: 50,
+  THREE: 51,
+  FOUR: 52,
+  FIVE: 53,
+  SIX: 54,
+  SEVEN: 55,
+  EIGHT: 56,
+  NINE: 57,
+  ZERO: 48,
+  BACKSPACE: 8,
+  TAB: 9,
+  Q: 81,
+  W: 87,
+  E: 69,
+  R: 82,
+  T: 84,
+  Y: 89,
+  U: 85,
+  I: 73,
+  O: 79,
+  P: 80,
+  CAPSLOCK: 20,
+  A: 65,
+  S: 83,
+  D: 68,
+  F: 70,
+  G: 71,
+  H: 72,
+  J: 74,
+  K: 75,
+  L: 76,
+  ENTER: 13,
+  Z: 90,
+  X: 88,
+  C: 67,
+  V: 86,
+  B: 66,
+  N: 78,
+  M: 77,
+  SPACE: 32,
+  PRINT_SCREEN: 42,
+  SCROLL_LOCK: 145,
+  BREAK: 19,
+  INSERT: 45,
+  HOME: 36,
+  PGUP: 33,
+  DEL: 46,
+  END: 35,
+  PGDOWN: 34,
+  UP: 38,
+  DOWN: 40,
+  RIGHT: 39,
+  LEFT: 37,
+  NUMLOCK: 144,
+  KP0: 96,
+  KP1: 97,
+  KP2: 98,
+  KP3: 99,
+  KP4: 100,
+  KP5: 101,
+  KP6: 102,
+  KP7: 103,
+  KP8: 104,
+  KP9: 105,
+  KP_PLUS: 107,
+  KP_MINUS: 109,
+  KP_STAR: 106,
+  KP_DIVIDE: 111,
+  KP_DECIMAL: 110,
+  NAVIGATE_BACK: 166,
+  NAVIGATE_FORWARD: 167,
+  RELOAD: 168,
+  FULL_SCREEN: 183,
+  WINDOW_OVERVIEW: 182,
+  BRIGHTNESS_UP: 216,
+  BRIGHTNESS_DOWN: 217
+}, hterm.Parser.identifiers.actions = {
+  CANCEL: hterm.Keyboard.KeyActions.CANCEL,
+  DEFAULT: hterm.Keyboard.KeyActions.DEFAULT,
+  PASS: hterm.Keyboard.KeyActions.PASS,
+  scrollPageUp: function(e) {
+    return e.scrollPageUp(), hterm.Keyboard.KeyActions.CANCEL;
+  },
+  scrollPageDown: function(e) {
+    return e.scrollPageDown(), hterm.Keyboard.KeyActions.CANCEL;
+  },
+  scrollToTop: function(e) {
+    return e.scrollEnd(), hterm.Keyboard.KeyActions.CANCEL;
+  },
+  scrollToBottom: function(e) {
+    return e.scrollEnd(), hterm.Keyboard.KeyActions.CANCEL;
+  },
+  clearScrollback: function(e) {
+    return e.wipeContents(), hterm.Keyboard.KeyActions.CANCEL;
+  }
+}, lib.rtdep('lib.f', 'lib.Storage'), hterm.PreferenceManager = function(e) {
+  lib.PreferenceManager.call(this, hterm.defaultStorage, '/hterm/profiles/' + e);
+  var t = hterm.PreferenceManager.defaultPreferences;
+  Object.keys(t).forEach(function(e) {
+    this.definePreference(e, t[e][1]);
+  }.bind(this));
+};, hterm.PreferenceManager.categories = {}, hterm.PreferenceManager.categories.Keyboard = 'Keyboard', hterm.PreferenceManager.categories.Appearance = 'Appearance', hterm.PreferenceManager.categories.CopyPaste = 'CopyPaste', hterm.PreferenceManager.categories.Sounds = 'Sounds', hterm.PreferenceManager.categories.Scrolling = 'Scrolling', hterm.PreferenceManager.categories.Encoding = 'Encoding', hterm.PreferenceManager.categories.Miscellaneous = 'Miscellaneous', hterm.PreferenceManager.categoryDefinitions = [{
+  id: hterm.PreferenceManager.categories.Appearance,
+  text: 'Appearance (fonts, colors, images)'
+}, {
+  id: hterm.PreferenceManager.categories.CopyPaste,
+  text: 'Copy & Paste'
+}, {
+  id: hterm.PreferenceManager.categories.Encoding,
+  text: 'Encoding'
+}, {
+  id: hterm.PreferenceManager.categories.Keyboard,
+  text: 'Keyboard'
+}, {
+  id: hterm.PreferenceManager.categories.Scrolling,
+  text: 'Scrolling'
+}, {
+  id: hterm.PreferenceManager.categories.Sounds,
+  text: 'Sounds'
+}, {
+  id: hterm.PreferenceManager.categories.Miscellaneous,
+  text: 'Misc.'
+}], hterm.PreferenceManager.defaultPreferences = {
+  'alt-gr-mode': [hterm.PreferenceManager.categories.Keyboard, null, [null, 'none', 'ctrl-alt', 'left-alt', 'right-alt'], "Select an AltGr detection hack^Wheuristic.\n\n'null': Autodetect based on navigator.language:\n      'en-us' => 'none', else => 'right-alt'\n'none': Disable any AltGr related munging.\n'ctrl-alt': Assume Ctrl+Alt means AltGr.\n'left-alt': Assume left Alt means AltGr.\n'right-alt': Assume right Alt means AltGr.\n"],
+  'alt-backspace-is-meta-backspace': [hterm.PreferenceManager.categories.Keyboard, !1, 'bool', 'If set, undoes the Chrome OS Alt-Backspace->DEL remap, so that alt-backspace indeed is alt-backspace.'],
+  'alt-is-meta': [hterm.PreferenceManager.categories.Keyboard, !1, 'bool', 'Set whether the alt key acts as a meta key or as a distinct alt key.'],
+  'alt-sends-what': [hterm.PreferenceManager.categories.Keyboard, 'escape', ['escape', '8-bit', 'browser-key'], "Controls how the alt key is handled.\n\n  escape....... Send an ESC prefix.\n  8-bit........ Add 128 to the unshifted character as in xterm.\n  browser-key.. Wait for the keypress event and see what the browser \n                says.  (This won't work well on platforms where the \n                browser performs a default action for some alt sequences.)"],
+  'audible-bell-sound': [hterm.PreferenceManager.categories.Sounds, 'lib-resource:hterm/audio/bell', 'url', 'URL of the terminal bell sound.  Empty string for no audible bell.'],
+  'desktop-notification-bell': [hterm.PreferenceManager.categories.Sounds, !1, 'bool', 'If true, terminal bells in the background will create a Web Notification. https://www.w3.org/TR/notifications/\n\nDisplaying notifications requires permission from the user. When this option is set to true, hterm will attempt to ask the user for permission if necessary. Note browsers may not show this permission request if it did not originate from a user action.\n\nChrome extensions with the "notifications" permission have permission to display notifications.'],
+  'background-color': [hterm.PreferenceManager.categories.Appearance, 'rgb(16, 16, 16)', 'color', 'The background color for text with no other color attributes.'],
+  'background-image': [hterm.PreferenceManager.categories.Appearance, '', 'string', 'CSS value of the background image.  Empty string for no image.\n\nFor example:\n  url(https://goo.gl/anedTK)\n  linear-gradient(top bottom, blue, red)'],
+  'background-size': [hterm.PreferenceManager.categories.Appearance, '', 'string', 'CSS value of the background image size.  Defaults to none.'],
+  'background-position': [hterm.PreferenceManager.categories.Appearance, '', 'string', 'CSS value of the background image position.\n\nFor example:\n  10% 10%\n  center'],
+  'backspace-sends-backspace': [hterm.PreferenceManager.categories.Keyboard, !1, 'bool', "If true, the backspace should send BS ('\\x08', aka ^H).  Otherwise the backspace key should send '\\x7f'."],
+  'character-map-overrides': [hterm.PreferenceManager.categories.Appearance, null, 'value', 'This is specified as an object. It is a sparse array, where each property is the character set code and the value is an object that is a sparse array itself. In that sparse array, each property is the received character and the value is the displayed character.\n\nFor example:\n  {"0":{"+":"\\u2192",",":"\\u2190","-":"\\u2191",".":"\\u2193", "0":"\\u2588"}}'],
+  'close-on-exit': [hterm.PreferenceManager.categories.Miscellaneous, !0, 'bool', 'Whether or not to close the window when the command exits.'],
+  'cursor-blink': [hterm.PreferenceManager.categories.Appearance, !1, 'bool', 'Whether or not to blink the cursor by default.'],
+  'cursor-blink-cycle': [hterm.PreferenceManager.categories.Appearance, [1e3, 500], 'value', 'The cursor blink rate in milliseconds.\n\nA two element array, the first of which is how long the cursor should be on, second is how long it should be off.'],
+  'cursor-color': [hterm.PreferenceManager.categories.Appearance, 'rgba(255, 0, 0, 0.5)', 'color', 'The color of the visible cursor.'],
+  'color-palette-overrides': [hterm.PreferenceManager.categories.Appearance, null, 'value', "Override colors in the default palette.\n\nThis can be specified as an array or an object.  If specified as an object it is assumed to be a sparse array, where each property is a numeric index into the color palette.\n\nValues can be specified as almost any css color value.  This includes #RGB, #RRGGBB, rgb(...), rgba(...), and any color names that are also part of the stock X11 rgb.txt file.\n\nYou can use 'null' to specify that the default value should be not be changed.  This is useful for skipping a small number of indices when the value is specified as an array."],
+  'copy-on-select': [hterm.PreferenceManager.categories.CopyPaste, !0, 'bool', 'Automatically copy mouse selection to the clipboard.'],
+  'use-default-window-copy': [hterm.PreferenceManager.categories.CopyPaste, !1, 'bool', 'Whether to use the default window copy behavior'],
+  'clear-selection-after-copy': [hterm.PreferenceManager.categories.CopyPaste, !0, 'bool', 'Whether to clear the selection after copying.'],
+  'ctrl-plus-minus-zero-zoom': [hterm.PreferenceManager.categories.Keyboard, !0, 'bool', 'If true, Ctrl-Plus/Minus/Zero controls zoom.\nIf false, Ctrl-Shift-Plus/Minus/Zero controls zoom, Ctrl-Minus sends ^_, Ctrl-Plus/Zero do nothing.'],
+  'ctrl-c-copy': [hterm.PreferenceManager.categories.Keyboard, !1, 'bool', 'Ctrl+C copies if true, send ^C to host if false.\nCtrl+Shift+C sends ^C to host if true, copies if false.'],
+  'ctrl-v-paste': [hterm.PreferenceManager.categories.Keyboard, !1, 'bool', 'Ctrl+V pastes if true, send ^V to host if false.\nCtrl+Shift+V sends ^V to host if true, pastes if false.'],
+  'east-asian-ambiguous-as-two-column': [hterm.PreferenceManager.categories.Keyboard, !1, 'bool', 'Set whether East Asian Ambiguous characters have two column width.'],
+  'enable-8-bit-control': [hterm.PreferenceManager.categories.Keyboard, !1, 'bool', "True to enable 8-bit control characters, false to ignore them.\n\nWe'll respect the two-byte versions of these control characters regardless of this setting."],
+  'enable-bold': [hterm.PreferenceManager.categories.Appearance, null, 'tristate', 'True if we should use bold weight font for text with the bold/bright attribute.  False to use the normal weight font.  Null to autodetect.'],
+  'enable-bold-as-bright': [hterm.PreferenceManager.categories.Appearance, !0, 'bool', 'True if we should use bright colors (8-15 on a 16 color palette) for any text with the bold attribute.  False otherwise.'],
+  'enable-blink': [hterm.PreferenceManager.categories.Appearance, !0, 'bool', 'True if we should respect the blink attribute.  False to ignore it.  '],
+  'enable-clipboard-notice': [hterm.PreferenceManager.categories.CopyPaste, !0, 'bool', 'Show a message in the terminal when the host writes to the clipboard.'],
+  'enable-clipboard-write': [hterm.PreferenceManager.categories.CopyPaste, !0, 'bool', 'Allow the host to write directly to the system clipboard.'],
+  'enable-dec12': [hterm.PreferenceManager.categories.Miscellaneous, !1, 'bool', "Respect the host's attempt to change the cursor blink status using DEC Private Mode 12."],
+  environment: [hterm.PreferenceManager.categories.Miscellaneous, {
+    TERM: 'xterm-256color'
+  }, 'value', 'The default environment variables, as an object.'],
+  'font-family': [hterm.PreferenceManager.categories.Appearance, '"DejaVu Sans Mono", "Everson Mono", FreeMono, "Menlo", "Terminal", monospace', 'string', 'Default font family for the terminal text.'],
+  'font-size': [hterm.PreferenceManager.categories.Appearance, 15, 'int', 'The default font size in pixels.'],
+  'font-smoothing': [hterm.PreferenceManager.categories.Appearance, 'antialiased', 'string', 'CSS font-smoothing property.'],
+  'foreground-color': [hterm.PreferenceManager.categories.Appearance, 'rgb(240, 240, 240)', 'color', 'The foreground color for text with no other color attributes.'],
+  'home-keys-scroll': [hterm.PreferenceManager.categories.Keyboard, !1, 'bool', 'If true, home/end will control the terminal scrollbar and shift home/end will send the VT keycodes.  If false then home/end sends VT codes and shift home/end scrolls.'],
+  keybindings: [hterm.PreferenceManager.categories.Keyboard, null, 'value', 'A map of key sequence to key actions.  Key sequences include zero or more modifier keys followed by a key code.  Key codes can be decimal or hexadecimal numbers, or a key identifier.  Key actions can be specified a string to send to the host, or an action identifier.  For a full list of key code and action identifiers, see https://goo.gl/8AoD09.\n\nSample keybindings:\n{ "Ctrl-Alt-K": "clearScrollback",\n  "Ctrl-Shift-L": "PASS",\n  "Ctrl-H": "\'HELLO\\n\'"\n}'],
+  'max-string-sequence': [hterm.PreferenceManager.categories.Encoding, 1e5, 'int', 'Max length of a DCS, OSC, PM, or APS sequence before we give up and ignore the code.'],
+  'media-keys-are-fkeys': [hterm.PreferenceManager.categories.Keyboard, !1, 'bool', 'If true, convert media keys to their Fkey equivalent. If false, let the browser handle the keys.'],
+  'meta-sends-escape': [hterm.PreferenceManager.categories.Keyboard, !0, 'bool', 'Set whether the meta key sends a leading escape or not.'],
+  'mouse-paste-button': [hterm.PreferenceManager.categories.CopyPaste, null, [null, 0, 1, 2, 3, 4, 5, 6], "Mouse paste button, or null to autodetect.\n\nFor autodetect, we'll try to enable middle button paste for non-X11 platforms.  On X11 we move it to button 3."],
+  'page-keys-scroll': [hterm.PreferenceManager.categories.Keyboard, !1, 'bool', 'If true, page up/down will control the terminal scrollbar and shift page up/down will send the VT keycodes.  If false then page up/down sends VT codes and shift page up/down scrolls.'],
+  'pass-alt-number': [hterm.PreferenceManager.categories.Keyboard, null, 'tristate', "Set whether we should pass Alt-1..9 to the browser.\n\nThis is handy when running hterm in a browser tab, so that you don't lose Chrome's \"switch to tab\" keyboard accelerators.  When not running in a tab it's better to send these keys to the host so they can be used in vim or emacs.\n\nIf true, Alt-1..9 will be handled by the browser.  If false, Alt-1..9 will be sent to the host.  If null, autodetect based on browser platform and window type."],
+  'pass-ctrl-number': [hterm.PreferenceManager.categories.Keyboard, null, 'tristate', "Set whether we should pass Ctrl-1..9 to the browser.\n\nThis is handy when running hterm in a browser tab, so that you don't lose Chrome's \"switch to tab\" keyboard accelerators.  When not running in a tab it's better to send these keys to the host so they can be used in vim or emacs.\n\nIf true, Ctrl-1..9 will be handled by the browser.  If false, Ctrl-1..9 will be sent to the host.  If null, autodetect based on browser platform and window type."],
+  'pass-meta-number': [hterm.PreferenceManager.categories.Keyboard, null, 'tristate', "Set whether we should pass Meta-1..9 to the browser.\n\nThis is handy when running hterm in a browser tab, so that you don't lose Chrome's \"switch to tab\" keyboard accelerators.  When not running in a tab it's better to send these keys to the host so they can be used in vim or emacs.\n\nIf true, Meta-1..9 will be handled by the browser.  If false, Meta-1..9 will be sent to the host.  If null, autodetect based on browser platform and window type."],
+  'pass-meta-v': [hterm.PreferenceManager.categories.Keyboard, !0, 'bool', 'Set whether meta-V gets passed to host.'],
+  'receive-encoding': [hterm.PreferenceManager.categories.Encoding, 'utf-8', ['utf-8', 'raw'], "Set the expected encoding for data received from the host.\n\nValid values are 'utf-8' and 'raw'."],
+  'scroll-on-keystroke': [hterm.PreferenceManager.categories.Scrolling, !0, 'bool', 'If true, scroll to the bottom on any keystroke.'],
+  'scroll-on-output': [hterm.PreferenceManager.categories.Scrolling, !1, 'bool', 'If true, scroll to the bottom on terminal output.'],
+  'scrollbar-visible': [hterm.PreferenceManager.categories.Scrolling, !0, 'bool', 'The vertical scrollbar mode.'],
+  'scroll-wheel-move-multiplier': [hterm.PreferenceManager.categories.Scrolling, 1, 'int', 'The multiplier for the pixel delta in mousewheel event caused by the scroll wheel. Alters how fast the page scrolls.'],
+  'send-encoding': [hterm.PreferenceManager.categories.Encoding, 'utf-8', ['utf-8', 'raw'], 'Set the encoding for data sent to host.'],
+  'shift-insert-paste': [hterm.PreferenceManager.categories.Keyboard, !0, 'bool', 'Shift + Insert pastes if true, sent to host if false.'],
+  'user-css': [hterm.PreferenceManager.categories.Appearance, '', 'url', 'URL of user stylesheet to include in the terminal document.']
+}, hterm.PreferenceManager.prototype = {
+  __proto__: lib.PreferenceManager.prototype
+}, hterm.PubSub = function() {
+  this.observers_ = {};
+};, hterm.PubSub.addBehavior = function(e) {
+  var t = new hterm.PubSub;
+  for (var r in hterm.PubSub.prototype) e[r] = hterm.PubSub.prototype[r].bind(t);
+};, hterm.PubSub.prototype.subscribe = function(e, t) {
+  e in this.observers_ || (this.observers_[e] = []), this.observers_[e].push(t);
+};, hterm.PubSub.prototype.unsubscribe = function(e, t) {
+  var r = this.observers_[e];
+  if (!r) throw 'Invalid subject: ' + e;
+  var o = r.indexOf(t);
+  if (0 > o) throw 'Not subscribed: ' + e;
+  r.splice(o, 1);
+};, hterm.PubSub.prototype.publish = function(e, t, r) {
+  function o(e) {
+    e < i.length - 1 && setTimeout(o, 0, e + 1), i[e](t);
+  }
+  var i = this.observers_[e];
+  i && (i = [].concat(i)), r && (i ? i.push(r) : i = [r]), i && setTimeout(o, 0, 0);
+};, lib.rtdep('lib.f', 'lib.wc', 'hterm.RowCol', 'hterm.Size', 'hterm.TextAttributes'), hterm.Screen = function(e) {
+  this.rowsArray = [], this.columnCount_ = e || 80, this.textAttributes = new hterm.TextAttributes(window.document), this.cursorPosition = new hterm.RowCol(0, 0), this.cursorRowNode_ = null, this.cursorNode_ = null, this.cursorOffset_ = null;
+};, hterm.Screen.prototype.getSize = function() {
+  return new hterm.Size(this.columnCount_, this.rowsArray.length);
+};, hterm.Screen.prototype.getHeight = function() {
+  return this.rowsArray.length;
+};, hterm.Screen.prototype.getWidth = function() {
+  return this.columnCount_;
+};, hterm.Screen.prototype.setColumnCount = function(e) {
+  this.columnCount_ = e, this.cursorPosition.column >= e && this.setCursorPosition(this.cursorPosition.row, e - 1);
+};, hterm.Screen.prototype.shiftRow = function() {
+  return this.shiftRows(1)[0];
+};, hterm.Screen.prototype.shiftRows = function(e) {
+  return this.rowsArray.splice(0, e);
+};, hterm.Screen.prototype.unshiftRow = function(e) {
+  this.rowsArray.splice(0, 0, e);
+};, hterm.Screen.prototype.unshiftRows = function(e) {
+  this.rowsArray.unshift.apply(this.rowsArray, e);
+};, hterm.Screen.prototype.popRow = function() {
+  return this.popRows(1)[0];
+};, hterm.Screen.prototype.popRows = function(e) {
+  return this.rowsArray.splice(this.rowsArray.length - e, e);
+};, hterm.Screen.prototype.pushRow = function(e) {
+  this.rowsArray.push(e);
+};, hterm.Screen.prototype.pushRows = function(e) {
+  e.push.apply(this.rowsArray, e);
+};, hterm.Screen.prototype.insertRow = function(e, t) {
+  this.rowsArray.splice(e, 0, t);
+};, hterm.Screen.prototype.insertRows = function(e, t) {
+  for (var r = 0; r < t.length; r++) this.rowsArray.splice(e + r, 0, t[r]);
+};, hterm.Screen.prototype.removeRow = function(e) {
+  return this.rowsArray.splice(e, 1)[0];
+};, hterm.Screen.prototype.removeRows = function(e, t) {
+  return this.rowsArray.splice(e, t);
+};, hterm.Screen.prototype.invalidateCursorPosition = function() {
+  this.cursorPosition.move(0, 0), this.cursorRowNode_ = null, this.cursorNode_ = null, this.cursorOffset_ = null;
+};, hterm.Screen.prototype.clearCursorRow = function() {
+  this.cursorRowNode_.innerHTML = '', this.cursorRowNode_.removeAttribute('line-overflow'), this.cursorOffset_ = 0, this.cursorPosition.column = 0, this.cursorPosition.overflow = !1;
+  var e;
+  e = this.textAttributes.isDefault() ? '' : lib.f.getWhitespace(this.columnCount_);
+  var t = this.textAttributes.inverse;
+  this.textAttributes.inverse = !1, this.textAttributes.syncColors();
+  var r = this.textAttributes.createContainer(e);
+  this.cursorRowNode_.appendChild(r), this.cursorNode_ = r, this.textAttributes.inverse = t, this.textAttributes.syncColors();
+};, hterm.Screen.prototype.commitLineOverflow = function() {
+  this.cursorRowNode_.setAttribute('line-overflow', !0);
+};, hterm.Screen.prototype.setCursorPosition = function(e, t) {
+  if (!this.rowsArray.length) return void console.warn('Attempt to set cursor position on empty screen.');
+  e >= this.rowsArray.length ? (console.error('Row out of bounds: ' + e), e = this.rowsArray.length - 1) : 0 > e && (console.error('Row out of bounds: ' + e), e = 0), t >= this.columnCount_ ? (console.error('Column out of bounds: ' + t), t = this.columnCount_ - 1) : 0 > t && (console.error('Column out of bounds: ' + t), t = 0), this.cursorPosition.overflow = !1;
+  var r = this.rowsArray[e],
+    o = r.firstChild;
+  o || (o = r.ownerDocument.createTextNode(''), r.appendChild(o));
+  var i = 0;
+  for (r == this.cursorRowNode_ ? t >= this.cursorPosition.column - this.cursorOffset_ && (o = this.cursorNode_, i = this.cursorPosition.column - this.cursorOffset_) : this.cursorRowNode_ = r, this.cursorPosition.move(e, t); o;) {
+    var s = t - i,
+      n = hterm.TextAttributes.nodeWidth(o);
+    if (!o.nextSibling || n > s) return this.cursorNode_ = o, void(this.cursorOffset_ = s);
+    i += n, o = o.nextSibling;
+  }
+};, hterm.Screen.prototype.syncSelectionCaret = function(e) {
+  try {
+    e.collapse(this.cursorNode_, this.cursorOffset_);
+  }
+  catch (t) {}
+};, hterm.Screen.prototype.splitNode_ = function(e, t) {
+  var r = e.cloneNode(!1),
+    o = e.textContent;
+  e.textContent = hterm.TextAttributes.nodeSubstr(e, 0, t), r.textContent = lib.wc.substr(o, t), r.textContent && e.parentNode.insertBefore(r, e.nextSibling), e.textContent || e.parentNode.removeChild(e);
+};, hterm.Screen.prototype.maybeClipCurrentRow = function() {
+  var e = hterm.TextAttributes.nodeWidth(this.cursorRowNode_);
+  if (e <= this.columnCount_) return void(this.cursorPosition.column >= this.columnCount_ && (this.setCursorPosition(this.cursorPosition.row, this.columnCount_ - 1), this.cursorPosition.overflow = !0));
+  var t = this.cursorPosition.column;
+  this.setCursorPosition(this.cursorPosition.row, this.columnCount_ - 1), e = hterm.TextAttributes.nodeWidth(this.cursorNode_), this.cursorOffset_ < e - 1 && (this.cursorNode_.textContent = hterm.TextAttributes.nodeSubstr(this.cursorNode_, 0, this.cursorOffset_ + 1));
+  for (var r = this.cursorRowNode_, o = this.cursorNode_.nextSibling; o;) r.removeChild(o), o = this.cursorNode_.nextSibling;
+  t < this.columnCount_ ? this.setCursorPosition(this.cursorPosition.row, t) : this.cursorPosition.overflow = !0;
+};, hterm.Screen.prototype.insertString = function(e) {
+  var t = this.cursorNode_,
+    r = t.textContent;
+  this.cursorRowNode_.removeAttribute('line-overflow');
+  var o = lib.wc.strWidth(e);
+  this.cursorPosition.column += o;
+  var i = this.cursorOffset_,
+    s = hterm.TextAttributes.nodeWidth(t) - i;
+  if (0 > s) {
+    var n = lib.f.getWhitespace(-s);
+    if (this.textAttributes.underline || this.textAttributes.strikethrough || this.textAttributes.background || this.textAttributes.wcNode || null != this.textAttributes.tileData)
+      if (3 != t.nodeType && (t.wcNode || t.tileNode || t.style.textDecoration || t.style.backgroundColor)) {
+        var a = t.ownerDocument.createTextNode(n);
+        this.cursorRowNode_.insertBefore(a, t.nextSibling), this.cursorNode_ = t = a, this.cursorOffset_ = i = -s, r = n;
+      }
+    else t.textContent = r += n;
+    else e = n + e;
+    s = 0;
+  }
+  if (this.textAttributes.matchesContainer(t)) return 0 == s ? t.textContent = r + e : 0 == i ? t.textContent = e + r : t.textContent = hterm.TextAttributes.nodeSubstr(t, 0, i) + e + hterm.TextAttributes.nodeSubstr(t, i), void(this.cursorOffset_ += o);
+  if (0 == i) {
+    var l = t.previousSibling;
+    if (l && this.textAttributes.matchesContainer(l)) return l.textContent += e, this.cursorNode_ = l, void(this.cursorOffset_ = lib.wc.strWidth(l.textContent));
+    var h = this.textAttributes.createContainer(e);
+    return this.cursorRowNode_.insertBefore(h, t), this.cursorNode_ = h, void(this.cursorOffset_ = o);
+  }
+  if (0 == s) {
+    var c = t.nextSibling;
+    if (c && this.textAttributes.matchesContainer(c)) return c.textContent = e + c.textContent, this.cursorNode_ = c, void(this.cursorOffset_ = lib.wc.strWidth(e));
+    var h = this.textAttributes.createContainer(e);
+    return this.cursorRowNode_.insertBefore(h, c), this.cursorNode_ = h, void(this.cursorOffset_ = hterm.TextAttributes.nodeWidth(h));
+  }
+  this.splitNode_(t, i);
+  var h = this.textAttributes.createContainer(e);
+  this.cursorRowNode_.insertBefore(h, t.nextSibling), this.cursorNode_ = h, this.cursorOffset_ = o;
+};, hterm.Screen.prototype.overwriteString = function(e) {
+  var t = this.columnCount_ - this.cursorPosition.column;
+  if (!t) return [e];
+  var r = lib.wc.strWidth(e);
+  return this.textAttributes.matchesContainer(this.cursorNode_) && this.cursorNode_.textContent.substr(this.cursorOffset_) == e ? (this.cursorOffset_ += r, void(this.cursorPosition.column += r)) : (this.deleteChars(Math.min(r, t)), void this.insertString(e));
+};, hterm.Screen.prototype.deleteChars = function(e) {
+  var t = this.cursorNode_,
+    r = this.cursorOffset_,
+    o = this.cursorPosition.column;
+  if (e = Math.min(e, this.columnCount_ - o), !e) return 0;
+  for (var i, s, n = e; t && e;) {
+    if (i = hterm.TextAttributes.nodeWidth(t), t.textContent = hterm.TextAttributes.nodeSubstr(t, 0, r) + hterm.TextAttributes.nodeSubstr(t, r + e), s = hterm.TextAttributes.nodeWidth(t), e -= i - s, i > r && s && i == s) {
+      var a = this.textAttributes.createContainer(' ');
+      t.parentNode.insertBefore(a, t.nextSibling), t.textContent = '', s = 0, e -= 1;
+    }
+    var l = t.nextSibling;
+    0 == s && t != this.cursorNode_ && t.parentNode.removeChild(t), t = l, r = 0;
+  }
+  if (3 != this.cursorNode_.nodeType && !this.cursorNode_.textContent) {
+    var h = this.cursorNode_;
+    if (h.previousSibling) this.cursorNode_ = h.previousSibling, this.cursorOffset_ = hterm.TextAttributes.nodeWidth(h.previousSibling);
+    else if (h.nextSibling) this.cursorNode_ = h.nextSibling, this.cursorOffset_ = 0;
+    else {
+      var c = this.cursorRowNode_.ownerDocument.createTextNode('');
+      this.cursorRowNode_.appendChild(c), this.cursorNode_ = c, this.cursorOffset_ = 0;
+    }
+    this.cursorRowNode_.removeChild(h);
+  }
+  return n;
+};, hterm.Screen.prototype.getLineStartRow_ = function(e) {
+  for (; e.previousSibling && e.previousSibling.hasAttribute('line-overflow');) e = e.previousSibling;
+  return e;
+};, hterm.Screen.prototype.getLineText_ = function(e) {
+  for (var t = ''; e && (t += e.textContent, e.hasAttribute('line-overflow'));) e = e.nextSibling;
+  return t;
+};, hterm.Screen.prototype.getXRowAncestor_ = function(e) {
+  for (; e && 'X-ROW' !== e.nodeName;) e = e.parentNode;
+  return e;
+};, hterm.Screen.prototype.getPositionWithOverflow_ = function(e, t, r) {
+  if (!t) return -1;
+  var o = this.getXRowAncestor_(t);
+  if (!o) return -1;
+  for (var i = 0; o != e;) {
+    if (i += hterm.TextAttributes.nodeWidth(e), !e.hasAttribute('line-overflow') || !e.nextSibling) return -1;
+    e = e.nextSibling;
+  }
+  return i + this.getPositionWithinRow_(e, t, r);
+};, hterm.Screen.prototype.getPositionWithinRow_ = function(e, t, r) {
+  if (t.parentNode != e) return this.getPositionWithinRow_(t.parentNode, t, r) + this.getPositionWithinRow_(e, t.parentNode, 0);
+  for (var o = 0, i = 0; i < e.childNodes.length; i++) {
+    var s = e.childNodes[i];
+    if (s == t) return o + r;
+    o += hterm.TextAttributes.nodeWidth(s);
+  }
+  return -1;
+};, hterm.Screen.prototype.getNodeAndOffsetWithOverflow_ = function(e, t) {
+  for (; e && t > hterm.TextAttributes.nodeWidth(e);) {
+    if (!e.hasAttribute('line-overflow') || !e.nextSibling) return -1;
+    t -= hterm.TextAttributes.nodeWidth(e), e = e.nextSibling;
+  }
+  return this.getNodeAndOffsetWithinRow_(e, t);
+};, hterm.Screen.prototype.getNodeAndOffsetWithinRow_ = function(e, t) {
+  for (var r = 0; r < e.childNodes.length; r++) {
+    var o = e.childNodes[r],
+      i = hterm.TextAttributes.nodeWidth(o);
+    if (i >= t) return 'SPAN' === o.nodeName ? this.getNodeAndOffsetWithinRow_(o, t) : [o, t];
+    t -= i;
+  }
+  return null;
+};, hterm.Screen.prototype.setRange_ = function(e, t, r, o) {
+  var i = this.getNodeAndOffsetWithOverflow_(e, t);
+  if (null != i) {
+    var s = this.getNodeAndOffsetWithOverflow_(e, r);
+    null != s && (o.setStart(i[0], i[1]), o.setEnd(s[0], s[1]));
+  }
+};, hterm.Screen.prototype.expandSelection = function(e) {
+  if (e) {
+    var t = e.getRangeAt(0);
+    if (t && !t.toString().match(/\s/)) {
+      var r = this.getLineStartRow_(this.getXRowAncestor_(t.startContainer));
+      if (r) {
+        var o = this.getPositionWithOverflow_(r, t.startContainer, t.startOffset);
+        if (-1 != o) {
+          var i = this.getPositionWithOverflow_(r, t.endContainer, t.endOffset);
+          if (-1 != i) {
+            var s = "[^\\s\\[\\](){}<>\"'\\^!@#$%&*,;:`]",
+              n = "[^\\s\\[\\](){}<>\"'\\^!@#$%&*,;:~.`]",
+              a = "[^\\s\\[\\](){}<>\"'\\^]*",
+              l = this.getLineText_(r),
+              h = lib.wc.substring(l, 0, i),
+              c = new RegExp(s + a + '$'),
+              u = h.search(c);
+            if (!(-1 == u || u > o)) {
+              var g = lib.wc.substring(l, o, lib.wc.strWidth(l)),
+                d = new RegExp('^' + a + n),
+                p = g.match(d);
+              if (p) {
+                var m = o + lib.wc.strWidth(p[0]); - 1 == m || i > m || (this.setRange_(r, u, m, t), e.addRange(t));
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+};, lib.rtdep('lib.f', 'hterm.PubSub', 'hterm.Size'), hterm.ScrollPort = function(e) {
+  hterm.PubSub.addBehavior(this), this.rowProvider_ = e, this.characterSize = new hterm.Size(10, 10), this.ruler_ = null, this.selection = new hterm.ScrollPort.Selection(this), this.currentRowNodeCache_ = null, this.previousRowNodeCache_ = {}, this.lastScreenWidth_ = null, this.lastScreenHeight_ = null, this.selectionEnabled_ = !0, this.lastRowCount_ = 0, this.scrollWheelMultiplier_ = 1, this.isScrolledEnd = !0, this.xrowCssRule_ = null, this.currentScrollbarWidthPx = 16, this.ctrlVPaste = !1, this.div_ = null, this.document_ = null, this.timeouts_ = {}, this.observers_ = {}, this.DEBUG_ = !1;
+};, hterm.ScrollPort.Selection = function(e) {
+  this.scrollPort_ = e, this.startRow = null, this.endRow = null, this.isMultiline = null, this.isCollapsed = null;
+};, hterm.ScrollPort.Selection.prototype.findFirstChild = function(e, t) {
+  for (var r = e.firstChild; r;) {
+    if (-1 != t.indexOf(r)) return r;
+    if (r.childNodes.length) {
+      var o = this.findFirstChild(r, t);
+      if (o) return o;
+    }
+    r = r.nextSibling;
+  }
+  return null;
+};, hterm.ScrollPort.Selection.prototype.sync = function() {
+  function e() {
+    r.startRow = i, r.startNode = o.anchorNode, r.startOffset = o.anchorOffset, r.endRow = s, r.endNode = o.focusNode, r.endOffset = o.focusOffset;
+  }
+
+  function t() {
+    r.startRow = s, r.startNode = o.focusNode, r.startOffset = o.focusOffset, r.endRow = i, r.endNode = o.anchorNode, r.endOffset = o.anchorOffset;
+  }
+  var r = this,
+    o = this.scrollPort_.getDocument().getSelection();
+  if (this.startRow = null, this.endRow = null, this.isMultiline = null, this.isCollapsed = !o || o.isCollapsed, !this.isCollapsed) {
+    for (var i = o.anchorNode; i && !('rowIndex' in i);) i = i.parentNode;
+    if (!i) return void console.error('Selection anchor is not rooted in a row node: ' + o.anchorNode.nodeName);
+    for (var s = o.focusNode; s && !('rowIndex' in s);) s = s.parentNode;
+    if (!s) return void console.error('Selection focus is not rooted in a row node: ' + o.focusNode.nodeName);
+    if (i.rowIndex < s.rowIndex) e();
+    else if (i.rowIndex > s.rowIndex) t();
+    else if (o.focusNode == o.anchorNode) o.anchorOffset < o.focusOffset ? e() : t();
+    else {
+      var n = this.findFirstChild(i, [o.anchorNode, o.focusNode]);
+      if (!n) throw new Error('Unexpected error syncing selection.');
+      n == o.anchorNode ? e() : t();
+    }
+    this.isMultiline = i.rowIndex != s.rowIndex;
+  }
+};, hterm.ScrollPort.prototype.decorate = function(e) {
+  this.div_ = e, this.iframe_ = e.ownerDocument.createElement('iframe'), this.iframe_.style.cssText = 'border: 0;height: 100%;position: absolute;width: 100%', 'mozInnerScreenX' in window && (this.iframe_.src = '#'), e.appendChild(this.iframe_), this.iframe_.contentWindow.addEventListener('resize', this.onResize_.bind(this));
+  var t = this.document_ = this.iframe_.contentDocument;
+  t.body.style.cssText = 'margin: 0px;padding: 0px;height: 100%;width: 100%;overflow: hidden;cursor: text;-webkit-user-select: none;-moz-user-select: none;';
+  var r = t.createElement('style');
+  r.textContent = 'x-row {}', t.head.appendChild(r), this.xrowCssRule_ = t.styleSheets[0].cssRules[0], this.xrowCssRule_.style.display = 'block', this.userCssLink_ = t.createElement('link'), this.userCssLink_.setAttribute('rel', 'stylesheet'), this.screen_ = t.createElement('x-screen'), this.screen_.setAttribute('role', 'textbox'), this.screen_.setAttribute('tabindex', '-1'), this.screen_.style.cssText = 'display: block;font-family: monospace;font-size: 15px;font-variant-ligatures: none;height: 100%;overflow-y: scroll; overflow-x: hidden;white-space: pre;width: 100%;outline: none !important', t.body.appendChild(this.screen_), this.screen_.addEventListener('scroll', this.onScroll_.bind(this)), this.screen_.addEventListener('mousewheel', this.onScrollWheel_.bind(this)), this.screen_.addEventListener('DOMMouseScroll', this.onScrollWheel_.bind(this)), this.screen_.addEventListener('copy', this.onCopy_.bind(this)), this.screen_.addEventListener('paste', this.onPaste_.bind(this)), t.body.addEventListener('keydown', this.onBodyKeyDown_.bind(this)), this.rowNodes_ = t.createElement('div'), this.rowNodes_.style.cssText = 'display: block;position: fixed;overflow: hidden;-webkit-user-select: text;-moz-user-select: text;', this.screen_.appendChild(this.rowNodes_), this.topSelectBag_ = t.createElement('x-select-bag'), this.topSelectBag_.style.cssText = 'display: block;overflow: hidden;white-space: pre;', this.bottomSelectBag_ = this.topSelectBag_.cloneNode(), this.topFold_ = t.createElement('x-fold'), this.topFold_.style.cssText = 'display: block;', this.rowNodes_.appendChild(this.topFold_), this.bottomFold_ = this.topFold_.cloneNode(), this.rowNodes_.appendChild(this.bottomFold_), this.scrollArea_ = t.createElement('div'), this.scrollArea_.style.cssText = 'visibility: hidden', this.screen_.appendChild(this.scrollArea_);
+  var o = 'http://www.w3.org/2000/svg';
+  this.svg_ = this.div_.ownerDocument.createElementNS(o, 'svg'), this.svg_.setAttribute('xmlns', o), this.svg_.setAttribute('version', '1.1'), this.svg_.style.cssText = 'position: absolute;top: 0;left: 0;visibility: hidden', this.pasteTarget_ = t.createElement('textarea'), this.pasteTarget_.setAttribute('tabindex', '-1'), this.pasteTarget_.style.cssText = 'position: absolute;height: 1px;width: 1px;left: 0px; bottom: 0px;opacity: 0', this.pasteTarget_.contentEditable = !0, this.screen_.appendChild(this.pasteTarget_), this.pasteTarget_.addEventListener('textInput', this.handlePasteTargetTextInput_.bind(this)), this.resize();
+};, hterm.ScrollPort.prototype.setFontFamily = function(e, t) {
+  this.screen_.style.fontFamily = e, t ? this.screen_.style.webkitFontSmoothing = t : this.screen_.style.webkitFontSmoothing = '', this.syncCharacterSize();
+};, hterm.ScrollPort.prototype.getFontFamily = function() {
+  return this.screen_.style.fontFamily;
+};, hterm.ScrollPort.prototype.setUserCss = function(e) {
+  e ? (this.userCssLink_.setAttribute('href', e), this.userCssLink_.parentNode || this.document_.head.appendChild(this.userCssLink_)) : this.userCssLink_.parentNode && this.document_.head.removeChild(this.userCssLink_);
+};, hterm.ScrollPort.prototype.focus = function() {
+  this.iframe_.focus(), this.screen_.focus();
+};, hterm.ScrollPort.prototype.getForegroundColor = function() {
+  return this.screen_.style.color;
+};, hterm.ScrollPort.prototype.setForegroundColor = function(e) {
+  this.screen_.style.color = e;
+};, hterm.ScrollPort.prototype.getBackgroundColor = function() {
+  return this.screen_.style.backgroundColor;
+};, hterm.ScrollPort.prototype.setBackgroundColor = function(e) {
+  this.screen_.style.backgroundColor = e;
+};, hterm.ScrollPort.prototype.setBackgroundImage = function(e) {
+  this.screen_.style.backgroundImage = e;
+};, hterm.ScrollPort.prototype.setBackgroundSize = function(e) {
+  this.screen_.style.backgroundSize = e;
+};, hterm.ScrollPort.prototype.setBackgroundPosition = function(e) {
+  this.screen_.style.backgroundPosition = e;
+};, hterm.ScrollPort.prototype.setCtrlVPaste = function(e) {
+  this.ctrlVPaste = e;
+};, hterm.ScrollPort.prototype.getScreenSize = function() {
+  var e = hterm.getClientSize(this.screen_);
+  return {
+    height: e.height,
+    width: e.width - this.currentScrollbarWidthPx
+  };
+};, hterm.ScrollPort.prototype.getScreenWidth = function() {
+  return this.getScreenSize().width;
+};, hterm.ScrollPort.prototype.getScreenHeight = function() {
+  return this.getScreenSize().height;
+};, hterm.ScrollPort.prototype.getDocument = function() {
+  return this.document_;
+};, hterm.ScrollPort.prototype.getScreenNode = function() {
+  return this.screen_;
+};, hterm.ScrollPort.prototype.resetCache = function() {
+  this.currentRowNodeCache_ = null, this.previousRowNodeCache_ = {};
+};, hterm.ScrollPort.prototype.setRowProvider = function(e) {
+  this.resetCache(), this.rowProvider_ = e, this.scheduleRedraw();
+};, hterm.ScrollPort.prototype.invalidate = function() {
+  for (var e = this.topFold_.nextSibling; e != this.bottomFold_;) {
+    var t = e.nextSibling;
+    e.parentElement.removeChild(e), e = t;
+  }
+  this.previousRowNodeCache_ = null;
+  var r = this.getTopRowIndex(),
+    o = this.getBottomRowIndex(r);
+  this.drawVisibleRows_(r, o);
+};, hterm.ScrollPort.prototype.scheduleInvalidate = function() {
+  if (!this.timeouts_.invalidate) {
+    var e = this;
+    this.timeouts_.invalidate = setTimeout(function() {
+      delete e.timeouts_.invalidate, e.invalidate();
+    }, 0);
+  }
+};, hterm.ScrollPort.prototype.setFontSize = function(e) {
+  this.screen_.style.fontSize = e + 'px', this.syncCharacterSize();
+};, hterm.ScrollPort.prototype.getFontSize = function() {
+  return parseInt(this.screen_.style.fontSize);
+};, hterm.ScrollPort.prototype.measureCharacterSize = function(e) {
+  var t = 100,
+    r = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
+  if (!this.ruler_) {
+    this.ruler_ = this.document_.createElement('div'), this.ruler_.style.cssText = 'position: absolute;top: 0;left: 0;visibility: hidden;height: auto !important;width: auto !important;', this.rulerSpan_ = this.document_.createElement('span');
+    for (var o = '' + r, i = 0; t - 1 > i; ++i) o += String.fromCharCode(13) + r;
+    this.rulerSpan_.innerHTML = o, this.ruler_.appendChild(this.rulerSpan_), this.rulerBaseline_ = this.document_.createElement('span'), this.rulerBaseline_.style.fontSize = '0px', this.rulerBaseline_.textContent = 'X';
+  }
+  this.rulerSpan_.style.fontWeight = e || '', this.rowNodes_.appendChild(this.ruler_);
+  var s = hterm.getClientSize(this.rulerSpan_),
+    n = new hterm.Size(s.width / r.length, s.height / t);
+  return this.ruler_.appendChild(this.rulerBaseline_), n.baseline = this.rulerBaseline_.offsetTop, this.ruler_.removeChild(this.rulerBaseline_), this.rowNodes_.removeChild(this.ruler_), this.div_.ownerDocument.body.appendChild(this.svg_), n.zoomFactor = this.svg_.currentScale, this.div_.ownerDocument.body.removeChild(this.svg_), n;
+};, hterm.ScrollPort.prototype.syncCharacterSize = function() {
+  this.characterSize = this.measureCharacterSize();
+  var e = this.characterSize.height + 'px';
+  this.xrowCssRule_.style.height = e, this.topSelectBag_.style.height = e, this.bottomSelectBag_.style.height = e, this.resize(), this.DEBUG_ && (this.document_.body.style.paddingTop = this.document_.body.style.paddingBottom = 3 * this.characterSize.height + 'px');
+};, hterm.ScrollPort.prototype.resize = function() {
+  this.currentScrollbarWidthPx = hterm.getClientWidth(this.screen_) - this.screen_.clientWidth, this.syncScrollHeight(), this.syncRowNodesDimensions_();
+  var e = this;
+  this.publish('resize', {
+    scrollPort: this
+  }, function() {
+    e.scrollRowToBottom(e.rowProvider_.getRowCount()), e.scheduleRedraw();
+  });
+};, hterm.ScrollPort.prototype.syncRowNodesDimensions_ = function() {
+  var e = this.getScreenSize();
+  this.lastScreenWidth_ = e.width, this.lastScreenHeight_ = e.height, this.visibleRowCount = lib.f.smartFloorDivide(e.height, this.characterSize.height);
+  var t = this.visibleRowCount * this.characterSize.height;
+  this.visibleRowTopMargin = 0, this.visibleRowBottomMargin = e.height - t, this.topFold_.style.marginBottom = this.visibleRowTopMargin + 'px';
+  for (var r = 0, o = this.topFold_.previousSibling; o;) r += hterm.getClientHeight(o), o = o.previousSibling;
+  this.rowNodes_.style.width = e.width + 'px', this.rowNodes_.style.height = t + r + 'px', this.rowNodes_.style.left = this.screen_.offsetLeft + 'px', this.rowNodes_.style.top = this.screen_.offsetTop - r + 'px';
+};, hterm.ScrollPort.prototype.syncScrollHeight = function() {
+  this.lastRowCount_ = this.rowProvider_.getRowCount(), this.scrollArea_.style.height = this.characterSize.height * this.lastRowCount_ + this.visibleRowTopMargin + this.visibleRowBottomMargin + 'px';
+};, hterm.ScrollPort.prototype.scheduleRedraw = function() {
+  if (!this.timeouts_.redraw) {
+    var e = this;
+    this.timeouts_.redraw = setTimeout(function() {
+      delete e.timeouts_.redraw, e.redraw_();
+    }, 0);
+  }
+};, hterm.ScrollPort.prototype.redraw_ = function() {
+  this.resetSelectBags_(), this.selection.sync(), this.syncScrollHeight(), this.currentRowNodeCache_ = {};
+  var e = this.getTopRowIndex(),
+    t = this.getBottomRowIndex(e);
+  this.drawTopFold_(e), this.drawBottomFold_(t), this.drawVisibleRows_(e, t), this.syncRowNodesDimensions_(), this.previousRowNodeCache_ = this.currentRowNodeCache_, this.currentRowNodeCache_ = null, this.isScrolledEnd = this.getTopRowIndex() + this.visibleRowCount >= this.lastRowCount_;
+};, hterm.ScrollPort.prototype.drawTopFold_ = function(e) {
+  if (!this.selection.startRow || this.selection.startRow.rowIndex >= e) return void(this.rowNodes_.firstChild != this.topFold_ && this.rowNodes_.insertBefore(this.topFold_, this.rowNodes_.firstChild));
+  if (!this.selection.isMultiline || this.selection.endRow.rowIndex >= e) this.selection.startRow.nextSibling != this.topFold_ && this.rowNodes_.insertBefore(this.topFold_, this.selection.startRow.nextSibling);
+  else
+    for (this.selection.endRow.nextSibling != this.topFold_ && this.rowNodes_.insertBefore(this.topFold_, this.selection.endRow.nextSibling); this.selection.startRow.nextSibling != this.selection.endRow;) this.rowNodes_.removeChild(this.selection.startRow.nextSibling);
+  for (; this.rowNodes_.firstChild != this.selection.startRow;) this.rowNodes_.removeChild(this.rowNodes_.firstChild);
+};, hterm.ScrollPort.prototype.drawBottomFold_ = function(e) {
+  if (!this.selection.endRow || this.selection.endRow.rowIndex <= e) return void(this.rowNodes_.lastChild != this.bottomFold_ && this.rowNodes_.appendChild(this.bottomFold_));
+  if (!this.selection.isMultiline || this.selection.startRow.rowIndex <= e) this.bottomFold_.nextSibling != this.selection.endRow && this.rowNodes_.insertBefore(this.bottomFold_, this.selection.endRow);
+  else
+    for (this.bottomFold_.nextSibling != this.selection.startRow && this.rowNodes_.insertBefore(this.bottomFold_, this.selection.startRow); this.selection.startRow.nextSibling != this.selection.endRow;) this.rowNodes_.removeChild(this.selection.startRow.nextSibling);
+  for (; this.rowNodes_.lastChild != this.selection.endRow;) this.rowNodes_.removeChild(this.rowNodes_.lastChild);
+};, hterm.ScrollPort.prototype.drawVisibleRows_ = function(e, t) {
+  function r(e, t) {
+    for (; e != t;) {
+      if (!e) throw 'Did not encounter target node';
+      if (e == o.bottomFold_) throw 'Encountered bottom fold before target node';
+      var r = e;
+      e = e.nextSibling, r.parentNode.removeChild(r);
+    }
+  }
+  for (var o = this, i = this.selection.startRow, s = this.selection.endRow, n = this.bottomFold_, a = this.topFold_.nextSibling, l = Math.min(this.visibleRowCount, this.rowProvider_.getRowCount()), h = 0; l > h; h++) {
+    var c = e + h;
+    if (a != n)
+      if (a.rowIndex != c)
+        if (i && i.rowIndex == c) r(a, i), a = i.nextSibling;
+        else if (s && s.rowIndex == c) r(a, s), a = s.nextSibling;
+    else if (a != i && a != s) {
+      var u = this.fetchRowNode_(c);
+      if (!u) {
+        console.log("Couldn't fetch row index: " + c);
+        break;
+      }
+      a != u ? (this.rowNodes_.insertBefore(u, a), !u.nextSibling, this.rowNodes_.removeChild(a), a = u.nextSibling) : a = a.nextSibling;
+    }
+    else {
+      var u = this.fetchRowNode_(c);
+      if (!u) {
+        console.log("Couldn't fetch row index: " + c);
+        break;
+      }
+      this.rowNodes_.insertBefore(u, a);
+    }
+    else a = a.nextSibling;
+    else {
+      var u = this.fetchRowNode_(c);
+      if (!u) {
+        console.log("Couldn't fetch row index: " + c);
+        break;
+      }
+      this.rowNodes_.insertBefore(u, a);
+    }
+  }
+  a != this.bottomFold_ && r(a, n);
+};, hterm.ScrollPort.prototype.resetSelectBags_ = function() {
+  this.topSelectBag_.parentNode && (this.topSelectBag_.textContent = '', this.topSelectBag_.parentNode.removeChild(this.topSelectBag_)), this.bottomSelectBag_.parentNode && (this.bottomSelectBag_.textContent = '', this.bottomSelectBag_.parentNode.removeChild(this.bottomSelectBag_));
+};, hterm.ScrollPort.prototype.cacheRowNode_ = function(e) {
+  this.currentRowNodeCache_[e.rowIndex] = e;
+};, hterm.ScrollPort.prototype.fetchRowNode_ = function(e) {
+  var t;
+  return t = this.previousRowNodeCache_ && e in this.previousRowNodeCache_ ? this.previousRowNodeCache_[e] : this.rowProvider_.getRowNode(e), this.currentRowNodeCache_ && this.cacheRowNode_(t), t;
+};, hterm.ScrollPort.prototype.selectAll = function() {
+  var e;
+  if (0 != this.topFold_.nextSibling.rowIndex) {
+    for (; this.topFold_.previousSibling;) this.rowNodes_.removeChild(this.topFold_.previousSibling);
+    e = this.fetchRowNode_(0), this.rowNodes_.insertBefore(e, this.topFold_), this.syncRowNodesDimensions_();
+  }
+  else e = this.topFold_.nextSibling;
+  var t, r = this.rowProvider_.getRowCount() - 1;
+  if (this.bottomFold_.previousSibling.rowIndex != r) {
+    for (; this.bottomFold_.nextSibling;) this.rowNodes_.removeChild(this.bottomFold_.nextSibling);
+    t = this.fetchRowNode_(r), this.rowNodes_.appendChild(t);
+  }
+  else t = this.bottomFold_.previousSibling.rowIndex;
+  var o = this.document_.getSelection();
+  o.collapse(e, 0), o.extend(t, t.childNodes.length), this.selection.sync();
+};, hterm.ScrollPort.prototype.getScrollMax_ = function(e) {
+  return hterm.getClientHeight(this.scrollArea_) + this.visibleRowTopMargin + this.visibleRowBottomMargin - hterm.getClientHeight(this.screen_);
+};, hterm.ScrollPort.prototype.scrollRowToTop = function(e) {
+  this.syncScrollHeight(), this.isScrolledEnd = e + this.visibleRowCount >= this.lastRowCount_;
+  var t = e * this.characterSize.height + this.visibleRowTopMargin,
+    r = this.getScrollMax_();
+  t > r && (t = r), this.screen_.scrollTop != t && (this.screen_.scrollTop = t, this.scheduleRedraw());
+};, hterm.ScrollPort.prototype.scrollRowToBottom = function(e) {
+  this.syncScrollHeight(), this.isScrolledEnd = e + this.visibleRowCount >= this.lastRowCount_;
+  var t = e * this.characterSize.height + this.visibleRowTopMargin + this.visibleRowBottomMargin;
+  t -= this.visibleRowCount * this.characterSize.height, 0 > t && (t = 0), this.screen_.scrollTop != t && (this.screen_.scrollTop = t);
+};, hterm.ScrollPort.prototype.getTopRowIndex = function() {
+  return Math.round(this.screen_.scrollTop / this.characterSize.height);
+};, hterm.ScrollPort.prototype.getBottomRowIndex = function(e) {
+  return e + this.visibleRowCount - 1;
+};, hterm.ScrollPort.prototype.onScroll_ = function(e) {
+  var t = this.getScreenSize();
+  return t.width != this.lastScreenWidth_ || t.height != this.lastScreenHeight_ ? void this.resize() : (this.redraw_(), void this.publish('scroll', {
+    scrollPort: this
+  }));
+};, hterm.ScrollPort.prototype.onScrollWheel = function(e) {};, hterm.ScrollPort.prototype.onScrollWheel_ = function(e) {
+  if (this.onScrollWheel(e), !e.defaultPrevented) {
+    var t = 'DOMMouseScroll' == e.type ? -1 * e.detail : e.wheelDeltaY;
+    t *= this.scrollWheelMultiplier_;
+    var r = this.screen_.scrollTop - t;
+    0 > r && (r = 0);
+    var o = this.getScrollMax_();
+    r > o && (r = o), r != this.screen_.scrollTop && (this.screen_.scrollTop = r, e.preventDefault());
+  }
+};, hterm.ScrollPort.prototype.onResize_ = function(e) {
+  this.syncCharacterSize(), this.resize();
+};, hterm.ScrollPort.prototype.onCopy = function(e) {};, hterm.ScrollPort.prototype.onCopy_ = function(e) {
+  if (this.onCopy(e), !e.defaultPrevented && (this.resetSelectBags_(), this.selection.sync(), this.selection.startRow && !(this.selection.endRow.rowIndex - this.selection.startRow.rowIndex < 2))) {
+    var t = this.getTopRowIndex(),
+      r = this.getBottomRowIndex(t);
+    if (this.selection.startRow.rowIndex < t) {
+      var o;
+      o = this.selection.endRow.rowIndex < t ? this.selection.endRow.rowIndex : this.topFold_.nextSibling.rowIndex, this.topSelectBag_.textContent = this.rowProvider_.getRowsText(this.selection.startRow.rowIndex + 1, o), this.rowNodes_.insertBefore(this.topSelectBag_, this.selection.startRow.nextSibling), this.syncRowNodesDimensions_();
+    }
+    if (this.selection.endRow.rowIndex > r) {
+      var i;
+      i = this.selection.startRow.rowIndex > r ? this.selection.startRow.rowIndex + 1 : this.bottomFold_.previousSibling.rowIndex + 1, this.bottomSelectBag_.textContent = this.rowProvider_.getRowsText(i, this.selection.endRow.rowIndex), this.rowNodes_.insertBefore(this.bottomSelectBag_, this.selection.endRow);
+    }
+  }
+};, hterm.ScrollPort.prototype.onBodyKeyDown_ = function(e) {
+  if (this.ctrlVPaste) {
+    var t = String.fromCharCode(e.which),
+      r = t.toLowerCase();
+    (e.ctrlKey || e.metaKey) && 'v' == r && this.pasteTarget_.focus();
+  }
+};, hterm.ScrollPort.prototype.onPaste_ = function(e) {
+  this.pasteTarget_.focus();
+  var t = this;
+  setTimeout(function() {
+    t.publish('paste', {
+      text: t.pasteTarget_.value
+    }), t.pasteTarget_.value = '', t.screen_.focus();
+  }, 0);
+};, hterm.ScrollPort.prototype.handlePasteTargetTextInput_ = function(e) {
+  e.stopPropagation();
+};, hterm.ScrollPort.prototype.setScrollbarVisible = function(e) {
+  this.screen_.style.overflowY = e ? 'scroll' : 'hidden';
+};, hterm.ScrollPort.prototype.setScrollWheelMoveMultipler = function(e) {
+  this.scrollWheelMultiplier_ = e;
+};, lib.rtdep('lib.colors', 'lib.PreferenceManager', 'lib.resource', 'lib.wc', 'lib.f', 'hterm.Keyboard', 'hterm.Options', 'hterm.PreferenceManager', 'hterm.Screen', 'hterm.ScrollPort', 'hterm.Size', 'hterm.TextAttributes', 'hterm.VT'), hterm.Terminal = function(e) {
+  this.profileId_ = null, this.primaryScreen_ = new hterm.Screen, this.alternateScreen_ = new hterm.Screen, this.screen_ = this.primaryScreen_, this.screenSize = new hterm.Size(0, 0), this.scrollPort_ = new hterm.ScrollPort(this), this.scrollPort_.subscribe('resize', this.onResize_.bind(this)), this.scrollPort_.subscribe('scroll', this.onScroll_.bind(this)), this.scrollPort_.subscribe('paste', this.onPaste_.bind(this)), this.scrollPort_.onCopy = this.onCopy_.bind(this), this.div_ = null, this.document_ = window.document, this.scrollbackRows_ = [], this.tabStops_ = [], this.defaultTabStops = !0, this.vtScrollTop_ = null, this.vtScrollBottom_ = null, this.cursorNode_ = null, this.cursorShape_ = hterm.Terminal.cursorShape.BLOCK, this.cursorColor_ = null, this.cursorBlinkCycle_ = [100, 100], this.myOnCursorBlink_ = this.onCursorBlink_.bind(this), this.backgroundColor_ = null, this.foregroundColor_ = null, this.scrollOnOutput_ = null, this.scrollOnKeystroke_ = null, this.defeatMouseReports_ = !1, this.bellAudio_ = this.document_.createElement('audio'), this.bellAudio_.setAttribute('preload', 'auto'), this.bellNotificationList_ = [], this.desktopNotificationBell_ = !1, this.savedOptions_ = {}, this.options_ = new hterm.Options, this.timeouts_ = {}, this.vt = new hterm.VT(this), this.keyboard = new hterm.Keyboard(this), this.io = new hterm.Terminal.IO(this), this.enableMouseDragScroll = !0, this.copyOnSelect = null, this.mousePasteButton = null, this.useDefaultWindowCopy = !1, this.clearSelectionAfterCopy = !0, this.realizeSize_(80, 24), this.setDefaultTabStops(), this.setProfile(e || 'default', function() {
+    this.onTerminalReady();
+  }.bind(this));
+};, hterm.Terminal.cursorShape = {
+  BLOCK: 'BLOCK',
+  BEAM: 'BEAM',
+  UNDERLINE: 'UNDERLINE'
+}, hterm.Terminal.prototype.onTerminalReady = function() {};, hterm.Terminal.prototype.tabWidth = 8, hterm.Terminal.prototype.setProfile = function(e, t) {
+  this.profileId_ = e.replace(/\//g, '');
+  var r = this;
+  this.prefs_ && this.prefs_.deactivate(), this.prefs_ = new hterm.PreferenceManager(this.profileId_), this.prefs_.addObservers(null, {
+    'alt-gr-mode': function(e) {
+      e = null == e ? 'en-us' == navigator.language.toLowerCase() ? 'none' : 'right-alt' : 'string' == typeof e ? e.toLowerCase() : 'none', /^(none|ctrl-alt|left-alt|right-alt)$/.test(e) || (e = 'none'), r.keyboard.altGrMode = e;
+    },
+    'alt-backspace-is-meta-backspace': function(e) {
+      r.keyboard.altBackspaceIsMetaBackspace = e;
+    },
+    'alt-is-meta': function(e) {
+      r.keyboard.altIsMeta = e;
+    },
+    'alt-sends-what': function(e) {
+      /^(escape|8-bit|browser-key)$/.test(e) || (e = 'escape'), r.keyboard.altSendsWhat = e;
+    },
+    'audible-bell-sound': function(e) {
+      var t = e.match(/^lib-resource:(\S+)/);
+      t ? r.bellAudio_.setAttribute('src', lib.resource.getDataUrl(t[1])) : r.bellAudio_.setAttribute('src', e);
+    },
+    'desktop-notification-bell': function(e) {
+      e && Notification ? (r.desktopNotificationBell_ = 'granted' === Notification.permission, r.desktopNotificationBell_ || console.warn('desktop-notification-bell is true but we do not have permission to display notifications.')) : r.desktopNotificationBell_ = !1;
+    },
+    'background-color': function(e) {
+      r.setBackgroundColor(e);
+    },
+    'background-image': function(e) {
+      r.scrollPort_.setBackgroundImage(e);
+    },
+    'background-size': function(e) {
+      r.scrollPort_.setBackgroundSize(e);
+    },
+    'background-position': function(e) {
+      r.scrollPort_.setBackgroundPosition(e);
+    },
+    'backspace-sends-backspace': function(e) {
+      r.keyboard.backspaceSendsBackspace = e;
+    },
+    'character-map-overrides': function(e) {
+      if (!(null == e || e instanceof Object)) return void console.warn('Preference character-map-modifications is not an object: ' + e);
+      for (var t in e) {
+        var r = hterm.VT.CharacterMap.maps[t].glmap;
+        for (var o in e[t]) r[o] = e[t][o];
+        hterm.VT.CharacterMap.maps[t].reset(r);
+      }
+    },
+    'cursor-blink': function(e) {
+      r.setCursorBlink(!!e);
+    },
+    'cursor-blink-cycle': function(e) {
+      e instanceof Array && 'number' == typeof e[0] && 'number' == typeof e[1] ? r.cursorBlinkCycle_ = e : 'number' == typeof e ? r.cursorBlinkCycle_ = [e, e] : r.cursorBlinkCycle_ = [100, 100]
+    },
+    'cursor-color': function(e) {
+      r.setCursorColor(e);
+    },
+    'color-palette-overrides': function(e) {
+      if (!(null == e || e instanceof Object || e instanceof Array)) return void console.warn('Preference color-palette-overrides is not an array or object: ' + e);
+      if (lib.colors.colorPalette = lib.colors.stockColorPalette.concat(), e)
+        for (var t in e) {
+          var o = parseInt(t);
+          if (isNaN(o) || 0 > o || o > 255) console.log('Invalid value in palette: ' + t + ': ' + e[t]);
+          else if (e[o]) {
+            var i = lib.colors.normalizeCSS(e[o]);
+            i && (lib.colors.colorPalette[o] = i);
+          }
+        }
+      r.primaryScreen_.textAttributes.resetColorPalette(), r.alternateScreen_.textAttributes.resetColorPalette();
+    },
+    'copy-on-select': function(e) {
+      r.copyOnSelect = !!e;
+    },
+    'use-default-window-copy': function(e) {
+      r.useDefaultWindowCopy = !!e;
+    },
+    'clear-selection-after-copy': function(e) {
+      r.clearSelectionAfterCopy = !!e;
+    },
+    'ctrl-plus-minus-zero-zoom': function(e) {
+      r.keyboard.ctrlPlusMinusZeroZoom = e;
+    },
+    'ctrl-c-copy': function(e) {
+      r.keyboard.ctrlCCopy = e;
+    },
+    'ctrl-v-paste': function(e) {
+      r.keyboard.ctrlVPaste = e, r.scrollPort_.setCtrlVPaste(e);
+    },
+    'east-asian-ambiguous-as-two-column': function(e) {
+      lib.wc.regardCjkAmbiguous = e;
+    },
+    'enable-8-bit-control': function(e) {
+      r.vt.enable8BitControl = !!e;
+    },
+    'enable-bold': function(e) {
+      r.syncBoldSafeState();
+    },
+    'enable-bold-as-bright': function(e) {
+      r.primaryScreen_.textAttributes.enableBoldAsBright = !!e, r.alternateScreen_.textAttributes.enableBoldAsBright = !!e;
+    },
+    'enable-blink': function(e) {
+      r.syncBlinkState();
+    },
+    'enable-clipboard-write': function(e) {
+      r.vt.enableClipboardWrite = !!e;
+    },
+    'enable-dec12': function(e) {
+      r.vt.enableDec12 = !!e;
+    },
+    'font-family': function(e) {
+      r.syncFontFamily();
+    },
+    'font-size': function(e) {
+      r.setFontSize(e);
+    },
+    'font-smoothing': function(e) {
+      r.syncFontFamily();
+    },
+    'foreground-color': function(e) {
+      r.setForegroundColor(e);
+    },
+    'home-keys-scroll': function(e) {
+      r.keyboard.homeKeysScroll = e;
+    },
+    keybindings: function(e) {
+      if (r.keyboard.bindings.clear(), e) {
+        if (!(e instanceof Object)) return void console.error('Error in keybindings preference: Expected object');
+        try {
+          r.keyboard.bindings.addBindings(e);
+        }
+        catch (t) {
+          console.error('Error in keybindings preference: ' + t);
+        }
+      }
+    },
+    'max-string-sequence': function(e) {
+      r.vt.maxStringSequence = e;
+    },
+    'media-keys-are-fkeys': function(e) {
+      r.keyboard.mediaKeysAreFKeys = e;
+    },
+    'meta-sends-escape': function(e) {
+      r.keyboard.metaSendsEscape = e;
+    },
+    'mouse-paste-button': function(e) {
+      r.syncMousePasteButton();
+    },
+    'page-keys-scroll': function(e) {
+      r.keyboard.pageKeysScroll = e;
+    },
+    'pass-alt-number': function(e) {
+      if (null == e) {
+        var t = window.navigator.userAgent.match(/Mac OS X/);
+        e = !t && 'popup' != hterm.windowType;
+      }
+      r.passAltNumber = e;
+    },
+    'pass-ctrl-number': function(e) {
+      if (null == e) {
+        var t = window.navigator.userAgent.match(/Mac OS X/);
+        e = !t && 'popup' != hterm.windowType;
+      }
+      r.passCtrlNumber = e;
+    },
+    'pass-meta-number': function(e) {
+      if (null == e) {
+        var t = window.navigator.userAgent.match(/Mac OS X/);
+        e = t && 'popup' != hterm.windowType;
+      }
+      r.passMetaNumber = e;
+    },
+    'pass-meta-v': function(e) {
+      r.keyboard.passMetaV = e;
+    },
+    'receive-encoding': function(e) {
+      /^(utf-8|raw)$/.test(e) || (console.warn('Invalid value for "receive-encoding": ' + e), e = 'utf-8'), r.vt.characterEncoding = e;
+    },
+    'scroll-on-keystroke': function(e) {
+      r.scrollOnKeystroke_ = e;
+    },
+    'scroll-on-output': function(e) {
+      r.scrollOnOutput_ = e;
+    },
+    'scrollbar-visible': function(e) {
+      r.setScrollbarVisible(e);
+    },
+    'scroll-wheel-move-multiplier': function(e) {
+      r.setScrollWheelMoveMultipler(e);
+    },
+    'send-encoding': function(e) {
+      /^(utf-8|raw)$/.test(e) || (console.warn('Invalid value for "send-encoding": ' + e), e = 'utf-8'), r.keyboard.characterEncoding = e;
+    },
+    'shift-insert-paste': function(e) {
+      r.keyboard.shiftInsertPaste = e;
+    },
+    'user-css': function(e) {
+      r.scrollPort_.setUserCss(e);
+    }
+  }), this.prefs_.readStorage(function() {
+    this.prefs_.notifyAll(), t && t();
+  }.bind(this));
+};, hterm.Terminal.prototype.getPrefs = function() {
+  return this.prefs_;
+};, hterm.Terminal.prototype.setBracketedPaste = function(e) {
+  this.options_.bracketedPaste = e;
+};, hterm.Terminal.prototype.setCursorColor = function(e) {
+  this.cursorColor_ = e, this.cursorNode_.style.backgroundColor = e, this.cursorNode_.style.borderColor = e;
+};, hterm.Terminal.prototype.getCursorColor = function() {
+  return this.cursorColor_;
+};, hterm.Terminal.prototype.setSelectionEnabled = function(e) {
+  this.enableMouseDragScroll = e;
+};, hterm.Terminal.prototype.setBackgroundColor = function(e) {
+  this.backgroundColor_ = lib.colors.normalizeCSS(e), this.primaryScreen_.textAttributes.setDefaults(this.foregroundColor_, this.backgroundColor_), this.alternateScreen_.textAttributes.setDefaults(this.foregroundColor_, this.backgroundColor_), this.scrollPort_.setBackgroundColor(e);
+};, hterm.Terminal.prototype.getBackgroundColor = function() {
+  return this.backgroundColor_;
+};, hterm.Terminal.prototype.setForegroundColor = function(e) {
+  this.foregroundColor_ = lib.colors.normalizeCSS(e), this.primaryScreen_.textAttributes.setDefaults(this.foregroundColor_, this.backgroundColor_), this.alternateScreen_.textAttributes.setDefaults(this.foregroundColor_, this.backgroundColor_), this.scrollPort_.setForegroundColor(e);
+};, hterm.Terminal.prototype.getForegroundColor = function() {
+  return this.foregroundColor_;
+};, hterm.Terminal.prototype.runCommandClass = function(e, t) {
+  var r = this.prefs_.get('environment');
+  ('object' != typeof r || null == r) && (r = {});
+  var o = this;
+  this.command = new e({
+    argString: t || '',
+    io: this.io.push(),
+    environment: r,
+    onExit: function(e) {
+      o.io.pop(), o.uninstallKeyboard(), o.prefs_.get('close-on-exit') && window.close();
+    }
+  }), this.installKeyboard(), this.command.run();
+};, hterm.Terminal.prototype.isPrimaryScreen = function() {
+  return this.screen_ == this.primaryScreen_;
+};, hterm.Terminal.prototype.installKeyboard = function() {
+  this.keyboard.installKeyboard(this.scrollPort_.getDocument().body);
+};, hterm.Terminal.prototype.uninstallKeyboard = function() {
+  this.keyboard.installKeyboard(null);
+};, hterm.Terminal.prototype.setFontSize = function(e) {
+  0 === e && (e = this.prefs_.get('font-size')), this.scrollPort_.setFontSize(e), this.wcCssRule_ && (this.wcCssRule_.style.width = 2 * this.scrollPort_.characterSize.width + 'px');
+};, hterm.Terminal.prototype.getFontSize = function() {
+  return this.scrollPort_.getFontSize();
+};, hterm.Terminal.prototype.getFontFamily = function() {
+  return this.scrollPort_.getFontFamily();
+};, hterm.Terminal.prototype.syncFontFamily = function() {
+  this.scrollPort_.setFontFamily(this.prefs_.get('font-family'), this.prefs_.get('font-smoothing')), this.syncBoldSafeState();
+};, hterm.Terminal.prototype.syncMousePasteButton = function() {
+  var e = this.prefs_.get('mouse-paste-button');
+  if ('number' == typeof e) return void(this.mousePasteButton = e);
+  var t = navigator.userAgent.match(/\(X11;\s+(\S+)/);
+  t && 'CrOS' != t[2] ? this.mousePasteButton = 3 : this.mousePasteButton = 2;
+};, hterm.Terminal.prototype.syncBoldSafeState = function() {
+  var e = this.prefs_.get('enable-bold');
+  if (null !== e) return this.primaryScreen_.textAttributes.enableBold = e, void(this.alternateScreen_.textAttributes.enableBold = e);
+  var t = this.scrollPort_.measureCharacterSize(),
+    r = this.scrollPort_.measureCharacterSize('bold'),
+    o = t.equals(r);
+  o || console.warn('Bold characters disabled: Size of bold weight differs from normal.  Font family is: ' + this.scrollPort_.getFontFamily()), this.primaryScreen_.textAttributes.enableBold = o, this.alternateScreen_.textAttributes.enableBold = o;
+};, hterm.Terminal.prototype.syncBlinkState = function() {
+  this.document_.documentElement.style.setProperty('--hterm-blink-node-duration', this.prefs_.get('enable-blink') ? '0.7s' : '0');
+};, hterm.Terminal.prototype.saveCursor = function() {
+  return this.screen_.cursorPosition.clone();
+};, hterm.Terminal.prototype.getTextAttributes = function() {
+  return this.screen_.textAttributes;
+};, hterm.Terminal.prototype.setTextAttributes = function(e) {
+  this.screen_.textAttributes = e;
+};, hterm.Terminal.prototype.getZoomFactor = function() {
+  return this.scrollPort_.characterSize.zoomFactor;
+};, hterm.Terminal.prototype.setWindowTitle = function(e) {
+  window.document.title = e;
+};, hterm.Terminal.prototype.restoreCursor = function(e) {
+  var t = lib.f.clamp(e.row, 0, this.screenSize.height - 1),
+    r = lib.f.clamp(e.column, 0, this.screenSize.width - 1);
+  this.screen_.setCursorPosition(t, r), (e.column > r || e.column == r && e.overflow) && (this.screen_.cursorPosition.overflow = !0);
+};, hterm.Terminal.prototype.clearCursorOverflow = function() {
+  this.screen_.cursorPosition.overflow = !1;
+};, hterm.Terminal.prototype.setCursorShape = function(e) {
+  this.cursorShape_ = e, this.restyleCursor_();
+};, hterm.Terminal.prototype.getCursorShape = function() {
+  return this.cursorShape_;
+};, hterm.Terminal.prototype.setWidth = function(e) {
+  return null == e ? void(this.div_.style.width = '100%') : (this.div_.style.width = Math.ceil(this.scrollPort_.characterSize.width * e + this.scrollPort_.currentScrollbarWidthPx) + 'px', this.realizeSize_(e, this.screenSize.height), void this.scheduleSyncCursorPosition_());
+};, hterm.Terminal.prototype.setHeight = function(e) {
+  return null == e ? void(this.div_.style.height = '100%') : (this.div_.style.height = this.scrollPort_.characterSize.height * e + 'px', this.realizeSize_(this.screenSize.width, e), void this.scheduleSyncCursorPosition_());
+};, hterm.Terminal.prototype.realizeSize_ = function(e, t) {
+  e != this.screenSize.width && this.realizeWidth_(e), t != this.screenSize.height && this.realizeHeight_(t), this.io.onTerminalResize_(e, t);
+};, hterm.Terminal.prototype.realizeWidth_ = function(e) {
+  if (0 >= e) throw new Error('Attempt to realize bad width: ' + e);
+  var t = e - this.screen_.getWidth();
+  if (this.screenSize.width = e, this.screen_.setColumnCount(e), t > 0) this.defaultTabStops && this.setDefaultTabStops(this.screenSize.width - t);
+  else
+    for (var r = this.tabStops_.length - 1; r >= 0 && !(this.tabStops_[r] < e); r--) this.tabStops_.pop();
+  this.screen_.setColumnCount(this.screenSize.width);
+};, hterm.Terminal.prototype.realizeHeight_ = function(e) {
+  if (0 >= e) throw new Error('Attempt to realize bad height: ' + e);
+  var t = e - this.screen_.getHeight();
+  this.screenSize.height = e;
+  var r = this.saveCursor();
+  if (0 > t) {
+    for (t *= -1; t;) {
+      var o = this.getRowCount() - 1;
+      if (o - this.scrollbackRows_.length == r.row) break;
+      if (this.getRowText(o)) break;
+      this.screen_.popRow(), t--;
+    }
+    var i = this.screen_.shiftRows(t);
+    this.scrollbackRows_.push.apply(this.scrollbackRows_, i), r.row = Math.max(r.row - t, 0);
+  }
+  else if (t > 0) {
+    if (t <= this.scrollbackRows_.length) {
+      var s = Math.min(t, this.scrollbackRows_.length),
+        n = this.scrollbackRows_.splice(this.scrollbackRows_.length - s, s);
+      this.screen_.unshiftRows(n), t -= s, r.row += s;
+    }
+    t && this.appendRows_(t);
+  }
+  this.setVTScrollRegion(null, null), this.restoreCursor(r);
+};, hterm.Terminal.prototype.scrollHome = function() {
+  this.scrollPort_.scrollRowToTop(0);
+};, hterm.Terminal.prototype.scrollEnd = function() {
+  this.scrollPort_.scrollRowToBottom(this.getRowCount());
+};, hterm.Terminal.prototype.scrollPageUp = function() {
+  var e = this.scrollPort_.getTopRowIndex();
+  this.scrollPort_.scrollRowToTop(e - this.screenSize.height + 1);
+};, hterm.Terminal.prototype.scrollPageDown = function() {
+  var e = this.scrollPort_.getTopRowIndex();
+  this.scrollPort_.scrollRowToTop(e + this.screenSize.height - 1);
+};, hterm.Terminal.prototype.wipeContents = function() {
+  this.scrollbackRows_.length = 0, this.scrollPort_.resetCache(), [this.primaryScreen_, this.alternateScreen_].forEach(function(e) {
+    var t = e.getHeight();
+    t > 0 && (this.renumberRows_(0, t), this.clearHome(e));
+  }.bind(this)), this.syncCursorPosition_(), this.scrollPort_.invalidate();
+};, hterm.Terminal.prototype.reset = function() {
+  this.clearAllTabStops(), this.setDefaultTabStops(), this.clearHome(this.primaryScreen_), this.primaryScreen_.textAttributes.reset(), this.clearHome(this.alternateScreen_), this.alternateScreen_.textAttributes.reset(), this.setCursorBlink(!!this.prefs_.get('cursor-blink')), this.vt.reset(), this.softReset();
+};, hterm.Terminal.prototype.softReset = function() {
+  this.options_ = new hterm.Options, this.options_.cursorBlink = !!this.timeouts_.cursorBlink, this.primaryScreen_.textAttributes.resetColorPalette(), this.alternateScreen_.textAttributes.resetColorPalette(), this.setVTScrollRegion(null, null), this.setCursorVisible(!0);
+};, hterm.Terminal.prototype.forwardTabStop = function() {
+  for (var e = this.screen_.cursorPosition.column, t = 0; t < this.tabStops_.length; t++)
+    if (this.tabStops_[t] > e) return void this.setCursorColumn(this.tabStops_[t]);
+  var r = this.screen_.cursorPosition.overflow;
+  this.setCursorColumn(this.screenSize.width - 1), this.screen_.cursorPosition.overflow = r;
+};, hterm.Terminal.prototype.backwardTabStop = function() {
+  for (var e = this.screen_.cursorPosition.column, t = this.tabStops_.length - 1; t >= 0; t--)
+    if (this.tabStops_[t] < e) return void this.setCursorColumn(this.tabStops_[t]);
+  this.setCursorColumn(1);
+};, hterm.Terminal.prototype.setTabStop = function(e) {
+  for (var t = this.tabStops_.length - 1; t >= 0; t--) {
+    if (this.tabStops_[t] == e) return;
+    if (this.tabStops_[t] < e) return void this.tabStops_.splice(t + 1, 0, e);
+  }
+  this.tabStops_.splice(0, 0, e);
+};, hterm.Terminal.prototype.clearTabStopAtCursor = function() {
+  var e = this.screen_.cursorPosition.column,
+    t = this.tabStops_.indexOf(e); - 1 != t && this.tabStops_.splice(t, 1);
+};, hterm.Terminal.prototype.clearAllTabStops = function() {
+  this.tabStops_.length = 0, this.defaultTabStops = !1;
+};, hterm.Terminal.prototype.setDefaultTabStops = function(e) {
+  var t = e || 0,
+    r = this.tabWidth;
+  t = t - 1 - (t - 1) % r + r;
+  for (var o = t; o < this.screenSize.width; o += r) this.setTabStop(o);
+  this.defaultTabStops = !0;
+};, hterm.Terminal.prototype.interpret = function(e) {
+  this.vt.interpret(e), this.scheduleSyncCursorPosition_();
+};, hterm.Terminal.prototype.decorate = function(e) {
+  this.div_ = e, this.scrollPort_.decorate(e), this.scrollPort_.setBackgroundImage(this.prefs_.get('background-image')), this.scrollPort_.setBackgroundSize(this.prefs_.get('background-size')), this.scrollPort_.setBackgroundPosition(this.prefs_.get('background-position')), this.scrollPort_.setUserCss(this.prefs_.get('user-css')), this.div_.focus = this.focus.bind(this), this.setFontSize(this.prefs_.get('font-size')), this.syncFontFamily(), this.setScrollbarVisible(this.prefs_.get('scrollbar-visible')), this.setScrollWheelMoveMultipler(this.prefs_.get('scroll-wheel-move-multiplier')), this.document_ = this.scrollPort_.getDocument(), this.document_.body.oncontextmenu = function() {
+    return !1;
+  };
+  var t = this.onMouse_.bind(this),
+    r = this.scrollPort_.getScreenNode();
+  r.addEventListener('mousedown', t), r.addEventListener('mouseup', t), r.addEventListener('mousemove', t), this.scrollPort_.onScrollWheel = t, r.addEventListener('focus', this.onFocusChange_.bind(this, !0)), r.addEventListener('mousedown', function() {
+    setTimeout(this.onFocusChange_.bind(this, !0));
+  }.bind(this)), r.addEventListener('blur', this.onFocusChange_.bind(this, !1));
+  var o = this.document_.createElement('style');
+  o.textContent = '.cursor-node[focus="false"] {  box-sizing: border-box;  background-color: transparent !important;  border-width: 2px;  border-style: solid;}.wc-node {  display: inline-block;  text-align: center;  width: ' + 2 * this.scrollPort_.characterSize.width + 'px;}:root {  --hterm-blink-node-duration: 0.7s;}@keyframes blink {  from { opacity: 1.0; }  to { opacity: 0.0; }}.blink-node {  animation-name: blink;  animation-duration: var(--hterm-blink-node-duration);  animation-iteration-count: infinite;  animation-timing-function: ease-in-out;  animation-direction: alternate;}', this.document_.head.appendChild(o);
+  var i = this.document_.styleSheets,
+    s = i[i.length - 1].cssRules;
+  this.wcCssRule_ = s[s.length - 1], this.cursorNode_ = this.document_.createElement('div'), this.cursorNode_.className = 'cursor-node', this.cursorNode_.style.cssText = 'position: absolute;top: -99px;display: block;width: ' + this.scrollPort_.characterSize.width + 'px;height: ' + this.scrollPort_.characterSize.height + 'px;-webkit-transition: opacity, background-color 100ms linear;-moz-transition: opacity, background-color 100ms linear;', this.setCursorColor(this.prefs_.get('cursor-color')), this.setCursorBlink(!!this.prefs_.get('cursor-blink')), this.restyleCursor_(), this.document_.body.appendChild(this.cursorNode_), this.scrollBlockerNode_ = this.document_.createElement('div'), this.scrollBlockerNode_.style.cssText = 'position: absolute;top: -99px;display: block;width: 10px;height: 10px;', this.document_.body.appendChild(this.scrollBlockerNode_), this.scrollPort_.onScrollWheel = t, ['mousedown', 'mouseup', 'mousemove', 'click', 'dblclick'].forEach(function(e) {
+    this.scrollBlockerNode_.addEventListener(e, t), this.cursorNode_.addEventListener(e, t), this.document_.addEventListener(e, t);
+  }.bind(this)), this.cursorNode_.addEventListener('mousedown', function() {
+    setTimeout(this.focus.bind(this));
+  }.bind(this)), this.setReverseVideo(!1), this.scrollPort_.focus(), this.scrollPort_.scheduleRedraw();
+};, hterm.Terminal.prototype.getDocument = function() {
+  return this.document_;
+};, hterm.Terminal.prototype.focus = function() {
+  this.scrollPort_.focus();
+};, hterm.Terminal.prototype.getRowNode = function(e) {
+  if (e < this.scrollbackRows_.length) return this.scrollbackRows_[e];
+  var t = e - this.scrollbackRows_.length;
+  return this.screen_.rowsArray[t];
+};, hterm.Terminal.prototype.getRowsText = function(e, t) {
+  for (var r = [], o = e; t > o; o++) {
+    var i = this.getRowNode(o);
+    r.push(i.textContent), t - 1 > o && !i.getAttribute('line-overflow') && r.push('\n');
+  }
+  return r.join('');
+};, hterm.Terminal.prototype.getRowText = function(e) {
+  var t = this.getRowNode(e);
+  return t.textContent;
+};, hterm.Terminal.prototype.getRowCount = function() {
+  return this.scrollbackRows_.length + this.screen_.rowsArray.length;
+};, hterm.Terminal.prototype.appendRows_ = function(e) {
+  for (var t = this.screen_.rowsArray.length, r = this.scrollbackRows_.length + t, o = 0; e > o; o++) {
+    var i = this.document_.createElement('x-row');
+    i.appendChild(this.document_.createTextNode('')), i.rowIndex = r + o, this.screen_.pushRow(i);
+  }
+  var s = this.screen_.rowsArray.length - this.screenSize.height;
+  if (s > 0) {
+    var n = this.screen_.shiftRows(s);
+    Array.prototype.push.apply(this.scrollbackRows_, n), this.scrollPort_.isScrolledEnd && this.scheduleScrollDown_();
+  }
+  t >= this.screen_.rowsArray.length && (t = this.screen_.rowsArray.length - 1), this.setAbsoluteCursorPosition(t, 0);
+};, hterm.Terminal.prototype.moveRows_ = function(e, t, r) {
+  var o = this.screen_.removeRows(e, t);
+  this.screen_.insertRows(r, o);
+  var i, s;
+  r > e ? (i = e, s = r + t) : (i = r, s = e + t), this.renumberRows_(i, s), this.scrollPort_.scheduleInvalidate();
+};, hterm.Terminal.prototype.renumberRows_ = function(e, t, r) {
+  for (var o = r || this.screen_, i = this.scrollbackRows_.length, s = e; t > s; s++) o.rowsArray[s].rowIndex = i + s;
+};, hterm.Terminal.prototype.print = function(e) {
+  for (var t = 0, r = lib.wc.strWidth(e); r > t;) {
+    this.options_.wraparound && this.screen_.cursorPosition.overflow && (this.screen_.commitLineOverflow(), this.newLine());
+    var o, i = r - t,
+      s = !1;
+    this.screen_.cursorPosition.column + i >= this.screenSize.width && (s = !0, i = this.screenSize.width - this.screen_.cursorPosition.column), s && !this.options_.wraparound ? (o = lib.wc.substr(e, t, i - 1) + lib.wc.substr(e, r - 1), i = r) : o = lib.wc.substr(e, t, i);
+    for (var n = hterm.TextAttributes.splitWidecharString(o), a = 0; a < n.length; a++) n[a].wcNode && (this.screen_.textAttributes.wcNode = !0), this.options_.insertMode ? this.screen_.insertString(n[a].str) : this.screen_.overwriteString(n[a].str), this.screen_.textAttributes.wcNode = !1;
+    this.screen_.maybeClipCurrentRow(), t += i;
+  }
+  this.scheduleSyncCursorPosition_(), this.scrollOnOutput_ && this.scrollPort_.scrollRowToBottom(this.getRowCount());
+};, hterm.Terminal.prototype.setVTScrollRegion = function(e, t) {
+  0 == e && t == this.screenSize.height - 1 ? (this.vtScrollTop_ = null, this.vtScrollBottom_ = null) : (this.vtScrollTop_ = e, this.vtScrollBottom_ = t);
+};, hterm.Terminal.prototype.getVTScrollTop = function() {
+  return null != this.vtScrollTop_ ? this.vtScrollTop_ : 0;
+};, hterm.Terminal.prototype.getVTScrollBottom = function() {
+  return null != this.vtScrollBottom_ ? this.vtScrollBottom_ : this.screenSize.height - 1;
+};, hterm.Terminal.prototype.newLine = function() {
+  var e = this.screen_.cursorPosition.row == this.screen_.rowsArray.length - 1;
+  null != this.vtScrollBottom_ ? this.screen_.cursorPosition.row == this.vtScrollBottom_ ? (this.vtScrollUp(1), this.setAbsoluteCursorPosition(this.screen_.cursorPosition.row, 0)) : e ? this.setAbsoluteCursorPosition(this.screen_.cursorPosition.row, 0) : this.setAbsoluteCursorPosition(this.screen_.cursorPosition.row + 1, 0) : e ? this.appendRows_(1) : this.setAbsoluteCursorPosition(this.screen_.cursorPosition.row + 1, 0)
+};, hterm.Terminal.prototype.lineFeed = function() {
+  var e = this.screen_.cursorPosition.column;
+  this.newLine(), this.setCursorColumn(e);
+};, hterm.Terminal.prototype.formFeed = function() {
+  this.options_.autoCarriageReturn ? this.newLine() : this.lineFeed();
+};, hterm.Terminal.prototype.reverseLineFeed = function() {
+  var e = this.getVTScrollTop(),
+    t = this.screen_.cursorPosition.row;
+  t == e ? this.insertLines(1) : this.setAbsoluteCursorRow(t - 1);
+};, hterm.Terminal.prototype.eraseToLeft = function() {
+  var e = this.saveCursor();
+  this.setCursorColumn(0), this.screen_.overwriteString(lib.f.getWhitespace(e.column + 1)), this.restoreCursor(e);
+};, hterm.Terminal.prototype.eraseToRight = function(e) {
+  if (!this.screen_.cursorPosition.overflow) {
+    var t = this.screenSize.width - this.screen_.cursorPosition.column,
+      r = e ? Math.min(e, t) : t;
+    if (this.screen_.textAttributes.background === this.screen_.textAttributes.DEFAULT_COLOR) {
+      var o = this.screen_.rowsArray[this.screen_.cursorPosition.row];
+      if (hterm.TextAttributes.nodeWidth(o) <= this.screen_.cursorPosition.column + r) return this.screen_.deleteChars(r), void this.clearCursorOverflow();
+    }
+    var i = this.saveCursor();
+    this.screen_.overwriteString(lib.f.getWhitespace(r)), this.restoreCursor(i), this.clearCursorOverflow();
+  }
+};, hterm.Terminal.prototype.eraseLine = function() {
+  var e = this.saveCursor();
+  this.screen_.clearCursorRow(), this.restoreCursor(e), this.clearCursorOverflow();
+};, hterm.Terminal.prototype.eraseAbove = function() {
+  var e = this.saveCursor();
+  this.eraseToLeft();
+  for (var t = 0; t < e.row; t++) this.setAbsoluteCursorPosition(t, 0), this.screen_.clearCursorRow();
+  this.restoreCursor(e), this.clearCursorOverflow();
+};, hterm.Terminal.prototype.eraseBelow = function() {
+  var e = this.saveCursor();
+  this.eraseToRight();
+  for (var t = this.screenSize.height - 1, r = e.row + 1; t >= r; r++) this.setAbsoluteCursorPosition(r, 0), this.screen_.clearCursorRow();
+  this.restoreCursor(e), this.clearCursorOverflow();
+};, hterm.Terminal.prototype.fill = function(e) {
+  var t = this.saveCursor();
+  this.setAbsoluteCursorPosition(0, 0);
+  for (var r = 0; r < this.screenSize.height; r++)
+    for (var o = 0; o < this.screenSize.width; o++) this.setAbsoluteCursorPosition(r, o), this.screen_.overwriteString(e);
+  this.restoreCursor(t);
+};, hterm.Terminal.prototype.clearHome = function(e) {
+  var t = e || this.screen_,
+    r = t.getHeight();
+  if (0 != r) {
+    for (var o = 0; r > o; o++) t.setCursorPosition(o, 0), t.clearCursorRow();
+    t.setCursorPosition(0, 0);
+  }
+};, hterm.Terminal.prototype.clear = function(e) {
+  var t = e || this.screen_,
+    r = t.cursorPosition.clone();
+  this.clearHome(t), t.setCursorPosition(r.row, r.column);
+};, hterm.Terminal.prototype.insertLines = function(e) {
+  var t = this.screen_.cursorPosition.row,
+    r = this.getVTScrollBottom();
+  e = Math.min(e, r - t);
+  var o = r - t - e + 1;
+  o && this.moveRows_(t, o, t + e);
+  for (var i = e - 1; i >= 0; i--) this.setAbsoluteCursorPosition(t + i, 0), this.screen_.clearCursorRow();
+};, hterm.Terminal.prototype.deleteLines = function(e) {
+  var t = this.saveCursor(),
+    r = t.row,
+    o = this.getVTScrollBottom(),
+    i = o - r + 1;
+  e = Math.min(e, i);
+  var s = o - e + 1;
+  e != i && this.moveRows_(r, e, s);
+  for (var n = 0; e > n; n++) this.setAbsoluteCursorPosition(s + n, 0), this.screen_.clearCursorRow();
+  this.restoreCursor(t), this.clearCursorOverflow();
+};, hterm.Terminal.prototype.insertSpace = function(e) {
+  var t = this.saveCursor(),
+    r = lib.f.getWhitespace(e || 1);
+  this.screen_.insertString(r), this.screen_.maybeClipCurrentRow(), this.restoreCursor(t), this.clearCursorOverflow();
+};, hterm.Terminal.prototype.deleteChars = function(e) {
+  var t = this.screen_.deleteChars(e);
+  if (t && !this.screen_.textAttributes.isDefault()) {
+    var r = this.saveCursor();
+    this.setCursorColumn(this.screenSize.width - t), this.screen_.insertString(lib.f.getWhitespace(t)), this.restoreCursor(r);
+  }
+  this.clearCursorOverflow();
+};, hterm.Terminal.prototype.vtScrollUp = function(e) {
+  var t = this.saveCursor();
+  this.setAbsoluteCursorRow(this.getVTScrollTop()), this.deleteLines(e), this.restoreCursor(t);
+};, hterm.Terminal.prototype.vtScrollDown = function(e) {
+  var t = this.saveCursor();
+  this.setAbsoluteCursorPosition(this.getVTScrollTop(), 0), this.insertLines(e), this.restoreCursor(t);
+};, hterm.Terminal.prototype.setCursorPosition = function(e, t) {
+  this.options_.originMode ? this.setRelativeCursorPosition(e, t) : this.setAbsoluteCursorPosition(e, t);
+};, hterm.Terminal.prototype.setRelativeCursorPosition = function(e, t) {
+  var r = this.getVTScrollTop();
+  e = lib.f.clamp(e + r, r, this.getVTScrollBottom()), t = lib.f.clamp(t, 0, this.screenSize.width - 1), this.screen_.setCursorPosition(e, t);
+};, hterm.Terminal.prototype.setAbsoluteCursorPosition = function(e, t) {
+  e = lib.f.clamp(e, 0, this.screenSize.height - 1), t = lib.f.clamp(t, 0, this.screenSize.width - 1), this.screen_.setCursorPosition(e, t);
+};, hterm.Terminal.prototype.setCursorColumn = function(e) {
+  this.setAbsoluteCursorPosition(this.screen_.cursorPosition.row, e);
+};, hterm.Terminal.prototype.getCursorColumn = function() {
+  return this.screen_.cursorPosition.column;
+};, hterm.Terminal.prototype.setAbsoluteCursorRow = function(e) {
+  this.setAbsoluteCursorPosition(e, this.screen_.cursorPosition.column);
+};, hterm.Terminal.prototype.getCursorRow = function() {
+  return this.screen_.cursorPosition.row;
+};, hterm.Terminal.prototype.scheduleRedraw_ = function() {
+  if (!this.timeouts_.redraw) {
+    var e = this;
+    this.timeouts_.redraw = setTimeout(function() {
+      delete e.timeouts_.redraw, e.scrollPort_.redraw_();
+    }, 0);
+  }
+};, hterm.Terminal.prototype.scheduleScrollDown_ = function() {
+  if (!this.timeouts_.scrollDown) {
+    var e = this;
+    this.timeouts_.scrollDown = setTimeout(function() {
+      delete e.timeouts_.scrollDown, e.scrollPort_.scrollRowToBottom(e.getRowCount());
+    }, 10);
+  }
+};, hterm.Terminal.prototype.cursorUp = function(e) {
+  return this.cursorDown(-(e || 1));
+};, hterm.Terminal.prototype.cursorDown = function(e) {
+  e = e || 1;
+  var t = this.options_.originMode ? this.getVTScrollTop() : 0,
+    r = this.options_.originMode ? this.getVTScrollBottom() : this.screenSize.height - 1,
+    o = lib.f.clamp(this.screen_.cursorPosition.row + e, t, r);
+  this.setAbsoluteCursorRow(o);
+};, hterm.Terminal.prototype.cursorLeft = function(e) {
+  if (e = e || 1, !(1 > e)) {
+    var t = this.screen_.cursorPosition.column;
+    if (this.options_.reverseWraparound) {
+      if (this.screen_.cursorPosition.overflow && (e--, this.clearCursorOverflow(), !e)) return;
+      var r = this.screen_.cursorPosition.row,
+        o = t - e;
+      0 > o && (r = r - Math.floor(e / this.screenSize.width) - 1, 0 > r && (r = this.screenSize.height + r % this.screenSize.height), o = this.screenSize.width + o % this.screenSize.width), this.setCursorPosition(Math.max(r, 0), o);
+    }
+    else {
+      var o = Math.max(t - e, 0);
+      this.setCursorColumn(o);
+    }
+  }
+};, hterm.Terminal.prototype.cursorRight = function(e) {
+  if (e = e || 1, !(1 > e)) {
+    var t = lib.f.clamp(this.screen_.cursorPosition.column + e, 0, this.screenSize.width - 1);
+    this.setCursorColumn(t);
+  }
+};, hterm.Terminal.prototype.setReverseVideo = function(e) {
+  this.options_.reverseVideo = e, e ? (this.scrollPort_.setForegroundColor(this.prefs_.get('background-color')), this.scrollPort_.setBackgroundColor(this.prefs_.get('foreground-color'))) : (this.scrollPort_.setForegroundColor(this.prefs_.get('foreground-color')), this.scrollPort_.setBackgroundColor(this.prefs_.get('background-color')));
+};, hterm.Terminal.prototype.ringBell = function() {
+  this.cursorNode_.style.backgroundColor = this.scrollPort_.getForegroundColor();
+  var e = this;
+  if (setTimeout(function() {
+      e.cursorNode_.style.backgroundColor = e.prefs_.get('cursor-color');
+    }, 200), !this.bellSquelchTimeout_ && (this.bellAudio_.getAttribute('src') ? (this.bellAudio_.play(), this.bellSequelchTimeout_ = setTimeout(function() {
+      delete this.bellSquelchTimeout_;
+    }.bind(this), 500)) : delete this.bellSquelchTimeout_, this.desktopNotificationBell_ && !this.document_.hasFocus())) {
+    var t = new Notification(lib.f.replaceVars(hterm.desktopNotificationTitle, {
+      title: window.document.title || 'hterm'
+    }));
+    this.bellNotificationList_.push(t), t.onclick = function() {
+      e.closeBellNotifications_();
+    };
+  }
+};, hterm.Terminal.prototype.setOriginMode = function(e) {
+  this.options_.originMode = e, this.setCursorPosition(0, 0);
+};, hterm.Terminal.prototype.setInsertMode = function(e) {
+  this.options_.insertMode = e;
+};, hterm.Terminal.prototype.setAutoCarriageReturn = function(e) {
+  this.options_.autoCarriageReturn = e;
+};, hterm.Terminal.prototype.setWraparound = function(e) {
+  this.options_.wraparound = e;
+};, hterm.Terminal.prototype.setReverseWraparound = function(e) {
+  this.options_.reverseWraparound = e;
+};, hterm.Terminal.prototype.setAlternateMode = function(e) {
+  var t = this.saveCursor();
+  if (this.screen_ = e ? this.alternateScreen_ : this.primaryScreen_, this.screen_.rowsArray.length && this.screen_.rowsArray[0].rowIndex != this.scrollbackRows_.length)
+    for (var r = this.scrollbackRows_.length, o = this.screen_.rowsArray, i = 0; i < o.length; i++) o[i].rowIndex = r + i;
+  this.realizeWidth_(this.screenSize.width), this.realizeHeight_(this.screenSize.height), this.scrollPort_.syncScrollHeight(), this.scrollPort_.invalidate(), this.restoreCursor(t), this.scrollPort_.resize();
+};, hterm.Terminal.prototype.setCursorBlink = function(e) {
+  this.options_.cursorBlink = e, !e && this.timeouts_.cursorBlink && (clearTimeout(this.timeouts_.cursorBlink), delete this.timeouts_.cursorBlink), this.options_.cursorVisible && this.setCursorVisible(!0);
+};, hterm.Terminal.prototype.setCursorVisible = function(e) {
+  if (this.options_.cursorVisible = e, !e) return this.timeouts_.cursorBlink && (clearTimeout(this.timeouts_.cursorBlink), delete this.timeouts_.cursorBlink), void(this.cursorNode_.style.opacity = '0');
+  if (this.syncCursorPosition_(), this.cursorNode_.style.opacity = '1', this.options_.cursorBlink) {
+    if (this.timeouts_.cursorBlink) return;
+    this.onCursorBlink_();
+  }
+  else this.timeouts_.cursorBlink && (clearTimeout(this.timeouts_.cursorBlink), delete this.timeouts_.cursorBlink);
+};, hterm.Terminal.prototype.syncCursorPosition_ = function() {
+  var e = this.scrollPort_.getTopRowIndex(),
+    t = this.scrollPort_.getBottomRowIndex(e),
+    r = this.scrollbackRows_.length + this.screen_.cursorPosition.row;
+  if (r > t) return void(this.cursorNode_.style.top = -this.scrollPort_.characterSize.height + 'px');
+  this.options_.cursorVisible && 'none' == this.cursorNode_.style.display && (this.cursorNode_.style.display = ''), this.cursorNode_.style.top = this.scrollPort_.visibleRowTopMargin + this.scrollPort_.characterSize.height * (r - e) + 'px', this.cursorNode_.style.left = this.scrollPort_.characterSize.width * this.screen_.cursorPosition.column + 'px', this.cursorNode_.setAttribute('title', '(' + this.screen_.cursorPosition.row + ', ' + this.screen_.cursorPosition.column + ')');
+  var o = this.document_.getSelection();
+  o && o.isCollapsed && this.screen_.syncSelectionCaret(o);
+};, hterm.Terminal.prototype.restyleCursor_ = function() {
+  var e = this.cursorShape_;
+  'false' == this.cursorNode_.getAttribute('focus') && (e = hterm.Terminal.cursorShape.BLOCK);
+  var t = this.cursorNode_.style;
+  switch (t.width = this.scrollPort_.characterSize.width + 'px', e) {
+    case hterm.Terminal.cursorShape.BEAM:
+      t.height = this.scrollPort_.characterSize.height + 'px', t.backgroundColor = 'transparent', t.borderBottomStyle = null, t.borderLeftStyle = 'solid';
+      break;
+    case hterm.Terminal.cursorShape.UNDERLINE:
+      t.height = this.scrollPort_.characterSize.baseline + 'px', t.backgroundColor = 'transparent', t.borderBottomStyle = 'solid', t.borderLeftStyle = null;
+      break;
+    default:
+      t.height = this.scrollPort_.characterSize.height + 'px', t.backgroundColor = this.cursorColor_, t.borderBottomStyle = null, t.borderLeftStyle = null;
+  }
+};, hterm.Terminal.prototype.scheduleSyncCursorPosition_ = function() {
+  if (!this.timeouts_.syncCursor) {
+    var e = this;
+    this.timeouts_.syncCursor = setTimeout(function() {
+      e.syncCursorPosition_(), delete e.timeouts_.syncCursor;
+    }, 0);
+  }
+};, hterm.Terminal.prototype.showZoomWarning_ = function(e) {
+  if (!this.zoomWarningNode_) {
+    if (!e) return;
+    this.zoomWarningNode_ = this.document_.createElement('div'), this.zoomWarningNode_.style.cssText = 'color: black;background-color: #ff2222;font-size: large;border-radius: 8px;opacity: 0.75;padding: 0.2em 0.5em 0.2em 0.5em;top: 0.5em;right: 1.2em;position: absolute;-webkit-text-size-adjust: none;-webkit-user-select: none;-moz-text-size-adjust: none;-moz-user-select: none;', this.zoomWarningNode_.addEventListener('click', function(e) {
+      this.parentNode.removeChild(this);
+    });
+  }
+  this.zoomWarningNode_.textContent = lib.MessageManager.replaceReferences(hterm.zoomWarningMessage, [parseInt(100 * this.scrollPort_.characterSize.zoomFactor)]), this.zoomWarningNode_.style.fontFamily = this.prefs_.get('font-family'), e ? this.zoomWarningNode_.parentNode || this.div_.parentNode.appendChild(this.zoomWarningNode_) : this.zoomWarningNode_.parentNode && this.zoomWarningNode_.parentNode.removeChild(this.zoomWarningNode_);
+};, hterm.Terminal.prototype.showOverlay = function(e, t) {
+  if (!this.overlayNode_) {
+    if (!this.div_) return;
+    this.overlayNode_ = this.document_.createElement('div'), this.overlayNode_.style.cssText = 'border-radius: 15px;font-size: xx-large;opacity: 0.75;padding: 0.2em 0.5em 0.2em 0.5em;position: absolute;-webkit-user-select: none;-webkit-transition: opacity 180ms ease-in;-moz-user-select: none;-moz-transition: opacity 180ms ease-in;', this.overlayNode_.addEventListener('mousedown', function(e) {
+      e.preventDefault(), e.stopPropagation();
+    }, !0);
+  }
+  this.overlayNode_.style.color = this.prefs_.get('background-color'), this.overlayNode_.style.backgroundColor = this.prefs_.get('foreground-color'), this.overlayNode_.style.fontFamily = this.prefs_.get('font-family'), this.overlayNode_.textContent = e, this.overlayNode_.style.opacity = '0.75', this.overlayNode_.parentNode || this.div_.appendChild(this.overlayNode_);
+  var r = hterm.getClientSize(this.div_),
+    o = hterm.getClientSize(this.overlayNode_);
+  this.overlayNode_.style.top = (r.height - o.height) / 2 + 'px', this.overlayNode_.style.left = (r.width - o.width - this.scrollPort_.currentScrollbarWidthPx) / 2 + 'px';
+  var i = this;
+  this.overlayTimeout_ && clearTimeout(this.overlayTimeout_), null !== t && (this.overlayTimeout_ = setTimeout(function() {
+    i.overlayNode_.style.opacity = '0', i.overlayTimeout_ = setTimeout(function() {
+      i.overlayNode_.parentNode && i.overlayNode_.parentNode.removeChild(i.overlayNode_), i.overlayTimeout_ = null, i.overlayNode_.style.opacity = '0.75';
+    }, 200);
+  }, t || 1500));
+};, hterm.Terminal.prototype.paste = function() {
+  hterm.pasteFromClipboard(this.document_);
+};, hterm.Terminal.prototype.copyStringToClipboard = function(e) {
+  this.prefs_.get('enable-clipboard-notice') && setTimeout(this.showOverlay.bind(this, hterm.notifyCopyMessage, 500), 200);
+  var t = this.document_.createElement('pre');
+  t.textContent = e, t.style.cssText = '-webkit-user-select: text;-moz-user-select: text;position: absolute;top: -99px', this.document_.body.appendChild(t);
+  var r = this.document_.getSelection(),
+    o = r.anchorNode,
+    i = r.anchorOffset,
+    s = r.focusNode,
+    n = r.focusOffset;
+  r.selectAllChildren(t), hterm.copySelectionToClipboard(this.document_), r.extend && (r.collapse(o, i), r.extend(s, n)), t.parentNode.removeChild(t);
+};, hterm.Terminal.prototype.getSelectionText = function() {
+  var e = this.scrollPort_.selection;
+  if (e.sync(), e.isCollapsed) return null;
+  var t = e.startOffset,
+    r = e.startNode;
+  if ('X-ROW' != r.nodeName)
+    for ('#text' == r.nodeName && 'SPAN' == r.parentNode.nodeName && (r = r.parentNode); r.previousSibling;) r = r.previousSibling, t += hterm.TextAttributes.nodeWidth(r);
+  var o = hterm.TextAttributes.nodeWidth(e.endNode) - e.endOffset;
+  if (r = e.endNode, 'X-ROW' != r.nodeName)
+    for ('#text' == r.nodeName && 'SPAN' == r.parentNode.nodeName && (r = r.parentNode); r.nextSibling;) r = r.nextSibling, o += hterm.TextAttributes.nodeWidth(r);
+  var i = this.getRowsText(e.startRow.rowIndex, e.endRow.rowIndex + 1);
+  return lib.wc.substring(i, t, lib.wc.strWidth(i) - o);
+};, hterm.Terminal.prototype.copySelectionToClipboard = function() {
+  var e = this.getSelectionText();
+  null != e && this.copyStringToClipboard(e);
+};, hterm.Terminal.prototype.overlaySize = function() {
+  this.showOverlay(this.screenSize.width + 'x' + this.screenSize.height);
+};, hterm.Terminal.prototype.onVTKeystroke = function(e) {
+  this.scrollOnKeystroke_ && this.scrollPort_.scrollRowToBottom(this.getRowCount()), this.io.onVTKeystroke(this.keyboard.encode(e));
+};, hterm.Terminal.prototype.openUrl = function(e) {
+  var t = window.open(e, '_blank');
+  t.focus();
+};, hterm.Terminal.prototype.openSelectedUrl_ = function() {
+  var e = this.getSelectionText();
+  null == e && (this.screen_.expandSelection(this.document_.getSelection()), e = this.getSelectionText()), e.length > 2048 || e.search(/[\s\[\](){}<>"'\\^`]/) >= 0 || (e.search('^[a-zA-Z][a-zA-Z0-9+.-]*://') < 0 && (e = 'http://' + e), this.openUrl(e));
+};, hterm.Terminal.prototype.onMouse_ = function(e) {
+  if (!e.processedByTerminalHandler_) {
+    var t = !this.defeatMouseReports_ && this.vt.mouseReport != this.vt.MOUSE_REPORT_DISABLED;
+    if (e.processedByTerminalHandler_ = !0, e.terminalRow = parseInt((e.clientY - this.scrollPort_.visibleRowTopMargin) / this.scrollPort_.characterSize.height) + 1, e.terminalColumn = parseInt(e.clientX / this.scrollPort_.characterSize.width) + 1, !('mousedown' == e.type && e.terminalColumn > this.screenSize.width)) {
+      if (this.options_.cursorVisible && !t && (e.terminalRow - 1 == this.screen_.cursorPosition.row && e.terminalColumn - 1 == this.screen_.cursorPosition.column ? this.cursorNode_.style.display = 'none' : 'none' == this.cursorNode_.style.display && (this.cursorNode_.style.display = '')), 'mousedown' == e.type && (e.altKey || !t ? (this.defeatMouseReports_ = !0, this.setSelectionEnabled(!0)) : (this.defeatMouseReports_ = !1, this.document_.getSelection().collapseToEnd(), this.setSelectionEnabled(!1), e.preventDefault())), t) this.scrollBlockerNode_.engaged || ('mousedown' == e.type ? (this.scrollBlockerNode_.engaged = !0, this.scrollBlockerNode_.style.top = e.clientY - 5 + 'px', this.scrollBlockerNode_.style.left = e.clientX - 5 + 'px') : 'mousemove' == e.type && (this.document_.getSelection().collapseToEnd(), e.preventDefault())), this.onMouse(e);
+      else {
+        if ('dblclick' == e.type && this.copyOnSelect && (this.screen_.expandSelection(this.document_.getSelection()), this.copySelectionToClipboard(this.document_)), 'click' == e.type && !e.shiftKey && e.ctrlKey) return clearTimeout(this.timeouts_.openUrl), void(this.timeouts_.openUrl = setTimeout(this.openSelectedUrl_.bind(this), 500));
+        'mousedown' == e.type && e.which == this.mousePasteButton && this.paste(), 'mouseup' == e.type && 1 == e.which && this.copyOnSelect && !this.document_.getSelection().isCollapsed && this.copySelectionToClipboard(this.document_), 'mousemove' != e.type && 'mouseup' != e.type || !this.scrollBlockerNode_.engaged || (this.scrollBlockerNode_.engaged = !1, this.scrollBlockerNode_.style.top = '-99px');
+      }
+      'mouseup' == e.type && this.document_.getSelection().isCollapsed && (this.defeatMouseReports_ = !1);
+    }
+  }
+};, hterm.Terminal.prototype.onMouse = function(e) {};, hterm.Terminal.prototype.onFocusChange_ = function(e) {
+  this.cursorNode_.setAttribute('focus', e), this.restyleCursor_(), e === !0 && this.closeBellNotifications_();
+};, hterm.Terminal.prototype.onScroll_ = function() {
+  this.scheduleSyncCursorPosition_();
+};, hterm.Terminal.prototype.onPaste_ = function(e) {
+  var t = e.text.replace(/\n/gm, '\r');
+  t = this.keyboard.encode(t), this.options_.bracketedPaste && (t = '[200~' + t + '[201~'), this.io.sendString(t);
+};, hterm.Terminal.prototype.onCopy_ = function(e) {
+  this.useDefaultWindowCopy || (e.preventDefault(), setTimeout(this.copySelectionToClipboard.bind(this), 0));
+};, hterm.Terminal.prototype.onResize_ = function() {
+  var e = Math.floor(this.scrollPort_.getScreenWidth() / this.scrollPort_.characterSize.width) || 0,
+    t = lib.f.smartFloorDivide(this.scrollPort_.getScreenHeight(), this.scrollPort_.characterSize.height) || 0;
+  if (!(0 >= e || 0 >= t)) {
+    var r = e != this.screenSize.width || t != this.screenSize.height;
+    this.realizeSize_(e, t), this.showZoomWarning_(1 != this.scrollPort_.characterSize.zoomFactor), r && this.overlaySize(), this.restyleCursor_(), this.scheduleSyncCursorPosition_();
+  }
+};, hterm.Terminal.prototype.onCursorBlink_ = function() {
+  return this.options_.cursorBlink ? void('false' == this.cursorNode_.getAttribute('focus') || '0' == this.cursorNode_.style.opacity ? (this.cursorNode_.style.opacity = '1', this.timeouts_.cursorBlink = setTimeout(this.myOnCursorBlink_, this.cursorBlinkCycle_[0])) : (this.cursorNode_.style.opacity = '0', this.timeouts_.cursorBlink = setTimeout(this.myOnCursorBlink_, this.cursorBlinkCycle_[1]))) : void delete this.timeouts_.cursorBlink;
+};, hterm.Terminal.prototype.setScrollbarVisible = function(e) {
+  this.scrollPort_.setScrollbarVisible(e);
+};, hterm.Terminal.prototype.setScrollWheelMoveMultipler = function(e) {
+  this.scrollPort_.setScrollWheelMoveMultipler(e);
+};, hterm.Terminal.prototype.closeBellNotifications_ = function() {
+  this.bellNotificationList_.forEach(function(e) {
+    e.close();
+  }), this.bellNotificationList_.length = 0;
+};, lib.rtdep('lib.encodeUTF8'), hterm.Terminal.IO = function(e) {
+  this.terminal_ = e, this.previousIO_ = null;
+};, hterm.Terminal.IO.prototype.showOverlay = function(e, t) {
+  this.terminal_.showOverlay(e, t);
+};, hterm.Terminal.IO.prototype.createFrame = function(e, t) {
+  return new hterm.Frame(this.terminal_, e, t);
+};, hterm.Terminal.IO.prototype.setTerminalProfile = function(e) {
+  this.terminal_.setProfile(e);
+};, hterm.Terminal.IO.prototype.push = function() {
+  var e = new hterm.Terminal.IO(this.terminal_);
+  return e.keyboardCaptured_ = this.keyboardCaptured_, e.columnCount = this.columnCount, e.rowCount = this.rowCount, e.previousIO_ = this.terminal_.io, this.terminal_.io = e, e;
+};, hterm.Terminal.IO.prototype.pop = function() {
+  this.terminal_.io = this.previousIO_;
+};, hterm.Terminal.IO.prototype.sendString = function(e) {
+  console.log('Unhandled sendString: ' + e);
+};, hterm.Terminal.IO.prototype.onVTKeystroke = function(e) {
+  console.log('Unobserverd VT keystroke: ' + JSON.stringify(e));
+};, hterm.Terminal.IO.prototype.onTerminalResize_ = function(e, t) {
+  for (var r = this; r;) r.columnCount = e, r.rowCount = t, r = r.previousIO_;
+  this.onTerminalResize(e, t);
+};, hterm.Terminal.IO.prototype.onTerminalResize = function(e, t) {};, hterm.Terminal.IO.prototype.writeUTF8 = function(e) {
+  if (this.terminal_.io != this) throw 'Attempt to print from inactive IO object.';
+  this.terminal_.interpret(e);
+};, hterm.Terminal.IO.prototype.writelnUTF8 = function(e) {
+  if (this.terminal_.io != this) throw 'Attempt to print from inactive IO object.';
+  this.terminal_.interpret(e + '\r\n');
+};, hterm.Terminal.IO.prototype.print = hterm.Terminal.IO.prototype.writeUTF16 = function(e) {
+  this.writeUTF8(lib.encodeUTF8(e));
+};, hterm.Terminal.IO.prototype.println = hterm.Terminal.IO.prototype.writelnUTF16 = function(e) {
+  this.writelnUTF8(lib.encodeUTF8(e));
+};, lib.rtdep('lib.colors'), hterm.TextAttributes = function(e) {
+  this.document_ = e, this.foregroundSource = this.SRC_DEFAULT, this.backgroundSource = this.SRC_DEFAULT, this.foreground = this.DEFAULT_COLOR, this.background = this.DEFAULT_COLOR, this.defaultForeground = 'rgb(255, 255, 255)', this.defaultBackground = 'rgb(0, 0, 0)', this.bold = !1, this.faint = !1, this.italic = !1, this.blink = !1, this.underline = !1, this.strikethrough = !1, this.inverse = !1, this.invisible = !1, this.wcNode = !1, this.tileData = null, this.colorPalette = null, this.resetColorPalette();
+};, hterm.TextAttributes.prototype.enableBold = !0, hterm.TextAttributes.prototype.enableBoldAsBright = !0, hterm.TextAttributes.prototype.DEFAULT_COLOR = new String(''), hterm.TextAttributes.prototype.SRC_DEFAULT = 'default', hterm.TextAttributes.prototype.SRC_RGB = 'rgb', hterm.TextAttributes.prototype.setDocument = function(e) {
+  this.document_ = e;
+};, hterm.TextAttributes.prototype.clone = function() {
+  var e = new hterm.TextAttributes(null);
+  for (var t in this) e[t] = this[t];
+  return e.colorPalette = this.colorPalette.concat(), e;
+};, hterm.TextAttributes.prototype.reset = function() {
+  this.foregroundSource = this.SRC_DEFAULT, this.backgroundSource = this.SRC_DEFAULT, this.foreground = this.DEFAULT_COLOR, this.background = this.DEFAULT_COLOR, this.bold = !1, this.faint = !1, this.italic = !1, this.blink = !1, this.underline = !1, this.strikethrough = !1, this.inverse = !1, this.invisible = !1, this.wcNode = !1;
+};, hterm.TextAttributes.prototype.resetColorPalette = function() {
+  this.colorPalette = lib.colors.colorPalette.concat(), this.syncColors();
+};, hterm.TextAttributes.prototype.isDefault = function() {
+  return !(this.foregroundSource != this.SRC_DEFAULT || this.backgroundSource != this.SRC_DEFAULT || this.bold || this.faint || this.italic || this.blink || this.underline || this.strikethrough || this.inverse || this.invisible || this.wcNode || null != this.tileData);
+};, hterm.TextAttributes.prototype.createContainer = function(e) {
+  if (this.isDefault()) return this.document_.createTextNode(e);
+  var t = this.document_.createElement('span'),
+    r = t.style,
+    o = [];
+  this.foreground != this.DEFAULT_COLOR && (r.color = this.foreground), this.background != this.DEFAULT_COLOR && (r.backgroundColor = this.background), this.enableBold && this.bold && (r.fontWeight = 'bold'), this.faint && (t.faint = !0), this.italic && (r.fontStyle = 'italic'), this.blink && (o.push('blink-node'), t.blinkNode = !0);
+  var i = '';
+  return this.underline && (i += ' underline', t.underline = !0), this.strikethrough && (i += ' line-through', t.strikethrough = !0), i && (r.textDecoration = i), this.wcNode && (o.push('wc-node'), t.wcNode = !0), null != this.tileData && (o.push('tile'), o.push('tile_' + this.tileData), t.tileNode = !0), e && (t.textContent = e), o.length && (t.className = o.join(' ')), t;
+};, hterm.TextAttributes.prototype.matchesContainer = function(e) {
+  if ('string' == typeof e || 3 == e.nodeType) return this.isDefault();
+  var t = e.style;
+  return !(this.wcNode || e.wcNode || null != this.tileData || e.tileNode || this.foreground != t.color || this.background != t.backgroundColor || (this.enableBold && this.bold) != !!t.fontWeight || this.blink != e.blinkNode || this.italic != !!t.fontStyle || !!this.underline != !!e.underline || !!this.strikethrough != !!e.strikethrough);
+};, hterm.TextAttributes.prototype.setDefaults = function(e, t) {
+  this.defaultForeground = e, this.defaultBackground = t, this.syncColors();
+};, hterm.TextAttributes.prototype.syncColors = function() {
+  function e(e) {
+    return 8 > e ? e + 8 : e;
+  }
+  var t = this.foregroundSource,
+    r = this.backgroundSource,
+    o = this.DEFAULT_COLOR,
+    i = this.DEFAULT_COLOR;
+  if (this.inverse && (t = this.backgroundSource, r = this.foregroundSource, o = this.defaultBackground, i = this.defaultForeground), this.enableBoldAsBright && this.bold && t != this.SRC_DEFAULT && t != this.SRC_RGB && (t = e(t)), this.invisible && (t = r, o = this.defaultBackground), t != this.SRC_RGB && (this.foreground = t == this.SRC_DEFAULT ? o : this.colorPalette[t]), this.faint && !this.invisible) {
+    var s = this.foreground == this.DEFAULT_COLOR ? this.defaultForeground : this.foreground;
+    this.foreground = lib.colors.mix(s, 'rgb(0, 0, 0)', .3333);
+  }
+  r != this.SRC_RGB && (this.background = r == this.SRC_DEFAULT ? i : this.colorPalette[r]);
+};, hterm.TextAttributes.containersMatch = function(e, t) {
+  if ('string' == typeof e) return hterm.TextAttributes.containerIsDefault(t);
+  if (e.nodeType != t.nodeType) return !1;
+  if (3 == e.nodeType) return !0;
+  var r = e.style,
+    o = t.style;
+  return r.color == o.color && r.backgroundColor == o.backgroundColor && r.fontWeight == o.fontWeight && r.fontStyle == o.fontStyle && r.textDecoration == o.textDecoration;
+};, hterm.TextAttributes.containerIsDefault = function(e) {
+  return 'string' == typeof e || 3 == e.nodeType;
+};, hterm.TextAttributes.nodeWidth = function(e) {
+  return e.wcNode ? lib.wc.strWidth(e.textContent) : e.textContent.length;
+};, hterm.TextAttributes.nodeSubstr = function(e, t, r) {
+  return e.wcNode ? lib.wc.substr(e.textContent, t, r) : e.textContent.substr(t, r);
+};, hterm.TextAttributes.nodeSubstring = function(e, t, r) {
+  return e.wcNode ? lib.wc.substring(e.textContent, t, r) : e.textContent.substring(t, r);
+};, hterm.TextAttributes.splitWidecharString = function(e) {
+  for (var t = [], r = 0, o = 0, i = 0; i < e.length;) {
+    var s = e.codePointAt(i),
+      n = 65535 >= s ? 1 : 2;
+    128 > s || 1 == lib.wc.charWidth(s) ? o += n : (o && t.push({
+      str: e.substr(r, o)
+    }), t.push({
+      str: e.substr(i, n),
+      wcNode: !0
+    }), r = i + n, o = 0), i += n;
+  }
+  return o && t.push({
+    str: e.substr(r, o)
+  }), t;
+};, lib.rtdep('lib.colors', 'lib.f', 'lib.UTF8Decoder', 'hterm.VT.CharacterMap'), hterm.VT = function(e) {
+  this.terminal = e, e.onMouse = this.onTerminalMouse_.bind(this), this.mouseReport = this.MOUSE_REPORT_DISABLED, this.parseState_ = new hterm.VT.ParseState(this.parseUnknown_), this.leadingModifier_ = '', this.trailingModifier_ = '', this.allowColumnWidthChanges_ = !1, this.oscTimeLimit_ = 2e4;
+  var t = Object.keys(hterm.VT.CC1).map(function(e) {
+    return '\\x' + lib.f.zpad(e.charCodeAt().toString(16), 2);
+  }).join('');
+  this.cc1Pattern_ = new RegExp('[' + t + ']'), this.utf8Decoder_ = new lib.UTF8Decoder, this.enable8BitControl = !1, this.enableClipboardWrite = !0, this.enableDec12 = !1, this.characterEncoding = 'utf-8', this.maxStringSequence = 1024, this.warnUnimplemented = !0, this.G0 = hterm.VT.CharacterMap.maps.B, this.G1 = hterm.VT.CharacterMap.maps[0], this.G2 = hterm.VT.CharacterMap.maps.B, this.G3 = hterm.VT.CharacterMap.maps.B, this.GL = 'G0', this.GR = 'G0', this.savedState_ = new hterm.VT.CursorState(this);
+};, hterm.VT.prototype.MOUSE_REPORT_DISABLED = 0, hterm.VT.prototype.MOUSE_REPORT_CLICK = 1, hterm.VT.prototype.MOUSE_REPORT_DRAG = 3, hterm.VT.ParseState = function(e, t) {
+  this.defaultFunction = e, this.buf = t || null, this.pos = 0, this.func = e, this.args = [];
+};, hterm.VT.ParseState.prototype.reset = function(e) {
+  this.resetParseFunction(), this.resetBuf(e || ''), this.resetArguments();
+};, hterm.VT.ParseState.prototype.resetParseFunction = function() {
+  this.func = this.defaultFunction;
+};, hterm.VT.ParseState.prototype.resetBuf = function(e) {
+  this.buf = 'string' == typeof e ? e : null, this.pos = 0;
+};, hterm.VT.ParseState.prototype.resetArguments = function(e) {
+  this.args.length = 0, 'undefined' != typeof e && (this.args[0] = e);
+};, hterm.VT.ParseState.prototype.iarg = function(e, t) {
+  var r = this.args[e];
+  if (r) {
+    var o = parseInt(r, 10);
+    return 0 == o && (o = t), o;
+  }
+  return t;
+};, hterm.VT.ParseState.prototype.advance = function(e) {
+  this.pos += e;
+};, hterm.VT.ParseState.prototype.peekRemainingBuf = function() {
+  return this.buf.substr(this.pos);
+};, hterm.VT.ParseState.prototype.peekChar = function() {
+  return this.buf.substr(this.pos, 1);
+};, hterm.VT.ParseState.prototype.consumeChar = function() {
+  return this.buf.substr(this.pos++, 1);
+};, hterm.VT.ParseState.prototype.isComplete = function() {
+  return null == this.buf || this.buf.length <= this.pos;
+};, hterm.VT.CursorState = function(e) {
+  this.vt_ = e, this.save();
+};, hterm.VT.CursorState.prototype.save = function() {
+  this.cursor = this.vt_.terminal.saveCursor(), this.textAttributes = this.vt_.terminal.getTextAttributes().clone(), this.GL = this.vt_.GL, this.GR = this.vt_.GR, this.G0 = this.vt_.G0, this.G1 = this.vt_.G1, this.G2 = this.vt_.G2, this.G3 = this.vt_.G3;
+};, hterm.VT.CursorState.prototype.restore = function() {
+  this.vt_.terminal.restoreCursor(this.cursor), this.vt_.terminal.setTextAttributes(this.textAttributes.clone()), this.vt_.GL = this.GL, this.vt_.GR = this.GR, this.vt_.G0 = this.G0, this.vt_.G1 = this.G1, this.vt_.G2 = this.G2, this.vt_.G3 = this.G3;
+};, hterm.VT.prototype.reset = function() {
+  this.G0 = hterm.VT.CharacterMap.maps.B, this.G1 = hterm.VT.CharacterMap.maps[0], this.G2 = hterm.VT.CharacterMap.maps.B, this.G3 = hterm.VT.CharacterMap.maps.B, this.GL = 'G0', this.GR = 'G0', this.savedState_ = new hterm.VT.CursorState(this), this.mouseReport = this.MOUSE_REPORT_DISABLED;
+};, hterm.VT.prototype.onTerminalMouse_ = function(e) {
+  if (this.mouseReport != this.MOUSE_REPORT_DISABLED) {
+    var t, r = 0;
+    e.shiftKey && (r |= 4), (e.metaKey || this.terminal.keyboard.altIsMeta && e.altKey) && (r |= 8), e.ctrlKey && (r |= 16);
+    var o = String.fromCharCode(lib.f.clamp(e.terminalColumn + 32, 32, 255)),
+      i = String.fromCharCode(lib.f.clamp(e.terminalRow + 32, 32, 255));
+    switch (e.type) {
+      case 'mousewheel':
+        s = (e.wheelDeltaY > 0 ? 0 : 1) + 96, s |= r, t = '' + String.fromCharCode(s) + o + i, e.preventDefault();
+        break;
+      case 'mousedown':
+        var s = Math.min(e.which - 1, 2) + 32;
+        s |= r, t = '' + String.fromCharCode(s) + o + i;
+        break;
+      case 'mouseup':
+        t = '#' + o + i;
+        break;
+      case 'mousemove':
+        this.mouseReport == this.MOUSE_REPORT_DRAG && e.which && (s = 32 + Math.min(e.which - 1, 2), s += 32, s |= r, t = '' + String.fromCharCode(s) + o + i);
+        break;
+      case 'click':
+      case 'dblclick':
+        break;
+      default:
+        console.error('Unknown mouse event: ' + e.type, e);
+    }
+    t && this.terminal.io.sendString(t);
+  }
+};, hterm.VT.prototype.interpret = function(e) {
+  for (this.parseState_.resetBuf(this.decode(e)); !this.parseState_.isComplete();) {
+    var t = this.parseState_.func,
+      r = this.parseState_.pos,
+      e = this.parseState_.buf;
+    if (this.parseState_.func.call(this, this.parseState_), this.parseState_.func == t && this.parseState_.pos == r && this.parseState_.buf == e) throw 'Parser did not alter the state!';
+  }
+};, hterm.VT.prototype.decode = function(e) {
+  return 'utf-8' == this.characterEncoding ? this.decodeUTF8(e) : e;
+};, hterm.VT.prototype.encodeUTF8 = function(e) {
+  return lib.encodeUTF8(e);
+};, hterm.VT.prototype.decodeUTF8 = function(e) {
+  return this.utf8Decoder_.decode(e);
+};, hterm.VT.prototype.parseUnknown_ = function(e) {
+  function t(e) {
+    r[r.GL].GL && (e = r[r.GL].GL(e)), r[r.GR].GR && (e = r[r.GR].GR(e)), r.terminal.print(e);
+  }
+  var r = this,
+    o = e.peekRemainingBuf(),
+    i = o.search(this.cc1Pattern_);
+  return 0 == i ? (this.dispatch('CC1', o.substr(0, 1), e), void e.advance(1)) : -1 == i ? (t(o), void e.reset()) : (t(o.substr(0, i)), this.dispatch('CC1', o.substr(i, 1), e), void e.advance(i + 1))
+};, hterm.VT.prototype.parseCSI_ = function(e) {
+  var t = e.peekChar(),
+    r = e.args;
+  t >= '@' && '~' >= t ? (this.dispatch('CSI', this.leadingModifier_ + this.trailingModifier_ + t, e), e.resetParseFunction()) : ';' == t ? this.trailingModifier_ ? e.resetParseFunction() : (r.length || r.push(''), r.push('')) : t >= '0' && '9' >= t ? this.trailingModifier_ ? e.resetParseFunction() : r.length ? r[r.length - 1] += t : r[0] = t : t >= ' ' && '?' >= t && ':' != t ? r.length ? this.trailingModifier_ += t : this.leadingModifier_ += t : this.cc1Pattern_.test(t) ? this.dispatch('CC1', t, e) : e.resetParseFunction(), e.advance(1);
+};, hterm.VT.prototype.parseUntilStringTerminator_ = function(e) {
+  var t = e.peekRemainingBuf(),
+    r = t.search(/(\x1b\\|\x07)/),
+    o = e.args;
+  if (o.length || (o[0] = '', o[1] = new Date), -1 == r) {
+    o[0] += t;
+    var i;
+    return o[0].length > this.maxStringSequence && (i = 'too long: ' + o[0].length), -1 != o[0].indexOf('') && (i = 'embedded escape: ' + o[0].indexOf('')), new Date - o[1] > this.oscTimeLimit_ && (i = 'timeout expired: ' + new Date - o[1]), i ? (console.log('parseUntilStringTerminator_: aborting: ' + i, o[0]), e.reset(o[0]), !1) : (e.advance(t.length), !0);
+  }
+  return o[0].length + r > this.maxStringSequence ? (e.reset(o[0] + t), !1) : (o[0] += t.substr(0, r), e.resetParseFunction(), e.advance(r + ('' == t.substr(r, 1) ? 2 : 1)), !0);
+};, hterm.VT.prototype.dispatch = function(e, t, r) {
+  var o = hterm.VT[e][t];
+  return o ? o == hterm.VT.ignore ? void(this.warnUnimplemented && console.warn('Ignored ' + e + ' code: ' + JSON.stringify(t))) : 'CC1' == e && t > '' && !this.enable8BitControl ? void console.warn('Ignoring 8-bit control code: 0x' + t.charCodeAt(0).toString(16)) : void o.apply(this, [r, t]) : void(this.warnUnimplemented && console.warn('Unknown ' + e + ' code: ' + JSON.stringify(t)))
+};, hterm.VT.prototype.setANSIMode = function(e, t) {
+  '4' == e ? this.terminal.setInsertMode(t) : '20' == e ? this.terminal.setAutoCarriageReturn(t) : this.warnUnimplemented && console.warn('Unimplemented ANSI Mode: ' + e)
+};, hterm.VT.prototype.setDECMode = function(e, t) {
+  switch (e) {
+    case '1':
+      this.terminal.keyboard.applicationCursor = t;
+      break;
+    case '3':
+      this.allowColumnWidthChanges_ && (this.terminal.setWidth(t ? 132 : 80), this.terminal.clearHome(), this.terminal.setVTScrollRegion(null, null));
+      break;
+    case '5':
+      this.terminal.setReverseVideo(t);
+      break;
+    case '6':
+      this.terminal.setOriginMode(t);
+      break;
+    case '7':
+      this.terminal.setWraparound(t);
+      break;
+    case '12':
+      this.enableDec12 && this.terminal.setCursorBlink(t);
+      break;
+    case '25':
+      this.terminal.setCursorVisible(t);
+      break;
+    case '40':
+      this.terminal.allowColumnWidthChanges_ = t;
+      break;
+    case '45':
+      this.terminal.setReverseWraparound(t);
+      break;
+    case '67':
+      this.terminal.keyboard.backspaceSendsBackspace = t;
+      break;
+    case '1000':
+      this.mouseReport = t ? this.MOUSE_REPORT_CLICK : this.MOUSE_REPORT_DISABLED;
+      break;
+    case '1002':
+      this.mouseReport = t ? this.MOUSE_REPORT_DRAG : this.MOUSE_REPORT_DISABLED;
+      break;
+    case '1010':
+      this.terminal.scrollOnOutput = t;
+      break;
+    case '1011':
+      this.terminal.scrollOnKeystroke = t;
+      break;
+    case '1036':
+      this.terminal.keyboard.metaSendsEscape = t;
+      break;
+    case '1039':
+      t ? this.terminal.keyboard.previousAltSendsWhat_ || (this.terminal.keyboard.previousAltSendsWhat_ = this.terminal.keyboard.altSendsWhat, this.terminal.keyboard.altSendsWhat = 'escape') : this.terminal.keyboard.previousAltSendsWhat_ && (this.terminal.keyboard.altSendsWhat = this.terminal.keyboard.previousAltSendsWhat_, this.terminal.keyboard.previousAltSendsWhat_ = null);
+      break;
+    case '47':
+    case '1047':
+      this.terminal.setAlternateMode(t);
+      break;
+    case '1048':
+      this.savedState_.save();
+    case '1049':
+      t ? (this.savedState_.save(), this.terminal.setAlternateMode(t), this.terminal.clear()) : (this.terminal.setAlternateMode(t), this.savedState_.restore());
+      break;
+    case '2004':
+      this.terminal.setBracketedPaste(t);
+      break;
+    default:
+      this.warnUnimplemented && console.warn('Unimplemented DEC Private Mode: ' + e);
+  }
+};, hterm.VT.ignore = function() {};, hterm.VT.CC1 = {}, hterm.VT.ESC = {}, hterm.VT.CSI = {}, hterm.VT.OSC = {}, hterm.VT.VT52 = {}, hterm.VT.CC1['\x00'] = function() {};, hterm.VT.CC1[''] = hterm.VT.ignore, hterm.VT.CC1[''] = function() {
+  this.terminal.ringBell();
+};, hterm.VT.CC1['\b'] = function() {
+  this.terminal.cursorLeft(1);
+};, hterm.VT.CC1['	'] = function() {
+  this.terminal.forwardTabStop();
+};, hterm.VT.CC1['\n'] = function() {
+  this.terminal.formFeed();
+};, hterm.VT.CC1[''] = hterm.VT.CC1['\n'], hterm.VT.CC1['\f'] = function() {
+  this.terminal.formFeed();
+};, hterm.VT.CC1['\r'] = function() {
+  this.terminal.setCursorColumn(0);
+};, hterm.VT.CC1[''] = function() {
+  this.GL = 'G1';
+};, hterm.VT.CC1[''] = function() {
+  this.GL = 'G0';
+};, hterm.VT.CC1[''] = hterm.VT.ignore, hterm.VT.CC1[''] = hterm.VT.ignore, hterm.VT.CC1[''] = function(e) {
+  'G1' == this.GL && (this.GL = 'G0'), e.resetParseFunction(), this.terminal.print('?');
+};, hterm.VT.CC1[''] = hterm.VT.CC1[''], hterm.VT.CC1[''] = function(e) {
+  function t(e) {
+    var r = e.consumeChar();
+    '' != r && (this.dispatch('ESC', r, e), e.func == t && e.resetParseFunction());
+  }
+  e.func = t;
+};, hterm.VT.CC1[''] = hterm.VT.ignore, hterm.VT.CC1['„'] = hterm.VT.ESC.D = function() {
+  this.terminal.lineFeed();
+};, hterm.VT.CC1['…'] = hterm.VT.ESC.E = function() {
+  this.terminal.setCursorColumn(0), this.terminal.cursorDown(1);
+};, hterm.VT.CC1['ˆ'] = hterm.VT.ESC.H = function() {
+  this.terminal.setTabStop(this.terminal.getCursorColumn());
+};, hterm.VT.CC1[''] = hterm.VT.ESC.M = function() {
+  this.terminal.reverseLineFeed();
+};, hterm.VT.CC1['Ž'] = hterm.VT.ESC.N = hterm.VT.ignore, hterm.VT.CC1[''] = hterm.VT.ESC.O = hterm.VT.ignore, hterm.VT.CC1[''] = hterm.VT.ESC.P = function(e) {
+  e.resetArguments(), e.func = this.parseUntilStringTerminator_;
+};, hterm.VT.CC1['–'] = hterm.VT.ESC.V = hterm.VT.ignore, hterm.VT.CC1['—'] = hterm.VT.ESC.W = hterm.VT.ignore, hterm.VT.CC1['˜'] = hterm.VT.ESC.X = hterm.VT.ignore, hterm.VT.CC1['š'] = hterm.VT.ESC.Z = function() {
+  this.terminal.io.sendString('[?1;2c');
+};, hterm.VT.CC1['›'] = hterm.VT.ESC['['] = function(e) {
+  e.resetArguments(), this.leadingModifier_ = '',
+    this.trailingModifier_ = '', e.func = this.parseCSI_;
+};, hterm.VT.CC1['œ'] = hterm.VT.ESC['\\'] = hterm.VT.ignore, hterm.VT.CC1[''] = hterm.VT.ESC[']'] = function(e) {
+  function t(e) {
+    if (this.parseUntilStringTerminator_(e) && e.func != t) {
+      var r = e.args[0].match(/^(\d+);(.*)$/);
+      r ? (e.args[0] = r[2], this.dispatch('OSC', r[1], e)) : console.warn('Invalid OSC: ' + JSON.stringify(e.args[0]));
+    }
+  }
+  e.resetArguments(), e.func = t;
+};, hterm.VT.CC1['ž'] = hterm.VT.ESC['^'] = function(e) {
+  e.resetArguments(), e.func = this.parseUntilStringTerminator_;
+};, hterm.VT.CC1['Ÿ'] = hterm.VT.ESC._ = function(e) {
+  e.resetArguments(), e.func = this.parseUntilStringTerminator_;
+};, hterm.VT.ESC[' '] = function(e) {
+  e.func = function(e) {
+    var t = e.consumeChar();
+    this.warnUnimplemented && console.warn('Unimplemented sequence: ESC 0x20 ' + t), e.resetParseFunction();
+  };
+};, hterm.VT.ESC['#'] = function(e) {
+  e.func = function(e) {
+    var t = e.consumeChar();
+    '8' == t && this.terminal.fill('E'), e.resetParseFunction();
+  };
+};, hterm.VT.ESC['%'] = function(e) {
+  e.func = function(e) {
+    var t = e.consumeChar();
+    '@' != t && 'G' != t && this.warnUnimplemented && console.warn('Unknown ESC % argument: ' + JSON.stringify(t)), e.resetParseFunction();
+  };
+};, hterm.VT.ESC['('] = hterm.VT.ESC[')'] = hterm.VT.ESC['*'] = hterm.VT.ESC['+'] = hterm.VT.ESC['-'] = hterm.VT.ESC['.'] = hterm.VT.ESC['/'] = function(e, t) {
+  e.func = function(e) {
+    var r = e.consumeChar();
+    return '' == r ? (e.resetParseFunction(), void e.func()) : (r in hterm.VT.CharacterMap.maps ? '(' == t ? this.G0 = hterm.VT.CharacterMap.maps[r] : ')' == t || '-' == t ? this.G1 = hterm.VT.CharacterMap.maps[r] : '*' == t || '.' == t ? this.G2 = hterm.VT.CharacterMap.maps[r] : ('+' == t || '/' == t) && (this.G3 = hterm.VT.CharacterMap.maps[r]) : this.warnUnimplemented && console.log('Invalid character set for "' + t + '": ' + r), void e.resetParseFunction());
+  };
+};, hterm.VT.ESC[6] = hterm.VT.ignore, hterm.VT.ESC[7] = function() {
+  this.savedState_.save();
+};, hterm.VT.ESC[8] = function() {
+  this.savedState_.restore();
+};, hterm.VT.ESC[9] = hterm.VT.ignore, hterm.VT.ESC['='] = function() {
+  this.terminal.keyboard.applicationKeypad = !0;
+};, hterm.VT.ESC['>'] = function() {
+  this.terminal.keyboard.applicationKeypad = !1;
+};, hterm.VT.ESC.F = hterm.VT.ignore, hterm.VT.ESC.c = function() {
+  this.reset(), this.terminal.reset();
+};, hterm.VT.ESC.l = hterm.VT.ESC.m = hterm.VT.ignore, hterm.VT.ESC.n = function() {
+  this.GL = 'G2';
+};, hterm.VT.ESC.o = function() {
+  this.GL = 'G3';
+};, hterm.VT.ESC['|'] = function() {
+  this.GR = 'G3';
+};, hterm.VT.ESC['}'] = function() {
+  this.GR = 'G2';
+};, hterm.VT.ESC['~'] = function() {
+  this.GR = 'G1';
+};, hterm.VT.OSC[0] = function(e) {
+  this.terminal.setWindowTitle(e.args[0]);
+};, hterm.VT.OSC[2] = hterm.VT.OSC[0], hterm.VT.OSC[4] = function(e) {
+  for (var t = e.args[0].split(';'), r = parseInt(t.length / 2), o = this.terminal.getTextAttributes().colorPalette, i = [], s = 0; r > s; ++s) {
+    var n = parseInt(t[2 * s]),
+      a = t[2 * s + 1];
+    n >= o.length || ('?' != a ? (a = lib.colors.x11ToCSS(a), a && (o[n] = a)) : (a = lib.colors.rgbToX11(o[n]), a && i.push(n + ';' + a)));
+  }
+  i.length && this.terminal.io.sendString(']4;' + i.join(';') + '');
+};, hterm.VT.OSC[50] = function(e) {
+  var t = e.args[0].match(/CursorShape=(.)/i);
+  if (!t) return void console.warn('Could not parse OSC 50 args: ' + e.args[0]);
+  switch (t[1]) {
+    case '1':
+      this.terminal.setCursorShape(hterm.Terminal.cursorShape.BEAM);
+      break;
+    case '2':
+      this.terminal.setCursorShape(hterm.Terminal.cursorShape.UNDERLINE);
+      break;
+    default:
+      this.terminal.setCursorShape(hterm.Terminal.cursorShape.BLOCK);
+  }
+};, hterm.VT.OSC[52] = function(e) {
+  var t = e.args[0].match(/^[cps01234567]*;(.*)/);
+  if (t) {
+    var r = window.atob(t[1]);
+    r && this.terminal.copyStringToClipboard(this.decode(r));
+  }
+};, hterm.VT.CSI['@'] = function(e) {
+  this.terminal.insertSpace(e.iarg(0, 1));
+};, hterm.VT.CSI.A = function(e) {
+  this.terminal.cursorUp(e.iarg(0, 1));
+};, hterm.VT.CSI.B = function(e) {
+  this.terminal.cursorDown(e.iarg(0, 1));
+};, hterm.VT.CSI.C = function(e) {
+  this.terminal.cursorRight(e.iarg(0, 1));
+};, hterm.VT.CSI.D = function(e) {
+  this.terminal.cursorLeft(e.iarg(0, 1));
+};, hterm.VT.CSI.E = function(e) {
+  this.terminal.cursorDown(e.iarg(0, 1)), this.terminal.setCursorColumn(0);
+};, hterm.VT.CSI.F = function(e) {
+  this.terminal.cursorUp(e.iarg(0, 1)), this.terminal.setCursorColumn(0);
+};, hterm.VT.CSI.G = function(e) {
+  this.terminal.setCursorColumn(e.iarg(0, 1) - 1);
+};, hterm.VT.CSI.H = function(e) {
+  this.terminal.setCursorPosition(e.iarg(0, 1) - 1, e.iarg(1, 1) - 1);
+};, hterm.VT.CSI.I = function(e) {
+  var t = e.iarg(0, 1);
+  t = lib.f.clamp(t, 1, this.terminal.screenSize.width);
+  for (var r = 0; t > r; r++) this.terminal.forwardTabStop();
+};, hterm.VT.CSI.J = hterm.VT.CSI['?J'] = function(e, t) {
+  var r = e.args[0];
+  r && '0' != r ? '1' == r ? this.terminal.eraseAbove() : '2' == r ? this.terminal.clear() : '3' == r && this.terminal.clear() : this.terminal.eraseBelow()
+};, hterm.VT.CSI.K = hterm.VT.CSI['?K'] = function(e, t) {
+  var r = e.args[0];
+  r && '0' != r ? '1' == r ? this.terminal.eraseToLeft() : '2' == r && this.terminal.eraseLine() : this.terminal.eraseToRight();
+};, hterm.VT.CSI.L = function(e) {
+  this.terminal.insertLines(e.iarg(0, 1));
+};, hterm.VT.CSI.M = function(e) {
+  this.terminal.deleteLines(e.iarg(0, 1));
+};, hterm.VT.CSI.P = function(e) {
+  this.terminal.deleteChars(e.iarg(0, 1));
+};, hterm.VT.CSI.S = function(e) {
+  this.terminal.vtScrollUp(e.iarg(0, 1));
+};, hterm.VT.CSI.T = function(e) {
+  e.args.length <= 1 && this.terminal.vtScrollDown(e.iarg(0, 1));
+};, hterm.VT.CSI['>T'] = hterm.VT.ignore, hterm.VT.CSI.X = function(e) {
+  this.terminal.eraseToRight(e.iarg(0, 1));
+};, hterm.VT.CSI.Z = function(e) {
+  var t = e.iarg(0, 1);
+  t = lib.f.clamp(t, 1, this.terminal.screenSize.width);
+  for (var r = 0; t > r; r++) this.terminal.backwardTabStop();
+};, hterm.VT.CSI['`'] = function(e) {
+  this.terminal.setCursorColumn(e.iarg(0, 1) - 1);
+};, hterm.VT.CSI.b = hterm.VT.ignore, hterm.VT.CSI.c = function(e) {
+  e.args[0] && '0' != e.args[0] || this.terminal.io.sendString('[?1;2c');
+};, hterm.VT.CSI['>c'] = function(e) {
+  this.terminal.io.sendString('[>0;256;0c');
+};, hterm.VT.CSI.d = function(e) {
+  this.terminal.setAbsoluteCursorRow(e.iarg(0, 1) - 1);
+};, hterm.VT.CSI.f = hterm.VT.CSI.H, hterm.VT.CSI.g = function(e) {
+  e.args[0] && '0' != e.args[0] ? '3' == e.args[0] && this.terminal.clearAllTabStops() : this.terminal.clearTabStopAtCursor(!1);
+};, hterm.VT.CSI.h = function(e) {
+  for (var t = 0; t < e.args.length; t++) this.setANSIMode(e.args[t], !0);
+};, hterm.VT.CSI['?h'] = function(e) {
+  for (var t = 0; t < e.args.length; t++) this.setDECMode(e.args[t], !0);
+};, hterm.VT.CSI.i = hterm.VT.CSI['?i'] = hterm.VT.ignore, hterm.VT.CSI.l = function(e) {
+  for (var t = 0; t < e.args.length; t++) this.setANSIMode(e.args[t], !1);
+};, hterm.VT.CSI['?l'] = function(e) {
+  for (var t = 0; t < e.args.length; t++) this.setDECMode(e.args[t], !1);
+};, hterm.VT.CSI.m = function(e) {
+  function t(t) {
+    return e.args.length < t + 2 || '5' != e.args[t + 1] ? null : e.iarg(t + 2, 0);
+  }
+
+  function r(t) {
+    if (e.args.length < t + 5 || '2' != e.args[t + 1]) return null;
+    var r = e.iarg(t + 2, 0),
+      o = e.iarg(t + 3, 0),
+      i = e.iarg(t + 4, 0);
+    return 'rgb(' + r + ' ,' + o + ' ,' + i + ')';
+  }
+  var o = this.terminal.getTextAttributes();
+  if (!e.args.length) return void o.reset();
+  for (var i = 0; i < e.args.length; i++) {
+    var s = e.iarg(i, 0);
+    if (30 > s) 0 == s ? o.reset() : 1 == s ? o.bold = !0 : 2 == s ? o.faint = !0 : 3 == s ? o.italic = !0 : 4 == s ? o.underline = !0 : 5 == s ? o.blink = !0 : 7 == s ? o.inverse = !0 : 8 == s ? o.invisible = !0 : 9 == s ? o.strikethrough = !0 : 22 == s ? (o.bold = !1, o.faint = !1) : 23 == s ? o.italic = !1 : 24 == s ? o.underline = !1 : 25 == s ? o.blink = !1 : 27 == s ? o.inverse = !1 : 28 == s ? o.invisible = !1 : 29 == s && (o.strikethrough = !1);
+    else if (50 > s)
+      if (38 > s) o.foregroundSource = s - 30;
+      else if (38 == s) {
+      var n = r(i);
+      if (null != n) o.foregroundSource = o.SRC_RGB, o.foreground = n, i += 5;
+      else {
+        var a = t(i);
+        if (null == a) break;
+        if (i += 2, a >= o.colorPalette.length) continue;
+        o.foregroundSource = a;
+      }
+    }
+    else if (39 == s) o.foregroundSource = o.SRC_DEFAULT;
+    else if (48 > s) o.backgroundSource = s - 40;
+    else if (48 == s) {
+      var n = r(i);
+      if (null != n) o.backgroundSource = o.SRC_RGB, o.background = n, i += 5;
+      else {
+        var a = t(i);
+        if (null == a) break;
+        if (i += 2, a >= o.colorPalette.length) continue;
+        o.backgroundSource = a;
+      }
+    }
+    else o.backgroundSource = o.SRC_DEFAULT;
+    else s >= 90 && 97 >= s ? o.foregroundSource = s - 90 + 8 : s >= 100 && 107 >= s && (o.backgroundSource = s - 100 + 8);
+  }
+  o.setDefaults(this.terminal.getForegroundColor(), this.terminal.getBackgroundColor());
+};, hterm.VT.CSI['>m'] = hterm.VT.ignore, hterm.VT.CSI.n = function(e) {
+  if ('5' == e.args[0]) this.terminal.io.sendString('0n');
+  else if ('6' == e.args[0]) {
+    var t = this.terminal.getCursorRow() + 1,
+      r = this.terminal.getCursorColumn() + 1;
+    this.terminal.io.sendString('[' + t + ';' + r + 'R');
+  }
+};, hterm.VT.CSI['>n'] = hterm.VT.ignore, hterm.VT.CSI['?n'] = function(e) {
+  if ('6' == e.args[0]) {
+    var t = this.terminal.getCursorRow() + 1,
+      r = this.terminal.getCursorColumn() + 1;
+    this.terminal.io.sendString('[' + t + ';' + r + 'R');
+  }
+  else '15' == e.args[0] ? this.terminal.io.sendString('[?11n') : '25' == e.args[0] ? this.terminal.io.sendString('[?21n') : '26' == e.args[0] ? this.terminal.io.sendString('[?12;1;0;0n') : '53' == e.args[0] && this.terminal.io.sendString('[?50n')
+};, hterm.VT.CSI['>p'] = hterm.VT.ignore, hterm.VT.CSI['!p'] = function() {
+  this.reset(), this.terminal.softReset();
+};, hterm.VT.CSI.$p = hterm.VT.ignore, hterm.VT.CSI['?$p'] = hterm.VT.ignore, hterm.VT.CSI['"p'] = hterm.VT.ignore, hterm.VT.CSI.q = hterm.VT.ignore, hterm.VT.CSI[' q'] = function(e) {
+  var t = e.args[0];
+  '0' == t || '1' == t ? (this.terminal.setCursorShape(hterm.Terminal.cursorShape.BLOCK), this.terminal.setCursorBlink(!0)) : '2' == t ? (this.terminal.setCursorShape(hterm.Terminal.cursorShape.BLOCK), this.terminal.setCursorBlink(!1)) : '3' == t ? (this.terminal.setCursorShape(hterm.Terminal.cursorShape.UNDERLINE), this.terminal.setCursorBlink(!0)) : '4' == t ? (this.terminal.setCursorShape(hterm.Terminal.cursorShape.UNDERLINE), this.terminal.setCursorBlink(!1)) : console.warn('Unknown cursor style: ' + t)
+};, hterm.VT.CSI['"q'] = hterm.VT.ignore, hterm.VT.CSI.r = function(e) {
+  var t = e.args,
+    r = t[0] ? parseInt(t[0], 10) - 1 : null,
+    o = t[1] ? parseInt(t[1], 10) - 1 : null;
+  this.terminal.setVTScrollRegion(r, o), this.terminal.setCursorPosition(0, 0);
+};, hterm.VT.CSI['?r'] = hterm.VT.ignore, hterm.VT.CSI.$r = hterm.VT.ignore, hterm.VT.CSI.s = function() {
+  this.savedState_.save();
+};, hterm.VT.CSI['?s'] = hterm.VT.ignore, hterm.VT.CSI.t = hterm.VT.ignore, hterm.VT.CSI.$t = hterm.VT.ignore, hterm.VT.CSI['>t'] = hterm.VT.ignore, hterm.VT.CSI[' t'] = hterm.VT.ignore, hterm.VT.CSI.u = function() {
+  this.savedState_.restore();
+};, hterm.VT.CSI[' u'] = hterm.VT.ignore, hterm.VT.CSI.$v = hterm.VT.ignore, hterm.VT.CSI["'w"] = hterm.VT.ignore, hterm.VT.CSI.x = hterm.VT.ignore, hterm.VT.CSI['*x'] = hterm.VT.ignore, hterm.VT.CSI.$x = hterm.VT.ignore, hterm.VT.CSI.z = function(e) {
+  if (!(e.args.length < 1)) {
+    var t = e.args[0];
+    if ('0' == t) {
+      if (e.args.length < 2) return;
+      this.terminal.getTextAttributes().tileData = e.args[1];
+    }
+    else '1' == t && (this.terminal.getTextAttributes().tileData = null);
+  }
+};, hterm.VT.CSI["'z"] = hterm.VT.ignore, hterm.VT.CSI.$z = hterm.VT.ignore, hterm.VT.CSI["'{"] = hterm.VT.ignore, hterm.VT.CSI["'|"] = hterm.VT.ignore, hterm.VT.CSI[' }'] = hterm.VT.ignore, hterm.VT.CSI[' ~'] = hterm.VT.ignore, lib.rtdep('lib.f'), hterm.VT.CharacterMap = function(e, t) {
+  this.name = e, this.GL = null, this.GR = null, t && this.reset(t);
+};, hterm.VT.CharacterMap.prototype.reset = function(e) {
+  this.glmap = e;
+  var t = Object.keys(this.glmap).map(function(e) {
+    return '\\x' + lib.f.zpad(e.charCodeAt(0).toString(16));
+  });
+  this.glre = new RegExp('[' + t.join('') + ']', 'g'), this.grmap = {}, t.forEach(function(e) {
+    var t = String.fromCharCode(128 & e.charCodeAt(0));
+    this.grmap[t] = this.glmap[e];
+  }.bind(this));
+  var r = Object.keys(this.grmap).map(function(e) {
+    return '\\x' + lib.f.zpad(e.charCodeAt(0).toString(16), 2);
+  });
+  this.grre = new RegExp('[' + r.join('') + ']', 'g'), this.GL = function(e) {
+    return e.replace(this.glre, function(e) {
+      return this.glmap[e];
+    }.bind(this));
+  }.bind(this), this.GR = function(e) {
+    return e.replace(this.grre, function(e) {
+      return this.grmap[e];
+    }.bind(this));
+  }.bind(this);
+};, hterm.VT.CharacterMap.maps = {}, hterm.VT.CharacterMap.maps[0] = new hterm.VT.CharacterMap('graphic', {
+  '`': '◆',
+  a: '▒',
+  b: '␉',
+  c: '␌',
+  d: '␍',
+  e: '␊',
+  f: '°',
+  g: '±',
+  h: '␤',
+  i: '␋',
+  j: '┘',
+  k: '┐',
+  l: '┌',
+  m: '└',
+  n: '┼',
+  o: '⎺',
+  p: '⎻',
+  q: '─',
+  r: '⎼',
+  s: '⎽',
+  t: '├',
+  u: '┤',
+  v: '┴',
+  w: '┬',
+  x: '│',
+  y: '≤',
+  z: '≥',
+  '{': 'π',
+  '|': '≠',
+  '}': '£',
+  '~': '·'
+}), hterm.VT.CharacterMap.maps.A = new hterm.VT.CharacterMap('british', {
+  '#': '£'
+}), hterm.VT.CharacterMap.maps.B = new hterm.VT.CharacterMap('us', null), hterm.VT.CharacterMap.maps[4] = new hterm.VT.CharacterMap('dutch', {
+  '#': '£',
+  '@': '¾',
+  '[': 'IJ',
+  '\\': '½',
+  ']': '|',
+  '{': '¨',
+  '|': 'f',
+  '}': '¼',
+  '~': '´'
+}), hterm.VT.CharacterMap.maps.C = hterm.VT.CharacterMap.maps[5] = new hterm.VT.CharacterMap('finnish', {
+  '[': 'Ä',
+  '\\': 'Ö',
+  ']': 'Å',
+  '^': 'Ü',
+  '`': 'é',
+  '{': 'ä',
+  '|': 'ö',
+  '}': 'å',
+  '~': 'ü'
+}), hterm.VT.CharacterMap.maps.R = new hterm.VT.CharacterMap('french', {
+  '#': '£',
+  '@': 'à',
+  '[': '°',
+  '\\': 'ç',
+  ']': '§',
+  '{': 'é',
+  '|': 'ù',
+  '}': 'è',
+  '~': '¨'
+}), hterm.VT.CharacterMap.maps.Q = new hterm.VT.CharacterMap('french canadian', {
+  '@': 'à',
+  '[': 'â',
+  '\\': 'ç',
+  ']': 'ê',
+  '^': 'î',
+  '`': 'ô',
+  '{': 'é',
+  '|': 'ù',
+  '}': 'è',
+  '~': 'û'
+}), hterm.VT.CharacterMap.maps.K = new hterm.VT.CharacterMap('german', {
+  '@': '§',
+  '[': 'Ä',
+  '\\': 'Ö',
+  ']': 'Ü',
+  '{': 'ä',
+  '|': 'ö',
+  '}': 'ü',
+  '~': 'ß'
+}), hterm.VT.CharacterMap.maps.Y = new hterm.VT.CharacterMap('italian', {
+  '#': '£',
+  '@': '§',
+  '[': '°',
+  '\\': 'ç',
+  ']': 'é',
+  '`': 'ù',
+  '{': 'à',
+  '|': 'ò',
+  '}': 'è',
+  '~': 'ì'
+}), hterm.VT.CharacterMap.maps.E = hterm.VT.CharacterMap.maps[6] = new hterm.VT.CharacterMap('norwegian/danish', {
+  '@': 'Ä',
+  '[': 'Æ',
+  '\\': 'Ø',
+  ']': 'Å',
+  '^': 'Ü',
+  '`': 'ä',
+  '{': 'æ',
+  '|': 'ø',
+  '}': 'å',
+  '~': 'ü'
+}), hterm.VT.CharacterMap.maps.Z = new hterm.VT.CharacterMap('spanish', {
+  '#': '£',
+  '@': '§',
+  '[': '¡',
+  '\\': 'Ñ',
+  ']': '¿',
+  '{': '°',
+  '|': 'ñ',
+  '}': 'ç'
+}), hterm.VT.CharacterMap.maps[7] = hterm.VT.CharacterMap.maps.H = new hterm.VT.CharacterMap('swedish', {
+  '@': 'É',
+  '[': 'Ä',
+  '\\': 'Ö',
+  ']': 'Å',
+  '^': 'Ü',
+  '`': 'é',
+  '{': 'ä',
+  '|': 'ö',
+  '}': 'å',
+  '~': 'ü'
+}), hterm.VT.CharacterMap.maps['='] = new hterm.VT.CharacterMap('swiss', {
+  '#': 'ù',
+  '@': 'à',
+  '[': 'é',
+  '\\': 'ç',
+  ']': 'ê',
+  '^': 'î',
+  _: 'è',
+  '`': 'ô',
+  '{': 'ä',
+  '|': 'ö',
+  '}': 'ü',
+  '~': 'û'
+}), lib.resource.add('hterm/audio/bell', 'audio/ogg;base64', 'T2dnUwACAAAAAAAAAADhqW5KAAAAAMFvEjYBHgF2b3JiaXMAAAAAAYC7AAAAAAAAAHcBAAAAAAC4AU9nZ1MAAAAAAAAAAAAA4aluSgEAAAAAesI3EC3//////////////////8kDdm9yYmlzHQAAAFhpcGguT3JnIGxpYlZvcmJpcyBJIDIwMDkwNzA5AAAAAAEFdm9yYmlzKUJDVgEACAAAADFMIMWA0JBVAAAQAABgJCkOk2ZJKaWUoSh5mJRISSmllMUwiZiUicUYY4wxxhhjjDHGGGOMIDRkFQAABACAKAmOo+ZJas45ZxgnjnKgOWlOOKcgB4pR4DkJwvUmY26mtKZrbs4pJQgNWQUAAAIAQEghhRRSSCGFFGKIIYYYYoghhxxyyCGnnHIKKqigggoyyCCDTDLppJNOOumoo4466ii00EILLbTSSkwx1VZjrr0GXXxzzjnnnHPOOeecc84JQkNWAQAgAAAEQgYZZBBCCCGFFFKIKaaYcgoyyIDQkFUAACAAgAAAAABHkRRJsRTLsRzN0SRP8ixREzXRM0VTVE1VVVVVdV1XdmXXdnXXdn1ZmIVbuH1ZuIVb2IVd94VhGIZhGIZhGIZh+H3f933f930gNGQVACABAKAjOZbjKaIiGqLiOaIDhIasAgBkAAAEACAJkiIpkqNJpmZqrmmbtmirtm3LsizLsgyEhqwCAAABAAQAAAAAAKBpmqZpmqZpmqZpmqZpmqZpmqZpmmZZlmVZlmVZlmVZlmVZlmVZlmVZlmVZlmVZlmVZlmVZlmVZlmVZQGjIKgBAAgBAx3Ecx3EkRVIkx3IsBwgNWQUAyAAACABAUizFcjRHczTHczzHczxHdETJlEzN9EwPCA1ZBQAAAgAIAAAAAABAMRzFcRzJ0SRPUi3TcjVXcz3Xc03XdV1XVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVYHQkFUAAAQAACGdZpZqgAgzkGEgNGQVAIAAAAAYoQhDDAgNWQUAAAQAAIih5CCa0JrzzTkOmuWgqRSb08GJVJsnuamYm3POOeecbM4Z45xzzinKmcWgmdCac85JDJqloJnQmnPOeRKbB62p0ppzzhnnnA7GGWGcc85p0poHqdlYm3POWdCa5qi5FJtzzomUmye1uVSbc84555xzzjnnnHPOqV6czsE54Zxzzonam2u5CV2cc875ZJzuzQnhnHPOOeecc84555xzzglCQ1YBAEAAAARh2BjGnYIgfY4GYhQhpiGTHnSPDpOgMcgppB6NjkZKqYNQUhknpXSC0JBVAAAgAACEEFJIIYUUUkghhRRSSCGGGGKIIaeccgoqqKSSiirKKLPMMssss8wyy6zDzjrrsMMQQwwxtNJKLDXVVmONteaec645SGultdZaK6WUUkoppSA0ZBUAAAIAQCBkkEEGGYUUUkghhphyyimnoIIKCA1ZBQAAAgAIAAAA8CTPER3RER3RER3RER3RER3P8RxREiVREiXRMi1TMz1VVFVXdm1Zl3Xbt4Vd2HXf133f141fF4ZlWZZlWZZlWZZlWZZlWZZlCUJDVgEAIAAAAEIIIYQUUkghhZRijDHHnINOQgmB0JBVAAAgAIAAAAAAR3EUx5EcyZEkS7IkTdIszfI0T/M00RNFUTRNUxVd0RV10xZlUzZd0zVl01Vl1XZl2bZlW7d9WbZ93/d93/d93/d93/d939d1IDRkFQAgAQCgIzmSIimSIjmO40iSBISGrAIAZAAABACgKI7iOI4jSZIkWZImeZZniZqpmZ7pqaIKhIasAgAAAQAEAAAAAACgaIqnmIqniIrniI4oiZZpiZqquaJsyq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7rukBoyCoAQAIAQEdyJEdyJEVSJEVyJAcIDVkFAMgAAAgAwDEcQ1Ikx7IsTfM0T/M00RM90TM9VXRFFwgNWQUAAAIACAAAAAAAwJAMS7EczdEkUVIt1VI11VItVVQ9VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV1TRN0zSB0JCVAAAZAAAjQQYZhBCKcpBCbj1YCDHmJAWhOQahxBiEpxAzDDkNInSQQSc9uJI5wwzz4FIoFURMg40lN44gDcKmXEnlOAhCQ1YEAFEAAIAxyDHEGHLOScmgRM4xCZ2UyDknpZPSSSktlhgzKSWmEmPjnKPSScmklBhLip2kEmOJrQAAgAAHAIAAC6HQkBUBQBQAAGIMUgophZRSzinmkFLKMeUcUko5p5xTzjkIHYTKMQadgxAppRxTzinHHITMQeWcg9BBKAAAIMABACDAQig0ZEUAECcA4HAkz5M0SxQlSxNFzxRl1xNN15U0zTQ1UVRVyxNV1VRV2xZNVbYlTRNNTfRUVRNFVRVV05ZNVbVtzzRl2VRV3RZV1bZl2xZ+V5Z13zNNWRZV1dZNVbV115Z9X9ZtXZg0zTQ1UVRVTRRV1VRV2zZV17Y1UXRVUVVlWVRVWXZlWfdVV9Z9SxRV1VNN2RVVVbZV2fVtVZZ94XRVXVdl2fdVWRZ+W9eF4fZ94RhV1dZN19V1VZZ9YdZlYbd13yhpmmlqoqiqmiiqqqmqtm2qrq1bouiqoqrKsmeqrqzKsq+rrmzrmiiqrqiqsiyqqiyrsqz7qizrtqiquq3KsrCbrqvrtu8LwyzrunCqrq6rsuz7qizruq3rxnHrujB8pinLpqvquqm6um7runHMtm0co6rqvirLwrDKsu/rui+0dSFRVXXdlF3jV2VZ921fd55b94WybTu/rfvKceu60vg5z28cubZtHLNuG7+t+8bzKz9hOI6lZ5q2baqqrZuqq+uybivDrOtCUVV9XZVl3zddWRdu3zeOW9eNoqrquirLvrDKsjHcxm8cuzAcXds2jlvXnbKtC31jyPcJz2vbxnH7OuP2daOvDAnHjwAAgAEHAIAAE8pAoSErAoA4AQAGIecUUxAqxSB0EFLqIKRUMQYhc05KxRyUUEpqIZTUKsYgVI5JyJyTEkpoKZTSUgehpVBKa6GU1lJrsabUYu0gpBZKaS2U0lpqqcbUWowRYxAy56RkzkkJpbQWSmktc05K56CkDkJKpaQUS0otVsxJyaCj0kFIqaQSU0mptVBKa6WkFktKMbYUW24x1hxKaS2kEltJKcYUU20txpojxiBkzknJnJMSSmktlNJa5ZiUDkJKmYOSSkqtlZJSzJyT0kFIqYOOSkkptpJKTKGU1kpKsYVSWmwx1pxSbDWU0lpJKcaSSmwtxlpbTLV1EFoLpbQWSmmttVZraq3GUEprJaUYS0qxtRZrbjHmGkppraQSW0mpxRZbji3GmlNrNabWam4x5hpbbT3WmnNKrdbUUo0txppjbb3VmnvvIKQWSmktlNJiai3G1mKtoZTWSiqxlZJabDHm2lqMOZTSYkmpxZJSjC3GmltsuaaWamwx5ppSi7Xm2nNsNfbUWqwtxppTS7XWWnOPufVWAADAgAMAQIAJZaDQkJUAQBQAAEGIUs5JaRByzDkqCULMOSepckxCKSlVzEEIJbXOOSkpxdY5CCWlFksqLcVWaykptRZrLQAAoMABACDABk2JxQEKDVkJAEQBACDGIMQYhAYZpRiD0BikFGMQIqUYc05KpRRjzknJGHMOQioZY85BKCmEUEoqKYUQSkklpQIAAAocAAACbNCUWByg0JAVAUAUAABgDGIMMYYgdFQyKhGETEonqYEQWgutddZSa6XFzFpqrbTYQAithdYySyXG1FpmrcSYWisAAOzAAQDswEIoNGQlAJAHAEAYoxRjzjlnEGLMOegcNAgx5hyEDirGnIMOQggVY85BCCGEzDkIIYQQQuYchBBCCKGDEEIIpZTSQQghhFJK6SCEEEIppXQQQgihlFIKAAAqcAAACLBRZHOCkaBCQ1YCAHkAAIAxSjkHoZRGKcYglJJSoxRjEEpJqXIMQikpxVY5B6GUlFrsIJTSWmw1dhBKaS3GWkNKrcVYa64hpdZirDXX1FqMteaaa0otxlprzbkAANwFBwCwAxtFNicYCSo0ZCUAkAcAgCCkFGOMMYYUYoox55xDCCnFmHPOKaYYc84555RijDnnnHOMMeecc845xphzzjnnHHPOOeecc44555xzzjnnnHPOOeecc84555xzzgkAACpwAAAIsFFkc4KRoEJDVgIAqQAAABFWYowxxhgbCDHGGGOMMUYSYowxxhhjbDHGGGOMMcaYYowxxhhjjDHGGGOMMcYYY4wxxhhjjDHGGGOMMcYYY4wxxhhjjDHGGGOMMcYYY4wxxhhjjDHGGFtrrbXWWmuttdZaa6211lprrQBAvwoHAP8HG1ZHOCkaCyw0ZCUAEA4AABjDmHOOOQYdhIYp6KSEDkIIoUNKOSglhFBKKSlzTkpKpaSUWkqZc1JSKiWlllLqIKTUWkottdZaByWl1lJqrbXWOgiltNRaa6212EFIKaXWWostxlBKSq212GKMNYZSUmqtxdhirDGk0lJsLcYYY6yhlNZaazHGGGstKbXWYoy1xlprSam11mKLNdZaCwDgbnAAgEiwcYaVpLPC0eBCQ1YCACEBAARCjDnnnHMQQgghUoox56CDEEIIIURKMeYcdBBCCCGEjDHnoIMQQgghhJAx5hx0EEIIIYQQOucchBBCCKGEUkrnHHQQQgghlFBC6SCEEEIIoYRSSikdhBBCKKGEUkopJYQQQgmllFJKKaWEEEIIoYQSSimllBBCCKWUUkoppZQSQgghlFJKKaWUUkIIoZRQSimllFJKCCGEUkoppZRSSgkhhFBKKaWUUkopIYQSSimllFJKKaUAAIADBwCAACPoJKPKImw04cIDUGjISgCADAAAcdhq6ynWyCDFnISWS4SQchBiLhFSijlHsWVIGcUY1ZQxpRRTUmvonGKMUU+dY0oxw6yUVkookYLScqy1dswBAAAgCAAwECEzgUABFBjIAIADhAQpAKCwwNAxXAQE5BIyCgwKx4Rz0mkDABCEyAyRiFgMEhOqgaJiOgBYXGDIB4AMjY20iwvoMsAFXdx1IIQgBCGIxQEUkICDE2544g1PuMEJOkWlDgIAAAAA4AAAHgAAkg0gIiKaOY4Ojw+QEJERkhKTE5QAAAAAALABgA8AgCQFiIiIZo6jw+MDJERkhKTE5AQlAAAAAAAAAAAACAgIAAAAAAAEAAAACAhPZ2dTAAQYOwAAAAAAAOGpbkoCAAAAmc74DRgyNjM69TAzOTk74dnLubewsbagmZiNp4d0KbsExSY/I3XUTwJgkeZdn1HY4zoj33/q9DFtv3Ui1/jmx7lCUtPt18/sYf9MkgAsAGRBd3gMGP4sU+qCPYBy9VrA3YqJosW3W2/ef1iO/u3cg8ZG/57jU+pPmbGEJUgkfnaI39DbPqxddZphbMRmCc5rKlkUMkyx8iIoug5dJv1OYH9a59c+3Gevqc7Z2XFdDjL/qHztRfjWEWxJ/aiGezjohu9HsCZdQBKbiH0VtU/3m85lDG2T/+xkZcYnX+E+aqzv/xTgOoTFG+x7SNqQ4N+oAABSxuVXw77Jd5bmmTmuJakX7509HH0kGYKvARPpwfOSAPySPAc2EkneDwB2HwAAJlQDYK5586N79GJCjx4+p6aDUd27XSvRyXLJkIC5YZ1jLv5lpOhZTz0s+DmnF1diptrnM6UDgIW11Xh8cHTd0/SmbgOAdxcyWwMAAGIrZ3fNSfZbzKiYrK4+tPqtnMVLOeWOG2kVvUY+p2PJ/hkCl5aFRO4TLGYPZcIU3vYM1hohS4jHFlnyW/2T5J7kGsShXWT8N05V+3C/GPqJ1QdWisGPxEzHqXISBPIinWDUt7IeJv/f5OtzBxpTzZZQ+CYEhHXfqG4aABQli72GJhN4oJv+hXcApAJSErAW8G2raAX4NUcABnVt77CzZAB+LsHcVe+Q4h+QB1wh/ZrJTPxSBdI8mgTeAdTsQOoFUEng9BHcVPhxSRRYkKWZJXOFYP6V4AEripJoEjXgA2wJRZHSExmJDm8F0A6gEXsg5a4ZsALItrMB7+fh7UKLvYWSdtsDwFf1mzYzS1F82N1h2Oyt2e76B1QdS0SAsQigLPMOgJS9JRC7hFXA6kUsLFNKD5cA5cTRvgSqPc3Fl99xW3QTi/MHR8DEm6WnvaVQATwRqRKjywQ9BrrhugR2AKTsPQeQckrAOgDOhbTESyrXQ50CkNpXdtWjW7W2/3UjeX3U95gIdalfRAoAmqUEiwp53hCdcCwlg47fcbfzlmQMAgaBkh7c+fcDgF+ifwDXfzegLPcLYJsAAJQArTXjnh/uXGy3v1Hk3pV6/3t5ruW81f6prfbM2Q3WNVy98BwUtbCwhFhAWuPev6Oe/4ZaFQUcgKrVs4defzh1TADA1DEh5b3VlDaECw5b+bPfkKos3tIAue3vJZOih3ga3l6O3PSfIkrLv0PAS86PPdL7g8oc2KteNFKKzKRehOv2gJoFLBPXmaXvPBQILgJon0bbWBszrYZYYwE7jl2j+vTdU7Vpk21LiU0QajPkywAAHqbUC0/YsYOdb4e6BOp7E0cCi04Ao/TgD8ZVAMid6h/A8IeBNkp6/xsAACZELEYIk+yvI6Qz1NN6lIftB/6IMWjWJNOqPTMedAmyaj6Es0QBklJpiSWWHnQ2CoYbGWAmt+0gLQBFKCBnp2QUUQZ/1thtZDBJUpFWY82z34ocorB62oX7qB5y0oPAv/foxH25wVmgIHf2xFOr8leZcBq1Kx3ZvCq9Bga639AxuHuPNL/71YCF4EywJpqHFAX6XF0sjVbuANnvvdLcrufYwOM/iDa6iA468AYAAB6mNBMXcgTD8HSRqJ4vw8CjAlCEPACASlX/APwPOJKl9xQAAAPmnev2eWp33Xgyw3Dvfz6myGk3oyP8YTKsCOvzAgALQi0o1c6Nzs2O2Pg2h4ACIJAgAGP0aNn5x0BDgVfH7u2TtyfDcRIuYAyQhBF/lvSRAttgA6TPbWZA9gaUrZWAUEAA+Dx47Q3/r87HxUUqZmB0BmUuMlojFjHt1gDunnvuX8MImsjSq5WkzSzGS62OEIlOufWWezxWpv6FBgDgJVltfXFYtNAAnqU0xQoD0YLiXo5cF5QV4CnY1tBLAkZCOABAhbk/AM+/AwSCCdlWAAAMcFjS7owb8GVDzveDiZvznbt2tF4bL5odN1YKl88TAEABCZvufq9YCTBtMwVAQUEAwGtNltzSaHvADYC3TxLVjqiRA+OZAMhzcqEgRcAOwoCgvdTxsTHLQEF6+oOb2+PAI8ciPQcXg7pOY+LjxQSv2fjmFuj34gGwz310/bGK6z3xgT887eomWULEaDd04wHetYxdjcgV2SxvSwn0VoZXJRqkRC5ASQ/muVoAUsX7AgAQMBNaVwAAlABRxT/1PmfqLqSRNDbhXb07berpB3b94jpuWEZjBCD2OcdXFpCKEgCDfcFPMw8AAADUwT4lnUm50lmwrpMMhPQIKj6u0E8fr2vGBngMNdIlrZsigjahljud6AFVg+tzXwUnXL3TJLpajaWKA4VAAAAMiFfqJgKAZ08XrtS3dxtQNYcpPvYEG8ClvrQRJgBephwnNWJjtGqmp6VEPSvBe7EBiU3qgJbQAwD4Le8LAMDMhHbNAAAlgK+tFs5O+YyJc9yCnJa3rxLPulGnxwsXV9Fsk2k4PisCAHC8FkwbGE9gJQAAoMnyksj0CdFMZLLgoz8M+FxziwYBgIx+zHiCBAKAlBKNpF1sO9JpVcyEi9ar15YlHgrut5fPJnkdJ6vEwZPyAHQBIEDUrlMcBAAd2KAS0Qq+JwRsE4AJZtMnAD6GnOYwYlOIZvtzUNdjreB7fiMkWI0CmBB6AIAKc38A9osEFlTSGECB+cbeRDC0aRpLHqNPplcK/76Lxn2rpmqyXsYJWRi/FQAAAKBQk9MCAOibrQBQADCDsqpooPutd+05Ce9g6iEdiYXgVmQAI4+4wskEBEiBloNQ6Ki0/KTQ0QjWfjxzi+AeuXKoMjEVfQOZzr0y941qLgM2AExvbZOqcxZ6J6krlrj4y2j9AdgKDx6GnJsVLhbc42uq584+ouSdNBpoCiCVHrz+WzUA/DDtD8ATgA3h0lMCAAzcFv+S+fSSNkeYWlTpb34mf2RfmqqJeMeklhHAfu7VoAEACgAApKRktL+KkQDWMwYCUAAAAHCKsp80xhp91UjqQBw3x45cetqkjQEyu3G9B6N+R650Uq8OVig7wOm6Wun0ea4lKDPoabJs6aLqgbhPzpv4KR4iODilw88ZpY7q1IOMcbASAOAVtmcCnobcrkG4KGS7/ZnskVWRNF9J0RUHKOnByy9WA8Dv6L4AAARMCQUA4GritfVM2lcZfH3Q3T/vZ47J2YHhcmBazjfdyuV25gLAzrc0cwAAAAAYCh6PdwAAAGyWjFW4yScjaWa2mGcofHxWxewKALglWBpLUvwwk+UOh5eNGyUOs1/EF+pZr+ud5OzoGwYdAABg2p52LiSgAY/ZVlOmilEgHn6G3OcwYjzI7vOj1t6xsx4S3lBY96EUQBF6AIBAmPYH4PoGYCoJAADWe+OZJZi7/x76/yH7Lzf9M5XzRKnFPmveMsilQHwVAAAAAKB3LQD8PCIAAADga0QujBLywzeJ4a6Z/ERVBAUlAEDqvoM7BQBAuAguzFqILtmjH3Kd4wfKobnOhA3z85qWoRPm9hwoOHoDAAlCbwDAA56FHAuXflHo3fe2ttG9XUDeA9YmYCBQ0oPr/1QC8IvuCwAAApbUAQCK22MmE3O78VAbHQT9PIPNoT9zNc3l2Oe7TAVLANBufT8MAQAAAGzT4PS8AQAAoELGHb2uaCwwEv1EWhFriUkbAaAZ27/fVZnTZXbWz3BwWpjUaMZKRj7dZ0J//gUeTdpVEwAAZOFsNxKAjQSgA+ABPoY8Jj5y2wje81jsXc/1TOQWTDYZBmAkNDiqVwuA2NJ9AQAAEBKAt9Vrsfs/2N19MO91S9rd8EHTZHnzC5MYmfQEACy/FBcAAADA5c4gi4z8RANs/m6FNXVo9DV46JG1BBDukqlw/Va5G7QbuGVSI+2aZaoLXJrdVj2zlC9Z5QEAEFz/5QzgVZwAAAAA/oXcxyC6WfTu+09Ve/c766J4VTAGUFmA51+VANKi/QPoPwYgYAkA715OH4S0s5KDHvj99MMq8TPFc3roKZnGOoT1bmIhVgc7XAMBAAAAAMAW1VbQw3gapzOpJd+Kd2fc4iSO62fJv9+movui1wUNPAj059N3OVxzk4gV73PmE8FIA2F5mRq37Evc76vLXfF4rD5UJJAw46hW6LZCb5sNLdx+kzMCAAB+hfy95+965ZCLP7B3/VlTHCvDEKtQhTm4KiCgAEAbrfbWTPssAAAAXpee1tVrozYYn41wD1aeYtkKfswN5/SXPO0JDnhO/4laUortv/s412fybe/nONdncoCHnBVliu0CQGBWlPY/5Kwom2L/kruPM6Q7oz4tvDQy+bZ3HzOi+gNHA4DZEgA='), lib.resource.add('hterm/concat/date', 'text/plain', 'Tue, 25 Apr 2017 15:12:45 +0000'), lib.resource.add('hterm/changelog/version', 'text/plain', '1.62'), lib.resource.add('hterm/changelog/date', 'text/plain', '2017-04-17'), lib.resource.add('hterm/git/HEAD', 'text/plain', 'git rev-parse HEAD');