From 2ff9221f457d3b8295134a1c58e5df53886e7ef9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Wed, 2 Nov 2016 12:34:55 +0100 Subject: [PATCH 01/35] Remove logs when PoP is added in order to hide the pass --- ns-manager/routes/dc.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/ns-manager/routes/dc.rb b/ns-manager/routes/dc.rb index 18eb8ef..3fb57f0 100644 --- a/ns-manager/routes/dc.rb +++ b/ns-manager/routes/dc.rb @@ -81,14 +81,12 @@ class DcController < TnovaManager description: pop_info['description'], extra_info: pop_info['extra_info'] } - logger.debug serv begin dc = Dc.find_by(name: pop_info['name']) halt 409, 'DC Duplicated. Use PUT for update.' # i es.update_attributes!(:host => pop_info['host'], :port => pop_info['port'], :token => @token, :depends_on => serv_reg['depends_on']) rescue Mongoid::Errors::DocumentNotFound => e begin - puts serv dc = Dc.create!(serv) rescue => e puts 'ERROR.................' From d8245487ccc0e711771684f50ffcdb88a35113a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Wed, 2 Nov 2016 12:50:40 +0100 Subject: [PATCH 02/35] End-to-end script: Fix when duplicated VNFD/NSD --- end_to_end.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/end_to_end.rb b/end_to_end.rb index 4b7b113..3b4191f 100644 --- a/end_to_end.rb +++ b/end_to_end.rb @@ -244,10 +244,12 @@ def check_if_descriptors(vnf_id, ns_id) def create_descriptors() puts "Creating descriptors" vnfd = File.read('vnfd-validator/assets/samples/vnfd_example.json') + puts begin response = JSON.parse(RestClient.post "#{@tenor}/vnfs", vnfd, :content_type => :json) rescue RestClient::ExceptionWithResponse => e puts e + puts "Using the created VNFD" response = {'vnfd' => {}} response['vnfd']['id'] = JSON.parse(vnfd)['vnfd']['id'] rescue => e @@ -263,6 +265,11 @@ def create_descriptors() nsd = File.read('nsd-validator/assets/samples/nsd_example.json') begin response = JSON.parse(RestClient.post "#{@tenor}/network-services", nsd, :content_type => :json) + rescue RestClient::ExceptionWithResponse => e + puts e + puts "Using the created NSD" + response = {'nsd' => {}} + response['nsd']['id'] = JSON.parse(nsd)['nsd']['id'] rescue => e puts "Error...." puts e From 0e4e2779a094d20573f85c7445ffc4fdbe66c623 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Wed, 2 Nov 2016 14:29:15 +0100 Subject: [PATCH 03/35] Updated VNFD/NSD catalogue in UI. incremental request. --- ui/README.md | 2 +- .../scripts/controllers/modulesController.js | 6 ++--- ui/app/scripts/controllers/nsController.js | 25 +++++++++++-------- ui/app/scripts/controllers/vnfController.js | 16 ++++++------ ui/app/views/t-nova/ns.html | 2 +- ui/app/views/t-nova/vnf.html | 2 +- vnf-manager/routes/catalogue.rb | 4 +-- 7 files changed, 31 insertions(+), 26 deletions(-) diff --git a/ui/README.md b/ui/README.md index d617fdb..d8a6c85 100644 --- a/ui/README.md +++ b/ui/README.md @@ -17,7 +17,7 @@ Copy the sample config file: Run `cp app/config.js.sample app/config.js` And edit the config.js with the correct IPs. -The UI uses the Gatekeeper Authentication. By default the UI has preconfigured the default user and password of Gatekeeper. If the admin password is different, please update the file app.rb. +The UI uses the TeNOR Authentication. By default the UI has preconfigured the default user and password. 3. Execute the UI Run `rake start` and the server will listen on port 9000 by default. diff --git a/ui/app/scripts/controllers/modulesController.js b/ui/app/scripts/controllers/modulesController.js index ad87bd3..1553488 100644 --- a/ui/app/scripts/controllers/modulesController.js +++ b/ui/app/scripts/controllers/modulesController.js @@ -4,7 +4,7 @@ angular.module('tNovaApp') .controller('modulesController', function ($scope, $filter, tenorService, $interval, $modal) { $scope.updateModulesList = function () { - tenorService.get("configs/services").then(function (data) { + tenorService.get("modules/services").then(function (data) { if (data === undefined) return; $scope.modulesCollection = data; }); @@ -25,7 +25,7 @@ angular.module('tNovaApp') }); }; $scope.deleteItem = function (id) { - tenorService.delete("configs/services?name=" + id).then(function (data) {}); + tenorService.delete("modules/services?name=" + id).then(function (data) {}); this.$hide(); }; @@ -38,7 +38,7 @@ angular.module('tNovaApp') $scope.registerService = function (service) { console.log("register service"); console.log(service); - tenorService.post("configs/registerService", JSON.stringify(service)).then(function (data) {}); + tenorService.post("modules/services", JSON.stringify(service)).then(function (data) {}); }; $scope.options = { diff --git a/ui/app/scripts/controllers/nsController.js b/ui/app/scripts/controllers/nsController.js index 42c728d..0aa946d 100644 --- a/ui/app/scripts/controllers/nsController.js +++ b/ui/app/scripts/controllers/nsController.js @@ -9,20 +9,25 @@ angular.module('tNovaApp') name: "UniMi" }]; $scope.descriptor = {}; - var page = 0; - - $scope.getServiceList = function () { - tenorService.get('network-services?limit=1000').then(function (data) { - $scope.dataCollection = _.sortBy(data, function (o) { - var dt = new Date(o.created_at); - return -dt; - }); + var page_num = 20; + var page = 1; + $scope.dataCollection = []; + $scope.getServiceList = function (page) { + tenorService.get('network-services?offset=' + page + '&limit=' + page_num).then(function (data) { + if (data.length > 0) { + $scope.dataCollection = _.sortBy($scope.dataCollection.concat(data), function (o) { + var dt = new Date(o.created_at); + return -dt; + }); + page++; + $scope.getServiceList(page); + } }); }; - $scope.getServiceList(); + $scope.getServiceList(page); var promise = $interval(function () { - $scope.getServiceList(); + $scope.getServiceList(page); }, defaultTimer); $scope.deleteDialog = function (id) { diff --git a/ui/app/scripts/controllers/vnfController.js b/ui/app/scripts/controllers/vnfController.js index f12332d..b339f59 100644 --- a/ui/app/scripts/controllers/vnfController.js +++ b/ui/app/scripts/controllers/vnfController.js @@ -4,25 +4,25 @@ angular.module('tNovaApp') .controller('vnfController', function ($scope, $stateParams, $filter, tenorService, $interval, $modal) { $scope.descriptor = {}; - var page_num = 200; - var page = 0; + var page_num = 20; + var page = 1; $scope.dataCollection = []; $scope.getVnfList = function (page) { - $scope.dataCollection = []; tenorService.get('vnfs?offset=' + page + '&limit=' + page_num).then(function (data) { - if (data !== []) { - $scope.dataCollection = _.sortBy(angular.extend($scope.dataCollection, data), function (o) { + if (data.length > 0) { + $scope.dataCollection = _.sortBy($scope.dataCollection.concat(data), function (o) { var dt = new Date(o.created_at); return -dt; - }) - page = page++; - //$scope.getVnfList(page); + }); + page++; + $scope.getVnfList(page); } }); }; $scope.getVnfList(page); var promise = $interval(function () { + $scope.dataCollection = []; $scope.getVnfList(page); }, 1000000); diff --git a/ui/app/views/t-nova/ns.html b/ui/app/views/t-nova/ns.html index 4e6ae5e..5efea90 100644 --- a/ui/app/views/t-nova/ns.html +++ b/ui/app/views/t-nova/ns.html @@ -37,7 +37,7 @@ - + {{row.nsd.id}} {{row.nsd.name}} {{row.nsd.description}} diff --git a/ui/app/views/t-nova/vnf.html b/ui/app/views/t-nova/vnf.html index d1b16a0..d2e7501 100644 --- a/ui/app/views/t-nova/vnf.html +++ b/ui/app/views/t-nova/vnf.html @@ -37,7 +37,7 @@ - + {{row.vnfd.name}} {{row.vnfd.id}} {{row.version}} diff --git a/vnf-manager/routes/catalogue.rb b/vnf-manager/routes/catalogue.rb index 6ac130f..295d44d 100644 --- a/vnf-manager/routes/catalogue.rb +++ b/vnf-manager/routes/catalogue.rb @@ -90,7 +90,7 @@ class Catalogue < VNFManager # Forward request to VNF Catalogue begin - response = RestClient.get catalogue.host + '/vnfs', 'X-Auth-Token' => catalogue.token + response = RestClient.get catalogue.host + request.fullpath, 'X-Auth-Token' => catalogue.token rescue Errno::ECONNREFUSED halt 500, 'VNF Catalogue unreachable' rescue => e @@ -141,7 +141,7 @@ class Catalogue < VNFManager catalogue, errors = ServiceConfigurationHelper.get_module('vnf_catalogue') halt 500, errors if errors - + # Forward request to VNF Catalogue begin response = RestClient.delete catalogue.host + '/vnfs/' + external_vnf_id, 'X-Auth-Token' => catalogue.token From 2129cc804c3b4b4a36905ff082bd987fad7f94eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Wed, 2 Nov 2016 14:30:18 +0100 Subject: [PATCH 04/35] Removed deprecated files --- dependencies/dialog_install_dependencies.sh | 79 --------------------- ns-manager/models/init.rb | 2 +- ns-manager/models/serviceModel.rb | 12 ---- tenor_development.sh | 5 +- 4 files changed, 3 insertions(+), 95 deletions(-) delete mode 100755 dependencies/dialog_install_dependencies.sh delete mode 100644 ns-manager/models/serviceModel.rb diff --git a/dependencies/dialog_install_dependencies.sh b/dependencies/dialog_install_dependencies.sh deleted file mode 100755 index 49b4e74..0000000 --- a/dependencies/dialog_install_dependencies.sh +++ /dev/null @@ -1,79 +0,0 @@ -#!/bin/bash -# Author: Wojciech Mąka -# -# -# -installation () { -echo $1 - if [ $1 -eq 0 ] #install mongodb - then - echo -e -n "\033[1;36mChecking if mongodb is installed" - mongod --version > /dev/null 2>&1 - MONGO_IS_INSTALLED=$? - if [ $MONGO_IS_INSTALLED -eq 0 ]; then - echo ">>> MongoDB already installed" - else - echo "Do you want to install mongodb? (y/n)" - read install - if [ "$install" = "y" ]; then - echo -e -n "\033[1;31mMongodb is not installed... Installing..." - install_mongodb - fi - fi - - prog=2 - return $prog - fi - if [ $1 -eq 1 ] #install gatekeeper - then - echo "Install gatekeeper" - - prog=4 - return $prog - fi - if [ $1 -eq 2 ] #install ruby - then - - prog=6 - return $prog - fi - if [ $1 -eq 3 ] #install npm - then - - prog=100 - return $prog - fi -} - -tmpv=${0%/*} -echo $tmpv -cd $tmpv - -dialog --title "Installing prerequisites..." \ ---backtitle "Installing prerequisites..." \ ---msgbox "This installer will install all dependecies needed for buildig: couchdb-qt, " 10 40 - -cmd=(dialog --separate-output --checklist "Select options:" 22 76 16) - options=(1 "Mongo DB" on # any option can be set to default to "on" - 2 "Gatekeeper" on - 3 "Ruby" on - 4 "NodeJS / NPM" on - 5 "RabbitMQ" off) - choices=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty) - clear - -phase=0 -prog=0 -{ -for choice in $choices -do - echo $choice - phase=$choice - installation $phase - prog=$? - echo $prog - phase=$[$phase+1] -done -} | dialog --title "Installing prerequisites..." \ - --backtitle "Installing prerequisites..." \ - --gauge "Installation in progress... " 10 40 $prog \ No newline at end of file diff --git a/ns-manager/models/init.rb b/ns-manager/models/init.rb index 1613f6b..b1513e2 100644 --- a/ns-manager/models/init.rb +++ b/ns-manager/models/init.rb @@ -1,4 +1,4 @@ -require_relative 'serviceModel'#deprecated +#require_relative 'serviceModel'#deprecated require_relative 'statisticModel' require_relative 'perfomanceStatisticModel' require_relative 'mongoid_prefixable' diff --git a/ns-manager/models/serviceModel.rb b/ns-manager/models/serviceModel.rb deleted file mode 100644 index 1619b93..0000000 --- a/ns-manager/models/serviceModel.rb +++ /dev/null @@ -1,12 +0,0 @@ -class ServiceModel - - include Mongoid::Document - - field :name, type: String - field :host, type: String - field :port, type: String - field :path, type: String - field :type, type: String - field :service_key, type: String - index({:name => 1}, {unique: true}) -end diff --git a/tenor_development.sh b/tenor_development.sh index 45d6945..614cfa4 100755 --- a/tenor_development.sh +++ b/tenor_development.sh @@ -1,10 +1,9 @@ #!/bin/bash SESSION='nsmanager' SESSION2='vnfmanager' -SESSION3='gatekeeper' -SESSION4='ui' +SESSION3='ui' -byobu -2 new-session -d -s $SESSION4 +byobu -2 new-session -d -s $SESSION3 echo "Starting User Interface..." byobu rename-window 'UI' byobu send-keys "cd ui" C-m From 303ae21ff4ed73b83619f61d62d011f38048bc2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Wed, 2 Nov 2016 16:27:37 +0100 Subject: [PATCH 05/35] Implemented password change from dashboard. --- ns-manager/routes/authentication.rb | 36 ++++++--- ns-manager/spec/auth_spec.rb | 74 ++++++++++++++++++- ui/app/scripts/controllers/auth.js | 3 +- .../controllers/configurationController.js | 37 +++++++++- ui/app/scripts/services/auth.js | 24 ++++++ ui/app/views/t-nova/configuration.html | 24 +++--- 6 files changed, 173 insertions(+), 25 deletions(-) diff --git a/ns-manager/routes/authentication.rb b/ns-manager/routes/authentication.rb index 71edd0f..49bf00b 100644 --- a/ns-manager/routes/authentication.rb +++ b/ns-manager/routes/authentication.rb @@ -108,17 +108,35 @@ class TeNORAuthentication < TnovaManager post '/:uid/reset_password' do user = User.where(email: params[:email]).first user.password_reset_hash = BCrypt::Engine.generate_salt - recoverPassMail(user.email, password_reset_hash) + #recoverPassMail(user.email, password_reset_hash) end - put '/:uid/update_password' do - user = User.where(email: params[:email], password_reset_hash: params[:verification_code]).first - user.password = params[:password] - user.password_salt = BCrypt::Engine.generate_salt - user.password_hash = BCrypt::Engine.hash_secret(params[:password], user.password_salt) - if user.password == password_confirmation - user.password_reset_hash = '' - user.save! + put '/:uid/update_password' do |uid| + + return 415 unless request.content_type == 'application/json' + credentials, errors = parse_json(request.body.read) + logger.error errors if errors + halt 400 if errors + + begin + user = User.find_by(id: uid) + rescue Mongoid::Errors::DocumentNotFound => e + logger.error 'User not found.' + halt 401 + end + + if user.password_hash == BCrypt::Engine.hash_secret(credentials['old_password'], user.password_salt) + logger.debug "Old password is correct." + if credentials['password'] == credentials['re_password'] + user.password = credentials['password'] + user.password_salt = BCrypt::Engine.generate_salt + user.password_hash = BCrypt::Engine.hash_secret(credentials['password'], user.password_salt) + user.save! + else + halt 404, "New passwords don't match." + end + else + halt 404, "Old password doesn't match." end status 200 end diff --git a/ns-manager/spec/auth_spec.rb b/ns-manager/spec/auth_spec.rb index 48b3999..704c177 100644 --- a/ns-manager/spec/auth_spec.rb +++ b/ns-manager/spec/auth_spec.rb @@ -132,6 +132,78 @@ def app end end + #update user password + describe 'PUT /auth' do + let(:user) { create :user } + + context 'given a missing header credentials' do + let(:response) { put '/invalid_id/update_password', {name: 'teste'}.to_json, rack_env={'CONTENT_TYPE' => 'application/x-www-form-urlencoded'} } + + it 'responds with a 415' do + puts user.id + expect(response.status).to eq 415 + end + + it 'responds with an empty body' do + expect(response.body).to be_empty + end + end + + context 'given an invalid user id' do + let(:response) { put '/invalid_id/update_password', {name: 'teste'}.to_json, rack_env={'CONTENT_TYPE' => 'application/json'} } + + it 'responds with a 404' do + expect(response.status).to eq 401 + end + + it 'responds with an empty body' do + expect(response.body).to be_empty + end + end + + context 'given a valid user id but invalid passwords' do + let(:response) { put '/' + user.id.to_s + '/update_password', {old_password: "secret2", password: "secret2", re_password: "secret2"}.to_json, rack_env={'CONTENT_TYPE' => 'application/json'} } + + it 'responds with a 404' do + puts user.id + expect(response.status).to eq 404 + end + + it 'response body should contain a String' do + puts user.id + expect(response.body).to be_a String + end + end + + context 'given a valid user id but invalid passwords' do + let(:response) { put '/' + user.id.to_s + '/update_password', {old_password: "secret", password: "secret2", re_password: "secret3"}.to_json, rack_env={'CONTENT_TYPE' => 'application/json'} } + + it 'responds with a 404' do + puts user.id + expect(response.status).to eq 404 + end + + it 'response body should contain a String' do + expect(response.body).to be_a String + end + end + + context 'given a valid user id and valid passwords' do + let(:response) { put '/' + user.id.to_s + '/update_password', {old_password: "secret", password: "secret2", re_password: "secret2"}.to_json, rack_env={'CONTENT_TYPE' => 'application/json'} } + + it 'responds with a 200' do + + puts user.name + puts user.password + expect(response.status).to eq 200 + end + + it 'response body should be empty' do + expect(response.body).to be_empty + end + end + end + =begin describe 'POST /auth' do context 'given an invalid content type' do @@ -198,6 +270,4 @@ def app end end =end - describe 'PUT /auth/:id' do - end end diff --git a/ui/app/scripts/controllers/auth.js b/ui/app/scripts/controllers/auth.js index 7bd6f7c..620a275 100644 --- a/ui/app/scripts/controllers/auth.js +++ b/ui/app/scripts/controllers/auth.js @@ -16,7 +16,8 @@ angular.module('tNovaApp') console.log(username); $window.localStorage.username = username $window.localStorage.token = data.token; - $window.localStorage.expiration = data.expiration; + $window.localStorage.expiration = data.expires_at; + $window.localStorage.uid = data.uid; $location.path('/dashboard'); },function (error) { $rootScope.loginError = 'Error with the Authentication module.'; diff --git a/ui/app/scripts/controllers/configurationController.js b/ui/app/scripts/controllers/configurationController.js index 49c81e1..ce96ba9 100644 --- a/ui/app/scripts/controllers/configurationController.js +++ b/ui/app/scripts/controllers/configurationController.js @@ -1,8 +1,43 @@ 'use strict'; angular.module('tNovaApp') - .controller('configurationController', function ($window, $scope, $filter, AuthService, $alert) { + .controller('configurationController', function ($window, $scope, $filter, AuthService, $alert, tenorService) { $scope.user = {}; + console.log($window.localStorage); + $scope.user.name = $window.localStorage.username; + var uid = $window.localStorage.uid; + + $scope.update_user = function(user){ + console.log(user); + AuthService.put('token', uid + '/update_password', user).then(function(d){ + console.log(d); + $alert({ + title: "Success: ", + content: "User password updated correctly.", + placement: 'top', + type: 'success', + keyboard: true, + show: true, + container: '#alerts-container', + duration: 5 + }); + $scope.user = {}; + $scope.user.name = $window.localStorage.username; + }, function errorCallback(response) { + console.log("Error"); + console.log(response); + $alert({ + title: "Error: ", + content: "User password not updated.", + placement: 'top', + type: 'danger', + keyboard: true, + show: true, + container: '#alerts-container', + duration: 5 + }); + }); + }; $scope.registerUser = function (user) { console.log(user); if (user.username === undefined || user.password === undefined || user.password2 === undefined) { diff --git a/ui/app/scripts/services/auth.js b/ui/app/scripts/services/auth.js index afda610..036f3b3 100644 --- a/ui/app/scripts/services/auth.js +++ b/ui/app/scripts/services/auth.js @@ -162,6 +162,27 @@ angular.module('tNovaApp') return deferred.promise; }; + var put = function (token, path, object) { + var deferred = $q.defer(); + var url = 'rest/api/auth/' + path; + $http.put(url, object, { + headers: { + 'X-Auth-Token': token, + 'X-host': TENOR + } + }).then( + function (response) { + console.log(response); + deferred.resolve(response.data); + }, + function (response) { + console.log(response); + deferred.reject(response); + } + ); + return deferred.promise; + }; + var remove = function (token, path) { var deferred = $q.defer(); var url = 'rest/gk/api/' + path; @@ -197,6 +218,9 @@ angular.module('tNovaApp') }, delete: function (token, path) { return remove(token, path); + }, + put: function (token, path, obj) { + return put(token, path, obj); } }; diff --git a/ui/app/views/t-nova/configuration.html b/ui/app/views/t-nova/configuration.html index 30941ff..1d86e89 100644 --- a/ui/app/views/t-nova/configuration.html +++ b/ui/app/views/t-nova/configuration.html @@ -9,24 +9,24 @@

Configuration

- +
- +
- +
- +
-
-
- Submit +
+
+
@@ -40,24 +40,24 @@

Configuration

- +
- +
- +
- Admin user + Admin user
- +
From 201a734b7b09475484ac4d512f2490de5ed1b60a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Wed, 2 Nov 2016 16:29:14 +0100 Subject: [PATCH 06/35] Refactor NS manager DC, and NS provisioning keystone --- ns-manager/helpers/dc.rb | 2 +- ns-manager/main.rb | 2 +- ns-manager/routes/dc.rb | 1 - ns-manager/routes/vnfs.rb | 2 +- ns-provisioning/helpers/init.rb | 6 +++--- ns-provisioning/helpers/instantiation.rb | 12 ------------ .../helpers/{ => keystone}/authentication.rb | 0 .../helpers/{ => keystone}/keystone_v2.rb | 1 + .../helpers/{ => keystone}/keystone_v3.rb | 0 9 files changed, 7 insertions(+), 19 deletions(-) rename ns-provisioning/helpers/{ => keystone}/authentication.rb (100%) rename ns-provisioning/helpers/{ => keystone}/keystone_v2.rb (99%) rename ns-provisioning/helpers/{ => keystone}/keystone_v3.rb (100%) diff --git a/ns-manager/helpers/dc.rb b/ns-manager/helpers/dc.rb index 77068d9..3449a1a 100644 --- a/ns-manager/helpers/dc.rb +++ b/ns-manager/helpers/dc.rb @@ -16,7 +16,7 @@ # limitations under the License. # # @see ApplicationHelper -module GatekeeperHelper +module DcHelper # Get list of PoPs # diff --git a/ns-manager/main.rb b/ns-manager/main.rb index a1be991..8ccb179 100644 --- a/ns-manager/main.rb +++ b/ns-manager/main.rb @@ -71,7 +71,7 @@ class TnovaManager < Sinatra::Application helpers ApplicationHelper helpers ServiceConfigurationHelper helpers AuthenticationHelper - helpers GatekeeperHelper + helpers DcHelper helpers StatisticsHelper helpers VimHelper diff --git a/ns-manager/routes/dc.rb b/ns-manager/routes/dc.rb index 3fb57f0..cab24a3 100644 --- a/ns-manager/routes/dc.rb +++ b/ns-manager/routes/dc.rb @@ -35,7 +35,6 @@ class DcController < TnovaManager # @overload get '/pops/dc/:id' # Returns a DC get '/dc/:id' do |id| - puts Dc.all.to_json begin dc = Dc.find(id.to_i) rescue Mongoid::Errors::DocumentNotFound => e diff --git a/ns-manager/routes/vnfs.rb b/ns-manager/routes/vnfs.rb index b637bc8..179edbe 100644 --- a/ns-manager/routes/vnfs.rb +++ b/ns-manager/routes/vnfs.rb @@ -124,7 +124,7 @@ class VNFCatalogue < TnovaManager rescue => e logger.error e.response # halt e.response.code, e.response.body - logger.error 'Any network service is using this VNF.' + logger.error 'No network services using this VNF.' end begin diff --git a/ns-provisioning/helpers/init.rb b/ns-provisioning/helpers/init.rb index 59e9cd5..522793c 100644 --- a/ns-provisioning/helpers/init.rb +++ b/ns-provisioning/helpers/init.rb @@ -24,6 +24,6 @@ require_relative 'hot' require_relative 'utils' require_relative 'instantiation' -require_relative 'authentication' -require_relative 'keystone_v2' -require_relative 'keystone_v3' +require_relative 'keystone/authentication' +require_relative 'keystone/keystone_v2' +require_relative 'keystone/keystone_v3' diff --git a/ns-provisioning/helpers/instantiation.rb b/ns-provisioning/helpers/instantiation.rb index 8221e88..85701f7 100644 --- a/ns-provisioning/helpers/instantiation.rb +++ b/ns-provisioning/helpers/instantiation.rb @@ -67,18 +67,6 @@ def create_authentication(instance, nsd_id, pop_info, callback_url) credentials, errors = generate_credentials(@instance, keystone_url, popUrls, tenant_id, user_id, token) return 400, errors if errors pop_auth = pop_auth.merge(credentials) -=begin - keystone_version = URI(keystone_url).path.split('/').last - if keystone_version == 'v2.0' - credentials, errors = generate_v2_credentials(@instance, popUrls, tenant_id, user_id, token) - return 400, errors if errors - pop_auth = pop_auth.merge(credentials) - elsif keystone_version == 'v3' - pop_auth, errors = generate_v3_credentials(@instance, popUrls, tenant_id, user_id, token) - return 400, errors if errors - pop_auth = pop_auth.merge(credentials) - end -=end end end pop_auth diff --git a/ns-provisioning/helpers/authentication.rb b/ns-provisioning/helpers/keystone/authentication.rb similarity index 100% rename from ns-provisioning/helpers/authentication.rb rename to ns-provisioning/helpers/keystone/authentication.rb diff --git a/ns-provisioning/helpers/keystone_v2.rb b/ns-provisioning/helpers/keystone/keystone_v2.rb similarity index 99% rename from ns-provisioning/helpers/keystone_v2.rb rename to ns-provisioning/helpers/keystone/keystone_v2.rb index e54ff12..4f078d0 100644 --- a/ns-provisioning/helpers/keystone_v2.rb +++ b/ns-provisioning/helpers/keystone/keystone_v2.rb @@ -17,6 +17,7 @@ # # @see NSProvisioner module Authenticationv2Helper + def generate_v2_credentials(instance, popUrls, tenant_id, user_id, token) @instance = instance pop_auth = {} diff --git a/ns-provisioning/helpers/keystone_v3.rb b/ns-provisioning/helpers/keystone/keystone_v3.rb similarity index 100% rename from ns-provisioning/helpers/keystone_v3.rb rename to ns-provisioning/helpers/keystone/keystone_v3.rb From 50cb188de1b7734adfbcc0da30a27b04820e698d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Wed, 2 Nov 2016 16:32:07 +0100 Subject: [PATCH 07/35] NS Provisioning removing unused functions --- ns-provisioning/helpers/ns.rb | 7 +++++-- ns-provisioning/helpers/pop.rb | 5 ----- ns-provisioning/helpers/vim.rb | 22 ---------------------- 3 files changed, 5 insertions(+), 29 deletions(-) diff --git a/ns-provisioning/helpers/ns.rb b/ns-provisioning/helpers/ns.rb index 449f7c8..b4e7636 100644 --- a/ns-provisioning/helpers/ns.rb +++ b/ns-provisioning/helpers/ns.rb @@ -133,7 +133,6 @@ def recoverState(instance, _error) unless settings.default_tenant && !popUrls[:is_admin] logger.info "Removing user stack...." stack_url = auth_info['stack_url'] - logger.debug 'Removing user reserved stack...' if !auth_info['stack_url'].nil? response, errors = delete_stack_with_wait(auth_info['stack_url'], token) logger.error errors if errors @@ -186,7 +185,11 @@ def instantiate(instance, nsd, instantiation_info) settings.infr_repository end - logger.info 'List of available PoPs: ' + pop_list.to_s + pop_list_ids = [] + pop_list.map do |hash| + pop_list_ids << { id: hash["id"] } + end + logger.info 'List of available PoPs: ' + pop_list_ids.to_s if pop_list.size == 1 || mapping_id.nil? pop_id = pop_list[0]['id'] elsif !mapping_id.nil? diff --git a/ns-provisioning/helpers/pop.rb b/ns-provisioning/helpers/pop.rb index 25ea544..9d0bf1d 100644 --- a/ns-provisioning/helpers/pop.rb +++ b/ns-provisioning/helpers/pop.rb @@ -62,13 +62,8 @@ def getPopUrls(extraInfo) popUrls[:compute] = item.split('=')[1] elsif key == 'orch-endpoint' popUrls[:orch] = item.split('=')[1] - elsif key == 'tenant-name'#deprecated - popUrls[:tenant] = item.split('=')[1] elsif key == 'dns' popUrls[:dns] << item.split('=')[1] unless item.split('=')[1].nil? - elsif key == 'isAdmin'#deprecated - popUrls[:is_admin] = false - popUrls[:is_admin] = true if item.split('=')[1].to_s == 'true' end end popUrls diff --git a/ns-provisioning/helpers/vim.rb b/ns-provisioning/helpers/vim.rb index 045b65b..ef59289 100644 --- a/ns-provisioning/helpers/vim.rb +++ b/ns-provisioning/helpers/vim.rb @@ -18,28 +18,6 @@ # @see NSProvisioner module VimHelper - #deprecated - def deleteTenant(keystoneUrl, tenant_id, token) - begin - response = RestClient.delete keystoneUrl + '/tenants/' + tenant_id, :content_type => :json, :'X-Auth-Token' => token - rescue => e - logger.error e - logger.error e.response.body - end - nil - end -#deprecated - def deleteUser(keystoneUrl, user_id, token) - begin - response = RestClient.delete keystoneUrl + '/users/' + user_id, :content_type => :json, :'X-Auth-Token' => token - rescue => e - logger.error e - # logger.error e.response.body - end - - nil - end - def getAdminRole(keystoneUrl, token) begin response = RestClient.get keystoneUrl + '/OS-KSADM/roles', :content_type => :json, :'X-Auth-Token' => token From 4183d63ab41af00d874be30831624b491172f14f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Wed, 2 Nov 2016 16:41:27 +0100 Subject: [PATCH 08/35] End to end handle errors fix --- end_to_end.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/end_to_end.rb b/end_to_end.rb index 3b4191f..7be2b2c 100644 --- a/end_to_end.rb +++ b/end_to_end.rb @@ -358,7 +358,7 @@ def recover_state(error) end @e2e[:instances].each do |instances| - delete_instance(instances) + delete_instance(instances[:id]) end exit From a739409fff91bb7f66df4c4bc01bc078424e7e35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Wed, 2 Nov 2016 17:36:32 +0100 Subject: [PATCH 09/35] NS Provisioning and VNFDvalicator refactor using Rubocop --- .codeclimate.yml | 4 + ns-provisioning/helpers/hot.rb | 2 +- ns-provisioning/helpers/init.rb | 1 - ns-provisioning/helpers/instantiation.rb | 48 ++-- .../helpers/keystone/authentication.rb | 132 ++++++----- .../helpers/keystone/keystone_v2.rb | 1 - .../helpers/keystone/keystone_v3.rb | 1 - ns-provisioning/helpers/mapping.rb | 77 ++++--- ns-provisioning/helpers/monitoring.rb | 113 +++++----- ns-provisioning/helpers/ns.rb | 31 ++- ns-provisioning/helpers/pop.rb | 1 - ns-provisioning/helpers/vim.rb | 5 +- ns-provisioning/routes/ns.rb | 9 +- ns-provisioning/routes/scaling.rb | 207 ++++++++---------- vnfd-validator/Rakefile | 12 +- vnfd-validator/helpers/vnfd.rb | 16 +- vnfd-validator/routes/vnfd.rb | 2 +- 17 files changed, 314 insertions(+), 348 deletions(-) create mode 100644 .codeclimate.yml diff --git a/.codeclimate.yml b/.codeclimate.yml new file mode 100644 index 0000000..d12b62a --- /dev/null +++ b/.codeclimate.yml @@ -0,0 +1,4 @@ +exclude_paths: +- "**/doc" +- "ui/app/bower_components" +- "**/.yardoc" diff --git a/ns-provisioning/helpers/hot.rb b/ns-provisioning/helpers/hot.rb index 7698c7b..bc4d688 100644 --- a/ns-provisioning/helpers/hot.rb +++ b/ns-provisioning/helpers/hot.rb @@ -258,7 +258,7 @@ def delete_stack_with_wait(stack_url, auth_token) def generateUserHotTemplate(hot_generator_message) begin - response = RestClient.post settings.hot_generator + "/userhot", hot_generator_message.to_json, content_type: :json, accept: :json + response = RestClient.post settings.hot_generator + '/userhot', hot_generator_message.to_json, content_type: :json, accept: :json rescue Errno::ECONNREFUSED error = { 'info' => 'HOT Generator unrechable.' } return 500, error diff --git a/ns-provisioning/helpers/init.rb b/ns-provisioning/helpers/init.rb index 522793c..4d61603 100644 --- a/ns-provisioning/helpers/init.rb +++ b/ns-provisioning/helpers/init.rb @@ -15,7 +15,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # -#require_relative 'utils' require_relative 'ns' require_relative 'vim' require_relative 'monitoring' diff --git a/ns-provisioning/helpers/instantiation.rb b/ns-provisioning/helpers/instantiation.rb index 85701f7..7f106a3 100644 --- a/ns-provisioning/helpers/instantiation.rb +++ b/ns-provisioning/helpers/instantiation.rb @@ -17,7 +17,6 @@ # # @see NSProvisioner module InstantiationHelper - # Create an authentication to PoP_id # # @param [JSON] instance NSR instance @@ -26,7 +25,7 @@ module InstantiationHelper # @param [JSON] callback_url Callback url in case of error happens # @return [Hash, nil] authentication # @return [Hash, String] if the parsed message is an invalid JSON - def create_authentication(instance, nsd_id, pop_info, callback_url) + def create_authentication(instance, _nsd_id, pop_info, _callback_url) @instance = instance logger.info 'Authentication not created for this PoP. Starting creation of credentials.' @@ -38,7 +37,7 @@ def create_authentication(instance, nsd_id, pop_info, callback_url) pop_auth['urls'] = popUrls # create credentials for pop_id - if popUrls[:keystone].nil? || popUrls[:orch].nil? #|| popUrls[:tenant].nil? + if popUrls[:keystone].nil? || popUrls[:orch].nil? # || popUrls[:tenant].nil? return handleError(@instance, 'Internal error: Keystone and/or openstack urls missing.') end @@ -56,14 +55,14 @@ def create_authentication(instance, nsd_id, pop_info, callback_url) token = credentials[:token] if !pop_info['is_admin'] - pop_auth['username'] = pop_info['user'] - pop_auth['tenant_name'] = pop_info['tenant_name'] - pop_auth['password'] = pop_info['password'] - pop_auth['tenant_id'] = tenant_id - pop_auth['user_id'] = user_id - pop_auth['token'] = token + pop_auth['username'] = pop_info['user'] + pop_auth['tenant_name'] = pop_info['tenant_name'] + pop_auth['password'] = pop_info['password'] + pop_auth['tenant_id'] = tenant_id + pop_auth['user_id'] = user_id + pop_auth['token'] = token else - #generate credentials + # generate credentials credentials, errors = generate_credentials(@instance, keystone_url, popUrls, tenant_id, user_id, token) return 400, errors if errors pop_auth = pop_auth.merge(credentials) @@ -107,13 +106,13 @@ def instantiate_vnf(instance, nsd_id, vnf, slaInfo) auth: { url: { keystone: popUrls[:keystone], - orch: popUrls[:orch],# to remove + orch: popUrls[:orch], # to remove heat: popUrls[:orch], compute: popUrls[:compute] }, tenant_id: pop_auth['tenant_id'], token: pop_auth['token'], - is_admin: pop_auth['is_admin'] + is_admin: pop_auth['is_admin'] }, reserved_resources: @instance['resource_reservation'].find { |resources| resources[:pop_id] == pop_id }, security_group_id: pop_auth['security_group_id'], @@ -126,18 +125,17 @@ def instantiate_vnf(instance, nsd_id, vnf, slaInfo) begin response = RestClient.post settings.vnf_manager + '/vnf-provisioning/vnf-instances', vnf_provisioning_info.to_json, content_type: :json -=begin rescue RestClient::ExceptionWithResponse => e - puts "Excepion with response" - puts e - logger.error e - logger.error e.response - if !e.response.nil? - logger.error e.response.body - end - #return e.response.code, e.response.body - logger.error 'Handle error.' - return -=end + # rescue RestClient::ExceptionWithResponse => e + # puts "Excepion with response" + # puts e + # logger.error e + # logger.error e.response + # if !e.response.nil? + # logger.error e.response.body + # end + # #return e.response.code, e.response.body + # logger.error 'Handle error.' + # return rescue => e @instance.push(lifecycle_event_history: 'ERROR_CREATING ' + vnf_id.to_s + ' VNF') @instance.update_attribute('status', 'ERROR_CREATING') @@ -165,7 +163,7 @@ def instantiate_vnf(instance, nsd_id, vnf, slaInfo) end end logger.error 'Handle error.' - return 400, "Error wiht the VNF" + return 400, 'Error wiht the VNF' end vnf_manager_response, errors = parse_json(response) diff --git a/ns-provisioning/helpers/keystone/authentication.rb b/ns-provisioning/helpers/keystone/authentication.rb index 23be6cb..57f1d10 100644 --- a/ns-provisioning/helpers/keystone/authentication.rb +++ b/ns-provisioning/helpers/keystone/authentication.rb @@ -17,81 +17,79 @@ # # @see NSProvisioner module AuthenticationHelper - - def authenticate(keystone_url, tenant_name, username, password) - keystone_version = URI(keystone_url).path.split('/').last - if keystone_version == 'v2.0' - user_authentication, errors = authentication_v2(keystone_url, tenant_name, username, password) - logger.error errors if errors - return 400, errors.to_json if errors - tenant_id = user_authentication['access']['token']['tenant']['id'] - user_id = user_authentication['access']['user']['id'] - token = user_authentication['access']['token']['id'] - elsif keystone_version == 'v3' - user_authentication, errors = authentication_v3(keystone_url, tenant_name, username, password) - logger.error errors if errors - return 400, errors.to_json if errors - if !user_authentication['token']['project'].nil? - tenant_id = user_authentication['token']['project']['id'] - user_id = user_authentication['token']['user']['id'] - token = user_authentication['token']['id'] - else - errors = "No project found with the authentication." - return 400, errors.to_json if errors - end + def authenticate(keystone_url, tenant_name, username, password) + keystone_version = URI(keystone_url).path.split('/').last + if keystone_version == 'v2.0' + user_authentication, errors = authentication_v2(keystone_url, tenant_name, username, password) + logger.error errors if errors + return 400, errors.to_json if errors + tenant_id = user_authentication['access']['token']['tenant']['id'] + user_id = user_authentication['access']['user']['id'] + token = user_authentication['access']['token']['id'] + elsif keystone_version == 'v3' + user_authentication, errors = authentication_v3(keystone_url, tenant_name, username, password) + logger.error errors if errors + return 400, errors.to_json if errors + if !user_authentication['token']['project'].nil? + tenant_id = user_authentication['token']['project']['id'] + user_id = user_authentication['token']['user']['id'] + token = user_authentication['token']['id'] + else + errors = 'No project found with the authentication.' + return 400, errors.to_json if errors + end + end + { tenant_id: tenant_id, user_id: user_id, token: token } end - {:tenant_id => tenant_id, :user_id => user_id, :token => token} - end - def generate_credentials(instance, keystone_url, popUrls, tenant_id, user_id, token) - keystone_version = URI(keystone_url).path.split('/').last - if keystone_version == 'v2.0' - credentials, errors = generate_v2_credentials(instance, popUrls, tenant_id, user_id, token) - return 400, errors if errors - elsif keystone_version == 'v3' - credentials, errors = generate_v3_credentials(instance, popUrls, tenant_id, user_id, token) - return 400, errors if errors + def generate_credentials(instance, keystone_url, popUrls, tenant_id, user_id, token) + keystone_version = URI(keystone_url).path.split('/').last + if keystone_version == 'v2.0' + credentials, errors = generate_v2_credentials(instance, popUrls, tenant_id, user_id, token) + return 400, errors if errors + elsif keystone_version == 'v3' + credentials, errors = generate_v3_credentials(instance, popUrls, tenant_id, user_id, token) + return 400, errors if errors + end + credentials end - credentials - end - - def create_user_and_project(heat_api, instance_id, project_name, username, password, tenant_id, token) - generated_credentials = {} - generated_credentials['password'] = password - generated_credentials['tenant_name'] = project_name - generated_credentials['username'] = username - hot_generator_message = { - project_name: generated_credentials['tenant_name'], - username: generated_credentials['username'], - password: generated_credentials['password'], - domain: nil - } + def create_user_and_project(heat_api, _instance_id, project_name, username, password, tenant_id, token) + generated_credentials = {} + generated_credentials['password'] = password + generated_credentials['tenant_name'] = project_name + generated_credentials['username'] = username - logger.info 'Generating user HOT template...' - hot, errors = generateUserHotTemplate(hot_generator_message) - return handleError(@instance, errors) if errors + hot_generator_message = { + project_name: generated_credentials['tenant_name'], + username: generated_credentials['username'], + password: generated_credentials['password'], + domain: nil + } - logger.info 'Send user template to HEAT Orchestration' - stack_name = 'user_' + @instance['id'].to_s - template = { stack_name: stack_name, template: hot } - stack, errors = sendStack(heat_api, tenant_id, template, token) - return handleError(@instance, errors) if errors - stack_id = stack['stack']['id'] - stack_url = stack['stack']['links'][0]['href'] + logger.info 'Generating user HOT template...' + hot, errors = generateUserHotTemplate(hot_generator_message) + return handleError(@instance, errors) if errors - logger.info 'Checking user stack creation...' - stack_info, errors = create_stack_wait(heat_api, tenant_id, stack_name, token, 'NS User') - return handleError(@instance, errors) if errors + logger.info 'Send user template to HEAT Orchestration' + stack_name = 'user_' + @instance['id'].to_s + template = { stack_name: stack_name, template: hot } + stack, errors = sendStack(heat_api, tenant_id, template, token) + return handleError(@instance, errors) if errors + stack_id = stack['stack']['id'] + stack_url = stack['stack']['links'][0]['href'] - logger.info 'User stack CREATE_COMPLETE. Reading user information from stack...' - sleep(3) - stack_info, errors = getStackInfo(heat_api, tenant_id, stack_name, token) - return handleError(@instance, errors) if errors - tenant_id = stack_info['stack']['outputs'].find{ |res| res['output_key'] == 'project_id' }['output_value'] - user_id = stack_info['stack']['outputs'].find{ |res| res['output_key'] == 'user_id' }['output_value'] + logger.info 'Checking user stack creation...' + stack_info, errors = create_stack_wait(heat_api, tenant_id, stack_name, token, 'NS User') + return handleError(@instance, errors) if errors - return stack_url, tenant_id, user_id - end + logger.info 'User stack CREATE_COMPLETE. Reading user information from stack...' + sleep(3) + stack_info, errors = getStackInfo(heat_api, tenant_id, stack_name, token) + return handleError(@instance, errors) if errors + tenant_id = stack_info['stack']['outputs'].find { |res| res['output_key'] == 'project_id' }['output_value'] + user_id = stack_info['stack']['outputs'].find { |res| res['output_key'] == 'user_id' }['output_value'] + [stack_url, tenant_id, user_id] + end end diff --git a/ns-provisioning/helpers/keystone/keystone_v2.rb b/ns-provisioning/helpers/keystone/keystone_v2.rb index 4f078d0..e54ff12 100644 --- a/ns-provisioning/helpers/keystone/keystone_v2.rb +++ b/ns-provisioning/helpers/keystone/keystone_v2.rb @@ -17,7 +17,6 @@ # # @see NSProvisioner module Authenticationv2Helper - def generate_v2_credentials(instance, popUrls, tenant_id, user_id, token) @instance = instance pop_auth = {} diff --git a/ns-provisioning/helpers/keystone/keystone_v3.rb b/ns-provisioning/helpers/keystone/keystone_v3.rb index aa9fb72..3ae9084 100644 --- a/ns-provisioning/helpers/keystone/keystone_v3.rb +++ b/ns-provisioning/helpers/keystone/keystone_v3.rb @@ -17,7 +17,6 @@ # # @see NSProvisioner module Authenticationv3Helper - def generate_v3_credentials(instance, popUrls, tenant_id, user_id, token) @instance = instance pop_auth = {} diff --git a/ns-provisioning/helpers/mapping.rb b/ns-provisioning/helpers/mapping.rb index 2732cab..33884d9 100644 --- a/ns-provisioning/helpers/mapping.rb +++ b/ns-provisioning/helpers/mapping.rb @@ -17,50 +17,47 @@ # # @see MappingHelper module MappingHelper - - # Call the Service Mapping for service allocation - # - # @param [JSON] Microservice information - # @return [Hash, nil] if the parsed message is a valid JSON - # @return [Hash, String] if the parsed message is an invalid JSON - def callMapping(ms, nsd) - - begin - response = RestClient.post settings.mapping + '/mapper', ms.to_json, :content_type => :json - rescue => e - logger.error e - if (defined?(e.response)).nil? - #halt 400, "NS-Mapping unavailable" + # Call the Service Mapping for service allocation + # + # @param [JSON] Microservice information + # @return [Hash, nil] if the parsed message is a valid JSON + # @return [Hash, String] if the parsed message is an invalid JSON + def callMapping(ms, _nsd) + begin + response = RestClient.post settings.mapping + '/mapper', ms.to_json, content_type: :json + rescue => e + logger.error e + if defined?(e.response).nil? + # halt 400, "NS-Mapping unavailable" + end + return 500, 'Service Mapping error.' + # halt e.response.code, e.response.body end - return 500, "Service Mapping error." - #halt e.response.code, e.response.body - end - mapping, errors = parse_json(response.body) - return 400, errors if errors + mapping, errors = parse_json(response.body) + return 400, errors if errors - return mapping - end - - # When the Mapping is not required, only one pop or is selected manually, use the same format for the response - def getMappingResponse(nsd, pop_id) - vnf_mapping = [] - nsd['vnfds'].each do |vnf_id| - vnf_mapping << {"maps_to_PoP" => "/pop/#{pop_id}", "vnf" => "/" + vnf_id.to_s} + mapping end - mapping = { - "created_at" => "Thu Nov 5 10:13:25 2015", - "links_mapping" => - [ - { - "vld_id" => "vld1", - "maps_to_link" => "/pop/link/85b0bc34-dff0-4399-8435-4fb2ed65790a" - } - ], - "vnf_mapping" => vnf_mapping - } - return mapping - end + # When the Mapping is not required, only one pop or is selected manually, use the same format for the response + def getMappingResponse(nsd, pop_id) + vnf_mapping = [] + nsd['vnfds'].each do |vnf_id| + vnf_mapping << { 'maps_to_PoP' => "/pop/#{pop_id}", 'vnf' => '/' + vnf_id.to_s } + end + mapping = { + 'created_at' => 'Thu Nov 5 10:13:25 2015', + 'links_mapping' => + [ + { + 'vld_id' => 'vld1', + 'maps_to_link' => '/pop/link/85b0bc34-dff0-4399-8435-4fb2ed65790a' + } + ], + 'vnf_mapping' => vnf_mapping + } + mapping + end end diff --git a/ns-provisioning/helpers/monitoring.rb b/ns-provisioning/helpers/monitoring.rb index 7aa50fd..197f2cb 100644 --- a/ns-provisioning/helpers/monitoring.rb +++ b/ns-provisioning/helpers/monitoring.rb @@ -17,72 +17,67 @@ # # @see OrchestratorNsProvisioner module MonitoringHelper + # Prepare the monitoring data and sends to the NS Monitoring + # + # @param [JSON] message the NSD + # @param [JSON] message the NSR id + # @param [JSON] message the ns instance + # @return [Hash, nil] if the parsed message is a valid JSON + # @return [Hash, String] if the parsed message is an invalid JSON + def monitoringData(nsd, nsi_id, instance) + monitoring = { nsi_id: nsi_id } - # Prepare the monitoring data and sends to the NS Monitoring - # - # @param [JSON] message the NSD - # @param [JSON] message the NSR id - # @param [JSON] message the ns instance - # @return [Hash, nil] if the parsed message is a valid JSON - # @return [Hash, String] if the parsed message is an invalid JSON - def monitoringData(nsd, nsi_id, instance) + vnfs = nsd['vnfds'] + monitor = nsd['monitoring_parameters'] - monitoring = {:nsi_id => nsi_id} + paramsVnf = [] + paramsNs = [] + sla = nsd['sla'] + sla.each do |s| + assurance_parameters = s['assurance_parameters'] + assurance_parameters.each_with_index do |x, i| + paramsVnf << { id: i + 1, name: x['name'], unit: x['unit'] } + paramsNs << { id: i + 1, name: x['name'], formula: x['formula'], value: x['value'] } + end + end + monitoring[:parameters] = paramsNs + vnf_instances = [] + instance['vnfrs'].each do |x| + vnf_instances << { id: x['vnfd_id'], parameters: paramsVnf, vnfr_id: x['vnfr_id'] } + end + monitoring[:vnf_instances] = vnf_instances - vnfs = nsd['vnfds'] - monitor = nsd['monitoring_parameters'] + # puts JSON.pretty_generate(monitoring) - paramsVnf = [] - paramsNs = [] - sla = nsd['sla'] - sla.each {|s| - assurance_parameters = s['assurance_parameters'] - assurance_parameters.each_with_index {|x, i| - paramsVnf << {:id => i+1, :name => x['name'], :unit => x['unit']} - paramsNs << {:id => i+1, :name => x['name'], :formula => x['formula'], :value => x['value']} - } - } - monitoring[:parameters] = paramsNs - vnf_instances = [] - instance['vnfrs'].each {|x| - vnf_instances << {:id => x['vnfd_id'], :parameters => paramsVnf, :vnfr_id => x['vnfr_id']} - } - monitoring[:vnf_instances] = vnf_instances + begin + response = RestClient.post settings.ns_monitoring + '/ns-monitoring/monitoring-parameters', monitoring.to_json, content_type: :json + rescue Errno::ECONNREFUSED + puts 'NS Monitoring unreachable' + # halt 500, 'NS Monitoring unreachable' + rescue => e + logger.error e + # halt e.response.code, e.response.body + end - #puts JSON.pretty_generate(monitoring) - - begin - response = RestClient.post settings.ns_monitoring + '/ns-monitoring/monitoring-parameters', monitoring.to_json, :content_type => :json - rescue Errno::ECONNREFUSED - puts 'NS Monitoring unreachable' -# halt 500, 'NS Monitoring unreachable' - rescue => e - logger.error e - #halt e.response.code, e.response.body + # return monitoring end - #return monitoring - end - - def sla_enforcement(nsd, instance_id) - parameters = [] + def sla_enforcement(nsd, instance_id) + parameters = [] - nsd['sla'].each do |sla| - #sla['id'] - sla['assurance_parameters'].each do |assurance_parameter| - parameters.push({:param_name => assurance_parameter['param_name'], :minimum => nil, :maximum => nil}) - end - - end - sla = {:nsi_id => instance_id, :parameters => parameters} - begin - response = RestClient.post settings.sla_enforcement + "/sla-enforcement/slas", sla.to_json, :content_type => :json - rescue => e - logger.error e - if (defined?(e.response)).nil? - halt 503, "SLA-Enforcement unavailable" - end - halt e.response.code, e.response.body + nsd['sla'].each do |sla| + # sla['id'] + sla['assurance_parameters'].each do |assurance_parameter| + parameters.push(param_name: assurance_parameter['param_name'], minimum: nil, maximum: nil) + end + end + sla = { nsi_id: instance_id, parameters: parameters } + begin + response = RestClient.post settings.sla_enforcement + '/sla-enforcement/slas', sla.to_json, content_type: :json + rescue => e + logger.error e + halt 503, 'SLA-Enforcement unavailable' if defined?(e.response).nil? + halt e.response.code, e.response.body + end end - end end diff --git a/ns-provisioning/helpers/ns.rb b/ns-provisioning/helpers/ns.rb index b4e7636..bf6b66c 100644 --- a/ns-provisioning/helpers/ns.rb +++ b/ns-provisioning/helpers/ns.rb @@ -131,19 +131,19 @@ def recoverState(instance, _error) end unless settings.default_tenant && !popUrls[:is_admin] - logger.info "Removing user stack...." + logger.info 'Removing user stack....' stack_url = auth_info['stack_url'] if !auth_info['stack_url'].nil? response, errors = delete_stack_with_wait(auth_info['stack_url'], token) logger.error errors if errors return 400, errors if errors - logger.info "User and tenant removed correctly." + logger.info 'User and tenant removed correctly.' else - logger.info "No user and tenant to remove." + logger.info 'No user and tenant to remove.' end end - logger.info "REMOVED: User " + auth_info['user_id'].to_s + " and tenant '" + auth_info['tenant_id'].to_s + logger.info 'REMOVED: User ' + auth_info['user_id'].to_s + " and tenant '" + auth_info['tenant_id'].to_s end message = { @@ -167,7 +167,7 @@ def instantiate(instance, nsd, instantiation_info) callback_url = @instance['notification'] flavour = @instance['service_deployment_flavour'] pop_list = instantiation_info['pop_list'] - #pop_id = instantiation_info['pop_id'] + # pop_id = instantiation_info['pop_id'] mapping_id = instantiation_info['mapping_id'] nap_id = instantiation_info['nap_id'] customer_id = instantiation_info['customer_id'] @@ -187,7 +187,7 @@ def instantiate(instance, nsd, instantiation_info) pop_list_ids = [] pop_list.map do |hash| - pop_list_ids << { id: hash["id"] } + pop_list_ids << { id: hash['id'] } end logger.info 'List of available PoPs: ' + pop_list_ids.to_s if pop_list.size == 1 || mapping_id.nil? @@ -233,7 +233,6 @@ def instantiate(instance, nsd, instantiation_info) # if mapping of all VNFs are in the same PoP. Create Authentication and network 1 time mapping['vnf_mapping'].each do |vnf| - logger.info 'Start authentication process of ' + vnf.to_s pop_id = vnf['maps_to_PoP'].gsub('/pop/', '') pop_info = pop_list.find { |p| p['id'] == pop_id.to_i } @@ -311,7 +310,7 @@ def instantiate(instance, nsd, instantiation_info) # generate networks for this PoP if @instance['authentication'].nil? - return handleError(@instance, "Authentication not valid.") + return handleError(@instance, 'Authentication not valid.') end pop_auth = @instance['authentication'][0] @@ -339,14 +338,14 @@ def instantiate(instance, nsd, instantiation_info) stack_id = stack['stack']['id'] - #save stack_url in reserved resurces - logger.info "Saving reserved stack...." + # save stack_url in reserved resurces + logger.info 'Saving reserved stack....' @resource_reservation = @instance['resource_reservation'] resource_reservation = [] resource_reservation << { ports: [], - network_stack: {:id => stack_id, :stack_url => stack['stack']['links'][0]['href']}, + network_stack: { id: stack_id, stack_url: stack['stack']['links'][0]['href'] }, public_network_id: publicNetworkId, dns_server: popUrls[:dns], pop_id: pop_auth['pop_id'], @@ -380,12 +379,12 @@ def instantiate(instance, nsd, instantiation_info) @instance.push(lifecycle_event_history: 'NETWORK CREATED') @instance.update_attribute('vlr', networks) - #get array - object = @resource_reservation.find {|s| s[:network_stack][:id] == stack['stack']['id'] } - #remove array + # get array + object = @resource_reservation.find { |s| s[:network_stack][:id] == stack['stack']['id'] } + # remove array @instance.pull(resource_reservation: object) - #add array - resource_reservation = resource_reservation.find {|s| s[:network_stack][:id] == stack['stack']['id'] } + # add array + resource_reservation = resource_reservation.find { |s| s[:network_stack][:id] == stack['stack']['id'] } resource_reservation[:routers] = routers resource_reservation[:networks] = networks @instance.push(resource_reservation: resource_reservation) diff --git a/ns-provisioning/helpers/pop.rb b/ns-provisioning/helpers/pop.rb index 9d0bf1d..78c0a88 100644 --- a/ns-provisioning/helpers/pop.rb +++ b/ns-provisioning/helpers/pop.rb @@ -17,7 +17,6 @@ # # @see NsProvisioner module PopHelper - # Returns the information of PoPs # # @param [String] message the pop id diff --git a/ns-provisioning/helpers/vim.rb b/ns-provisioning/helpers/vim.rb index ef59289..bc2e9cd 100644 --- a/ns-provisioning/helpers/vim.rb +++ b/ns-provisioning/helpers/vim.rb @@ -17,7 +17,6 @@ # # @see NSProvisioner module VimHelper - def getAdminRole(keystoneUrl, token) begin response = RestClient.get keystoneUrl + '/OS-KSADM/roles', :content_type => :json, :'X-Auth-Token' => token @@ -55,9 +54,7 @@ def publicNetworkId(neutronUrl, token) if network.nil? network = networks['networks'].find { |role| role['router:external'] } end - if network.nil? - return 400, "No external network defined in Openstack." - end + return 400, 'No external network defined in Openstack.' if network.nil? network['id'] end diff --git a/ns-provisioning/routes/ns.rb b/ns-provisioning/routes/ns.rb index 1832e74..95b9d42 100644 --- a/ns-provisioning/routes/ns.rb +++ b/ns-provisioning/routes/ns.rb @@ -17,15 +17,14 @@ # # @see NsProvisioning class Provisioner < NsProvisioning - # @method get_ns_instances # @overload get "/ns-instances" # Gets all ns-instances get '/' do instances = if params[:status] - Nsr.where(status: params[:status]) - else - Nsr.all + Nsr.where(status: params[:status]) + else + Nsr.all end return instances.to_json @@ -146,7 +145,7 @@ class Provisioner < NsProvisioning if popInfo == 400 logger.error 'Pop id no exists.' - return + return end pop_auth = @nsInstance['authentication'].find { |pop| pop['pop_id'] == vnf['pop_id'] } diff --git a/ns-provisioning/routes/scaling.rb b/ns-provisioning/routes/scaling.rb index c81d449..c0df5b0 100644 --- a/ns-provisioning/routes/scaling.rb +++ b/ns-provisioning/routes/scaling.rb @@ -17,118 +17,103 @@ # # @see NsProvisioner class Scaling < NsProvisioning - - # @method post_ns_instances_scale_out - # @overload post '/ns-instances/scaling/:id/scale_out' - # Post a Scale out request - # @param [JSON] - post "/:id/scale_out" do - - halt 415 unless request.content_type == 'application/json' - - begin - instance = Nsr.find(params["id"]) - rescue Mongoid::Errors::DocumentNotFound => e - halt(404) + # @method post_ns_instances_scale_out + # @overload post '/ns-instances/scaling/:id/scale_out' + # Post a Scale out request + # @param [JSON] + post '/:id/scale_out' do |id| + halt 415 unless request.content_type == 'application/json' + + begin + instance = Nsr.find(id) + rescue Mongoid::Errors::DocumentNotFound => e + halt(404) + end + + instance['vnfrs'].each do |vnf| + logger.info 'Scale out VNF ' + vnf['vnfr_id'].to_s + + puts 'Pop_id: ' + vnf['pop_id'].to_s + raise 'VNF not defined' if vnf['pop_id'].nil? + + pop_info = getPopInfo(vnf['pop_id']) + if pop_info == 400 + logger.error 'Pop id no exists.' + return + end + + pop_auth = instance['authentication'].find { |pop| pop['pop_id'] == vnf['pop_id'] } + pop_urls = pop_auth['urls'] + + scale = { + auth => { + tenant => pop_auth['tenant_name'], + username => pop_auth['username'], + password => pop_auth['password'], + url => { + keystone => pop_urls[:keystone], + heat => pop_urls[:orch] + } + } + } + begin + response = RestClient.post settings.vnf_manager + '/vnf-instances/scaling/' + vnf['vnfr_id'] + '/scale_out', scale.to_json, content_type => :json + rescue => e + logger.error e + end + + logger.debug response + end + halt 200, 'Scale out done.' end - instance['vnfrs'].each do |vnf| - puts vnf - logger.info "Scale out VNF " + vnf['vnfr_id'].to_s - - puts "Pop_id: " + vnf['pop_id'].to_s - if vnf['pop_id'].nil? - raise "VNF not defined" - end - - popInfo = getPopInfo(vnf['pop_id']) - if popInfo == 400 - logger.error "Pop id no exists." - return - raise "Pop id no exists." - end - - pop_auth = instance['authentication'].find { |pop| pop['pop_id'] == vnf['pop_id'] } - popUrls = pop_auth['urls'] - - scale = { - :auth => { - :tenant => pop_auth['tenant_name'], - :username => pop_auth['username'], - :password => pop_auth['password'], - :url => { - :keystone => popUrls[:keystone], - :heat => popUrls[:orch], - } - } - } - begin - response = RestClient.post settings.vnf_manager + '/vnf-instances/scaling/' + vnf['vnfr_id'] + '/scale_out', scale.to_json, :content_type => :json - rescue => e - logger.error e - end - - logger.debug response - + # @method post_ns_instances_scale_in + # @overload post '/ns-instances/scaling/:id/scale_in' + # Post a Scale in request + # @param [JSON] + post '/:id/scale_in' do |id| + halt 415 unless request.content_type == 'application/json' + + begin + instance = Nsr.find(id) + rescue Mongoid::Errors::DocumentNotFound => e + halt(404) + end + + instance['vnfrs'].each do |vnf| + logger.info 'Scale in VNF ' + vnf['vnfr_id'].to_s + + puts 'Pop_id: ' + vnf['pop_id'].to_s + raise 'VNF not defined' if vnf['pop_id'].nil? + + pop_info = getPopInfo(vnf['pop_id']) + if pop_info == 400 + logger.error 'Pop id no exists.' + return + end + + pop_auth = instance['authentication'].find { |pop| pop['pop_id'] == vnf['pop_id'] } + pop_urls = pop_auth['urls'] + + scale = { + auth => { + tenant => pop_auth['tenant_name'], + username => pop_auth['username'], + password => pop_auth['password'], + url => { + keystone => pop_urls[:keystone], + heat => pop_urls[:orch] + } + } + } + begin + response = RestClient.post settings.vnf_manager + '/vnf-instances/scaling/' + vnf['vnfr_id'] + '/scale_in', scale.to_json, content_type => :json + rescue => e + logger.error e + end + + logger.debug response + end + halt 200, 'Scale in done.' end - halt 200, "Scale out done." - - end - - # @method post_ns_instances_scale_in - # @overload post '/ns-instances/scaling/:id/scale_in' - # Post a Scale in request - # @param [JSON] - post "/:id/scale_in" do - - halt 415 unless request.content_type == 'application/json' - - begin - instance = Nsr.find(params["id"]) - rescue Mongoid::Errors::DocumentNotFound => e - halt(404) - end - - instance['vnfrs'].each do |vnf| - puts vnf - logger.info "Scale in VNF " + vnf['vnfr_id'].to_s - - puts "Pop_id: " + vnf['pop_id'].to_s - if vnf['pop_id'].nil? - raise "VNF not defined" - end - - popInfo = getPopInfo(vnf['pop_id']) - if popInfo == 400 - logger.error "Pop id no exists." - return - raise "Pop id no exists." - end - - pop_auth = instance['authentication'].find { |pop| pop['pop_id'] == vnf['pop_id'] } - popUrls = pop_auth['urls'] - - scale = { - :auth => { - :tenant => pop_auth['tenant_name'], - :username => pop_auth['username'], - :password => pop_auth['password'], - :url => { - :keystone => popUrls[:keystone], - :heat => popUrls[:orch], - } - } - } - begin - response = RestClient.post settings.vnf_manager + '/vnf-instances/scaling/' + vnf['vnfr_id'] + '/scale_in', scale.to_json, :content_type => :json - rescue => e - logger.error e - end - - logger.debug response - - end - halt 200, "Scale in done." - end - end diff --git a/vnfd-validator/Rakefile b/vnfd-validator/Rakefile index 39dada8..245a3d8 100644 --- a/vnfd-validator/Rakefile +++ b/vnfd-validator/Rakefile @@ -3,17 +3,17 @@ require 'yaml' require 'rspec/core/rake_task' RSpec::Core::RakeTask.new :specs do |task| - task.pattern = Dir['spec/*_spec.rb'] + task.pattern = Dir['spec/*_spec.rb'] end -task :default => ['specs'] +task default: ['specs'] desc 'Start the service' task :start do - conf = File.expand_path('config/puma.rb', File.dirname(__FILE__)) - exec("puma -C #{conf}") + conf = File.expand_path('config/puma.rb', File.dirname(__FILE__)) + exec("puma -C #{conf}") end YARD::Rake::YardocTask.new do |t| - t.files = ['main.rb', 'helpers/vnfd.rb', 'routes/vnfd.rb'] -end \ No newline at end of file + t.files = ['main.rb', 'helpers/vnfd.rb', 'routes/vnfd.rb'] +end diff --git a/vnfd-validator/helpers/vnfd.rb b/vnfd-validator/helpers/vnfd.rb index 4489e93..49cc1b8 100644 --- a/vnfd-validator/helpers/vnfd.rb +++ b/vnfd-validator/helpers/vnfd.rb @@ -17,7 +17,6 @@ # # @see VnfdValidatorHelper module VnfdValidatorHelper - # Checks if a JSON message is valid # # @param [JSON] message some JSON message @@ -98,19 +97,19 @@ def validate_xml_vnfd(vnfd) def validate_lifecycle_events(vnfd) vnfd['vnf_lifecycle_events'].each do |event| - event['events'].each do |type, object| - if (object['template_file'].nil?) - logger.error "Template file in Lifecycle events is not defined." - halt 400, "Template file in Lifecycle events is not defined." + event['events'].each do |_type, object| + if object['template_file'].nil? + logger.error 'Template file in Lifecycle events is not defined.' + halt 400, 'Template file in Lifecycle events is not defined.' else begin JSON.parse(object['template_file']) rescue JSON::ParserError => e logger.error e - halt 400, "Lifecycle events template incorrect. JSON parser error. Error: " + e.to_s + halt 400, 'Lifecycle events template incorrect. JSON parser error. Error: ' + e.to_s rescue => e logger.error e - halt 400, "Lifecycle events template incorrect. Error: " + e.to_s + halt 400, 'Lifecycle events template incorrect. Error: ' + e.to_s end end end @@ -118,5 +117,4 @@ def validate_lifecycle_events(vnfd) vnfd end - -end \ No newline at end of file +end diff --git a/vnfd-validator/routes/vnfd.rb b/vnfd-validator/routes/vnfd.rb index a2a4633..17a81ec 100644 --- a/vnfd-validator/routes/vnfd.rb +++ b/vnfd-validator/routes/vnfd.rb @@ -66,4 +66,4 @@ class VnfdValidator < Sinatra::Application halt 200 end -end \ No newline at end of file +end From 9b10633d8b6553adf002def0a98b2bf622fd800c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Thu, 3 Nov 2016 09:33:12 +0100 Subject: [PATCH 10/35] Code refactor according to Rubocop --- hot-generator/models/vnfd_to_hot.rb | 966 +++++++++--------- hot-generator/routes/hot.rb | 290 +++--- ns-catalogue/routes/ns.rb | 285 +++--- ns-monitoring/helpers/expression_evaluator.rb | 10 +- ns-monitoring/helpers/monitoring.rb | 287 +++--- ns-monitoring/helpers/sla.rb | 80 +- ns-monitoring/models/sla.rb | 109 +- ns-monitoring/routes/monitoring.rb | 4 +- vnf-catalogue/helpers/vnfs.rb | 152 ++- vnf-provisioning/helpers/compute.rb | 33 +- vnf-provisioning/helpers/hot.rb | 20 +- vnf-provisioning/helpers/mapi.rb | 8 +- vnf-provisioning/helpers/vnf.rb | 99 +- vnf-provisioning/routes/scaling.rb | 33 +- vnf-provisioning/routes/vnf.rb | 200 ++-- 15 files changed, 1265 insertions(+), 1311 deletions(-) diff --git a/hot-generator/models/vnfd_to_hot.rb b/hot-generator/models/vnfd_to_hot.rb index 3fc1ea6..3c9f25d 100644 --- a/hot-generator/models/vnfd_to_hot.rb +++ b/hot-generator/models/vnfd_to_hot.rb @@ -16,550 +16,536 @@ # limitations under the License. # class VnfdToHot - - # Initializes VnfdToHot object - # - # @param [String] name the name for the HOT - # @param [String] description the description for the HOT - def initialize(name, description, public_network_id) - @hot = Hot.new(description) - @name = name - @outputs = {} - @type = "" - @vnfr_id = "" - @public_network_id = public_network_id - end - - # Converts VNFD to HOT - # - # @param [Hash] vnfd the VNFD - # @param [String] tnova_flavour the T-NOVA flavour to generate the HOT for - # @param [Array] networks_id the IDs of the networks created by NS Manager - # @param [String] security_group_id the ID of the T-NOVA security group - # @return [HOT] returns an HOT object - def build(vnfd, tnova_flavour, networks_id, routers_id, security_group_id, vnfr_id, dns, flavours) - # Parse needed outputs - parse_outputs(vnfd['vnf_lifecycle_events'].find { |lifecycle| lifecycle['flavor_id_ref'] == tnova_flavour }['events']) - - @type = vnfd['type'] - @vnfr_id = vnfr_id - - key = create_key_pair(SecureRandom.urlsafe_base64(9)) - router_id = routers_id[0]['id'] - - # Get T-NOVA deployment flavour - deployment_information = vnfd['deployment_flavours'].detect { |flavour| flavour['id'] == tnova_flavour } - raise CustomException::NoFlavorError, "Flavor #{tnova_flavour} not found" if deployment_information.nil? - - # Get the vlinks references for the deployment flavour - vlinks = deployment_information['vlink_reference'] - - networks_id = [] - router_interfaces = [] - - vlinks.each do |vlink| - vlink_json = vnfd['vlinks'].detect { |vl| vl['id'] == vlink } - if !vlink_json['existing_net_id'].nil? - networks_id << {'id' => vlink, 'alias' => vlink_json['alias'], 'heat_id' => vlink_json['existing_net_id']} - else - net_name, router_interface = create_networks(vlink_json, dns, router_id) - networks_id << {'id' => vlink, 'alias' => vlink_json['alias'], 'heat' => vlink} - router_interfaces << router_interface - end + # Initializes VnfdToHot object + # + # @param [String] name the name for the HOT + # @param [String] description the description for the HOT + def initialize(name, description, public_network_id) + @hot = Hot.new(description) + @name = name + @outputs = {} + @type = '' + @vnfr_id = '' + @public_network_id = public_network_id end - deployment_information['vdu_reference'].each do |vdu_ref| - # Get VDU for deployment - vdu = vnfd['vdu'].detect { |vdu| vdu['id'] == vdu_ref } - - if vdu['vm_image_format'] == 'openstack_id' - image_name = vdu['vm_image'] - else - image_name = {get_resource: create_image(vdu)} - end - if flavours.detect { |fl| fl['id'] == vdu_ref } - flavor_name = flavours.find { |fl| fl['id'] == vdu_ref }['flavour_id'] - else - flavor_name = {get_resource: create_flavor(vdu)} - end - - #ports = create_ports(vdu['id'], vdu['connection_points'], vnfd['vlinks'], networks_id, security_group_id) - nets = [] - vdu['connection_points'].each do |connection_point| - l = networks_id.find { |vlink| vlink['id'] == connection_point['vlink_ref'] } - nets << {:network => {get_resource: l['heat']}} - end - - #create AutoScalingGroup if the VNF can scale - if (vdu['scale_in_out']['maximum'] > 10) - #generate template for server - nested_template = generate_nested_template(vdu, vnfd, networks_id, security_group_id, nets, router_interfaces, router_id) - - #save template in folder - name = vnfd['id'].to_s - filename = "assets/templates/" + name + ".yaml" - File.open(filename, 'w') { |file| file.write(nested_template.to_yaml) } - - url = HotGenerator.manager + "/files/" + name + ".yaml" - properties = { - :image => image_name, - :flavor => flavor_name - } + # Converts VNFD to HOT + # + # @param [Hash] vnfd the VNFD + # @param [String] tnova_flavour the T-NOVA flavour to generate the HOT for + # @param [Array] networks_id the IDs of the networks created by NS Manager + # @param [String] security_group_id the ID of the T-NOVA security group + # @return [HOT] returns an HOT object + def build(vnfd, tnova_flavour, networks_id, routers_id, security_group_id, vnfr_id, dns, flavours) + # Parse needed outputs + parse_outputs(vnfd['vnf_lifecycle_events'].find { |lifecycle| lifecycle['flavor_id_ref'] == tnova_flavour }['events']) + + @type = vnfd['type'] + @vnfr_id = vnfr_id + + key = create_key_pair(SecureRandom.urlsafe_base64(9)) + router_id = routers_id[0]['id'] + + # Get T-NOVA deployment flavour + deployment_information = vnfd['deployment_flavours'].detect { |flavour| flavour['id'] == tnova_flavour } + raise CustomException::NoFlavorError, "Flavor #{tnova_flavour} not found" if deployment_information.nil? + + # Get the vlinks references for the deployment flavour + vlinks = deployment_information['vlink_reference'] + + networks_id = [] + router_interfaces = [] + + vlinks.each do |vlink| + vlink_json = vnfd['vlinks'].detect { |vl| vl['id'] == vlink } + if !vlink_json['existing_net_id'].nil? + networks_id << { 'id' => vlink, 'alias' => vlink_json['alias'], 'heat_id' => vlink_json['existing_net_id'] } + else + net_name, router_interface = create_networks(vlink_json, dns, router_id) + networks_id << { 'id' => vlink, 'alias' => vlink_json['alias'], 'heat' => vlink } + router_interfaces << router_interface + end + end + + deployment_information['vdu_reference'].each do |vdu_ref| + # Get VDU for deployment + vdu = vnfd['vdu'].detect { |vdu| vdu['id'] == vdu_ref } + + image_name = if vdu['vm_image_format'] == 'openstack_id' + vdu['vm_image'] + else + { get_resource: create_image(vdu) } + end + if flavours.detect { |fl| fl['id'] == vdu_ref } + flavor_name = flavours.find { |fl| fl['id'] == vdu_ref }['flavour_id'] + else + flavor_name = { get_resource: create_flavor(vdu) } + end + + # ports = create_ports(vdu['id'], vdu['connection_points'], vnfd['vlinks'], networks_id, security_group_id) + nets = [] + vdu['connection_points'].each do |connection_point| + l = networks_id.find { |vlink| vlink['id'] == connection_point['vlink_ref'] } + nets << { network: { get_resource: l['heat'] } } + end + + # create AutoScalingGroup if the VNF can scale + if vdu['scale_in_out']['maximum'] > 10 + # generate template for server + nested_template = generate_nested_template(vdu, vnfd, networks_id, security_group_id, nets, router_interfaces, router_id) + + # save template in folder + name = vnfd['id'].to_s + filename = 'assets/templates/' + name + '.yaml' + File.open(filename, 'w') { |file| file.write(nested_template.to_yaml) } + url = HotGenerator.manager + '/files/' + name + '.yaml' + properties = { + image: image_name, + flavor: flavor_name + } + + networks_id.each do |net| + properties[net['heat']] = { 'get_resource' => net['heat'] } + end + router_interfaces.each do |iface| + properties[iface] = { 'get_resource' => iface } + end + # properties['depends_on'] = router_interfaces + + scaled_resource = GenericResource.new(vdu['id'], url, properties, router_interfaces) + auto_scale_group = create_autoscale_group(60, vdu['scale_in_out']['maximum'], vdu['scale_in_out']['minimum'], 1, scaled_resource) + scale_out_policy = create_scale_policy(auto_scale_group, 1) + scale_in_policy = create_scale_policy(auto_scale_group, -1) + @hot.outputs_list << Output.new("#{vdu['id']}#scale_out_url", 'Url of scale out.', get_attr: [scale_out_policy, 'alarm_url']) + @hot.outputs_list << Output.new("#{vdu['id']}#scale_in_url", 'Url of scale in.', get_attr: [scale_in_policy, 'alarm_url']) + @hot.outputs_list << Output.new("#{vdu['id']}#scale_group", "#{vdu['id']} ID", get_resource: auto_scale_group) + else + ports = create_ports(vdu['id'], vdu['connection_points'], vnfd['vlinks'], networks_id, security_group_id, router_interfaces) + create_server(vdu, image_name, flavor_name, ports, key, false) + end + end + + # puts @hot.to_yaml + + @hot + end + + def generate_nested_template(vdu, vnfd, networks_id, security_group_id, _nets, router_interfaces, _router_id) + hot = Hot.new('server') + hot.parameters_list = [] + outputs_list = {} + hot.parameters_list << Parameter.new('image', '', 'string') + hot.parameters_list << Parameter.new('flavor', '', 'string') + # for each network, create a parameter networks_id.each do |net| - properties[net['heat']] = {"get_resource" => net['heat']} + hot.parameters_list << Parameter.new(net['heat'], '', 'string') end router_interfaces.each do |iface| - properties[iface] = {"get_resource" => iface} + hot.parameters_list << Parameter.new(iface, '', 'string') end - #properties['depends_on'] = router_interfaces - - scaled_resource = GenericResource.new(vdu['id'], url, properties, router_interfaces) - auto_scale_group = create_autoscale_group(60, vdu['scale_in_out']['maximum'], vdu['scale_in_out']['minimum'], 1, scaled_resource) - scale_out_policy = create_scale_policy(auto_scale_group, 1) - scale_in_policy = create_scale_policy(auto_scale_group, -1) - @hot.outputs_list << Output.new("#{vdu['id']}#scale_out_url", "Url of scale out.", {get_attr: [scale_out_policy, 'alarm_url']}) - @hot.outputs_list << Output.new("#{vdu['id']}#scale_in_url", "Url of scale in.", {get_attr: [scale_in_policy, 'alarm_url']}) - @hot.outputs_list << Output.new("#{vdu['id']}#scale_group", "#{vdu['id']} ID", {get_resource: auto_scale_group}) - else - ports = create_ports(vdu['id'], vdu['connection_points'], vnfd['vlinks'], networks_id, security_group_id, router_interfaces) - create_server(vdu, image_name, flavor_name, ports, key, false) - end - end - #puts @hot.to_yaml + arr = [] + router_interfaces.each do |iface| + arr << { 'get_param' => iface } + end - @hot - end + ports = [] + connection_points = vdu['connection_points'] + vlinks = vnfd['vlinks'] + vdu_id = vdu['id'] + auto_scale_name = get_resource_name + connection_points.each do |connection_point| + vlink = vlinks.find { |vlink| vlink['id'] == connection_point['vlink_ref'] } + # detect, and return error if not. + network = networks_id.detect { |network| network['alias'] == vlink['alias'] } + next if network.nil? + port_name = (connection_point['id']).to_s + ports << { 'port' => { 'get_resource' => port_name } } + if vlink['existing_net_id'] + if vlink['port_security_enabled'] + hot.resources_list << Port.new(port_name, network['heat_id'], security_group_id) + else + hot.resources_list << Port.new(port_name, network['heat_id']) + end + else + if vlink['port_security_enabled'] + hot.resources_list << Port.new(port_name, { 'get_param' => network['heat'] }, security_group_id) + else + hot.resources_list << Port.new(port_name, 'get_param' => network['heat']) + end + end + # router_interface_name = get_resource_name_nested(hot) + # hot.resources_list << RouterInterface.new(router_interface_name, router_id, nil, {"get_resource" => port_name}) - def generate_nested_template(vdu, vnfd, networks_id, security_group_id, nets, router_interfaces, router_id) - hot = Hot.new("server") - hot.parameters_list = [] - outputs_list = {} - hot.parameters_list << Parameter.new('image', '', 'string') - hot.parameters_list << Parameter.new('flavor', '', 'string') - #for each network, create a parameter - networks_id.each do |net| - hot.parameters_list << Parameter.new(net['heat'], '', 'string') - end - router_interfaces.each do |iface| - hot.parameters_list << Parameter.new(iface, '', 'string') - end + # Check if it's necessary to create an output for this resource + if outputs_list.key?('ip') && outputs_list['ip'].include?(port_name) + hot.outputs_list << Output.new("#{port_name}#ip", "#{port_name} IP address", 'get_attr' => [port_name, 'fixed_ips', 0, 'ip_address']) + end - arr = [] - router_interfaces.each do |iface| - arr << {"get_param" => iface} + # Check if the port has a Floating IP + if vlink['access'] + floating_ip_name = get_resource_name_nested(hot) + # TODO: Receive the floating ip pool name? + hot.resources_list << FloatingIp.new(floating_ip_name, @public_network_id) + hot.resources_list << FloatingIpAssociation.new(get_resource_name_nested(hot), { 'get_resource' => floating_ip_name }, { 'get_resource' => port_name }, []) + hot.outputs_list << Output.new("#{vdu_id}##{connection_point['id']}#PublicIp", "#{port_name} Floating IP", 'get_attr' => [floating_ip_name, 'floating_ip_address']) + @hot.outputs_list << Output.new("#{vdu_id}##{connection_point['id']}#PublicIp", "#{port_name} Nested outputs_list", 'get_attr' => [auto_scale_name, 'outputs_list', "#{vdu_id}##{connection_point['id']}#PublicIp"]) + else + hot.outputs_list << Output.new("#{vdu_id}##{connection_point['id']}#PrivateIp", "#{port_name} Private IP", 'get_attr' => [port_name, 'fixed_ips', 0, 'ip_address']) + @hot.outputs_list << Output.new("#{vdu_id}##{connection_point['id']}#fixed_ips#0#ip_address", "#{port_name} Nested outputs_list", 'get_attr' => [auto_scale_name, 'outputs_list', "#{vdu_id}##{connection_point['id']}#PrivateIp"]) + end + end + + hot.resources_list << Server.new( + vdu['id'], + { 'get_param' => 'flavor' }, + { 'get_param' => 'image' }, + ports, + add_wait_condition2(vdu, hot), + nil + ) + hot.outputs_list << Output.new("#{vdu['id']}#id", "#{vdu['id']} ID", 'get_resource' => vdu['id']) + @hot.outputs_list << Output.new("#{vdu['id']}#vdus", "#{vdu['id']} ID", 'get_attr' => [auto_scale_name, 'outputs_list', "#{vdu['id']}#id"]) + hot end - ports = [] - connection_points = vdu['connection_points'] - vlinks = vnfd['vlinks'] - vdu_id = vdu['id'] - auto_scale_name = get_resource_name - connection_points.each do |connection_point| - vlink = vlinks.find { |vlink| vlink['id'] == connection_point['vlink_ref'] } - #detect, and return error if not. - network = networks_id.detect { |network| network['alias'] == vlink['alias'] } - if network != nil - port_name = "#{connection_point['id']}" - ports << {"port" => {"get_resource" => port_name}} - if vlink['existing_net_id'] - if vlink['port_security_enabled'] - hot.resources_list << Port.new(port_name, network['heat_id'], security_group_id) - else - hot.resources_list << Port.new(port_name, network['heat_id']) - end - else - if vlink['port_security_enabled'] - hot.resources_list << Port.new(port_name, {"get_param" => network['heat']}, security_group_id) - else - hot.resources_list << Port.new(port_name, {"get_param" => network['heat']}) - end + def create_networks(vlink, dns_server, router_id) + network_name = create_network(vlink['id'], vlink['alias'], vlink['port_security_enabled']) + cidr = if vlink['net_segment'] && vlink['net_segment'] != '' + vlink['net_segment'] + else + '192.' + rand(256).to_s + '.' + rand(256).to_s + '.0/24' + end + subnet_name = create_subnet(vlink['id'], dns_server, cidr) + if vlink['connectivity_type'] == 'E-LAN' + # create_router_interface(router_id, subnet_name) + elsif vlink['connectivity_type'] == 'E-LINE' + # nothig to do end - #router_interface_name = get_resource_name_nested(hot) - #hot.resources_list << RouterInterface.new(router_interface_name, router_id, nil, {"get_resource" => port_name}) - # Check if it's necessary to create an output for this resource - if outputs_list.has_key?('ip') && outputs_list['ip'].include?(port_name) - hot.outputs_list << Output.new("#{port_name}#ip", "#{port_name} IP address", {"get_attr" => [port_name, 'fixed_ips', 0, 'ip_address']}) - end + router_interface = create_router_interface(router_id, subnet_name, nil) - # Check if the port has a Floating IP - if vlink['access'] - floating_ip_name = get_resource_name_nested(hot) - # TODO: Receive the floating ip pool name? - hot.resources_list << FloatingIp.new(floating_ip_name, @public_network_id) - hot.resources_list << FloatingIpAssociation.new(get_resource_name_nested(hot), {"get_resource" => floating_ip_name}, {"get_resource" => port_name}, []) - hot.outputs_list << Output.new("#{vdu_id}##{connection_point['id']}#PublicIp", "#{port_name} Floating IP", {"get_attr" => [floating_ip_name, 'floating_ip_address']}) - @hot.outputs_list << Output.new("#{vdu_id}##{connection_point['id']}#PublicIp", "#{port_name} Nested outputs_list", {"get_attr" => [auto_scale_name, 'outputs_list', "#{vdu_id}##{connection_point['id']}#PublicIp"]}) - else - hot.outputs_list << Output.new("#{vdu_id}##{connection_point['id']}#PrivateIp", "#{port_name} Private IP", {"get_attr" => [port_name,'fixed_ips',0,'ip_address']}) - @hot.outputs_list << Output.new("#{vdu_id}##{connection_point['id']}#fixed_ips#0#ip_address", "#{port_name} Nested outputs_list", {"get_attr" => [auto_scale_name, 'outputs_list', "#{vdu_id}##{connection_point['id']}#PrivateIp"]}) - end - end + [network_name, router_interface] + end + def create_network(resource_name, network_name, port_security_enabled) + name = get_resource_name + @hot.resources_list << Network.new(resource_name, network_name, port_security_enabled) + name end - hot.resources_list << Server.new( - vdu['id'], - {"get_param" => 'flavor'}, - {"get_param" => 'image'}, - ports, - add_wait_condition2(vdu, hot), - nil) - hot.outputs_list << Output.new("#{vdu['id']}#id", "#{vdu['id']} ID", {"get_resource" => vdu['id']}) - @hot.outputs_list << Output.new("#{vdu['id']}#vdus", "#{vdu['id']} ID", {"get_attr" => [auto_scale_name, 'outputs_list', "#{vdu['id']}#id"]}) - hot - end - - def create_networks(vlink, dns_server, router_id) - network_name = create_network(vlink['id'], vlink['alias'], vlink['port_security_enabled']) - if vlink['net_segment'] && vlink['net_segment'] != "" - cidr = vlink['net_segment'] - else - cidr = "192." + rand(256).to_s + "." + rand(256).to_s + ".0/24" + def create_subnet(network_name, dns_server, cidr) + name = get_resource_name + @hot.resources_list << Subnet.new(name, { get_resource: network_name }, dns_server, cidr) + name end - subnet_name = create_subnet(vlink['id'], dns_server, cidr) - if vlink['connectivity_type'] == 'E-LAN' - #create_router_interface(router_id, subnet_name) - elsif vlink['connectivity_type'] == 'E-LINE' - #nothig to do + + def create_router_interface(router_id, subnet_name, port_name) + name = get_resource_name + @hot.resources_list << RouterInterface.new(name, router_id, { get_resource: subnet_name }, get_resource: port_name) + name end - router_interface = create_router_interface(router_id, subnet_name, nil) - - return network_name, router_interface - end - - def create_network(resource_name, network_name, port_security_enabled) - name = get_resource_name - @hot.resources_list << Network.new(resource_name, network_name, port_security_enabled) - name - end - - def create_subnet(network_name, dns_server, cidr) - name = get_resource_name - @hot.resources_list << Subnet.new(name, {get_resource: network_name}, dns_server, cidr) - name - end - - def create_router_interface(router_id, subnet_name, port_name) - name = get_resource_name - @hot.resources_list << RouterInterface.new(name, router_id, {get_resource: subnet_name}, {get_resource: port_name}) - name - end - - # Parse the outputs from the VNFD and builds an outputs hash - # - # @param [Hash] events the VNF lifecycle events - def parse_outputs(events) - outputs = [] - - events.each do |event, event_info| - unless event_info.nil? || event_info['template_file'].nil? - raise CustomException::InvalidTemplateFileFormat, "Template file format not supported" unless event_info['template_file_format'].downcase == 'json' - JSON.parse(event_info['template_file']).each do |id, output| - unless outputs.include?(output) - outputs << output - - match = output.delete(' ').match(/^get_attr\[(.*)\]$/i).to_a - if match.size == 0 - puts output - puts "The match is null." - else - string = match[1].split(",").map(&:strip) - if string.size == 0 - puts "Error getting the 'get_attr' of " + match[1] - else - get_attr = {get_attr: []} - string.each_with_index do |type, i| - if CommonMethods.is_num?(type) - get_attr[:get_attr] << type.to_i - else - get_attr[:get_attr] << type - end + # Parse the outputs from the VNFD and builds an outputs hash + # + # @param [Hash] events the VNF lifecycle events + def parse_outputs(events) + outputs = [] + + events.each do |_event, event_info| + next if event_info.nil? || event_info['template_file'].nil? + raise CustomException::InvalidTemplateFileFormat, 'Template file format not supported' unless event_info['template_file_format'].casecmp('json').zero? + JSON.parse(event_info['template_file']).each do |_id, output| + next if outputs.include?(output) + outputs << output + + match = output.delete(' ').match(/^get_attr\[(.*)\]$/i).to_a + if match.empty? + puts output + puts 'The match is null.' + else + string = match[1].split(',').map(&:strip) + if string.empty? + puts "Error getting the 'get_attr' of " + match[1] + else + get_attr = { get_attr: [] } + string.each_with_index do |type, _i| + get_attr[:get_attr] << if CommonMethods.is_num?(type) + type.to_i + else + type + end + end + + if @outputs.key?(match[2]) + @outputs[match[2]] << match[1] + else + @outputs[match[2]] = [match[1]] + end + if string[1] == 'fixed_ips' + # @hot.outputs_list << Output.new(id, "", get_attr) + end + if string[1] != 'PublicIp' + # @hot.outputs_list << Output.new(id, "", get_attr) + end + end end + end + end + end + + # Creates an HEAT key pair resource + # + # @param [Hash] keypair_name the Name of the KeyPair + # @return [String] the name of the created resource + def create_key_pair(keypair_name) + name = get_resource_name + + @hot.resources_list << KeyPair.new(name, keypair_name) + @hot.outputs_list << Output.new('private_key', 'Private key', get_attr: [name, 'private_key']) + name + end - if @outputs.has_key?(match[2]) - @outputs[match[2]] << match[1] + # Creates an HEAT image resource from the VNFD + # + # @param [Hash] vdu the VDU from the VNFD + # @return [String] the name of the created resource + def create_image(vdu) + name = get_resource_name + + raise CustomException::NoExtensionError, "#{vdu['vm_image']} does not have a file extension" if vdu['vm_image_format'].empty? + raise CustomException::InvalidExtensionError, "#{vdu['vm_image']} has an invalid extension. Allowed extensions: ami, ari, aki, vhd, vmdk, raw, qcow2, vdi and iso" unless %w(ami ari aki vhd vmdk raw qcow2 vdi iso).include? vdu['vm_image_format'] + + @hot.resources_list << Image.new(name, vdu['vm_image_format'], vdu['vm_image']) + name + end + + # Creates an HEAT port resource from the VNFD + # + # @param [String] vdu_id the VDU ID from the VNFD + # @param [String] vnfc_id the VNFC ID from the VNFD + # @param [Array] vnfcs the list of VNFCS for the VDU + # @param [Array] networks_id the IDs of the networks created by NS Manager + # @param [String] security_group_id the ID of the T-NOVA security group + # @return [Array] a list of ports + def create_ports(vdu_id, connection_points, vlinks, networks_id, security_group_id, router_interfaces) + ports = [] + + connection_points.each do |connection_point| + vlink = vlinks.find { |vlink| vlink['id'] == connection_point['vlink_ref'] } + # detect, and return error if not. + network = networks_id.detect { |network| network['alias'] == vlink['alias'] } + next if network.nil? + port_name = (connection_point['id']).to_s + ports << { port: { get_resource: port_name } } + if vlink['existing_net_id'] + if vlink['port_security_enabled'] + @hot.resources_list << Port.new(port_name, network['heat_id'], security_group_id) else - @outputs[match[2]] = [match[1]] - end - if string[1] == 'fixed_ips' - #@hot.outputs_list << Output.new(id, "", get_attr) + @hot.resources_list << Port.new(port_name, network['heat_id']) end - if string[1] != 'PublicIp' - #@hot.outputs_list << Output.new(id, "", get_attr) + else + if vlink['port_security_enabled'] + @hot.resources_list << Port.new(port_name, { get_resource: network['heat'] }, security_group_id) + else + @hot.resources_list << Port.new(port_name, get_resource: network['heat']) end - end end - end + + # Check if it's necessary to create an output for this resource + if @outputs.key?('ip') && @outputs['ip'].include?(port_name) + @hot.outputs_list << Output.new("#{port_name}#ip", "#{port_name} IP address", get_attr: [port_name, 'fixed_ips', 0, 'ip_address']) + end + + # Check if the port has a Floating IP + if vlink['access'] + floating_ip_name = get_resource_name + # TODO: Receive the floating ip pool name? + @hot.resources_list << FloatingIp.new(floating_ip_name, @public_network_id) + @hot.resources_list << FloatingIpAssociation.new(get_resource_name, { get_resource: floating_ip_name }, { get_resource: port_name }, router_interfaces) + # @hot.outputs_list << Output.new("#{port_name}#floating_ip", "#{port_name} Floating IP", {get_attr: [floating_ip_name, 'floating_ip_address']}) + @hot.outputs_list << Output.new("#{vdu_id}##{connection_point['id']}#PublicIp", "#{port_name} Floating IP", get_attr: [floating_ip_name, 'floating_ip_address']) + @hot.outputs_list << Output.new("#{vdu_id}##{connection_point['id']}#fixed_ips#0#ip_address", "#{port_name} private address", 'get_attr' => [port_name, 'fixed_ips', 0, 'ip_address']) + else + @hot.outputs_list << Output.new("#{vdu_id}##{connection_point['id']}#fixed_ips#0#ip_address", "#{port_name} private address", 'get_attr' => [port_name, 'fixed_ips', 0, 'ip_address']) + end end - end + + ports + end + + # Creates an HEAT flavor resource from the VNFD + # + # @param [Hash] vdu the VDU from the VNFD + # @return [String] the name of the created resource + def create_flavor(vdu) + name = get_resource_name + storage_info = vdu['resource_requirements']['storage'] + @hot.resources_list << Flavor.new( + name, + unit_converter(storage_info['size'], storage_info['size_unit'], 'gb'), + unit_converter(vdu['resource_requirements']['memory'], vdu['resource_requirements']['memory_unit'], 'mb'), + vdu['resource_requirements']['vcpus'] + ) + name end - end - - # Creates an HEAT key pair resource - # - # @param [Hash] keypair_name the Name of the KeyPair - # @return [String] the name of the created resource - def create_key_pair(keypair_name) - name = get_resource_name - - @hot.resources_list << KeyPair.new(name, keypair_name) - @hot.outputs_list << Output.new("private_key", "Private key", {get_attr: [name, 'private_key']}) - name - end - - # Creates an HEAT image resource from the VNFD - # - # @param [Hash] vdu the VDU from the VNFD - # @return [String] the name of the created resource - def create_image(vdu) - name = get_resource_name - - raise CustomException::NoExtensionError, "#{vdu['vm_image']} does not have a file extension" if vdu['vm_image_format'].empty? - raise CustomException::InvalidExtensionError, "#{vdu['vm_image']} has an invalid extension. Allowed extensions: ami, ari, aki, vhd, vmdk, raw, qcow2, vdi and iso" unless ['ami', 'ari', 'aki', 'vhd', 'vmdk', 'raw', 'qcow2', 'vdi', 'iso'].include? vdu['vm_image_format'] - - @hot.resources_list << Image.new(name, vdu['vm_image_format'], vdu['vm_image']) - name - end - - # Creates an HEAT port resource from the VNFD - # - # @param [String] vdu_id the VDU ID from the VNFD - # @param [String] vnfc_id the VNFC ID from the VNFD - # @param [Array] vnfcs the list of VNFCS for the VDU - # @param [Array] networks_id the IDs of the networks created by NS Manager - # @param [String] security_group_id the ID of the T-NOVA security group - # @return [Array] a list of ports - def create_ports(vdu_id, connection_points, vlinks, networks_id, security_group_id, router_interfaces) - ports = [] - - connection_points.each do |connection_point| - vlink = vlinks.find { |vlink| vlink['id'] == connection_point['vlink_ref'] } - #detect, and return error if not. - network = networks_id.detect { |network| network['alias'] == vlink['alias'] } - if network != nil - port_name = "#{connection_point['id']}" - ports << {port: {get_resource: port_name}} - if vlink['existing_net_id'] - if vlink['port_security_enabled'] - @hot.resources_list << Port.new(port_name, network['heat_id'], security_group_id) - else - @hot.resources_list << Port.new(port_name, network['heat_id']) - end + + # Creates an HEAT server resource from the VNFD + # + # @param [Hash] vdu the VDU from the VNFD + # @param [String] image_name the image resource name + # @param [String] flavour_name the flavour resource name + # @param [Array] ports list of the ports resource + def create_server(vdu, image, flavour_name, ports, key_name, scale) + if scale + server = Server.new( + vdu['id'], + flavour_name, + image, + ports, + add_wait_condition(vdu), + get_resource: key_name + ) else - if vlink['port_security_enabled'] - @hot.resources_list << Port.new(port_name, {get_resource: network['heat']}, security_group_id) - else - @hot.resources_list << Port.new(port_name, {get_resource: network['heat']}) - end + @hot.resources_list << Server.new( + vdu['id'], + flavour_name, + image, + ports, + add_wait_condition(vdu), + get_resource: key_name + ) + @hot.outputs_list << Output.new("#{vdu['id']}#id", "#{vdu['id']} ID", get_resource: vdu['id']) end - # Check if it's necessary to create an output for this resource - if @outputs.has_key?('ip') && @outputs['ip'].include?(port_name) - @hot.outputs_list << Output.new("#{port_name}#ip", "#{port_name} IP address", {get_attr: [port_name, 'fixed_ips', 0, 'ip_address']}) + server + end + + # Adds a Wait Condition resource to the VDU + # + # @param [Hash] vdu the VDU from the VNFD + # @return [Hash] the user_data script with the Wait Condition + def add_wait_condition(vdu) + wc_handle_name = get_resource_name + + # if vdu['wc_notify'] + if @type != 'vSA' + @hot.resources_list << WaitConditionHandle.new(wc_handle_name) + @hot.resources_list << WaitCondition.new(get_resource_name, wc_handle_name, 2000) end + # end - # Check if the port has a Floating IP - if vlink['access'] - floating_ip_name = get_resource_name - # TODO: Receive the floating ip pool name? - @hot.resources_list << FloatingIp.new(floating_ip_name, @public_network_id) - @hot.resources_list << FloatingIpAssociation.new(get_resource_name, {get_resource: floating_ip_name}, {get_resource: port_name}, router_interfaces) - # @hot.outputs_list << Output.new("#{port_name}#floating_ip", "#{port_name} Floating IP", {get_attr: [floating_ip_name, 'floating_ip_address']}) - @hot.outputs_list << Output.new("#{vdu_id}##{connection_point['id']}#PublicIp", "#{port_name} Floating IP", {get_attr: [floating_ip_name, 'floating_ip_address']}) - @hot.outputs_list << Output.new("#{vdu_id}##{connection_point['id']}#fixed_ips#0#ip_address", "#{port_name} private address", {"get_attr" => [port_name,'fixed_ips',0,'ip_address']}) - else - @hot.outputs_list << Output.new("#{vdu_id}##{connection_point['id']}#fixed_ips#0#ip_address", "#{port_name} private address", {"get_attr" => [port_name,'fixed_ips',0,'ip_address']}) + wc_notify = '' + wc_notify = "\nwc_notify --data-binary '{\"status\": \"SUCCESS\"}'\n" + if vdu['wc_notify'] + wc_notify = "\nwc_notify --data-binary '{\"status\": \"SUCCESS\"}'\n" + end + if @type == 'vSBC' + wc_notify = '' + elsif @type == 'vSA' + wc_notify = '\n echo "tenor_url: http://10.10.1.61:4000/vnf-provisioning/' + @vnfr_id + '/stack/create_complete" > /etc/tenor.cfg' + wc_notify = '\n echo curl -XPOST http://10.10.1.61:4000/vnf-provisioning/' + @vnfr_id + '/stack/create_complete -d "info" ' + wc_notify = '' + wc_notify += "\nwc_notify --data-binary '{\"status\": \"SUCCESS\"}'\n" end - end + # if vdu['wc_notify'] + shell = '#!/bin/bash' + shell = '#!/bin/tcsh' if @type == 'vSA' + if @type != 'vSA' + bootstrap_script = vdu.key?('bootstrap_script') ? vdu['bootstrap_script'] : shell + { + str_replace: { + params: { + wc_notify: { + get_attr: [wc_handle_name, 'curl_cli'] + } + }, + template: bootstrap_script + wc_notify + } + } + else + bootstrap_script = '#!/bin/bash' + wc_notify + end + # end end - ports - end - - # Creates an HEAT flavor resource from the VNFD - # - # @param [Hash] vdu the VDU from the VNFD - # @return [String] the name of the created resource - def create_flavor(vdu) - name = get_resource_name - storage_info = vdu['resource_requirements']['storage'] - @hot.resources_list << Flavor.new( - name, - unit_converter(storage_info['size'], storage_info['size_unit'], 'gb'), - unit_converter(vdu['resource_requirements']['memory'], vdu['resource_requirements']['memory_unit'], 'mb'), - vdu['resource_requirements']['vcpus']) - name - end - - # Creates an HEAT server resource from the VNFD - # - # @param [Hash] vdu the VDU from the VNFD - # @param [String] image_name the image resource name - # @param [String] flavour_name the flavour resource name - # @param [Array] ports list of the ports resource - def create_server(vdu, image, flavour_name, ports, key_name, scale) - if scale - server = Server.new( - vdu['id'], - flavour_name, - image, - ports, - add_wait_condition(vdu), - {get_resource: key_name}) - else - @hot.resources_list << Server.new( - vdu['id'], - flavour_name, - image, - ports, - add_wait_condition(vdu), - {get_resource: key_name}) - @hot.outputs_list << Output.new("#{vdu['id']}#id", "#{vdu['id']} ID", {get_resource: vdu['id']}) - end + def add_wait_condition2(vdu, hot) + wc_handle_name = get_resource_name_nested(hot) - server - end - - # Adds a Wait Condition resource to the VDU - # - # @param [Hash] vdu the VDU from the VNFD - # @return [Hash] the user_data script with the Wait Condition - def add_wait_condition(vdu) - wc_handle_name = get_resource_name - - #if vdu['wc_notify'] - if @type != 'vSA' - @hot.resources_list << WaitConditionHandle.new(wc_handle_name) - @hot.resources_list << WaitCondition.new(get_resource_name, wc_handle_name, 2000) - end - #end - - wc_notify = "" - wc_notify = "\nwc_notify --data-binary '{\"status\": \"SUCCESS\"}'\n" - if vdu['wc_notify'] - wc_notify = "\nwc_notify --data-binary '{\"status\": \"SUCCESS\"}'\n" - end - if @type == 'vSBC' - wc_notify = "" - elsif @type == 'vSA' - wc_notify = '\n echo "tenor_url: http://10.10.1.61:4000/vnf-provisioning/'+ @vnfr_id +'/stack/create_complete" > /etc/tenor.cfg' - wc_notify = '\n echo curl -XPOST http://10.10.1.61:4000/vnf-provisioning/'+ @vnfr_id +'/stack/create_complete -d "info" ' - wc_notify = "" - wc_notify = wc_notify + "\nwc_notify --data-binary '{\"status\": \"SUCCESS\"}'\n" - end + # if vdu['wc_notify'] + if @type != 'vSA' && !vdu['wc_notify'].nil? + hot.resources_list << WaitConditionHandle.new(wc_handle_name) + hot.resources_list << WaitCondition.new(get_resource_name_nested(hot), wc_handle_name, 2000) + # end + end + + wc_notify = '' + wc_notify = "\nwc_notify --data-binary '{\"status\": \"SUCCESS\"}'\n" + if vdu['wc_notify'] + wc_notify = "\nwc_notify --data-binary '{\"status\": \"SUCCESS\"}'\n" + end - #if vdu['wc_notify'] - shell = "#!/bin/bash" - if @type == 'vSA' - shell = "#!/bin/tcsh" - end - if @type != 'vSA' - bootstrap_script = vdu.has_key?('bootstrap_script') ? vdu['bootstrap_script'] : shell + shell = '#!/bin/bash' + shell = '#!/bin/tcsh' if @type == 'vSA' + + bootstrap_script = vdu.key?('bootstrap_script') ? vdu['bootstrap_script'] : shell { - str_replace: { - params: { - wc_notify: { - get_attr: [wc_handle_name, 'curl_cli'] + 'str_replace' => { + 'params' => { + 'wc_notify' => { + 'get_attr' => [wc_handle_name, 'curl_cli'] } }, - template: bootstrap_script + wc_notify + 'template' => bootstrap_script + wc_notify } } - else - bootstrap_script = "#!/bin/bash" + wc_notify - end - #end - end - - def add_wait_condition2(vdu, hot) - wc_handle_name = get_resource_name_nested(hot) - - #if vdu['wc_notify'] - if @type != 'vSA' && !vdu['wc_notify'].nil? - hot.resources_list << WaitConditionHandle.new(wc_handle_name) - hot.resources_list << WaitCondition.new(get_resource_name_nested(hot), wc_handle_name, 2000) - #end end - wc_notify = "" - wc_notify = "\nwc_notify --data-binary '{\"status\": \"SUCCESS\"}'\n" - if vdu['wc_notify'] - wc_notify = "\nwc_notify --data-binary '{\"status\": \"SUCCESS\"}'\n" + # Generates a new resource name + # + # @return [String] the generated resource name + def get_resource_name + @name + '_' + @hot.resources_list.length.to_s unless @name.empty? end - shell = "#!/bin/bash" - if @type == 'vSA' - shell = "#!/bin/tcsh" + def get_resource_name_nested(hot) + @name + '_nested_' + hot.resources_list.length.to_s unless @name.empty? end - bootstrap_script = vdu.has_key?('bootstrap_script') ? vdu['bootstrap_script'] : shell - { - "str_replace" => { - "params" => { - "wc_notify" => { - "get_attr" => [wc_handle_name, 'curl_cli'] - } - }, - "template" => bootstrap_script + wc_notify - } - } - end - - # Generates a new resource name - # - # @return [String] the generated resource name - def get_resource_name - @name + '_' + @hot.resources_list.length.to_s unless @name.empty? - end - - def get_resource_name_nested(hot) - @name + '_nested_' + hot.resources_list.length.to_s unless @name.empty? - end - - # Converts a value to another unit - # - # @param [Numeric] value the value to convert - # @param [String] input_unit the unit to convert from - # @param [String] output_unit the unit to convert to - # @return [Numeric] the converted value - def unit_converter(value, input_unit, output_unit) - return 0 if value == 0 - return value if input_unit.downcase == output_unit.downcase - - if input_unit.downcase == 'gb' - if output_unit.downcase == 'mb' - return value * 1024 - end - else - if input_unit.downcase == 'mb' - if output_unit.downcase == 'gb' - return value / 1024 - end - else - if input_unit.downcase == 'tb' - if output_unit.downcase == 'gb' - return value * 1024 - end + # Converts a value to another unit + # + # @param [Numeric] value the value to convert + # @param [String] input_unit the unit to convert from + # @param [String] output_unit the unit to convert to + # @return [Numeric] the converted value + def unit_converter(value, input_unit, output_unit) + return 0 if value == 0 + return value if input_unit.casecmp(output_unit.downcase).zero? + + if input_unit.casecmp('gb').zero? + return value * 1024 if output_unit.casecmp('mb').zero? + else + if input_unit.casecmp('mb').zero? + return value / 1024 if output_unit.casecmp('gb').zero? + else + if input_unit.casecmp('tb').zero? + return value * 1024 if output_unit.casecmp('gb').zero? + end + end end - end end - end - - def create_autoscale_group(cooldown, max_size, min_size, desired_capacity, resource) - name = get_resource_name - @hot.resources_list << AutoScalingGroup.new(name, cooldown, max_size, min_size, desired_capacity, resource) - name - end - def create_scale_policy(auto_scaling_group, scaling_adjustment) - name = get_resource_name - @hot.resources_list << ScalingPolicy.new(name, {get_resource: auto_scaling_group}, scaling_adjustment) - name - end + def create_autoscale_group(cooldown, max_size, min_size, desired_capacity, resource) + name = get_resource_name + @hot.resources_list << AutoScalingGroup.new(name, cooldown, max_size, min_size, desired_capacity, resource) + name + end + def create_scale_policy(auto_scaling_group, scaling_adjustment) + name = get_resource_name + @hot.resources_list << ScalingPolicy.new(name, { get_resource: auto_scaling_group }, scaling_adjustment) + name + end end diff --git a/hot-generator/routes/hot.rb b/hot-generator/routes/hot.rb index a8de88e..566f48a 100644 --- a/hot-generator/routes/hot.rb +++ b/hot-generator/routes/hot.rb @@ -17,197 +17,193 @@ # # @see OrchestratorHotGenerator class HotGenerator < Sinatra::Application + # @method post_hot_flavour + # @overload post '/hot/:flavour' + # Convert a VNFD into a HOT + # @param [String] flavour the T-NOVA flavour to generate the HOT + # @param [JSON] the VNFD to convert + # Convert a VNFD into a HOT + post '/hot/:flavour' do + # Return if content-type is invalid + halt 415 unless request.content_type == 'application/json' + + # Validate JSON format + provision_info = JSON.parse(request.body.read) + # return 400, errors.to_json if errors - # @method post_hot_flavour - # @overload post '/hot/:flavour' - # Convert a VNFD into a HOT - # @param [String] flavour the T-NOVA flavour to generate the HOT - # @param [JSON] the VNFD to convert - # Convert a VNFD into a HOT - post '/hot/:flavour' do - # Return if content-type is invalid - halt 415 unless request.content_type == 'application/json' + vnf = provision_info['vnf'] + + networks_id = provision_info['networks_id'] + halt 400, 'Networks ID not found' if networks_id.nil? - # Validate JSON format - provision_info = JSON.parse(request.body.read) - #return 400, errors.to_json if errors + routers_id = provision_info['routers_id'] + halt 400, 'Routers ID not found' if routers_id.nil? - vnf = provision_info['vnf'] + security_group_id = nil if provision_info['security_group_id'].nil? - networks_id = provision_info['networks_id'] - halt 400, 'Networks ID not found' if networks_id.nil? + vnfr_id = provision_info['vnfr_id'] + halt 400, 'Vnfr ID not found' if vnfr_id.nil? - routers_id = provision_info['routers_id'] - halt 400, 'Routers ID not found' if routers_id.nil? + logger.debug 'Networks IDs: ' + networks_id.to_json + logger.debug 'Security Group ID: ' + security_group_id.to_json - if provision_info['security_group_id'].nil? - security_group_id = nil - end + dns_server = provision_info['dns_server'] + halt 400, 'DNS server not found' if dns_server.nil? - vnfr_id = provision_info['vnfr_id'] - halt 400, 'Vnfr ID not found' if vnfr_id.nil? + public_network_id = provision_info['public_network_id'] + halt 400, 'Public Network ID not found' if public_network_id.nil? - logger.debug 'Networks IDs: ' + networks_id.to_json - logger.debug 'Security Group ID: ' + security_group_id.to_json + flavours = provision_info['flavours'] + # TODO: if flavour is not an array, return 400 + # halt 400, 'Public Network ID not found' if flavours.nil? - dns_server = provision_info['dns_server'] - halt 400, 'DNS server not found' if dns_server.nil? + # Build a HOT template + logger.debug 'T-NOVA flavour: ' + params[:flavour] + hot = CommonMethods.generate_hot_template(vnf['vnfd'], params[:flavour], networks_id, routers_id, security_group_id, vnfr_id, dns_server, public_network_id, flavours) - public_network_id = provision_info['public_network_id'] - halt 400, 'Public Network ID not found' if public_network_id.nil? + halt 200, hot.to_json + end - flavours = provision_info['flavours'] - # TODO if flavour is not an array, return 400 - #halt 400, 'Public Network ID not found' if flavours.nil? + # @method post_networkhot_flavour + # @overload post '/networkhot/:flavour' + # Build a HOT to create the networks + # @param [String] flavour the T-NOVA flavour to generate the HOT + # @param [JSON] the networks information + # Convert a VNFD into a HOT + post '/networkhot/:flavour' do + # Return if content-type is invalid + halt 415 unless request.content_type == 'application/json' - # Build a HOT template - logger.debug 'T-NOVA flavour: ' + params[:flavour] - hot = CommonMethods.generate_hot_template(vnf['vnfd'], params[:flavour], networks_id, routers_id, security_group_id, vnfr_id, dns_server, public_network_id, flavours) + # Validate JSON format + networkInfo = JSON.parse(request.body.read) + # return 400, errors.to_json if errors - halt 200, hot.to_json - end + nsr_id = networkInfo['nsr_id'] + halt 400, 'NSR ID not found' if nsr_id.nil? - # @method post_networkhot_flavour - # @overload post '/networkhot/:flavour' - # Build a HOT to create the networks - # @param [String] flavour the T-NOVA flavour to generate the HOT - # @param [JSON] the networks information - # Convert a VNFD into a HOT - post '/networkhot/:flavour' do - # Return if content-type is invalid - halt 415 unless request.content_type == 'application/json' + nsd = networkInfo['nsd'] + halt 400, 'NSD not found' if nsd.nil? - # Validate JSON format - networkInfo = JSON.parse(request.body.read) - #return 400, errors.to_json if errors + public_net_id = networkInfo['public_net_id'] + halt 400, 'Public network ID not found' if public_net_id.nil? - nsr_id = networkInfo['nsr_id'] - halt 400, 'NSR ID not found' if nsr_id.nil? + dns_server = networkInfo['dns_server'] + halt 400, 'DNS server not found' if dns_server.nil? - nsd = networkInfo['nsd'] - halt 400, 'NSD not found' if nsd.nil? + # Build a HOT template + logger.debug 'T-NOVA flavour: ' + params[:flavour] + hot = CommonMethods.generate_network_hot_template(nsd, public_net_id, dns_server, params[:flavour], nsr_id) - public_net_id = networkInfo['public_net_id'] - halt 400, 'Public network ID not found' if public_net_id.nil? + halt 200, hot.to_json + end - dns_server = networkInfo['dns_server'] - halt 400, 'DNS server not found' if dns_server.nil? + # @method post_wicmhot + # @overload post '/wicmhot' + # Build a HOT to create the WICM-SFC integration + # Convert a VNFD into a HOT + post '/wicmhot' do + # Return if content-type is invalid + halt 415 unless request.content_type == 'application/json' - # Build a HOT template - logger.debug 'T-NOVA flavour: ' + params[:flavour] - hot = CommonMethods.generate_network_hot_template(nsd, public_net_id, dns_server, params[:flavour], nsr_id) + # Validate JSON format + provider_info = JSON.parse(request.body.read) + # return 400, errors.to_json if errors - halt 200, hot.to_json - end + # Build a HOT template + hot = CommonMethods.generate_wicm_hot_template(provider_info) - # @method post_wicmhot - # @overload post '/wicmhot' - # Build a HOT to create the WICM-SFC integration - # Convert a VNFD into a HOT - post '/wicmhot' do - # Return if content-type is invalid - halt 415 unless request.content_type == 'application/json' + halt 200, hot.to_json + end - # Validate JSON format - provider_info = JSON.parse(request.body.read) - #return 400, errors.to_json if errors + # @method post_networkhot_flavour + # @overload post '/networkhot/:flavour' + # Build a HOT to create the networks + # @param [String] flavour the T-NOVA flavour to generate the HOT + # @param [JSON] the networks information + # Convert a VNFD into a HOT + post '/scale/:flavour' do + # Return if content-type is invalid + halt 415 unless request.content_type == 'application/json' - # Build a HOT template - hot = CommonMethods.generate_wicm_hot_template(provider_info) + # Validate JSON format + provision_info = JSON.parse(request.body.read) + # return 400, errors.to_json if errors - halt 200, hot.to_json - end + vnf = provision_info['vnf'] - # @method post_networkhot_flavour - # @overload post '/networkhot/:flavour' - # Build a HOT to create the networks - # @param [String] flavour the T-NOVA flavour to generate the HOT - # @param [JSON] the networks information - # Convert a VNFD into a HOT - post '/scale/:flavour' do - # Return if content-type is invalid - halt 415 unless request.content_type == 'application/json' + networks_id = provision_info['networks_id'] + halt 400, 'Networks ID not found' if networks_id.nil? - # Validate JSON format - provision_info = JSON.parse(request.body.read) - #return 400, errors.to_json if errors + security_group_id = provision_info['security_group_id'] + halt 400, 'Security group ID not found' if security_group_id.nil? - vnf = provision_info['vnf'] + vdus_deployed_info = provision_info['vdus_deployed_info'] + halt 400, 'VDUs info not found' if vdus_deployed_info.nil? - networks_id = provision_info['networks_id'] - halt 400, 'Networks ID not found' if networks_id.nil? + public_network_id = provision_info['public_network_id'] + halt 400, 'Public Network ID not found' if public_network_id.nil? - security_group_id = provision_info['security_group_id'] - halt 400, 'Security group ID not found' if security_group_id.nil? + logger.debug 'Networks IDs: ' + networks_id.to_json + logger.debug 'Security Group ID: ' + security_group_id.to_json - vdus_deployed_info= provision_info['vdus_deployed_info'] - halt 400, 'VDUs info not found' if vdus_deployed_info.nil? + # Build a HOT template + logger.debug 'Scale T-NOVA flavour: ' + params[:flavour] + hot = CommonMethods.generate_hot_template_scaling(vnf['vnfd'], params[:flavour], networks_id, security_group_id, public_network_id, vdus_deployed_info) - public_network_id = provision_info['public_network_id'] - halt 400, 'Public Network ID not found' if public_network_id.nil? + halt 200, hot.to_json + end - logger.debug 'Networks IDs: ' + networks_id.to_json - logger.debug 'Security Group ID: ' + security_group_id.to_json + # @method post_netflochot + # @overload post '/netfloc' + # Build a HOT to create the Netfloc integration + # Convert a VNFFG into a HOT + post '/netfloc' do + # Return if content-type is invalid + halt 415 unless request.content_type == 'application/json' - # Build a HOT template - logger.debug 'Scale T-NOVA flavour: ' + params[:flavour] - hot = CommonMethods.generate_hot_template_scaling(vnf['vnfd'], params[:flavour], networks_id, security_group_id, public_network_id, vdus_deployed_info) + # Validate JSON format + provision_info = JSON.parse(request.body.read) + # return 400, errors.to_json if errors - halt 200, hot.to_json - end + ports = provision_info['ports'] + halt 400, 'Ports not found' if ports.nil? - # @method post_netflochot - # @overload post '/netfloc' - # Build a HOT to create the Netfloc integration - # Convert a VNFFG into a HOT - post '/netfloc' do - # Return if content-type is invalid - halt 415 unless request.content_type == 'application/json' + odl_username = provision_info['odl_username'] + halt 400, 'ODL username not found' if odl_username.nil? - # Validate JSON format - provision_info = JSON.parse(request.body.read) - #return 400, errors.to_json if errors + odl_password = provision_info['odl_password'] + halt 400, 'ODL password not found' if odl_password.nil? - ports = provision_info['ports'] - halt 400, 'Ports not found' if ports.nil? + netfloc_ip_port = provision_info['netfloc_ip_port'] + halt 400, 'Netfloc IP not found' if netfloc_ip_port.nil? - odl_username = provision_info['odl_username'] - halt 400, 'ODL username not found' if odl_username.nil? + # Build a HOT template + hot = CommonMethods.generate_netfloc_hot_template(ports, odl_username, odl_password, netfloc_ip_port) - odl_password = provision_info['odl_password'] - halt 400, 'ODL password not found' if odl_password.nil? + halt 200, hot.to_json + end - netfloc_ip_port = provision_info['netfloc_ip_port'] - halt 400, 'Netfloc IP not found' if netfloc_ip_port.nil? + # @method post_userhot + # @overload post '/userhot' + # Build a HOT to create the Users and Projects + post '/userhot' do + # Return if content-type is invalid + halt 415 unless request.content_type == 'application/json' - # Build a HOT template - hot = CommonMethods.generate_netfloc_hot_template(ports, odl_username, odl_password, netfloc_ip_port) + # Validate JSON format + credentials_info = JSON.parse(request.body.read) - halt 200, hot.to_json - end + halt 400, 'Username not found' if credentials_info['username'].nil? + halt 400, 'Password not found' if credentials_info['password'].nil? + halt 400, 'Project name not found' if credentials_info['project_name'].nil? - # @method post_userhot - # @overload post '/userhot' - # Build a HOT to create the Users and Projects - post '/userhot' do - # Return if content-type is invalid - halt 415 unless request.content_type == 'application/json' + # Build a HOT template + hot = CommonMethods.generate_user_hot_template(credentials_info) - # Validate JSON format - credentials_info = JSON.parse(request.body.read) - - halt 400, 'Username not found' if credentials_info['username'].nil? - halt 400, 'Password not found' if credentials_info['password'].nil? - halt 400, 'Project name not found' if credentials_info['project_name'].nil? - - # Build a HOT template - hot = CommonMethods.generate_user_hot_template(credentials_info) - - halt 200, hot.to_json - end - - get '/files/:file_name' do - File.read(File.join('assets/templates', params[:file_name])) - end + halt 200, hot.to_json + end + get '/files/:file_name' do + File.read(File.join('assets/templates', params[:file_name])) + end end diff --git a/ns-catalogue/routes/ns.rb b/ns-catalogue/routes/ns.rb index 681f240..4063bcb 100644 --- a/ns-catalogue/routes/ns.rb +++ b/ns-catalogue/routes/ns.rb @@ -16,159 +16,156 @@ # limitations under the License. # @see NsCatalogue class Catalogue < NsCatalogue - - # @method get_network_services - # @overload get '/network-services' - # Returns a list of NSs - get '/' do - params[:offset] ||= 1 - params[:limit] ||= 20 - - # Only accept positive numbers - params[:offset] = 1 if params[:offset].to_i < 1 - params[:limit] = 2 if params[:limit].to_i < 1 - - # Get paginated list - nss = Ns.paginate(:page => params[:offset], :limit => params[:limit]) - - # Build HTTP Link Header - headers['Link'] = build_http_link(params[:offset].to_i, params[:limit]) - - begin - return 200, nss.to_json - rescue - logger.error "Error Establishing a Database Connection" - return 500, "Error Establishing a Database Connection" + # @method get_network_services + # @overload get '/network-services' + # Returns a list of NSs + get '/' do + params[:offset] ||= 1 + params[:limit] ||= 20 + + # Only accept positive numbers + params[:offset] = 1 if params[:offset].to_i < 1 + params[:limit] = 2 if params[:limit].to_i < 1 + + # Get paginated list + nss = Ns.paginate(page: params[:offset], limit: params[:limit]) + + # Build HTTP Link Header + headers['Link'] = build_http_link(params[:offset].to_i, params[:limit]) + + begin + return 200, nss.to_json + rescue + logger.error 'Error Establishing a Database Connection' + return 500, 'Error Establishing a Database Connection' + end end - end - - # @method get_network_services_id - # @overload get '/network-services/:external_ns_id' - # Show a NS - # @param [Integer] external_ns_id NS external ID - get '/:id' do |id| - begin - ns = Ns.find_by({"nsd.id" => id}) - rescue Mongoid::Errors::DocumentNotFound => e - logger.error 'NSD not found.' - halt 404 - end - return 200, ns.nsd.to_json - #NsSerializer.new(ns).to_json - end - - # @method post_network_services - # @overload post '/network-services' - # Post a NS in JSON format - # @param [JSON] NS in JSON format - post '/' do - # Return if content-type is invalid - return 415 unless request.content_type == 'application/json' - - # Validate JSON format - ns, errors = parse_json(request.body.read) - return 400, errors.to_json if errors - - # Validate NS - return 400, 'ERROR: NSD not found' unless ns.has_key?('nsd') - - # Validate NSD - begin - RestClient.post settings.nsd_validator + '/nsds', ns.to_json, :content_type => :json - rescue Errno::ECONNREFUSED - logger.error 'NSD Validator unreachable' - halt 500, 'NSD Validator unreachable' - rescue => e - logger.error e - halt e.response.code, e.response.body + # @method get_network_services_id + # @overload get '/network-services/:external_ns_id' + # Show a NS + # @param [Integer] external_ns_id NS external ID + get '/:id' do |id| + begin + ns = Ns.find_by('nsd.id' => id) + rescue Mongoid::Errors::DocumentNotFound => e + logger.error 'NSD not found.' + halt 404 + end + return 200, ns.nsd.to_json + # NsSerializer.new(ns).to_json end - begin - ns = Ns.find_by({"nsd.id" => ns['nsd']['id'], "nsd.version" => ns['nsd']['version'], "nsd.vendor" => ns['nsd']['vendor']}) - logger.error ns - if ns != nil - logger.error 'ERROR: Duplicated NS ID, Version or Vendor' - return 409, 'ERROR: Duplicated NS ID, Version or Vendor' - end - rescue Mongoid::Errors::DocumentNotFound => e + # @method post_network_services + # @overload post '/network-services' + # Post a NS in JSON format + # @param [JSON] NS in JSON format + post '/' do + # Return if content-type is invalid + return 415 unless request.content_type == 'application/json' + + # Validate JSON format + ns, errors = parse_json(request.body.read) + return 400, errors.to_json if errors + + # Validate NS + return 400, 'ERROR: NSD not found' unless ns.key?('nsd') + + # Validate NSD + begin + RestClient.post settings.nsd_validator + '/nsds', ns.to_json, content_type: :json + rescue Errno::ECONNREFUSED + logger.error 'NSD Validator unreachable' + halt 500, 'NSD Validator unreachable' + rescue => e + logger.error e + halt e.response.code, e.response.body + end + + begin + ns = Ns.find_by('nsd.id' => ns['nsd']['id'], 'nsd.version' => ns['nsd']['version'], 'nsd.vendor' => ns['nsd']['vendor']) + logger.error ns + unless ns.nil? + logger.error 'ERROR: Duplicated NS ID, Version or Vendor' + return 409, 'ERROR: Duplicated NS ID, Version or Vendor' + end + rescue Mongoid::Errors::DocumentNotFound => e + end + + # Save to BD + begin + new_ns = Ns.create!(ns) + rescue Moped::Errors::OperationFailure => e + return 400, 'ERROR: Duplicated NS ID' if e.message.include? 'E11000' + rescue => e + logger.error 'Some other error.' + logger.error e + end + + return 200, new_ns.to_json end - # Save to BD - begin - new_ns = Ns.create!(ns) - rescue Moped::Errors::OperationFailure => e - return 400, 'ERROR: Duplicated NS ID' if e.message.include? 'E11000' - rescue => e - logger.error "Some other error." - logger.error e + # @method put_nss + # @overload put '/network-services/:id' + # Update a NS + # @param [JSON] NS in JSON format + put '/:external_ns_id' do + # Return if content-type is invalid + return 415 unless request.content_type == 'application/json' + + # Validate JSON format + new_ns, errors = parse_json(request.body.read) + return 400, errors.to_json if errors + + begin + ns = Ns.find_by('nsd.id' => params[:external_ns_id]) + rescue Mongoid::Errors::DocumentNotFound => e + return 400, 'This NSD no exists' + end + + nsd = {} + prng = Random.new + new_ns['id'] = new_ns['id'] + prng.rand(1000).to_s + nsd['nsd'] = new_ns + + # Validate NSD + begin + RestClient.post settings.nsd_validator + '/nsds', nsd.to_json, content_type: :json + rescue => e + logger.error e.response + return e.response.code, e.response.body + end + + begin + new_ns = Ns.create!(nsd) + rescue Moped::Errors::OperationFailure => e + return 400, 'ERROR: Duplicated NS ID' if e.message.include? 'E11000' + end + + return 200, new_ns.to_json end - return 200, new_ns.to_json - end - - # @method put_nss - # @overload put '/network-services/:id' - # Update a NS - # @param [JSON] NS in JSON format - put '/:external_ns_id' do - - # Return if content-type is invalid - return 415 unless request.content_type == 'application/json' - - # Validate JSON format - new_ns, errors = parse_json(request.body.read) - return 400, errors.to_json if errors - - begin - ns = Ns.find_by({"nsd.id" => params[:external_ns_id]}) - rescue Mongoid::Errors::DocumentNotFound => e - return 400, 'This NSD no exists' - end - - nsd = {} - prng = Random.new - new_ns['id'] = new_ns['id'] + prng.rand(1000).to_s - nsd['nsd'] = new_ns - - # Validate NSD - begin - RestClient.post settings.nsd_validator + '/nsds', nsd.to_json, :content_type => :json - rescue => e - logger.error e.response - return e.response.code, e.response.body + # @method delete_ns_id + # @overload delete '/network-services/:external_vnf_id' + # Delete a NS by its ID + # @param [Integer] external_ns_id NS external ID + delete '/:external_ns_id' do + begin + # ns = Ns.find( params[:external_ns_id] ) + ns = Ns.find_by('nsd.id' => params[:external_ns_id]) + rescue Mongoid::Errors::DocumentNotFound => e + halt 404 + end + ns.destroy + return 200 end - begin - new_ns = Ns.create!(nsd) - rescue Moped::Errors::OperationFailure => e - return 400, 'ERROR: Duplicated NS ID' if e.message.include? 'E11000' - end - - return 200, new_ns.to_json - end - - # @method delete_ns_id - # @overload delete '/network-services/:external_vnf_id' - # Delete a NS by its ID - # @param [Integer] external_ns_id NS external ID - delete '/:external_ns_id' do - begin - #ns = Ns.find( params[:external_ns_id] ) - ns = Ns.find_by({"nsd.id" => params[:external_ns_id]}) - rescue Mongoid::Errors::DocumentNotFound => e - halt 404 - end - ns.destroy - return 200 - end - - get '/vnf/:vnf_id' do - begin - nss = Ns.find_by({"nsd.vnfds" => params[:vnf_id]}) - rescue Mongoid::Errors::DocumentNotFound => e - halt 404, "No services using this VNFD" + get '/vnf/:vnf_id' do + begin + nss = Ns.find_by('nsd.vnfds' => params[:vnf_id]) + rescue Mongoid::Errors::DocumentNotFound => e + halt 404, 'No services using this VNFD' + end + return 200, nss.to_json end - return 200, nss.to_json - end end diff --git a/ns-monitoring/helpers/expression_evaluator.rb b/ns-monitoring/helpers/expression_evaluator.rb index 7184d29..2607e26 100644 --- a/ns-monitoring/helpers/expression_evaluator.rb +++ b/ns-monitoring/helpers/expression_evaluator.rb @@ -18,9 +18,7 @@ # @see NSMonitoring module ExpressionEvaluatorHelper def self.calc_expression(formula, values) - if values.size == 1 - return values[0] - end + return values[0] if values.size == 1 operations = formula.split('(')[0] response = 0 @@ -56,15 +54,15 @@ def find_max(values) def find_avg(values) val = 0 values.each do |v| - val = val + v + val += v end - val/values.size + val / values.size end def find_sum(values) val = 0 values.each do |v| - val = val + v + val += v end val end diff --git a/ns-monitoring/helpers/monitoring.rb b/ns-monitoring/helpers/monitoring.rb index 2d4e0b1..4a54431 100644 --- a/ns-monitoring/helpers/monitoring.rb +++ b/ns-monitoring/helpers/monitoring.rb @@ -17,167 +17,164 @@ # # @see NSMonitoring module MonitoringHelper + @conn = Bunny.new + @conn.start + @channel = @conn.create_channel + @@testThreads = [] + + # Checks if a JSON message is valid + # + # @param [JSON] message some JSON message + # @return [Hash, nil] if the parsed message is a valid JSON + # @return [Hash, String] if the parsed message is an invalid JSON + def parse_json(message) + # Check JSON message format + begin + parsed_message = JSON.parse(message) # parse json message + rescue JSON::ParserError => e + # If JSON not valid, return with errors + logger.error "JSON parsing: #{e}" + return message, e.to_s + "\n" + end - @conn = Bunny.new - @conn.start - @channel = @conn.create_channel - @@testThreads = [] - - # Checks if a JSON message is valid - # - # @param [JSON] message some JSON message - # @return [Hash, nil] if the parsed message is a valid JSON - # @return [Hash, String] if the parsed message is an invalid JSON - def parse_json(message) - # Check JSON message format - begin - parsed_message = JSON.parse(message) # parse json message - rescue JSON::ParserError => e - # If JSON not valid, return with errors - logger.error "JSON parsing: #{e.to_s}" - return message, e.to_s + "\n" + [parsed_message, nil] end - return parsed_message, nil - end - - # Subcription thread method - # - # @param [JSON] message monitoring information - def self.subcriptionThread(monitoring) - logger.info "Subcription thread for NSr: " + monitoring['nsi_id'].to_s - nsi_id = monitoring['nsi_id'].to_s - vnf_instances = monitoring['vnf_instances'] - parameters = monitoring['parameters'] - - ch = @channel - vnf_instances.each do |vnf_instance| - logger.debug "VNF_Instance_id: " + vnf_instance['vnfr_id'] - begin - t = ch.queue(vnf_instance['vnfr_id'], :exclusive => false).subscribe do |delivery_info, metadata, payload| - - logger.info "Receving subcription data of" + vnf_instance['vnfr_id'].to_s - measurements = JSON.parse(payload) - logger.debug measurements.to_json - - begin - @queue = VnfQueue.find_or_create_by(:nsi_id => nsi_id, :vnfi_id => vnf_instance['vnfr_id'], :parameter_id => measurements['type']) - @queue.update_attributes({:value => measurements['value'], :timestamp => measurements['timestamp'], :unit => measurements['unit']}) - rescue => e - puts e - end - logger.debug @queue - begin - @list_vnfs_parameters = VnfQueue.where(:nsi_id => nsi_id, :parameter_id => measurements['type']) - if @list_vnfs_parameters.length == vnf_instances.length - #logger.debug "Lisf of vnfs_params is equal." - logger.debug @list_vnfs_parameters.to_json - param = parameters.find {|p| p['name'] == measurements['type'] } - if param.nil? - logger.debug "Params outside the SLA (assurance parameters field)" - calculation = measurements['value'] - else - logger.info "Params inside the SLA (checking SLA)..." - values = [] - @list_vnfs_parameters.each do |p| - values << p['value'] + # Subcription thread method + # + # @param [JSON] message monitoring information + def self.subcriptionThread(monitoring) + logger.info 'Subcription thread for NSr: ' + monitoring['nsi_id'].to_s + nsi_id = monitoring['nsi_id'].to_s + vnf_instances = monitoring['vnf_instances'] + parameters = monitoring['parameters'] + + ch = @channel + vnf_instances.each do |vnf_instance| + logger.debug 'VNF_Instance_id: ' + vnf_instance['vnfr_id'] + begin + t = ch.queue(vnf_instance['vnfr_id'], exclusive: false).subscribe do |_delivery_info, _metadata, payload| + logger.info 'Receving subcription data of' + vnf_instance['vnfr_id'].to_s + measurements = JSON.parse(payload) + logger.debug measurements.to_json + + begin + @queue = VnfQueue.find_or_create_by(nsi_id: nsi_id, vnfi_id: vnf_instance['vnfr_id'], parameter_id: measurements['type']) + @queue.update_attributes(value: measurements['value'], timestamp: measurements['timestamp'], unit: measurements['unit']) + rescue => e + puts e + end + logger.debug @queue + begin + @list_vnfs_parameters = VnfQueue.where(nsi_id: nsi_id, parameter_id: measurements['type']) + if @list_vnfs_parameters.length == vnf_instances.length + # logger.debug "Lisf of vnfs_params is equal." + logger.debug @list_vnfs_parameters.to_json + param = parameters.find { |p| p['name'] == measurements['type'] } + if param.nil? + logger.debug 'Params outside the SLA (assurance parameters field)' + calculation = measurements['value'] + else + logger.info 'Params inside the SLA (checking SLA)...' + values = [] + @list_vnfs_parameters.each do |p| + values << p['value'] + end + + logger.debug 'Send to Expression Evaluator.' + calculation = ExpressionEvaluatorHelper.calc_expression(param['formula'], values) + logger.debug 'Calculation response: ' + calculation.to_s + + begin + sla = Sla.find_by!(nsi_id: nsi_id) + sla_breach = sla.process_reading(param, calculation) + # if sla_breach + # logger.info "Breach reached!" + # end + rescue ActiveRecord::RecordNotFound => e + logger.error 'SLA information not found for NSR ' + nsi_id + # return 404, "Could not find an SLA for NS Instance ID #{nsi_id}" + end + + # logger.debug "Calculation: " + calculation + # if SlaHelper.check_breach_sla(param['value'], calculation) + # SlaHelper.process_breach() + # end + end + ns_measurement = { + instance_id: nsi_id, + type: @queue['parameter_id'], + unit: @queue['unit'], + value: calculation, + timestamp: @queue['timestamp'] + } + logger.debug ns_measurement + + q = ch.queue('ns_monitoring') + q.publish(ns_measurement.to_json, persistent: true) + + VnfQueue.destroy_all(nsi_id: nsi_id, parameter_id: measurements['parameter_id']) + else + logger.error 'NO equal. Wait next value' + end + rescue => e + puts e + end end + logger.debug 'Adding to queue' + @@testThreads << { vnfi_id: vnf_instance['vnfr_id'], queue: t } + rescue Interrupt => _ + logger.error 'THREAD INTERRUPTION ...' + conn.close + end + end + end - logger.debug "Send to Expression Evaluator." - calculation = ExpressionEvaluatorHelper.calc_expression(param['formula'], values) - logger.debug "Calculation response: " + calculation.to_s + def self.startSubcription + logger.info 'Getting list of instances...' + begin + response = RestClient.get Sinatra::Application.settings.ns_provisioner + '/ns-instances', content_type: :json + @ns_instances = JSON.parse(response) + logger.info 'Creating a monitoring thread for each instance...' + @ns_instances.each do |instance| begin - sla = Sla.find_by!(nsi_id: nsi_id) - sla_breach = sla.process_reading(param, calculation) - #if sla_breach - #logger.info "Breach reached!" - #end - rescue ActiveRecord::RecordNotFound => e - logger.error "SLA information not found for NSR " + nsi_id - #return 404, "Could not find an SLA for NS Instance ID #{nsi_id}" + monitoring = NsMonitoringParameter.find_by('nsi_id' => instance['id']) + nsi_id = monitoring['nsi_id'].to_s + logger.info 'Creating thread for NS instance ' + nsi_id.to_s + logger.debug monitoring # to remove + + Thread.new do + Thread.current['name'] = nsi_id + MonitoringHelper.subcriptionThread(monitoring) + Thread.stop + end + rescue Mongoid::Errors::DocumentNotFound => e + logger.debug 'No monitoring configuration in the BD for NSr_id ' + instance['id'] end - - #logger.debug "Calculation: " + calculation - #if SlaHelper.check_breach_sla(param['value'], calculation) - #SlaHelper.process_breach() - #end - end - ns_measurement = { - :instance_id => nsi_id, - :type => @queue['parameter_id'], - :unit => @queue['unit'], - :value => calculation, - :timestamp => @queue['timestamp'] - } - logger.debug ns_measurement - - q = ch.queue("ns_monitoring") - q.publish(ns_measurement.to_json, :persistent => true) - - VnfQueue.destroy_all(:nsi_id => nsi_id, :parameter_id => measurements['parameter_id']) - else - logger.error "NO equal. Wait next value" end - rescue => e + rescue => e + puts 'Error!' puts e - end - end - logger.debug "Adding to queue" - @@testThreads << {:vnfi_id => vnf_instance['vnfr_id'], :queue => t} - rescue Interrupt => _ - logger.error "THREAD INTERRUPTION ..." - conn.close - end end - end - - def self.startSubcription() - logger.info "Getting list of instances..." - begin - response = RestClient.get Sinatra::Application.settings.ns_provisioner + '/ns-instances', :content_type => :json - @ns_instances = JSON.parse(response) - logger.info "Creating a monitoring thread for each instance..." - @ns_instances.each do |instance| + def destroy_monitoring_data(nsi_id) + logger.error 'Destroy Monitoring Data of ' + nsi_id begin - monitoring = NsMonitoringParameter.find_by("nsi_id" => instance['id']) - nsi_id = monitoring['nsi_id'].to_s - logger.info "Creating thread for NS instance " + nsi_id.to_s - logger.debug monitoring # to remove - - Thread.new { - Thread.current["name"] = nsi_id; - MonitoringHelper.subcriptionThread(monitoring) - Thread.stop - } - rescue Mongoid::Errors::DocumentNotFound => e - logger.debug "No monitoring configuration in the BD for NSr_id " + instance['id'] + response = RestClient.delete settings.ns_monitoring_repo + "/ns-monitoring/#{nsi_id}", content_type: :json + rescue => e + logger.error e.response + # return e.response.code, e.response.body end - end - rescue => e - puts "Error!" - puts e end - end - - def destroy_monitoring_data(nsi_id) - logger.error "Destroy Monitoring Data of " + nsi_id - begin - response = RestClient.delete settings.ns_monitoring_repo + "/ns-monitoring/#{nsi_id}", content_type: :json - rescue => e - logger.error e.response - # return e.response.code, e.response.body - end - end - def self.logger - Logging.logger - end + def self.logger + Logging.logger + end - # Global, memoized, lazy initialized instance of a logger - def self.logger - @logger ||= Logger.new(STDOUT) - end + # Global, memoized, lazy initialized instance of a logger + def self.logger + @logger ||= Logger.new(STDOUT) + end end diff --git a/ns-monitoring/helpers/sla.rb b/ns-monitoring/helpers/sla.rb index 3548e92..7eefa33 100644 --- a/ns-monitoring/helpers/sla.rb +++ b/ns-monitoring/helpers/sla.rb @@ -17,53 +17,51 @@ # # @see NSMonitoring module SlaHelper + def self.process_breach + puts 'BREACh.' + logger.info 'SLA Breach!' - def self.process_breach() - puts "BREACh." - logger.info "SLA Breach!" + logger.info 'Inform to NS Manager about this.' - logger.info "Inform to NS Manager about this." + puts Sinatra::Application.settings.manager - puts Sinatra::Application.settings.manager + begin + response = RestClient.get settings.vnf_provisioning + '/vnf-provisioning/vnf-instances/' + vnfr_id, content_type: :json, accept: :json + rescue => e + puts e + end + end - begin - response = RestClient.get settings.vnf_provisioning + "/vnf-provisioning/vnf-instances/" + vnfr_id, :content_type => :json, :accept => :json - rescue => e - puts e - end - - end - - # Check if the value is inside the threshold - # Threshold format: GT(#integer), LE(#integer)... - def self.check_breach_sla(threshold, value) - operation = threshold.split("(")[0] - threshold = threshold.split("(")[1].split(")")[0] - response = false + # Check if the value is inside the threshold + # Threshold format: GT(#integer), LE(#integer)... + def self.check_breach_sla(threshold, value) + operation = threshold.split('(')[0] + threshold = threshold.split('(')[1].split(')')[0] + response = false - case operation - when 'GT' - response = threshold.to_f < value.to_f - when 'LT' - response = threshold.to_f > value.to_f - when 'GE' - response = threshold.to_f <= value.to_f - when 'LE' - response = threshold.to_f >= value.to_f - when 'EQ' - response = threshold.to_f == value.to_f - when 'NE' - response = threshold.to_f != value.to_f + case operation + when 'GT' + response = threshold.to_f < value.to_f + when 'LT' + response = threshold.to_f > value.to_f + when 'GE' + response = threshold.to_f <= value.to_f + when 'LE' + response = threshold.to_f >= value.to_f + when 'EQ' + response = threshold.to_f == value.to_f + when 'NE' + response = threshold.to_f != value.to_f + end + response end - return response - end - def self.logger - Logging.logger - end + def self.logger + Logging.logger + end - # Global, memoized, lazy initialized instance of a logger - def self.logger - @logger ||= Logger.new(STDOUT) - end + # Global, memoized, lazy initialized instance of a logger + def self.logger + @logger ||= Logger.new(STDOUT) + end end diff --git a/ns-monitoring/models/sla.rb b/ns-monitoring/models/sla.rb index fa1d130..d47c41a 100644 --- a/ns-monitoring/models/sla.rb +++ b/ns-monitoring/models/sla.rb @@ -1,62 +1,63 @@ class Sla < ActiveRecord::Base - has_many :parameters -# has_many :breaches + has_many :parameters + # has_many :breaches - validates_presence_of :nsi_id + validates_presence_of :nsi_id - def includes?(param_id) - self.parameters.select {|parameter| parameter[:id] == param_id} - end + def includes?(param_id) + parameters.select { |parameter| parameter[:id] == param_id } + end + + def process_reading(parameter_values, reading) + # parameter = Parameter.where("sla_id = ? AND parameter_id = ?", self.id, parameter_values['id']).first + parameter = Parameter.where('sla_id = ? AND name = ?', id, parameter_values['name']).first + + unless parameter.nil? + if SlaHelper.check_breach_sla(parameter['threshold'], reading) + @breach = process_breach(parameter, reading) + end + end + @breach + # TODO: the above is instant processing, must process along a time-interval + end - def process_reading(parameter_values, reading) - #parameter = Parameter.where("sla_id = ? AND parameter_id = ?", self.id, parameter_values['id']).first - parameter = Parameter.where("sla_id = ? AND name = ?", self.id, parameter_values['name']).first + private - unless parameter.nil? - if SlaHelper.check_breach_sla(parameter['threshold'], reading) - @breach = process_breach(parameter, reading) - end + def process_breach(parameter, reading) + store_breach(parameter, reading) + notify_ns_manager @breach end - @breach - # TODO: the above is instant processing, must process along a time-interval - end - - private - - def process_breach(parameter, reading) - store_breach(parameter, reading) - notify_ns_manager @breach - end - - def store_breach(parameter, reading) - @breach = Breach.create(nsi_id: self.nsi_id, external_parameter_id: parameter.id, value: reading) - end - - def notify_ns_manager(breach) - self - puts "SLA Breach!" - puts breach.inspect - puts self.inspect - puts "NSR:ID: " self.nsr_id - - request = { - parameter_id: breach.external_parameter_id - } - - puts "Inform to NS Manager about this." - return - begin - response = RestClient.post Sinatra::Application.settings.manager + "/ns-instances/scaling/" +self.nsr_id + "/auto_scale", :content_type => :json, :accept => :json - rescue => e - puts e + + def store_breach(parameter, reading) + @breach = Breach.create(nsi_id: nsi_id, external_parameter_id: parameter.id, value: reading) + end + + def notify_ns_manager(breach) + self + puts 'SLA Breach!' + puts breach.inspect + puts inspect + puts 'NSR:ID: ' + nsi_id + + request = { + parameter_id: breach.external_parameter_id + } + + puts 'Inform to NS Manager about this.' + puts Sinatra::Application.settings.manager + '/ns-instances/scaling/' + nsi_id + '/auto_scale' + # Thread.new { + begin + response = RestClient.post Sinatra::Application.settings.manager + '/ns-instances/scaling/' + nsi_id + '/auto_scale', request.to_json, content_type: :json, accept: :json + rescue => e + puts e + end + puts response + # } + # auto_scale_policy: [ + # { + # criteria: [{"assurance_parameter_id": "assurance_parameter_id" }], + # actions: [ {"type": "scaling_out"}] + # } + # ] end -=begin -auto_scale_policy: [ -{ -criteria: [{"assurance_parameter_id": "assurance_parameter_id" }], -actions: [ {"type": "scaling_out"}] -} -] -=end - end end diff --git a/ns-monitoring/routes/monitoring.rb b/ns-monitoring/routes/monitoring.rb index 78cf27d..d952e03 100644 --- a/ns-monitoring/routes/monitoring.rb +++ b/ns-monitoring/routes/monitoring.rb @@ -99,7 +99,7 @@ class NSMonitoring < Sinatra::Application # Unsubcribe ns instance # @param [Integer] external_ns_id NS external ID post '/monitoring-data/unsubscribe/:nsi_id' do |nsi_id| - logger.info "Unsubcribe " + nsi_id + logger.info 'Unsubcribe ' + nsi_id begin monMetrics = NsMonitoringParameter.find_by('nsi_id' => nsi_id) rescue Mongoid::Errors::DocumentNotFound => e @@ -132,7 +132,7 @@ class NSMonitoring < Sinatra::Application monMetrics.destroy sla.destroy - halt 200, "Correct unsubcription." + halt 200, 'Correct unsubcription.' end # This interface is with the VNF Monitoring micro-service, upon successfully receiving a monitoring parameter reading for a given VNF instance. diff --git a/vnf-catalogue/helpers/vnfs.rb b/vnf-catalogue/helpers/vnfs.rb index d7c9c8e..76cae95 100644 --- a/vnf-catalogue/helpers/vnfs.rb +++ b/vnf-catalogue/helpers/vnfs.rb @@ -17,84 +17,82 @@ # # @see CatalogueHelper module CatalogueHelper + # Checks if a JSON message is valid + # + # @param [JSON] message some JSON message + # @return [Hash] if the parsed message is a valid JSON + def parse_json(message) + # Check JSON message format + begin + parsed_message = JSON.parse(message) # parse json message + rescue JSON::ParserError => e + # If JSON not valid, return with errors + logger.error "JSON parsing: #{e}" + halt 400, e.to_s + "\n" + end - # Checks if a JSON message is valid - # - # @param [JSON] message some JSON message - # @return [Hash] if the parsed message is a valid JSON - def parse_json(message) - # Check JSON message format - begin - parsed_message = JSON.parse(message) # parse json message - rescue JSON::ParserError => e - # If JSON not valid, return with errors - logger.error "JSON parsing: #{e.to_s}" - halt 400, e.to_s + "\n" - end + parsed_message + end - parsed_message - end + # Builds pagination link header + # + # @param [Integer] offset the pagination offset requested + # @param [Integer] limit the pagination limit requested + # @return [String] the built link to use in header + def build_http_link(offset, limit) + link = '' + # Next link + next_offset = offset + 1 + next_vnfs = Vnf.paginate(page: next_offset, limit: limit) + link << '; rel="next"' unless next_vnfs.empty? - # Builds pagination link header - # - # @param [Integer] offset the pagination offset requested - # @param [Integer] limit the pagination limit requested - # @return [String] the built link to use in header - def build_http_link(offset, limit) - link = '' - # Next link - next_offset = offset + 1 - next_vnfs = Vnf.paginate(:page => next_offset, :limit => limit) - link << '; rel="next"' unless next_vnfs.empty? + unless offset == 1 + # Previous link + previous_offset = offset - 1 + previous_vnfs = Vnf.paginate(page: previous_offset, limit: limit) + unless previous_vnfs.empty? + link << ', ' unless next_vnfs.empty? + link << '; rel="last"' + end + end + link + end - unless offset == 1 - # Previous link - previous_offset = offset - 1 - previous_vnfs = Vnf.paginate(:page => previous_offset, :limit => limit) - unless previous_vnfs.empty? - link << ', ' unless next_vnfs.empty? - link << '; rel="last"' - end - end - link - end - - # Method which lists all available interfaces - # - # @return [Array] an array of hashes containing all interfaces - def interfaces_list - [ - { - 'uri' => '/', - 'method' => 'GET', - 'purpose' => 'REST API Structure and Capability Discovery' - }, - { - 'uri' => '/vnfs', - 'method' => 'GET', - 'purpose' => 'List all VNFs' - }, - { - 'uri' => '/vnfs/{external_vnf_id}', - 'method' => 'GET', - 'purpose' => 'List a specific VNF' - }, - { - 'uri' => '/vnfs', - 'method' => 'POST', - 'purpose' => 'Store a new VNF' - }, - { - 'uri' => '/vnfs/{external_vnf_id}', - 'method' => 'PUT', - 'purpose' => 'Update a stored VNF' - }, - { - 'uri' => '/vnfs/{external_vnf_id}', - 'method' => 'DELETE', - 'purpose' => 'Delete a specific VNF' - } - ] - end - -end \ No newline at end of file + # Method which lists all available interfaces + # + # @return [Array] an array of hashes containing all interfaces + def interfaces_list + [ + { + 'uri' => '/', + 'method' => 'GET', + 'purpose' => 'REST API Structure and Capability Discovery' + }, + { + 'uri' => '/vnfs', + 'method' => 'GET', + 'purpose' => 'List all VNFs' + }, + { + 'uri' => '/vnfs/{external_vnf_id}', + 'method' => 'GET', + 'purpose' => 'List a specific VNF' + }, + { + 'uri' => '/vnfs', + 'method' => 'POST', + 'purpose' => 'Store a new VNF' + }, + { + 'uri' => '/vnfs/{external_vnf_id}', + 'method' => 'PUT', + 'purpose' => 'Update a stored VNF' + }, + { + 'uri' => '/vnfs/{external_vnf_id}', + 'method' => 'DELETE', + 'purpose' => 'Delete a specific VNF' + } + ] + end +end diff --git a/vnf-provisioning/helpers/compute.rb b/vnf-provisioning/helpers/compute.rb index ce49dc6..214b5f4 100644 --- a/vnf-provisioning/helpers/compute.rb +++ b/vnf-provisioning/helpers/compute.rb @@ -17,54 +17,51 @@ # # @see ComputeHelper module ComputeHelper - def get_list_flavors(compute_url, tenant_id, query_params, auth_token) + def get_list_flavors(compute_url, tenant_id, query_params, auth_token) begin - response = RestClient.get compute_url +"/#{tenant_id}/flavors" + query_params, 'X-Auth-Token' => auth_token, :accept => :json + response = RestClient.get compute_url + "/#{tenant_id}/flavors" + query_params, 'X-Auth-Token' => auth_token, :accept => :json rescue Errno::ECONNREFUSED # halt 500, 'VIM unreachable' rescue RestClient::ResourceNotFound logger.error 'Already removed from the VIM.' return 404 rescue => e - logger.error e - #logger.error e.response + logger.error e + # logger.error e.response return # halt e.response.code, e.response.body end response - end + end def get_vdu_flavour(vdu, compute_url, tenant_id, auth_token) - minDisk = vdu['resource_requirements']['storage']['size'] - minRam = vdu['resource_requirements']['memory']*1000 + minRam = vdu['resource_requirements']['memory'] * 1000 retries = 0 retries_max = 10 query_params = "?minDisk=#{minDisk}&minRam=#{minRam}" flavors = JSON.parse(get_list_flavors(compute_url, tenant_id, query_params, auth_token)) - if flavors['flavors'].size > 0 - return flavors['flavors'][0]['name'] - end + return flavors['flavors'][0]['name'] unless flavors['flavors'].empty? static_disk = nil static_ram = nil - while retries < retries_max do + while retries < retries_max query_params = "?minDisk=#{minDisk}" puts query_params flavors_disk = get_list_flavors(compute_url, tenant_id, query_params, auth_token) - if flavors['flavors'].size > 0 - puts "Disk size has flavours" - minRam = minRam/2 + if !flavors['flavors'].empty? + puts 'Disk size has flavours' + minRam /= 2 query_params = "?minRam=#{minRam}" puts query_params flavors_disk = get_list_flavors(compute_url, tenant_id, query_params, auth_token) return flavors['flavors'][0]['name'] else - minDisk = minDisk/2 + minDisk /= 2 end - retries +=1 + retries += 1 end - puts "Raise??" - raise "Flavor not found." + puts 'Raise??' + raise 'Flavor not found.' end end diff --git a/vnf-provisioning/helpers/hot.rb b/vnf-provisioning/helpers/hot.rb index 08e1f38..9519dbe 100644 --- a/vnf-provisioning/helpers/hot.rb +++ b/vnf-provisioning/helpers/hot.rb @@ -18,17 +18,15 @@ # @see HotHelper module HotHelper def deleteStack(stack_url, auth_token) - begin - response = RestClient.delete stack_url, 'X-Auth-Token' => auth_token, :accept => :json - rescue Errno::ECONNREFUSED - # halt 500, 'VIM unreachable' - rescue RestClient::ResourceNotFound - logger.error 'Already removed from the VIM.' - return 404 - rescue => e - logger.error e.response - return - end + response = RestClient.delete stack_url, 'X-Auth-Token' => auth_token, :accept => :json + rescue Errno::ECONNREFUSED + # halt 500, 'VIM unreachable' + rescue RestClient::ResourceNotFound + logger.error 'Already removed from the VIM.' + return 404 + rescue => e + logger.error e.response + return end def getStackResources(stack_url, auth_token) diff --git a/vnf-provisioning/helpers/mapi.rb b/vnf-provisioning/helpers/mapi.rb index e2bd1ce..1e5bc46 100644 --- a/vnf-provisioning/helpers/mapi.rb +++ b/vnf-provisioning/helpers/mapi.rb @@ -17,7 +17,6 @@ # # @see MapiHelper module MapiHelper - def registerRequestToMAPI(vnfr) logger.debug 'Registring VNF to mAPI...' @@ -43,7 +42,7 @@ def registerRequestToMAPI(vnfr) end def sendCommandToMAPI(vnfr_id, mapi_request) - logger.debug "Sending command to mAPI..." + logger.debug 'Sending command to mAPI...' # Send request to the mAPI begin if mapi_request[:event].casecmp('start').zero? @@ -57,11 +56,11 @@ def sendCommandToMAPI(vnfr_id, mapi_request) logger.error e.response halt e.response.code, e.response.body end - return response + response end def sendDeleteCommandToMAPI(vnfr_id) - logger.debug "Sending remove command to mAPI..." + logger.debug 'Sending remove command to mAPI...' begin response = RestClient.delete "#{settings.mapi}/vnf_api/#{vnfr_id}/" rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH @@ -76,5 +75,4 @@ def sendDeleteCommandToMAPI(vnfr_id) logger.error e end end - end diff --git a/vnf-provisioning/helpers/vnf.rb b/vnf-provisioning/helpers/vnf.rb index 06a1144..f87ffc3 100644 --- a/vnf-provisioning/helpers/vnf.rb +++ b/vnf-provisioning/helpers/vnf.rb @@ -125,7 +125,7 @@ def provision_vnf(vim_info, vnf_name, hot) # # @param [String] url the HEAT URL for the stack # @param [String] auth_token the auth token to authenticate with the VIM - def create_thread_to_monitor_stack(vnfr_id, stack_url, vim_info, ns_manager_callback, scale_resources=nil) + def create_thread_to_monitor_stack(vnfr_id, stack_url, vim_info, ns_manager_callback, scale_resources = nil) # Check when stack change state thread = Thread.new do sleep_time = 10 # set wait time in seconds @@ -184,74 +184,74 @@ def vnf_complete_parsing(vnfr_id, stack_info, scale_resources) vms_id[output['output_key'].match(/^(.*)#id$/i)[1]] = output['output_value'] vnfr.lifecycle_info['events'].each do |event, event_info| next if event_info.nil? - JSON.parse(event_info['template_file']).each do |id, parameter| + JSON.parse(event_info['template_file']).each do |_id, parameter| parameter_match = parameter.delete(' ').match(/^get_attr\[(.*)\]$/i).to_a string = parameter_match[1].split(',').map(&:strip) key_string = string.join('#') key_string2 = output['output_key'].partition('#') - logger.info key_string + " - " + output['output_key'].to_s - if string[1] == 'vdus' && string[0] == key_string2[0]# PrivateIp + logger.info key_string + ' - ' + output['output_key'].to_s + if string[1] == 'vdus' && string[0] == key_string2[0] # PrivateIp lifecycle_events_values[event] = {} unless lifecycle_events_values.key?(event) lifecycle_events_values[event][key_string] = output['output_value'] end end end else - # other parameters - vnfr.lifecycle_info['events'].each do |event, event_info| - next if event_info.nil? - JSON.parse(event_info['template_file']).each do |id, parameter| - parameter_match = parameter.delete(' ').match(/^get_attr\[(.*)\]$/i).to_a - string = parameter_match[1].split(',').map(&:strip) - key_string = string.join('#') - if string[1] == 'PublicIp' # DEPRECATED: to be removed when all VNF developers uses the new form - vnf_addresses[output['output_key']] = output['output_value'] - lifecycle_events_values[event] = {} unless lifecycle_events_values.key?(event) - lifecycle_events_values[event][key_string] = output['output_value'] - elsif string[2] == 'PublicIp' - if key_string == output['output_key'] - if id == 'controller' - vnf_addresses['controller'] = output['output_value'] - end - vnf_addresses[output['output_key']] = output['output_value'] - lifecycle_events_values[event] = {} unless lifecycle_events_values.key?(event) - lifecycle_events_values[event][key_string] = output['output_value'] - end - elsif string[1] == 'fixed_ips' # PrivateIp - key_string2 = output['output_key'].partition('#')[2] - if key_string2 == key_string - vnf_addresses[output['output_key']] = output['output_value'] - lifecycle_events_values[event] = {} unless lifecycle_events_values.key?(event) - if output['output_value'].is_a?(Array) - lifecycle_events_values[event][key_string] = output['output_value'][0] - else - lifecycle_events_values[event][key_string] = output['output_value'] - end - end - elsif output['output_key'] =~ /^#{parameter_match[1]}##{parameter_match[2]}$/i - vnf_addresses[(parameter_match[1]).to_s] = output['output_value'] if parameter_match[2] == 'ip' && !vnf_addresses.key?((parameter_match[1]).to_s) # Only to populate VNF - lifecycle_events_values[event] = {} unless lifecycle_events_values.key?(event) - lifecycle_events_values[event]["#{parameter_match[1]}##{parameter_match[2]}"] = output['output_value'] - elsif output['output_key'] == id # 'controller' - lifecycle_events_values[event] = {} unless lifecycle_events_values.key?(event) - lifecycle_events_values[event][key_string] = output['output_value'] - end - end - end + # other parameters + vnfr.lifecycle_info['events'].each do |event, event_info| + next if event_info.nil? + JSON.parse(event_info['template_file']).each do |id, parameter| + parameter_match = parameter.delete(' ').match(/^get_attr\[(.*)\]$/i).to_a + string = parameter_match[1].split(',').map(&:strip) + key_string = string.join('#') + if string[1] == 'PublicIp' # DEPRECATED: to be removed when all VNF developers uses the new form + vnf_addresses[output['output_key']] = output['output_value'] + lifecycle_events_values[event] = {} unless lifecycle_events_values.key?(event) + lifecycle_events_values[event][key_string] = output['output_value'] + elsif string[2] == 'PublicIp' + if key_string == output['output_key'] + if id == 'controller' + vnf_addresses['controller'] = output['output_value'] + end + vnf_addresses[output['output_key']] = output['output_value'] + lifecycle_events_values[event] = {} unless lifecycle_events_values.key?(event) + lifecycle_events_values[event][key_string] = output['output_value'] + end + elsif string[1] == 'fixed_ips' # PrivateIp + key_string2 = output['output_key'].partition('#')[2] + if key_string2 == key_string + vnf_addresses[output['output_key']] = output['output_value'] + lifecycle_events_values[event] = {} unless lifecycle_events_values.key?(event) + if output['output_value'].is_a?(Array) + lifecycle_events_values[event][key_string] = output['output_value'][0] + else + lifecycle_events_values[event][key_string] = output['output_value'] + end + end + elsif output['output_key'] =~ /^#{parameter_match[1]}##{parameter_match[2]}$/i + vnf_addresses[(parameter_match[1]).to_s] = output['output_value'] if parameter_match[2] == 'ip' && !vnf_addresses.key?((parameter_match[1]).to_s) # Only to populate VNF + lifecycle_events_values[event] = {} unless lifecycle_events_values.key?(event) + lifecycle_events_values[event]["#{parameter_match[1]}##{parameter_match[2]}"] = output['output_value'] + elsif output['output_key'] == id # 'controller' + lifecycle_events_values[event] = {} unless lifecycle_events_values.key?(event) + lifecycle_events_values[event][key_string] = output['output_value'] + end + end + end end end logger.debug 'VMs ID: ' + vms_id.to_json logger.debug 'VNF Addresses: ' + vnf_addresses.to_json logger.debug 'Lifecycle events values: ' + lifecycle_events_values.to_json - event = "scaling_out" + event = 'scaling_out' # Update the VNFR vnfr.push(lifecycle_event_history: stack_info['stack']['stack_status']) - resource = vnfr['scale_resources'].find { |res| res['name'] == scale_resources[:name]} + resource = vnfr['scale_resources'].find { |res| res['name'] == scale_resources[:name] } resource = vnfr['scale_resources'][vnfr['scale_resources'].size - 1] - scaled_resource = vnfr['scale_resources'].find { |res| res['name'] == scale_resources[:name]} + scaled_resource = vnfr['scale_resources'].find { |res| res['name'] == scale_resources[:name] } vnfr.pull(scale_resources: resource) scaled_resource['vnf_addresses'] = vnf_addresses @@ -290,8 +290,7 @@ def vnf_complete_parsing(vnfr_id, stack_info, scale_resources) vnfi_id = [] vnfr.vms_id.each { |_key, value| vnfi_id << value } message = { vnfd_id: vnfr.vnfd_reference, vnfi_id: vnfi_id, vnfr_id: vnfr.id, vnf_addresses: vnf_addresses, stack_resources: vnfr } - #nsmanager_callback(stack_info['ns_manager_callback'], message) - + # nsmanager_callback(stack_info['ns_manager_callback'], message) end # Verify if the VDU images are accessible to download diff --git a/vnf-provisioning/routes/scaling.rb b/vnf-provisioning/routes/scaling.rb index b1f9a7a..df09369 100644 --- a/vnf-provisioning/routes/scaling.rb +++ b/vnf-provisioning/routes/scaling.rb @@ -21,7 +21,7 @@ class Scaling < VnfProvisioning # @overload post '/vnf-instances/scaling/:id/scale_out' # Post a Scale out request # @param [JSON] - post '/:vnfr_id/scale_out' do |vnfr_id| + post '/:vnfr_id/scale_out' do |_vnfr_id| # Return if content-type is invalid halt 415 unless request.content_type == 'application/json' @@ -48,7 +48,7 @@ class Scaling < VnfProvisioning # check if the VNFR can scale_out scaled_vdu = [] vnfr['scale_resources'].each do |scaled_resource| - if scaled_resource.key?("vdus") + if scaled_resource.key?('vdus') scaled_vdu.push(scaled_resource['vdus'].find { |v| v == vdu['id'] }) end end @@ -58,9 +58,7 @@ class Scaling < VnfProvisioning end end - if vdus_to_scale.size == 0 - halt 200, "No VDUs to scale." - end + halt 200, 'No VDUs to scale.' if vdus_to_scale.empty? vdus_id_to_scale = [] vdus_to_scale.each do |vdu| vdus_id_to_scale.push(vdu['id']) @@ -101,8 +99,8 @@ class Scaling < VnfProvisioning logger.debug 'Provision response: ' + response.to_json stack_url = response['stack']['links'][0]['href'] - vnfr.push(scale_resources: {stack_url: stack_url, name: name, vdus: vdus_id_to_scale}) - create_thread_to_monitor_stack(vnfr['_id'], stack_url, vim_info, vnfr['notifications'][0], vnfr['scale_resources'][vnfr['scale_resources'].size - 1 ]) + vnfr.push(scale_resources: { stack_url: stack_url, name: name, vdus: vdus_id_to_scale }) + create_thread_to_monitor_stack(vnfr['_id'], stack_url, vim_info, vnfr['notifications'][0], vnfr['scale_resources'][vnfr['scale_resources'].size - 1]) vnfr.push(lifecycle_event_history: "Executed a #{event}") @@ -114,7 +112,6 @@ class Scaling < VnfProvisioning # Post a Scale in request # @param [JSON] post '/:vnfr_id/scale_in' do - halt 415 unless request.content_type == 'application/json' begin @@ -131,13 +128,11 @@ class Scaling < VnfProvisioning event = 'scaling_in' - if vnfr['scale_resources'].size == 0 - halt 200, "Nothing to scale in." - end + halt 200, 'Nothing to scale in.' if vnfr['scale_resources'].empty? resource = vnfr['scale_resources'][vnfr['scale_resources'].size - 1] logger.debug resource - logger.debug "Using scaling-in saved events..." + logger.debug 'Using scaling-in saved events...' scaling_in_events = {} resource['lifecycle_events_values']['scaling_in'].each do |param, value| scaling_in_events[param] = value @@ -155,9 +150,9 @@ class Scaling < VnfProvisioning # Send request to the mAPI response = sendCommandToMAPI(params[:vnfr_id], mapi_request) - #wait 60 seconds? - logger.info "Waiting 60 seconds..." - #sleep(60) + # wait 60 seconds? + logger.info 'Waiting 60 seconds...' + # sleep(60) vim_info = scale_info['auth'] vim_info['keystone'] = vim_info['url']['keystone'] @@ -168,7 +163,7 @@ class Scaling < VnfProvisioning logger.info 'Sending request to Openstack for Scale IN' response, errors = delete_stack_with_wait(stack_url, vim_info['token']) vnfr.pull(scale_resources: resource) - logger.info "Scale in correct" + logger.info 'Scale in correct' # Update the VNFR event history vnfr.push(lifecycle_event_history: "Executed a #{mapi_request[:event]}") @@ -214,9 +209,9 @@ class Scaling < VnfProvisioning vim_info = scale_info['auth'] vim_info['keystone'] = vim_info['url']['keystone'] vim_info['heat'] = vim_info['url']['heat'] - #token_info = request_auth_token(vim_info) - #tenant_id = token_info['access']['token']['tenant']['id'] - #auth_token = token_info['access']['token']['id'] + # token_info = request_auth_token(vim_info) + # tenant_id = token_info['access']['token']['tenant']['id'] + # auth_token = token_info['access']['token']['id'] auth_token = vim_info['token'] tenant_id = vim_info['tenant_id'] diff --git a/vnf-provisioning/routes/vnf.rb b/vnf-provisioning/routes/vnf.rb index 69915a6..6a5ead5 100644 --- a/vnf-provisioning/routes/vnf.rb +++ b/vnf-provisioning/routes/vnf.rb @@ -122,14 +122,14 @@ class Provisioning < VnfProvisioning dns_server: instantiation_info['reserved_resources']['dns_server'], flavours: [] } - if !vim_info['is_admin'] + unless vim_info['is_admin'] flavors = [] vnf['vnfd']['vdu'].each do |vdu| flavour_id = get_vdu_flavour(vdu, vim_info['compute'], vim_info['tenant_id'], vim_info['token']) if flavour_id.nil? - halt 400, "No flavours available for the vdu " + vdu['id'].to_s + halt 400, 'No flavours available for the vdu ' + vdu['id'].to_s end - flavors << {:id => vdu['id'], :flavour_id => flavour_id} + flavors << { id: vdu['id'], flavour_id: flavour_id } end hot_generator_message['flavours'] = flavors end @@ -189,7 +189,7 @@ class Provisioning < VnfProvisioning # Get a specific VNFR by its ID get '/vnf-instances/:vnfr_id' do |vnfr_id| begin - vnfr = Vnfr.find(vnfr_id) + vnfr = Vnfr.find(vnfr_id) rescue Mongoid::Errors::DocumentNotFound => e halt 404 end @@ -223,22 +223,20 @@ class Provisioning < VnfProvisioning callback_url = destroy_info['callback_url'] # if the stack contains nested templates, remove nesed before -=begin - resources = getStackResources(vnfr.stack_url, auth_token) - resources.each do |resource| - next unless resource['resource_type'] == 'OS::Heat::AutoScalingGroup' - next unless resource['links'].find { |link| link['rel'] == 'nested' } - stack_url = resource['links'].find { |link| link['rel'] == 'nested' }['href'] - response = delete_stack_with_wait(stack_url, auth_token) - logger.debug 'VIM response to destroy the AutoScalingGroup: ' + response.to_json - end -=end + # resources = getStackResources(vnfr.stack_url, auth_token) + # resources.each do |resource| + # next unless resource['resource_type'] == 'OS::Heat::AutoScalingGroup' + # next unless resource['links'].find { |link| link['rel'] == 'nested' } + # stack_url = resource['links'].find { |link| link['rel'] == 'nested' }['href'] + # response = delete_stack_with_wait(stack_url, auth_token) + # logger.debug 'VIM response to destroy the AutoScalingGroup: ' + response.to_json + # end vnfr['scale_resources'].each do |resource| stack_url = resource['stack_url'] logger.info 'Sending request to Openstack for Remove scaled resources' response, errors = delete_stack_with_wait(stack_url, vim_info['token']) vnfr.pull(scale_resources: resource) - logger.info "Removed scaled resources." + logger.info 'Removed scaled resources.' end # Requests the VIM to delete the stack @@ -255,7 +253,7 @@ class Provisioning < VnfProvisioning else # Delete the VNFR from mAPI logger.info 'Sending delete command to mAPI...' - logger.debug "VNFR: " + vnfr_id + logger.debug 'VNFR: ' + vnfr_id sendDeleteCommandToMAPI(vnfr_id) end @@ -392,95 +390,93 @@ class Provisioning < VnfProvisioning lifecycle_events_values = {} vnf_addresses = {} scale_urls = {} - #auto_scale_resources = [] + # auto_scale_resources = [] stack_info['stack']['outputs'].select do |output| if output['output_key'] == 'private_key' private_key = output['output_value'] elsif output['output_key'] =~ /^.*#id$/i vms_id[output['output_key'].match(/^(.*)#id$/i)[1]] = output['output_value'] -=begin - elsif output['output_key'] =~ /^.*#scale_in_url/i - scale_resource = auto_scale_resources.find { |res| res[:vdu] == output['output_key'].match(/^(.*)#scale_in_url/i)[1] } - if scale_resource.nil? - auto_scale_resources << { vdu: output['output_key'].match(/^(.*)#scale_in_url/i)[1], scale_in: output['output_value'] } - else - scale_resource[:scale_in] = output['output_value'] - end - elsif output['output_key'] =~ /^.*#scale_out_url/i - scale_resource = auto_scale_resources.find { |res| res[:vdu] == output['output_key'].match(/^(.*)#scale_out_url/i)[1] } - if scale_resource.nil? - auto_scale_resources << { vdu: output['output_key'].match(/^(.*)#scale_out_url/i)[1], scale_out: output['output_value'] } - else - scale_resource[:scale_out] = output['output_value'] - end - elsif output['output_key'] =~ /^.*#scale_group/i - scale_resource = auto_scale_resources.find { |res| res[:vdu] == output['output_key'].match(/^(.*)#scale_group/i)[1] } - if scale_resource.nil? - auto_scale_resources << { vdu: output['output_key'].match(/^(.*)#scale_group/i)[1], id: output['output_value'] } - else - scale_resource[:id] = output['output_value'] - end - elsif output['output_key'] =~ /^.*#vdus/i - vms_id[output['output_key']] = output['output_value'] - elsif output['output_key'] =~ /^.*#networks/i - # TODO - # scale_resource = auto_scale_resources.find { |res| res[:vdu] == output['output_key'].match(/^(.*)#networks/i)[1] } - # if scale_resource.nil? - # auto_scale_resources << {:vdu => output['output_key'].match(/^(.*)#scale_out_url/i)[1], :networks => output['output_value']} - # else - # scale_resource[:networks] = output['output_value'] - # end - # vnf_addresses[output['output_key']] = output['output_value'] -=end + # elsif output['output_key'] =~ /^.*#scale_in_url/i + # scale_resource = auto_scale_resources.find { |res| res[:vdu] == output['output_key'].match(/^(.*)#scale_in_url/i)[1] } + # if scale_resource.nil? + # auto_scale_resources << { vdu: output['output_key'].match(/^(.*)#scale_in_url/i)[1], scale_in: output['output_value'] } + # else + # scale_resource[:scale_in] = output['output_value'] + # end + # elsif output['output_key'] =~ /^.*#scale_out_url/i + # scale_resource = auto_scale_resources.find { |res| res[:vdu] == output['output_key'].match(/^(.*)#scale_out_url/i)[1] } + # if scale_resource.nil? + # auto_scale_resources << { vdu: output['output_key'].match(/^(.*)#scale_out_url/i)[1], scale_out: output['output_value'] } + # else + # scale_resource[:scale_out] = output['output_value'] + # end + # elsif output['output_key'] =~ /^.*#scale_group/i + # scale_resource = auto_scale_resources.find { |res| res[:vdu] == output['output_key'].match(/^(.*)#scale_group/i)[1] } + # if scale_resource.nil? + # auto_scale_resources << { vdu: output['output_key'].match(/^(.*)#scale_group/i)[1], id: output['output_value'] } + # else + # scale_resource[:id] = output['output_value'] + # end + # elsif output['output_key'] =~ /^.*#vdus/i + # vms_id[output['output_key']] = output['output_value'] + # elsif output['output_key'] =~ /^.*#networks/i + # # TODO + # # scale_resource = auto_scale_resources.find { |res| res[:vdu] == output['output_key'].match(/^(.*)#networks/i)[1] } + # # if scale_resource.nil? + # # auto_scale_resources << {:vdu => output['output_key'].match(/^(.*)#scale_out_url/i)[1], :networks => output['output_value']} + # # else + # # scale_resource[:networks] = output['output_value'] + # # end + # # vnf_addresses[output['output_key']] = output['output_value'] else - if output['output_key'] =~ /^.*#PublicIp$/i - # vnf_addresses['controller'] = output['output_value'] - end - - # other parameters - vnfr.lifecycle_info['events'].each do |event, event_info| - next if event_info.nil? - JSON.parse(event_info['template_file']).each do |id, parameter| - logger.debug parameter - parameter_match = parameter.delete(' ').match(/^get_attr\[(.*)\]$/i).to_a - string = parameter_match[1].split(',').map(&:strip) - key_string = string.join('#') - logger.debug 'Key string: ' + key_string.to_s + '. Out_key: ' + output['output_key'].to_s - if string[1] == 'PublicIp' # DEPRECATED: to be removed when all VNF developers uses the new form - vnf_addresses[output['output_key']] = output['output_value'] - lifecycle_events_values[event] = {} unless lifecycle_events_values.key?(event) - lifecycle_events_values[event][key_string] = output['output_value'] - elsif string[2] == 'PublicIp' - if key_string == output['output_key'] - if id == 'controller' - vnf_addresses['controller'] = output['output_value'] - end - vnf_addresses[output['output_key']] = output['output_value'] - lifecycle_events_values[event] = {} unless lifecycle_events_values.key?(event) - lifecycle_events_values[event][key_string] = output['output_value'] - end - elsif string[1] == 'fixed_ips' # PrivateIp - key_string2 = output['output_key'].partition('#')[2] - if key_string2 == key_string - vnf_addresses[output['output_key']] = output['output_value'] - lifecycle_events_values[event] = {} unless lifecycle_events_values.key?(event) - if output['output_value'].is_a?(Array) - lifecycle_events_values[event][key_string] = output['output_value'][0] - else - lifecycle_events_values[event][key_string] = output['output_value'] - end - end - elsif output['output_key'] =~ /^#{parameter_match[1]}##{parameter_match[2]}$/i - vnf_addresses[(parameter_match[1]).to_s] = output['output_value'] if parameter_match[2] == 'ip' && !vnf_addresses.key?((parameter_match[1]).to_s) # Only to populate VNF - lifecycle_events_values[event] = {} unless lifecycle_events_values.key?(event) - lifecycle_events_values[event]["#{parameter_match[1]}##{parameter_match[2]}"] = output['output_value'] - elsif output['output_key'] == id # 'controller' - lifecycle_events_values[event] = {} unless lifecycle_events_values.key?(event) - lifecycle_events_values[event][key_string] = output['output_value'] - end - end - end + if output['output_key'] =~ /^.*#PublicIp$/i + # vnf_addresses['controller'] = output['output_value'] + end + + # other parameters + vnfr.lifecycle_info['events'].each do |event, event_info| + next if event_info.nil? + JSON.parse(event_info['template_file']).each do |id, parameter| + logger.debug parameter + parameter_match = parameter.delete(' ').match(/^get_attr\[(.*)\]$/i).to_a + string = parameter_match[1].split(',').map(&:strip) + key_string = string.join('#') + logger.debug 'Key string: ' + key_string.to_s + '. Out_key: ' + output['output_key'].to_s + if string[1] == 'PublicIp' # DEPRECATED: to be removed when all VNF developers uses the new form + vnf_addresses[output['output_key']] = output['output_value'] + lifecycle_events_values[event] = {} unless lifecycle_events_values.key?(event) + lifecycle_events_values[event][key_string] = output['output_value'] + elsif string[2] == 'PublicIp' + if key_string == output['output_key'] + if id == 'controller' + vnf_addresses['controller'] = output['output_value'] + end + vnf_addresses[output['output_key']] = output['output_value'] + lifecycle_events_values[event] = {} unless lifecycle_events_values.key?(event) + lifecycle_events_values[event][key_string] = output['output_value'] + end + elsif string[1] == 'fixed_ips' # PrivateIp + key_string2 = output['output_key'].partition('#')[2] + if key_string2 == key_string + vnf_addresses[output['output_key']] = output['output_value'] + lifecycle_events_values[event] = {} unless lifecycle_events_values.key?(event) + if output['output_value'].is_a?(Array) + lifecycle_events_values[event][key_string] = output['output_value'][0] + else + lifecycle_events_values[event][key_string] = output['output_value'] + end + end + elsif output['output_key'] =~ /^#{parameter_match[1]}##{parameter_match[2]}$/i + vnf_addresses[(parameter_match[1]).to_s] = output['output_value'] if parameter_match[2] == 'ip' && !vnf_addresses.key?((parameter_match[1]).to_s) # Only to populate VNF + lifecycle_events_values[event] = {} unless lifecycle_events_values.key?(event) + lifecycle_events_values[event]["#{parameter_match[1]}##{parameter_match[2]}"] = output['output_value'] + elsif output['output_key'] == id # 'controller' + lifecycle_events_values[event] = {} unless lifecycle_events_values.key?(event) + lifecycle_events_values[event][key_string] = output['output_value'] + end + end + end end end @@ -496,8 +492,8 @@ class Provisioning < VnfProvisioning vms_id: vms_id, vms: vms, lifecycle_events_values: lifecycle_events_values, - scale_info: scale_urls#, - #scale_resources: scale_resources + scale_info: scale_urls # , + # scale_resources: scale_resources ) if vnfr.lifecycle_info['authentication_type'] == 'PubKeyAuthentication' @@ -535,8 +531,8 @@ class Provisioning < VnfProvisioning logger.error 'Response from the VIM about the error: ' + response.to_s # Request VIM to delete the stack - #response, errors = delete_stack_with_wait(stack_url, auth_token) - #logger.debug 'Response from VIM to destroy allocated resources: ' + response.to_json + # response, errors = delete_stack_with_wait(stack_url, auth_token) + # logger.debug 'Response from VIM to destroy allocated resources: ' + response.to_json logger.error 'VIM ERROR: ' + response['stack']['stack_status_reason'].to_s vnfr.push(lifecycle_event_history: stack_info['stack']['stack_status']) vnfr.update_attributes!( From ba8f9de9bdd135e387fbdc7dfb547db2834cfbfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Thu, 3 Nov 2016 16:35:58 +0100 Subject: [PATCH 11/35] Updated service registration. Mapping and Infr. repository tested --- ns-manager/models/service.rb | 3 + ns-manager/routes/config.rb | 38 ++++++++-- sinatra-gkauth-gem/lib/sinatra/gk_auth.rb | 7 +- ui/apis/proxy.rb | 8 +- ui/app/scripts/app.js | 4 +- .../controllers/infraRepoController.js | 36 +++++---- .../scripts/controllers/modulesController.js | 30 ++++++-- ui/app/scripts/services/infrRepoService.js | 11 ++- ui/app/views/t-nova/modules.html | 76 +++++++++++++++---- ui/app/views/t-nova/pop.html | 4 +- 10 files changed, 162 insertions(+), 55 deletions(-) diff --git a/ns-manager/models/service.rb b/ns-manager/models/service.rb index 9571f1d..f8161a4 100644 --- a/ns-manager/models/service.rb +++ b/ns-manager/models/service.rb @@ -5,6 +5,9 @@ class Service validates :name, presence: true, uniqueness: true field :host, type: String field :port, type: String + field :path, type: String field :token, type: String field :depends_on, type: Array, default: [] + field :type, type: String + field :status, type: String end diff --git a/ns-manager/routes/config.rb b/ns-manager/routes/config.rb index 5912280..41b8b98 100644 --- a/ns-manager/routes/config.rb +++ b/ns-manager/routes/config.rb @@ -35,7 +35,7 @@ class ServiceConfiguration < TnovaManager logger.error 'DC not found' return 404 end - return service.to_json + service.to_json end get '/services/name/:name' do |name| @@ -45,7 +45,17 @@ class ServiceConfiguration < TnovaManager logger.error 'DC not found' return 404 end - return service['token'] + service['token'] + end + + get '/services/type/:type' do |type| + begin + services = Service.where(:type => type) + rescue Mongoid::Errors::DocumentNotFound => e + logger.error 'DC not found' + return 404 + end + services.to_json end post '/services' do @@ -57,13 +67,15 @@ class ServiceConfiguration < TnovaManager name: serv_reg['name'], host: serv_reg['host'], port: serv_reg['port'], + path: serv_reg['path'], token: @token, - depends_on: serv_reg['depends_on'] + depends_on: serv_reg['depends_on'], + type: serv_reg['type'] } logger.debug serv begin s = Service.find_by(name: serv_reg['name']) - s.update_attributes!(host: serv_reg['host'], port: serv_reg['port'], token: @token, depends_on: serv_reg['depends_on']) + s.update_attributes!(host: serv_reg['host'], port: serv_reg['port'], token: @token, depends_on: serv_reg['depends_on'], type: serv_reg['type']) rescue Mongoid::Errors::DocumentNotFound => e Service.create!(serv) rescue => e @@ -81,7 +93,7 @@ class ServiceConfiguration < TnovaManager logger.debug "Service found but is down." s.destroy else - depends_on << { name: s['name'], host: s['host'], port: s['port'], token: s['token'] } + depends_on << { name: s['name'], host: s['host'], port: s['port'], token: s['token'], depends_on: s['depends_on'] } end rescue Mongoid::Errors::DocumentNotFound => e logger.error 'User not found.' @@ -104,6 +116,22 @@ class ServiceConfiguration < TnovaManager end end end + +puts "Manager..." +puts serv[:type] + if serv[:type] == 'manager' + puts "Send to VNF MANAger..." + depends_on.each do |dep| + puts dep + begin + RestClient.post serv[:host] + ':' + serv[:port].to_s + '/modules/services', dep.to_json, :content_type => :json, 'X-Auth-Token' => serv['token'] + rescue => e + # logger.error e + puts e + # halt 500, {'Content-Type' => 'text/plain'}, "Error sending dependencies to " +service['name'] + end + end + end halt 201, { depends_on: depends_on }.to_json end diff --git a/sinatra-gkauth-gem/lib/sinatra/gk_auth.rb b/sinatra-gkauth-gem/lib/sinatra/gk_auth.rb index 95ce891..0df6f59 100644 --- a/sinatra-gkauth-gem/lib/sinatra/gk_auth.rb +++ b/sinatra-gkauth-gem/lib/sinatra/gk_auth.rb @@ -11,7 +11,11 @@ module Helpers def initialize sleep(2) puts 'Initializing gem GK...' - service_info = { name: settings.servicename, host: settings.address, port: settings.port, depends_on: settings.dependencies, secret: settings.servicename } + begin + service_info = { name: settings.servicename, host: settings.address, port: settings.port, depends_on: settings.dependencies, secret: settings.servicename, type: settings.type} + rescue + service_info = { name: settings.servicename, host: settings.address, port: settings.port, depends_on: settings.dependencies, secret: settings.servicename, type: "" } + end publish_service(service_info) if settings.environment != 'development' if settings.environment == 'development' @@ -35,7 +39,6 @@ def publish_service(service_info) $time = 5 if $time > $max_retries publish_service(service_info) end - puts response return if response.nil? services, errors = parse_json(response) return 400, errors.to_json if errors diff --git a/ui/apis/proxy.rb b/ui/apis/proxy.rb index d743382..83320b7 100644 --- a/ui/apis/proxy.rb +++ b/ui/apis/proxy.rb @@ -9,7 +9,7 @@ class App::Proxy < Sinatra::Base host = request.env["HTTP_X_HOST"] begin - response = RestClient.get host + "/" + params[:splat][0] + "?" + request.env['QUERY_STRING'], :content_type => :json + response = RestClient.get host + "/" + params[:splat][0] + "?" + request.env['QUERY_STRING'], :accept => request.env["HTTP_ACCEPT"] rescue Errno::ECONNREFUSED halt 500, "Errno::ECONNREFUSED" rescue => e @@ -21,15 +21,9 @@ class App::Proxy < Sinatra::Base end post '/rest/api/*' do - puts "POST........." -puts request.env["HTTP_X_AUTH_TOKEN"] host = request.env["HTTP_X_HOST"] body = request.body.read - puts params[:splat][0] - puts host - puts body - begin response = RestClient.post host + "/" + params[:splat][0], body, :content_type => :json, :'X-Auth-Token' => request.env["HTTP_X_AUTH_TOKEN"] rescue Errno::ECONNREFUSED diff --git a/ui/app/scripts/app.js b/ui/app/scripts/app.js index f7c7da2..659faa1 100644 --- a/ui/app/scripts/app.js +++ b/ui/app/scripts/app.js @@ -237,8 +237,10 @@ angular.module('tNovaApp', ['ui.router', 'ngSanitize', 'tNovaApp.config', 'tNova } else { config.url = config.url + '?token=' + authToken; } - if (Math.floor(Date.now() / 1000) > $window.localStorage.expiration) + if (Math.floor(Date.now() / 1000) > $window.localStorage.expiration){ + $window.localStorage.clear(); $rootScope.logout(); + } } else { $location.path('/login'); } diff --git a/ui/app/scripts/controllers/infraRepoController.js b/ui/app/scripts/controllers/infraRepoController.js index 2ecaa3d..fb14e01 100644 --- a/ui/app/scripts/controllers/infraRepoController.js +++ b/ui/app/scripts/controllers/infraRepoController.js @@ -1,7 +1,7 @@ 'use strict'; angular.module('tNovaApp') - .controller('infrastructureRepositoryController', function ($rootScope, $scope, $http, $q, localStorageService, $interval, $modal, $timeout, infrRepoService, $loading) { + .controller('infrastructureRepositoryController', function ($rootScope, $scope, $http, $q, localStorageService, $interval, $modal, $timeout, infrRepoService, $loading, tenorService) { var url = ''; $scope.showPop = false; @@ -14,6 +14,14 @@ angular.module('tNovaApp') $scope.showTopology = false; + tenorService.get("modules/services/type/infr_repo").then(function (data) { + if (data === undefined) return; + console.log(data); + $scope.infr_repo_url = data[0].host + ":" + data[0].port; + console.log($scope.infr_repo_url); + $scope.getPops(); + }); + $scope.ui_handler = function (uid, type) { var selected; console.log(uid + " " + type); @@ -125,12 +133,12 @@ angular.module('tNovaApp') if (elType === 'floatingip') continue; if (elType === 'pu') continue; url = 'pop/' + $scope.infrModel[popId]['occi.epa.popuuid'] + '/' + elType + '/'; - infrRepoService.get(url).then(function (_data) { + infrRepoService.get($scope.infr_repo_url, url).get(url).then(function (_data) { if (_data.length === 0) $scope.dataCollection = []; var j = 0; angular.forEach(_data, function (res) { - infrRepoService.get(res.identifier.slice(1)).then(function (resource) { + infrRepoService.get($scope.infr_repo_url, res.identifier.slice(1)).then(function (resource) { //console.log(resource) $scope.dataCollection.push(resource.attributes); data.nodes.push({ @@ -185,12 +193,12 @@ angular.module('tNovaApp') if (elType === 'floatingip') continue; url = 'pop/' + $scope.infrModel[popId]['occi.epa.popuuid'] + '/' + elType + '/'; - infrRepoService.get(url).then(function (_data) { + infrRepoService.get($scope.infr_repo_url, url).then(function (_data) { if (_data.length === 0) $loading.finish('table'); $scope.dataCollection = []; var j = 0; angular.forEach(_data, function (res) { - infrRepoService.get(res.identifier.slice(1)).then(function (resource) { + infrRepoService.get($scope.infr_repo_url, res.identifier.slice(1)).then(function (resource) { data.nodes.push({ id: resource['identifier'], label: resource.attributes['occi.epa.name'], @@ -252,7 +260,7 @@ angular.module('tNovaApp') $scope.types = []; $scope.getTypes = function () { url = '-/'; - infrRepoService.get(url).then(function (_data) { + infrRepoService.get($scope.infr_repo_url, url).then(function (_data) { _data.forEach(function (_data) { $scope.types.push({ id: _data.term, @@ -277,13 +285,13 @@ angular.module('tNovaApp') $scope.showPop = false; url = 'pop/'; - infrRepoService.get(url).then(function (_data) { + infrRepoService.get($scope.infr_repo_url, url).then(function (_data) { $scope.pops = _data; if (_data.length === 0) $loading.finish('pops'); $scope.infrModel = []; angular.forEach(_data, function (pop, index, array) { url = pop.identifier.slice(1); - infrRepoService.get(url).then(function (_data) { + infrRepoService.get($scope.infr_repo_url, url).then(function (_data) { $scope.infrModel.push(_data.attributes); $scope.infrModel[$scope.infrModel.length - 1].resources = {}; @@ -301,8 +309,6 @@ angular.module('tNovaApp') }); }; - $scope.getPops(); - $scope.getResourcesByType = function (popId, type) { $loading.start('table'); var type = $scope.types.filter(function (d) { @@ -314,11 +320,11 @@ angular.module('tNovaApp') $scope.showTables = true; $scope.showTopology = false; url = 'pop/' + $scope.infrModel[popId]['occi.epa.popuuid'] + type.location; - infrRepoService.get(url).then(function (_data) { + infrRepoService.get($scope.infr_repo_url, url).then(function (_data) { if (_data.length === 0) $loading.finish('table'); $scope.dataCollection = []; angular.forEach(_data, function (res) { - infrRepoService.get(res.identifier.slice(1)).then(function (resource) { + infrRepoService.get($scope.infr_repo_url, res.identifier.slice(1)).then(function (resource) { if ($scope.infrModel[popId][resource.attributes['occi.epa.index_type']] === undefined) { $scope.infrModel[popId][resource.attributes['occi.epa.index_type']] = []; } @@ -358,7 +364,7 @@ angular.module('tNovaApp') //$scope.getResourcesByPoP(popId); return; url = 'pop/' + $scope.infrModel[popId]['occi.epa.popuuid'].slice(1); - infrRepoService.get(url).then(function (_data) { + infrRepoService.get($scope.infr_repo_url, url).then(function (_data) { console.log(_data); $scope.pop = _data.attributes; }); @@ -370,9 +376,9 @@ angular.module('tNovaApp') angular.forEach($scope.types, function (type) { if (type.id.indexOf("link") > -1) return; url = 'pop/' + $scope.infrModel[popId]['occi.epa.popuuid'] + type.location; - infrRepoService.get(url).then(function (_data) { + infrRepoService.get($scope.infr_repo_url, url).then(function (_data) { angular.forEach(_data, function (res, index, _ary) { - infrRepoService.get(res.identifier.slice(1)).then(function (resource) { + infrRepoService.get($scope.infr_repo_url, res.identifier.slice(1)).then(function (resource) { if ($scope.infrModel[popId].resources[resource.attributes['occi.epa.index_type']] === undefined) { $scope.infrModel[popId].resources[resource.attributes['occi.epa.index_type']] = []; } diff --git a/ui/app/scripts/controllers/modulesController.js b/ui/app/scripts/controllers/modulesController.js index 1553488..8e71ff1 100644 --- a/ui/app/scripts/controllers/modulesController.js +++ b/ui/app/scripts/controllers/modulesController.js @@ -3,16 +3,32 @@ angular.module('tNovaApp') .controller('modulesController', function ($scope, $filter, tenorService, $interval, $modal) { + $scope.types_internal_modules = ["", "manager"]; + $scope.types_external_modules = ["mapping", "infr_repo"]; + $scope.types_modules = $scope.types_internal_modules.concat($scope.types_external_modules) + $scope.externalModulesCollection = []; + $scope.updateModulesList = function () { tenorService.get("modules/services").then(function (data) { if (data === undefined) return; $scope.modulesCollection = data; }); - } + }; + + $scope.updateExternalModulesList = function () { + $scope.types_external_modules.forEach(function(type){ + tenorService.get("modules/services/type/" + type).then(function (data) { + if (data === undefined) return; + $scope.externalModulesCollection = $scope.externalModulesCollection.concat(data); + }); + }) + }; $scope.updateModulesList(); + $scope.updateExternalModulesList(); var promise = $interval(function () { - $scope.updateModulesList + $scope.updateModulesList(); + //$scope.updateExternalModulesList(); }, defaultTimer); $scope.deleteDialog = function (id) { @@ -38,7 +54,11 @@ angular.module('tNovaApp') $scope.registerService = function (service) { console.log("register service"); console.log(service); - tenorService.post("modules/services", JSON.stringify(service)).then(function (data) {}); + service.secret = service.name + service.depends_on = []; + tenorService.post("modules/services", JSON.stringify(service)).then(function (data) { + console.log(data); + }); }; $scope.options = { @@ -78,7 +98,7 @@ angular.module('tNovaApp') if (!data) return; $scope.log = $scope.log.concat(data); angular.forEach(data, function (element) { - console.log(element); + //console.log(element); $scope.data.items.add({ id: element.id, content: element.module + " - " + element.msg, @@ -91,7 +111,7 @@ angular.module('tNovaApp') $scope.log = []; angular.forEach($scope.modules, function (module) { - $scope.timelineLog(module); + //$scope.timelineLog(module); }); $scope.selectSeverity = function (severity) { diff --git a/ui/app/scripts/services/infrRepoService.js b/ui/app/scripts/services/infrRepoService.js index b5e03cc..814b8a4 100644 --- a/ui/app/scripts/services/infrRepoService.js +++ b/ui/app/scripts/services/infrRepoService.js @@ -1,15 +1,18 @@ 'use strict'; services - .factory('infrRepoService', function ($http, REPOSITORY) { + .factory('infrRepoService', function ($http) { return { - get: function (url) { - var promise = $http.get("rest/api/" + url, { + get: function (infr_repo_url, path) { + console.log(infr_repo_url); + var promise = $http.get("rest/api/" + path, { headers: { 'Accept': 'application/occi+json', - "X-host": REPOSITORY + "X-host": infr_repo_url } }).then(function (response) { + console.log(response); + console.log(response.data); return response.data; }, function (response) {}); return promise; diff --git a/ui/app/views/t-nova/modules.html b/ui/app/views/t-nova/modules.html index 53198b1..116f67f 100644 --- a/ui/app/views/t-nova/modules.html +++ b/ui/app/views/t-nova/modules.html @@ -1,9 +1,9 @@

Configuration

-
+
-
Modules List of connected services in the orchestrator. table with status. Should be able to edit ip/port. +
Internal Modules List of connected services in the orchestrator. table with status. Should be able to edit ip/port.
@@ -22,7 +22,7 @@

Configuration

- + @@ -43,29 +43,77 @@

Configuration

-
-
-
-
Register new service
+
+
+
External Modules List of connected services in the orchestrator. table with status. Should be able to edit ip/port. +
+
{{row.name}} {{row.host}} {{row.port}}
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameIPPortTypeStatusActions
+ +
{{row.name}}{{row.host}}{{row.port}}{{row.type}}{{row.status}} + +
+
+
+
+
+
+
Register new service
- -
-
- - +
- +
- + +
+
+ + +
+
+ +
+ +
diff --git a/ui/app/views/t-nova/pop.html b/ui/app/views/t-nova/pop.html index 0099081..bee5a63 100644 --- a/ui/app/views/t-nova/pop.html +++ b/ui/app/views/t-nova/pop.html @@ -67,9 +67,9 @@

Available openstacks Reading information from Infrastructure Reposit {{row['occi.epa.popuuid']}} - {{row['occi.epa.pop.lon']}} + {{row['occi.epa.pop.name']}} - + From 0b3a3dacea0cbf927105987d85232935398417f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Thu, 3 Nov 2016 16:36:59 +0100 Subject: [PATCH 12/35] NS Manager routes, fixed Monitoring and updated PoP-mapping relation when instatiating --- ns-manager/main.rb | 3 -- ns-manager/routes/mapping.rb | 54 ++++++++++++++++++++++++++++ ns-manager/routes/monitoring.rb | 32 ++++++----------- ns-manager/routes/ns_provisioning.rb | 23 +++++++++--- 4 files changed, 83 insertions(+), 29 deletions(-) create mode 100644 ns-manager/routes/mapping.rb diff --git a/ns-manager/main.rb b/ns-manager/main.rb index 8ccb179..f1a1099 100644 --- a/ns-manager/main.rb +++ b/ns-manager/main.rb @@ -75,9 +75,6 @@ class TnovaManager < Sinatra::Application helpers StatisticsHelper helpers VimHelper - #AuthenticationHelper.loginGK - #ServiceConfigurationHelper.publishServices - get '/' do return 200, JSON.pretty_generate(interfaces_list) end diff --git a/ns-manager/routes/mapping.rb b/ns-manager/routes/mapping.rb new file mode 100644 index 0000000..4f6a4af --- /dev/null +++ b/ns-manager/routes/mapping.rb @@ -0,0 +1,54 @@ +# +# TeNOR - NS Manager +# +# Copyright 2014-2016 i2CAT Foundation, Portugal Telecom Inovação +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @see MappingController +class MappingController < TnovaManager + + # @method get_mapping + # @overload get '/logs/*' + # Get logs from fluentd-mongodb. Different strings allowed in order to filter the required data + # @param [string] + get '/' do + modules = ["ns_manager", "ns_catalogue", "ns_provisioner", "ns_monitoring", "nsd_validator", "vnf_manager", "vnf_catalogue", "vnf_provisioner", "vnf_monitoring", "hot_generator", "vnfd_validator"] + response = [] + params['from'] = Time.at(params['from'].to_i) + params['until'] = Time.at(params['until'].to_i) + if !params['module'].nil? + if !params['severity'].nil? && params['from'].nil? + response = Tenor.prefix(params['module']).where(severity: params['severity'].downcase) + elsif !params['severity'].nil? && !params['from'].nil? + response = Tenor.prefix(params['module']).where(severity: params['severity'].downcase).where(:time.gte => params['from'], :time.lte => params['until']) + elsif params['severity'].nil? && !params['from'].nil? + response = Tenor.prefix(params['module']).where(:time.gte => params['from'], :time.lte => params['until']) + else + response = Tenor.prefix(params['module']).all + end + else + if !params['severity'].nil? && params['from'].nil? + modules.each { |x| response.concat(Tenor.prefix(x).where(severity: params['severity'].downcase))} + elsif !params['severity'].nil? && !params['from'].nil? + modules.each { |x| response.concat(Tenor.prefix(x).where(severity: params['severity'].downcase).where(:time.gte => params['from'], :time.lte => params['until']))} + elsif params['severity'].nil? && !params['from'].nil? + modules.each { |x| response.concat(Tenor.prefix(x).where(:time.gte => params['from'], :time.lte => params['until']))} + else + modules.each { |x| response.concat(Tenor.prefix(x).all)} + end + end + + response.to_json + end +end diff --git a/ns-manager/routes/monitoring.rb b/ns-manager/routes/monitoring.rb index 024d08f..4a665b1 100644 --- a/ns-manager/routes/monitoring.rb +++ b/ns-manager/routes/monitoring.rb @@ -26,18 +26,12 @@ class NsMonitoring < TnovaManager # @param [string] metric get '/:instance_id/monitoring-data/' do if params['instance_type'] == 'ns' - begin - @service = ServiceModel.find_by(name: "ns_monitoring") - rescue Mongoid::Errors::DocumentNotFound => e - halt 500, {'Content-Type' => "text/plain"}, "Microservice unrechable." - end + monitoring, errors = ServiceConfigurationHelper.get_module('ns_monitoring') + halt 500, errors if errors composedUrl = "/ns-monitoring/"+params['instance_id'].to_s+"/monitoring-data/?"+request.env['QUERY_STRING'] elsif params['instance_type'] == 'vnf' - begin - @service = ServiceModel.find_by(name: "vnf_manager") - rescue Mongoid::Errors::DocumentNotFound => e - halt 500, {'Content-Type' => "text/plain"}, "Microservice unrechable." - end + monitoring, errors = ServiceConfigurationHelper.get_module('vnf_manager') + halt 500, errors if errors composedUrl = "/vnf-monitoring/"+params['instance_id'].to_s+"/monitoring-data/?"+request.env['QUERY_STRING'] end @@ -45,7 +39,7 @@ class NsMonitoring < TnovaManager #composedUrl = composedUrl + "/" + params["metric"] end begin - response = RestClient.get @service.host.to_s + ":" + @service.port.to_s + composedUrl.to_s, 'X-Auth-Token' => @client_token, :content_type => :json + response = RestClient.get monitoring.host + composedUrl.to_s, 'X-Auth-Token' => monitoring.token, :content_type => :json rescue Errno::ECONNREFUSED halt 500, 'NS Monitoring unreachable' rescue => e @@ -81,23 +75,17 @@ class NsMonitoring < TnovaManager get '/:instance_id/monitoring-data/last100/' do if params['instance_type'] == 'ns' - begin - @service = ServiceModel.find_by(name: "ns_monitoring") - rescue Mongoid::Errors::DocumentNotFound => e - halt 500, {'Content-Type' => "text/plain"}, "Microservice unrechable." - end + monitoring, errors = ServiceConfigurationHelper.get_module('ns_monitoring') + halt 500, errors if errors composedUrl = "/ns-monitoring/"+params['instance_id'].to_s+"/monitoring-data/last100/?"+request.env['QUERY_STRING'] elsif params['instance_type'] == 'vnf' - begin - @service = ServiceModel.find_by(name: "vnf_manager") - rescue Mongoid::Errors::DocumentNotFound => e - halt 500, {'Content-Type' => "text/plain"}, "Microservice unrechable." - end + monitoring, errors = ServiceConfigurationHelper.get_module('vnf_manager') + halt 500, errors if errors composedUrl = "/vnf-monitoring/"+params['instance_id'].to_s+"/monitoring-data/last100/?"+request.env['QUERY_STRING'] end begin - response = RestClient.get @service.host.to_s + ":" + @service.port.to_s + composedUrl.to_s, 'X-Auth-Token' => @client_token, :content_type => :json + response = RestClient.get monitoring.host + composedUrl.to_s, 'X-Auth-Token' => monitoring.token, :content_type => :json rescue Errno::ECONNREFUSED halt 500, 'NS Monitoring unreachable' rescue => e diff --git a/ns-manager/routes/ns_provisioning.rb b/ns-manager/routes/ns_provisioning.rb index b994779..45085b8 100644 --- a/ns-manager/routes/ns_provisioning.rb +++ b/ns-manager/routes/ns_provisioning.rb @@ -45,17 +45,33 @@ class NsProvisioner < TnovaManager end logger.info "INSTANTIATION INFO: " + instantiation_info.to_s + pop_list = [] + mapping_info = {} if instantiation_info['pop_id'].nil? pop_list = JSON.parse(getDcs()) if pop_list.empty? halt 400, "No PoPs registereds." end + if !instantiation_info['mapping_id'].nil? + #using the Mapping algorithm specified in the instantiation request + mapping = ServiceConfigurationHelper.get_module_by_id(instantiation_info['mapping_id']) + mapping_info = mapping.host + ":" + mapping.port.to_s + mapping.path + elsif pop_list.size > 1 + #using the first mapping algorithm + mapping, errors = ServiceConfigurationHelper.get_module_by_type('mapping') + mapping_info = mapping.host + ":" + mapping.port.to_s + mapping.path + else + #deploy to the unic PoP + end else - pop_list = [] + #deploying the Instance into the requested PoP pop_list << JSON.parse(getDc(instantiation_info['pop_id'])) end + infr_repo_url, errors = ServiceConfigurationHelper.get_module_by_type('infr_repo') + infr_repo_url = nil if errors + provisioning = { :nsd => JSON.parse(nsd), :customer_id => instantiation_info['customer_id'], @@ -63,9 +79,8 @@ class NsProvisioner < TnovaManager :callback_url => instantiation_info['callbackUrl'], :flavour => instantiation_info['flavour'], :pop_list => pop_list, - #:pop_id => instantiation_info['pop_id'], - #:pop_info => pop_info, - :mapping_id => instantiation_info['mapping_id'] + :mapping => mapping_info, + :infr_repo_url => infr_repo_url } begin response = RestClient.post provisioner.host + request.fullpath, provisioning.to_json, 'X-Auth-Token' => provisioner.token, :content_type => :json From 66118fae55e9d2f3acf02ac3e43925673509750a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Thu, 3 Nov 2016 16:37:38 +0100 Subject: [PATCH 13/35] Updaed NS manager (DC and Services) helpers --- ns-manager/helpers/config.rb | 120 ++++------------------------------ ns-manager/helpers/dc.rb | 2 +- ns-manager/helpers/mapping.rb | 68 +++++++++++++++++++ 3 files changed, 83 insertions(+), 107 deletions(-) create mode 100644 ns-manager/helpers/mapping.rb diff --git a/ns-manager/helpers/config.rb b/ns-manager/helpers/config.rb index 3bdbb10..f95bb93 100644 --- a/ns-manager/helpers/config.rb +++ b/ns-manager/helpers/config.rb @@ -17,7 +17,6 @@ # # @see ServiceConfigurationHelper module ServiceConfigurationHelper - def is_port_open?(ip, port) begin Timeout::timeout(1) do @@ -34,128 +33,37 @@ def is_port_open?(ip, port) return false end - def self.get_module(name) + def self.get_module_by_id(id) begin - service = Service.find_by(name: name) + s = Service.find(id) rescue Mongoid::Errors::DocumentNotFound => e return 500, name + " not registred." end - service.host = service.host + ":" + service.port.to_s - service + s end - def registerService(json) - @json = JSON.parse(json) - @json[:type] = "internal" - - AuthenticationHelper.loginGK() - gkServices = AuthenticationHelper.getGKServices() - - index = 0 - while index < gkServices['shortname'].length do - if gkServices['shortname'][index] == @json['name'] - begin - @service = ServiceModel.find_by(:name => @json['name']) - @json['service_key'] = gkServices['service-key'][index] - serviceUri = @json['host'] + ":" + @json['port'].to_s - AuthenticationHelper.sendServiceAuth(serviceUri, gkServices['service-key'][index]) - @service.update_attributes(@json) - return "Service updated" - rescue Mongoid::Errors::DocumentNotFound => e - @json['service_key'] = gkServices['service-key'][index] - @service = ServiceModel.create!(@json) - serviceUri = @json['host'] + ":" + @json['port'].to_s - AuthenticationHelper.sendServiceAuth(serviceUri, gkServices['service-key'][index]) - return "Service registered" - end - end - index +=1 - end - - if index === gkServices['shortname'].length - begin - @service = ServiceModel.find_by(:name => @json['name']) - key = registerServiceinGK(@json['name']) - metadata = JSON.parse(key) - @json['service_key'] = gkServices['service-key'][index] - access = @json['host'] + ":" + @json['port'].to_s - AuthenticationHelper.sendServiceAuth(access, metadata["info"][0]["service-key"]) - @service.update_attributes(@json) - return "Service updated" - rescue Mongoid::Errors::DocumentNotFound => e - begin - key = registerServiceinGK(@json['name']) - metadata = JSON.parse(key) - @json['service_key'] = gkServices['service-key'][index] - access = @json['host'] + ":" + @json['port'].to_s - AuthenticationHelper.sendServiceAuth(access, metadata["info"][0]["service-key"]) - @service = ServiceModel.create!(@json) - return "Service registered" - rescue => e - logger.error e - halt 500, {'Content-Type' => 'text/plain'}, "Error registering the service" - end - end + def self.get_module(name) + begin + s = Service.find_by(name: name) + rescue Mongoid::Errors::DocumentNotFound => e + return 500, name + " not registred." end + s.host = s.host + ":" + s.port.to_s + s end - def registerExternalService() - @json = JSON.parse(json) - @json[:type] = "external" + def self.get_module_by_type(type) begin - @service = ServiceModel.find_by(:name => @json['name']) - @service.update_attributes(@json) - return "Service updated" + s = Service.find_by(type: type) rescue Mongoid::Errors::DocumentNotFound => e - begin - @service = ServiceModel.create!(@json) - return "Service registered" - rescue => e - logger.error e - halt 500, {'Content-Type' => 'text/plain'}, "Error registering the service" - end + return 500, name + " not registred." end + s.host + ":" + s.port.to_s end - def unregisterService(name) - settings.services[name] = nil - ServiceModel.find_by(name: params["microservice"]).delete - end - def updateService(service) - @service = ServiceModel.find_by(name: params["name"]) - @service.update_attributes(@json) - end - # Unregister all the services - def unRegisterAllService - ServiceModel.delete_all - end - - # Check if the token of service is correct - def auth(key) - #TODO - #return response - status 201 - end - - def self.getServices() - begin - @services = ServiceModel.all - rescue => e - puts e - end - return @services - end - def self.getService(name) - begin - @service = ServiceModel.find_by(:name => name) - rescue => e - puts e - end - return @service - end def self.publishServices services = getServices() diff --git a/ns-manager/helpers/dc.rb b/ns-manager/helpers/dc.rb index 3449a1a..5ee5bbe 100644 --- a/ns-manager/helpers/dc.rb +++ b/ns-manager/helpers/dc.rb @@ -24,7 +24,7 @@ module DcHelper # @return [String] the object converted into the expected format. def getDcs() begin - return 200, Dc.all.to_json + return Dc.all.to_json rescue => e logger.error e logger.error 'Error Establishing a Database Connection' diff --git a/ns-manager/helpers/mapping.rb b/ns-manager/helpers/mapping.rb new file mode 100644 index 0000000..ce73d45 --- /dev/null +++ b/ns-manager/helpers/mapping.rb @@ -0,0 +1,68 @@ +# +# TeNOR - NS Manager +# +# Copyright 2014-2016 i2CAT Foundation, Portugal Telecom Inovação +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @see ApplicationHelper +module MappingHelper + + # Get list of Mapping Algorithms + # + # @param [Symbol] format the format type, `:text` or `:html` + # @return [String] the object converted into the expected format. + def getMappings() + begin + return 200, Mapping.all.to_json + rescue => e + logger.error e + logger.error 'Error Establishing a Database Connection' + return 500, 'Error Establishing a Database Connection' + end + end + + # Get a Mapping + # + # @param [Symbol] format the format type, `:text` or `:html` + # @return [String] the object converted into the expected format. + def getMapping(id) + begin + dc = Mapping.find(id) + rescue Mongoid::Errors::DocumentNotFound => e + logger.error 'mapping not found' + return 404 + end + return dc.to_json + end + + def saveMapping(mapping) + begin + mapping = Mapping.find_by(name: mapping['name']) + halt 409, 'DC Duplicated. Use PUT for update.' + # i es.update_attributes!(:host => pop_info['host'], :port => pop_info['port'], :token => @token, :depends_on => serv_reg['depends_on']) + rescue Mongoid::Errors::DocumentNotFound => e + begin + mapping = Mapping.create!(mapping) + rescue => e + puts 'ERROR.................' + puts e + end + rescue => e + puts e + logger.error 'Error saving mapping.' + halt 400 + end + end + +end From 9bbcc692eec3a87176a887075a35fcdb3683c241 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Thu, 3 Nov 2016 17:57:02 +0100 Subject: [PATCH 14/35] Updated UI using the Available mapping algorithms saved in TeNOR --- ui/app/scripts/controllers/nsController.js | 8 ++-- ui/app/scripts/controllers/popController.js | 40 ++++++++++++++----- .../views/t-nova/modals/nsInstantiation.html | 2 +- ui/app/views/t-nova/nsMonitoring.html | 10 ++--- ui/app/views/t-nova/vnfMonitoring.html | 12 +++--- 5 files changed, 43 insertions(+), 29 deletions(-) diff --git a/ui/app/scripts/controllers/nsController.js b/ui/app/scripts/controllers/nsController.js index 0aa946d..bbb7b02 100644 --- a/ui/app/scripts/controllers/nsController.js +++ b/ui/app/scripts/controllers/nsController.js @@ -4,10 +4,10 @@ angular.module('tNovaApp') .controller('nsController', function ($scope, $stateParams, $filter, tenorService, $interval, $modal, $location, AuthService, $window, $alert) { $scope.registeredDcList = []; - $scope.serviceMapping = [{ - id: 0, - name: "UniMi" - }]; + tenorService.get("modules/services/type/mapping").then(function (data) { + if (data === undefined) return; + $scope.serviceMapping = data; + }); $scope.descriptor = {}; var page_num = 20; var page = 1; diff --git a/ui/app/scripts/controllers/popController.js b/ui/app/scripts/controllers/popController.js index 560ea7b..c32d5be 100644 --- a/ui/app/scripts/controllers/popController.js +++ b/ui/app/scripts/controllers/popController.js @@ -17,6 +17,12 @@ angular.module('tNovaApp') $scope.openstack_ip = ""; + tenorService.get("modules/services/type/infr_repo").then(function (data) { + if (data === undefined) return; + $scope.infr_repo_url = data[0].host + ":" + data[0].port; + $scope.refreshPoPList(); + }); + $scope.refreshPoPList = function () { tenorService.get('pops/dc').then(function (d) { console.log(d); @@ -30,12 +36,12 @@ angular.module('tNovaApp') console.log($scope.registeredDcList); var url = 'pop/'; - infrRepoService.get(url).then(function (_data) { + infrRepoService.get($scope.infr_repo_url, url).then(function (_data) { $scope.pops = _data; $scope.availableDcList = []; angular.forEach(_data, function (pop, index, array) { url = pop.identifier.slice(1); - infrRepoService.get(url).then(function (_data) { + infrRepoService.get($scope.infr_repo_url, url).then(function (_data) { var exist = _.some($scope.registeredDcList, function (c) { return _data.attributes['occi.epa.popuuid'] !== c; @@ -49,19 +55,31 @@ angular.module('tNovaApp') }); }); }; - $scope.refreshPoPList(); + //$scope.refreshPoPList(); - $scope.addDialog = function (id) { - if (id === "") { - $scope.emptyId = true; - } + $scope.addDialog = function (infr_repo_pop) { $scope.object = $scope.defaultPoP; - $scope.object.id = id; + console.log($scope.object); + + console.log(infr_repo_pop); + if (infr_repo_pop !== undefined){ + $scope.object.id = infr_repo_pop['occi.epa.popuuid']; + $scope.object.msg = infr_repo_pop['occi.epa.pop.name']; + $scope.emptyId = true; + }else{ + $scope.object.id = "Pop_identification"; + $scope.object.msg = "Pop_description"; + }; + /*if (id === "") { + $scope.emptyId = true; + }*/ + + //$scope.object.id = id; $scope.dc_default = $scope.defaultPoP; $scope.openstack_ip = ""; $scope.dc_default = { - msg: "Description", - id: "infrRepository-Pop-ID", + msg: $scope.object.msg, + id: $scope.object.id, adminid: "admin", password: "adminpass", isAdmin: false, @@ -73,7 +91,7 @@ angular.module('tNovaApp') dns: "8.8.8.8" }; $modal({ - title: "Registring DC - " + id, + title: "Registring DC - " + $scope.object.id, template: "views/t-nova/modals/addPop.html", show: true, scope: $scope, diff --git a/ui/app/views/t-nova/modals/nsInstantiation.html b/ui/app/views/t-nova/modals/nsInstantiation.html index 46c2225..e31c2c6 100644 --- a/ui/app/views/t-nova/modals/nsInstantiation.html +++ b/ui/app/views/t-nova/modals/nsInstantiation.html @@ -45,7 +45,7 @@ -

diff --git a/ui/app/views/t-nova/nsMonitoring.html b/ui/app/views/t-nova/nsMonitoring.html index 4e671eb..bd96b75 100644 --- a/ui/app/views/t-nova/nsMonitoring.html +++ b/ui/app/views/t-nova/nsMonitoring.html @@ -5,9 +5,8 @@

Network Service Monitoring

-
-
-
Instance {{instanceId}}
+
+
Instance {{instanceId}}
@@ -49,9 +48,8 @@

Network Service Monitoring

-
-
-
{{graph_name}}
+
+
{{graph_name}}
diff --git a/ui/app/views/t-nova/vnfMonitoring.html b/ui/app/views/t-nova/vnfMonitoring.html index b7ec0fb..7e09a8f 100644 --- a/ui/app/views/t-nova/vnfMonitoring.html +++ b/ui/app/views/t-nova/vnfMonitoring.html @@ -5,9 +5,9 @@

Virtual Network Function Instances

-
-
-
Instance {{instanceId}}
+
+
Instance {{instanceId}} +
@@ -48,10 +48,8 @@

Virtual Network Function Instances

-
-
-
-
{{graph_name}}
+
+
{{graph_name}}
From 9a6d7cf9c3c23bfeb930ec7d3e3ccc7b0baa0f0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Fri, 4 Nov 2016 12:02:32 +0100 Subject: [PATCH 15/35] Updated Config samples --- hot-generator/config/config.yml.sample | 2 +- ns-catalogue/config/config.yml.sample | 2 -- ns-manager/config/config.yml.sample | 11 ----------- ns-monitoring-repository/config/config.yml.sample | 3 --- ns-monitoring/config/config.yml.sample | 9 +-------- ns-provisioning/config/config.yml.sample | 9 --------- nsd-validator/config/config.yml.sample | 3 --- vnf-catalogue/config/config.yml.sample | 5 ----- vnf-manager/config/config.yml.sample | 10 +--------- vnf-monitoring-repository/config/config.yml.sample | 3 --- vnf-monitoring/config/config.yml.sample | 7 ------- vnf-provisioning/config/config.yml.sample | 7 +------ vnfd-validator/config/config.yml.sample | 3 --- 13 files changed, 4 insertions(+), 70 deletions(-) diff --git a/hot-generator/config/config.yml.sample b/hot-generator/config/config.yml.sample index 6647753..8654119 100644 --- a/hot-generator/config/config.yml.sample +++ b/hot-generator/config/config.yml.sample @@ -9,7 +9,7 @@ timeout: 30 max_persistent_conns: 512 daemonize: false logger_host: 127.0.0.1 -logger_port: 5228 +logger_port: 24224 port_security: false dependencies: [] diff --git a/ns-catalogue/config/config.yml.sample b/ns-catalogue/config/config.yml.sample index 900c57f..ffa69b8 100644 --- a/ns-catalogue/config/config.yml.sample +++ b/ns-catalogue/config/config.yml.sample @@ -12,6 +12,4 @@ threaded: true logger_host: 127.0.0.1 logger_port: 24224 -nsd_validator: localhost:4015 - dependencies: [nsd_validator] diff --git a/ns-manager/config/config.yml.sample b/ns-manager/config/config.yml.sample index e14a10c..7ae657c 100644 --- a/ns-manager/config/config.yml.sample +++ b/ns-manager/config/config.yml.sample @@ -11,14 +11,3 @@ daemonize: false threaded: true logger_host: 127.0.0.1 logger_port: 24224 - -#ns_catalogue: http://localhost:4011 -#ns_provisioner: http://localhost:4012 -#ns_monitoring: http://localhost:4014 -#ns_sla_enforcment: http://localhost:4016 - -gatekeeper: http://localhost:8000 -gk_token: -gk_user: t-nova-admin -gk_user_id: 1 -gk_pass: Eq7K8h9gpg diff --git a/ns-monitoring-repository/config/config.yml.sample b/ns-monitoring-repository/config/config.yml.sample index e31644b..707b354 100644 --- a/ns-monitoring-repository/config/config.yml.sample +++ b/ns-monitoring-repository/config/config.yml.sample @@ -12,7 +12,4 @@ threaded: true logger_host: 127.0.0.1 logger_port: 24224 -gk: -service_key: - dependencies: [] diff --git a/ns-monitoring/config/config.yml.sample b/ns-monitoring/config/config.yml.sample index 6d3694b..74765c8 100644 --- a/ns-monitoring/config/config.yml.sample +++ b/ns-monitoring/config/config.yml.sample @@ -12,11 +12,4 @@ threaded: true logger_host: 127.0.0.1 logger_port: 24224 -vnf_manager: http://localhost:4567 -ns_provisioner: 10.10.1.61:4012 -ns_monitoring_repo: 10.10.1.61:4017 - -gk: -service_key: - -dependencies: [ns_monitoring_repo, ns_provisioner, vnf_manager] +dependencies: [ns_monitoring_repo, vnf_manager] diff --git a/ns-provisioning/config/config.yml.sample b/ns-provisioning/config/config.yml.sample index 45c2703..9c1ecbe 100644 --- a/ns-provisioning/config/config.yml.sample +++ b/ns-provisioning/config/config.yml.sample @@ -12,9 +12,6 @@ threaded: true logger_host: 127.0.0.1 logger_port: 24224 -mapping: http://localhost:4042 -sla_enforcement: http://localhost:4016 - #optional fields default_tenant: true default_user_name: tenor_user @@ -23,12 +20,6 @@ default_tenant_name: tenor_tenant dependencies: [ns_monitoring, vnf_manager, wicm, mAPI, mapping, hot_generator, infr_repository, netfloc] -gk: -service_key: - -#infr_repo: http://10.10.1.1:8080 -#wicm: http://10.30.0.12:12891 - netfloc: odl_username: admin odl_password: admin diff --git a/nsd-validator/config/config.yml.sample b/nsd-validator/config/config.yml.sample index 319e7b4..29b55dd 100644 --- a/nsd-validator/config/config.yml.sample +++ b/nsd-validator/config/config.yml.sample @@ -15,7 +15,4 @@ logger_port: 24224 xml_schema: assets/schemas/nsd.xsd json_schema: assets/schemas/nsd_schema.json -gk: -service_key: - dependencies: [] diff --git a/vnf-catalogue/config/config.yml.sample b/vnf-catalogue/config/config.yml.sample index 5d0880f..83ad67f 100644 --- a/vnf-catalogue/config/config.yml.sample +++ b/vnf-catalogue/config/config.yml.sample @@ -12,9 +12,4 @@ threaded: true logger_host: 127.0.0.1 logger_port: 24224 -vnfd_validator: http://localhost:4570 - -gk: -service_key: - dependencies: [vnfd_validator] diff --git a/vnf-manager/config/config.yml.sample b/vnf-manager/config/config.yml.sample index 97781dd..273ba71 100644 --- a/vnf-manager/config/config.yml.sample +++ b/vnf-manager/config/config.yml.sample @@ -1,5 +1,6 @@ --- servicename: vnf_manager +type: manager manager: localhost:4000 environment: development address: 0.0.0.0 @@ -12,13 +13,4 @@ threaded: true logger_host: 127.0.0.1 logger_port: 24224 -vnf_catalogue: http://localhost:4569 -vnf_provisioning: http://localhost:4572 -vnf_monitoring: http://localhost:4573 -ns_manager: http://localhost:4000 -wicm: http://193.136.92.173:12891 - -gk: -service_key: - dependencies: [ns_manager, wicm, mAPI, mapping, hot_generator, infr_repository] diff --git a/vnf-monitoring-repository/config/config.yml.sample b/vnf-monitoring-repository/config/config.yml.sample index f044ecf..2044652 100644 --- a/vnf-monitoring-repository/config/config.yml.sample +++ b/vnf-monitoring-repository/config/config.yml.sample @@ -12,7 +12,4 @@ threaded: true logger_host: 127.0.0.1 logger_port: 24224 -gk: -service_key: - dependencies: [] diff --git a/vnf-monitoring/config/config.yml.sample b/vnf-monitoring/config/config.yml.sample index 52e4133..149934e 100644 --- a/vnf-monitoring/config/config.yml.sample +++ b/vnf-monitoring/config/config.yml.sample @@ -12,11 +12,4 @@ threaded: true logger_host: 127.0.0.1 logger_port: 24224 -vnf_manager: http://10.10.1.61:4567 -vim_monitoring: http://10.10.1.62:8080 -ns_manager: http://10.10.1.61:4000 - -gk: -service_key: - dependencies: [ns_manager, vim_monitoring, vnf_manager] diff --git a/vnf-provisioning/config/config.yml.sample b/vnf-provisioning/config/config.yml.sample index d8bac87..51d3894 100644 --- a/vnf-provisioning/config/config.yml.sample +++ b/vnf-provisioning/config/config.yml.sample @@ -12,11 +12,6 @@ threaded: true logger_host: 127.0.0.1 logger_port: 24224 -vnf_manager: http://localhost:4567 -hot_generator: http://localhost:4571 -mapi: http://admin:changeme@10.10.1.67:1234 - -gk: -service_key: +mapi: dependencies: [vnf_manager, mapi, hot_generator] diff --git a/vnfd-validator/config/config.yml.sample b/vnfd-validator/config/config.yml.sample index b7244d6..9c3a3a7 100644 --- a/vnfd-validator/config/config.yml.sample +++ b/vnfd-validator/config/config.yml.sample @@ -15,7 +15,4 @@ logger_port: 24224 xml_schema: assets/schemas/vnfd.xsd json_schema: assets/schemas/vnfd_schema.json -gk: -service_key: - dependencies: [] From b7980b22d8023bc0f3410419d10162cd706d7b1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Fri, 4 Nov 2016 12:20:30 +0100 Subject: [PATCH 16/35] Updated Microservice Manager --- ns-manager/helpers/config.rb | 159 ++++++----- ns-manager/main.rb | 22 +- ns-manager/routes/config.rb | 55 ++-- sinatra-gkauth-gem/lib/sinatra/gk_auth.rb | 31 +- vnf-manager/routes/configs.rb | 151 +++------- vnf-manager/routes/provisioning.rb | 329 +++++++++++----------- 6 files changed, 324 insertions(+), 423 deletions(-) diff --git a/ns-manager/helpers/config.rb b/ns-manager/helpers/config.rb index f95bb93..f4493dd 100644 --- a/ns-manager/helpers/config.rb +++ b/ns-manager/helpers/config.rb @@ -17,85 +17,112 @@ # # @see ServiceConfigurationHelper module ServiceConfigurationHelper - def is_port_open?(ip, port) - begin - Timeout::timeout(1) do - begin - s = TCPSocket.new(ip, port) - s.close - return true - rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH - return false - end - end - rescue Timeout::Error - end - return false - end - - def self.get_module_by_id(id) - begin - s = Service.find(id) - rescue Mongoid::Errors::DocumentNotFound => e - return 500, name + " not registred." + def self.is_port_open?(ip, port) + begin + Timeout.timeout(1) do + begin + s = TCPSocket.new(ip, port) + s.close + return true + rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH + return false + end + end + rescue Timeout::Error + end + false end - s - end - def self.get_module(name) - begin - s = Service.find_by(name: name) - rescue Mongoid::Errors::DocumentNotFound => e - return 500, name + " not registred." + def self.get_module_by_id(id) + begin + s = Service.find(id) + rescue Mongoid::Errors::DocumentNotFound => e + return 500, name + ' not registred.' + end + s end - s.host = s.host + ":" + s.port.to_s - s - end - def self.get_module_by_type(type) - begin - s = Service.find_by(type: type) - rescue Mongoid::Errors::DocumentNotFound => e - return 500, name + " not registred." + def self.get_module(name) + begin + s = Service.find_by(name: name) + rescue Mongoid::Errors::DocumentNotFound => e + return 500, name + ' not registred.' + end + s.host = s.host + ':' + s.port.to_s + s end - s.host + ":" + s.port.to_s - end - - - + def self.get_module_by_type(type) + begin + s = Service.find_by(type: type) + rescue Mongoid::Errors::DocumentNotFound => e + return 500, name + ' not registred.' + end + s.host + ':' + s.port.to_s + end - def self.publishServices - services = getServices() - services.each do |service| - logger.debug "Sending dependencies to " + service['name'] - if service['type'] == "internal" + def self.get_modules begin - RestClient.post service['host'] + ":" + service['port'] + "/gk_dependencies", services.to_json, :content_type => :json + services = Service.all rescue => e - #logger.error e - #puts e - #halt 500, {'Content-Type' => 'text/plain'}, "Error sending dependencies to " +service['name'] + logger.error e end - end + services end - end - def self.publishService(name) - services = getServices - service = getService(name) - begin - RestClient.post service['host'] + ":" + service['port'] + "/gk_dependencies", services.to_json, :content_type => :json - rescue => e - #logger.error e - puts e - #halt 500, {'Content-Type' => 'text/plain'}, "Error sending dependencies to " +service['name'] + def self.publishModules + services = get_modules + services.each do |service| + logger.debug 'Sending dependencies to ' + service['name'] + if service['type'] == '' + service['depends_on'].each do |serv| + begin + logger.debug "Checking if dependant Services of #{serv} is Up and Running...." + s = Service.where(name: serv).first + next if s.nil? + dependant_status = is_port_open?(s['host'], s['port']) + if dependant_status == false + logger.debug "Service found but is down." + s.destroy + else + dep = { name: s['name'], host: s['host'], port: s['port'], token: s['token'], depends_on: s['depends_on'] } + send_dependencies_to_module(service, dep) + begin + RestClient.post service['host'] + ':' + service['port'] + '/gk_dependencies', dep.to_json, content_type: :json, 'X-Auth-Token' => service['token'] + rescue => e + logger.error e + end + end + rescue Mongoid::Errors::DocumentNotFound => e + logger.error 'Service not found.' + end + end + elsif service['type'] == 'manager' + send_dependencies_to_manager(service, service['depends_on']) + end + end end - end + def self.send_dependencies_to_module(s, dep) + begin + RestClient.post s['host'] + ':' + s['port'] + '/gk_dependencies', dep.to_json, :content_type => :json, 'X-Auth-Token' => s['token'] + rescue => e + logger.error e + end + end - # Global, memoized, lazy initialized instance of a logger - def self.logger - @logger ||= TnovaManager.logger - end + def self.send_dependencies_to_manager(manager, depends_on) + depends_on.each do |dep| + begin + RestClient.post manager[:host] + ':' + manager[:port].to_s + '/modules/services', dep.to_json, :content_type => :json, 'X-Auth-Token' => manager['token'] + rescue => e + logger.error e + end + end + end + + # Global, memoized, lazy initialized instance of a logger + def self.logger + @logger ||= TnovaManager.logger + end end diff --git a/ns-manager/main.rb b/ns-manager/main.rb index f1a1099..91287b1 100644 --- a/ns-manager/main.rb +++ b/ns-manager/main.rb @@ -47,25 +47,6 @@ class TnovaManager < Sinatra::Application before do env['rack.logger'] = settings.logger - -=begin - if settings.environment == 'development' - @client_token = 'test-token-client-id' - return - end - - pass if request.path_info == '/' - # Validate every request with Gatekeeper - @client_token = request.env['HTTP_X_AUTH_TOKEN'] - begin - response = RestClient.get "#{settings.gatekeeper}/token/validate/#{@client_token}", 'X-Auth-Service-Key' => settings.service_key, :content_type => :json - rescue Errno::ECONNREFUSED - halt 500, 'Gatekeeper unreachable' - rescue => e - # logger.error e.response - halt e.response.code, e.response.body - end -=end end helpers ApplicationHelper @@ -75,6 +56,9 @@ class TnovaManager < Sinatra::Application helpers StatisticsHelper helpers VimHelper + #publish services + ServiceConfigurationHelper.publishModules + get '/' do return 200, JSON.pretty_generate(interfaces_list) end diff --git a/ns-manager/routes/config.rb b/ns-manager/routes/config.rb index 41b8b98..9656a14 100644 --- a/ns-manager/routes/config.rb +++ b/ns-manager/routes/config.rb @@ -17,7 +17,9 @@ # # @see TnovaManager class ServiceConfiguration < TnovaManager - # /modules/services + # @method get_modules_services + # @overload get '/modules/services' + # Retrieve the microservices list get '/services' do begin return 200, Service.all.to_json @@ -28,6 +30,9 @@ class ServiceConfiguration < TnovaManager end end + # @method get_modules_services_id + # @overload get '/modules/services:id' + # Retrieve a microservice given an id get '/services/:id' do |id| begin service = Service.find(id) @@ -38,9 +43,12 @@ class ServiceConfiguration < TnovaManager service.to_json end + # @method get_modules_services_name + # @overload get '/modules/services/:name' + # Retrieve the token of a microservice given a name get '/services/name/:name' do |name| begin - service = Service.find_by(:name => name) + service = Service.find_by(name: name) rescue Mongoid::Errors::DocumentNotFound => e logger.error 'DC not found' return 404 @@ -48,6 +56,9 @@ class ServiceConfiguration < TnovaManager service['token'] end + # @method get_modules_services_type + # @overload get '/modules/services/:type' + # Retrieve the microservices list by type get '/services/type/:type' do |type| begin services = Service.where(:type => type) @@ -58,9 +69,13 @@ class ServiceConfiguration < TnovaManager services.to_json end + # @method post_modules_services + # @overload post '/modules/services' + # Register a new microservice post '/services' do return 415 unless request.content_type == 'application/json' serv_reg, errors = parse_json(request.body.read) + logger.info "POST SERVICE REQUEST -------------------------------------------------------------- " + serv_reg['name'] @token = JWT.encode({ service_name: serv_reg['name'] }, serv_reg['secret'], 'HS256') serv = { @@ -88,7 +103,7 @@ class ServiceConfiguration < TnovaManager logger.debug "Checking if dependant Services of #{serv} is Up and Running...." s = Service.where(name: serv).first next if s.nil? - dependant_status = is_port_open?(s['host'], s['port']) + dependant_status = ServiceConfigurationHelper.is_port_open?(s['host'], s['port']) if dependant_status == false logger.debug "Service found but is down." s.destroy @@ -96,41 +111,22 @@ class ServiceConfiguration < TnovaManager depends_on << { name: s['name'], host: s['host'], port: s['port'], token: s['token'], depends_on: s['depends_on'] } end rescue Mongoid::Errors::DocumentNotFound => e - logger.error 'User not found.' - # halt 404 + logger.error 'Service not found.' end end - logger.debug 'Find service that has this module as dependency:' - # Service + logger.debug 'Find services that have this module as dependency:' dependencies = Service.any_of(depends_on: serv[:name]).entries logger.debug dependencies if dependencies.any? dependencies.each do |dependency| - begin - RestClient.post dependency['host'] + ':' + dependency['port'] + '/gk_dependencies', serv.to_json, :content_type => :json, 'X-Auth-Token' => dependency['token'] - rescue => e - # logger.error e - puts e - # halt 500, {'Content-Type' => 'text/plain'}, "Error sending dependencies to " +service['name'] - end + ServiceConfigurationHelper.send_dependencies_to_module(dependency, serv) end end -puts "Manager..." -puts serv[:type] if serv[:type] == 'manager' - puts "Send to VNF MANAger..." - depends_on.each do |dep| - puts dep - begin - RestClient.post serv[:host] + ':' + serv[:port].to_s + '/modules/services', dep.to_json, :content_type => :json, 'X-Auth-Token' => serv['token'] - rescue => e - # logger.error e - puts e - # halt 500, {'Content-Type' => 'text/plain'}, "Error sending dependencies to " +service['name'] - end - end + logger.debug "Sending dependencies to VNF Manager..." + ServiceConfigurationHelper.send_dependencies_to_manager(serv, depends_on) end halt 201, { depends_on: depends_on }.to_json end @@ -138,9 +134,12 @@ class ServiceConfiguration < TnovaManager put '/services' do end + # @method delete_modules_services_name + # @overload delete '/modules/services/:name' + # Remove a microservice delete '/services/:name' do |name| begin - Service.find_by(:name => name).destroy + Service.find_by(name: name).destroy rescue Mongoid::Errors::DocumentNotFound => e halt 404 end diff --git a/sinatra-gkauth-gem/lib/sinatra/gk_auth.rb b/sinatra-gkauth-gem/lib/sinatra/gk_auth.rb index 0df6f59..6a4c63c 100644 --- a/sinatra-gkauth-gem/lib/sinatra/gk_auth.rb +++ b/sinatra-gkauth-gem/lib/sinatra/gk_auth.rb @@ -6,6 +6,7 @@ module Sinatra module Gk_Auth module Helpers + puts 'Loaded 1....' $time = 5 $max_retries = 150 # in seconds def initialize @@ -32,7 +33,7 @@ def publish_service(service_info) begin response = RestClient.post settings.manager + '/modules/services', service_info.to_json, accept: :json, content_type: :json rescue => e - puts 'Error registring or receiving dependencies to the Manager, waiting: ' + $time.to_s + ' seconds for next rety...' + puts 'Error registring or receiving dependencies to the Manager, waiting: ' + $time.to_s + ' seconds for next retry...' puts e sleep($time) # wait $time seconds $time = $time * 2 @@ -98,40 +99,20 @@ def self.registered(app) app.helpers Gk_Auth::Helpers app.before do - # env['rack.logger'] = app.settings.logger - return if request.path_info == '/gk_credentials' - return if settings.environment == 'development' authorized? end - # to be removed... - app.post '/gk_credentials' do - # credentials = {gk_url: url, service_key: key} - return 415 unless request.content_type == 'application/json' - credentials, errors = parse_json(request.body.read) - return 400, errors.to_json if errors - - app.set :gk, credentials['gk_url'] - app.set :service_key, credentials['service_key'] - - updateValues('gk', credentials['gk_url']) - updateValues('service_key', credentials['service_key']) - - return 200 - end - app.post '/gk_dependencies' do return 415 unless request.content_type == 'application/json' - services, errors = parse_json(request.body.read) + ms, errors = parse_json(request.body.read) return 400, errors.to_json if errors return 200 if settings.dependencies.nil? - service = services - unless settings.dependencies.detect { |sv| sv == service['name'] }.nil? - app.set service['name'], service['host'].to_s + ':' + service['port'].to_s - app.set service['name'] + '_token', service['token'].to_s + unless settings.dependencies.detect { |sv| sv == ms['name'] }.nil? + app.set ms['name'], ms['host'].to_s + ':' + ms['port'].to_s + app.set ms['name'] + '_token', ms['token'].to_s end return 200 diff --git a/vnf-manager/routes/configs.rb b/vnf-manager/routes/configs.rb index aaf32c3..0057883 100644 --- a/vnf-manager/routes/configs.rb +++ b/vnf-manager/routes/configs.rb @@ -17,8 +17,9 @@ # # @see ServiceConfiguration class ServiceConfiguration < VNFManager - - # /modules/services + # @method get_modules_services + # @overload get '/modules/services' + # Retrieve the microservices list get '/services' do begin return 200, Service.all.to_json @@ -29,6 +30,9 @@ class ServiceConfiguration < VNFManager end end + # @method get_modules_services_id + # @overload get '/modules/services:id' + # Retrieve a microservice given an id get '/services/:id' do |id| begin service = Service.find(id) @@ -39,32 +43,44 @@ class ServiceConfiguration < VNFManager return service.to_json end + # @method get_modules_services_name + # @overload get '/modules/services/:name' + # Retrieve the token of a microservice given a name get '/services/name/:name' do |name| begin - service = Service.find_by(:name => name) + service = Service.find_by(name: name) rescue Mongoid::Errors::DocumentNotFound => e logger.error 'DC not found' return 404 end - return service['token'] + service['token'] end + # @method post_modules_services + # @overload get '/modules/services' + # Register a microservice post '/services' do return 415 unless request.content_type == 'application/json' serv_reg, errors = parse_json(request.body.read) - @token = JWT.encode({ service_name: serv_reg['name'] }, serv_reg['secret'], 'HS256') + if serv_reg['token'].nil? + @token = JWT.encode({ service_name: serv_reg['name'] }, serv_reg['secret'], 'HS256') + else + @token = serv_reg['token'] + end serv = { name: serv_reg['name'], host: serv_reg['host'], port: serv_reg['port'], + path: serv_reg['path'], token: @token, - depends_on: serv_reg['depends_on'] + depends_on: serv_reg['depends_on'], + type: serv_reg['type'] } logger.debug serv begin s = Service.find_by(name: serv_reg['name']) - s.update_attributes!(host: serv_reg['host'], port: serv_reg['port'], token: @token, depends_on: serv_reg['depends_on']) + s.update_attributes!(host: serv_reg['host'], port: serv_reg['port'], token: @token, depends_on: serv_reg['depends_on'], type: serv_reg['type']) rescue Mongoid::Errors::DocumentNotFound => e Service.create!(serv) rescue => e @@ -74,28 +90,28 @@ class ServiceConfiguration < VNFManager depends_on = [] serv_reg['depends_on'].each do |serv| begin - logger.info "Checking if dependant Services of #{serv} is Up and Running...." + logger.debug "Checking if dependant Services of #{serv} is Up and Running...." s = Service.where(name: serv).first next if s.nil? dependant_status = is_port_open?(s['host'], s['port']) if dependant_status == false - logger.info "Service found but is down." + logger.debug "Service found but is down." s.destroy else + logger.debug 'Packing dependent services...' depends_on << { name: s['name'], host: s['host'], port: s['port'], token: s['token'] } end rescue Mongoid::Errors::DocumentNotFound => e - logger.error 'User not found.' - # halt 404 + logger.error 'Service not found.' end end - logger.error 'Find service that has this module as dependency:' - # Service + logger.debug 'Find services that have this module as dependency:' dependencies = Service.any_of(depends_on: serv[:name]).entries - logger.error dependencies + logger.debug dependencies if dependencies.any? dependencies.each do |dependency| + puts dependency begin RestClient.post dependency['host'] + ':' + dependency['port'] + '/gk_dependencies', serv.to_json, :content_type => :json, 'X-Auth-Token' => dependency['token'] rescue => e @@ -111,114 +127,15 @@ class ServiceConfiguration < VNFManager put '/services' do end + # @method delete_modules_services_name + # @overload delete '/modules/services/:name' + # Remove a microservice delete '/services/:name' do |name| begin - Service.find_by(:name => name).destroy + Service.find_by(name: name).destroy rescue Mongoid::Errors::DocumentNotFound => e halt 404 end halt 200 end - - - - - - -=begin - # @method put_configs_config_id - # @overload put '/configs/:config_id' - # Update a configuration value - # @param [Integer] config_id the configuration ID - # Update a configuration - put '/:config_id' do - halt 501, 'Not implemented yet' - - # Return if service ID is invalid - halt 400, 'Invalid service ID' unless ['vnf-catalogue', 'vnf-provisioning', 'vnf-monitoring', 'vnf-scaling'].include? params[:config_id] - - begin - response = RestClient.put settings.ns_manager + '/configs/services', 'X-Auth-Token' => @client_token - rescue Errno::ECONNREFUSED - halt 500, 'NS Manager unreachable' - rescue => e - logger.error e.response - halt e.response.code, e.response.body - end - - halt response.code, response.body - end - - # @method get_configs - # @overload get '/configs' - # List all configurations - # Get all configs - get '/' do - if params['name'] - begin - response = ServiceModel.find_by(name: params["name"]).to_json - rescue Mongoid::Errors::DocumentNotFound => e - halt 404 - end - return response - else - return ServiceModel.all.to_json - end - end - - # @method get_configs_config_id - # @overload get '/configs/:config_id' - # Show a specific configuration - # @param [Integer] config_id the configuration ID - # Get a specific config - get '/:config_id' do - # Forward request to NS Manager - begin - response = RestClient.get settings.ns_manager + '/configs/services', {params: {name: params[:config_id]}}, 'X-Auth-Token' => @client_token - rescue Errno::ECONNREFUSED - halt 500, 'NS Manager unreachable' - rescue RestClient::NotFound => e - halt 404 - rescue => e - logger.error e.response - halt e.response.code, e.response.body - end - - halt response.code, response.body - end - - # @method delete_configs_config_id - # @overload delete '/configs/:config_id' - # Delete a specific configuration - # @param [Integer] config_id the configuration ID - # Delete a configuration - delete '/:config_id' do - # Forward request to NS Manager - begin - response = RestClient.delete settings.ns_manager + '/configs/services', {params: {name: params[:config_id]}}, 'X-Auth-Token' => @client_token - rescue Errno::ECONNREFUSED - halt 500, 'NS Manager unreachable' - rescue => e - logger.error e.response - halt e.response.code, e.response.body - end - - halt response.code, response.body - end - - # @method get_configs_services_publish_microservice - # @overload get '/configs/services/:name/status' - # Get dependencies for specific microservice, asyncrhonous call - post '/services/publish/:microservice' do - name = params[:microservice] - - #registerService(request.body.read) - - #Thread.new do - # ServiceConfigurationHelper.publishServices() - #end - - return 200 - end -=end end diff --git a/vnf-manager/routes/provisioning.rb b/vnf-manager/routes/provisioning.rb index 9f95715..4001401 100644 --- a/vnf-manager/routes/provisioning.rb +++ b/vnf-manager/routes/provisioning.rb @@ -17,185 +17,178 @@ # # @see VNFManager class Provisioning < VNFManager + # @method get_vnf_provisioning_network_service_ns_id + # @overload get '/vnf-provisioning/network-service/:ns_id' + # Get all the VNFRs of a specific NS + # @param [Integer] ns_id the network service ID + # Get all the VNFRs of a specific NS + get '/network-service/:ns_id' do |ns_id| + provisioner, errors = ServiceConfigurationHelper.get_module('vnf_provisioner') + halt 500, errors if errors + + # Forward the request to the VNF Provisioning + begin + response = RestClient.get provisioner.host + '/vnf-provisioning/network-service/' + ns_id, 'X-Auth-Token' => provisioner.token, :accept => :json + rescue Errno::ECONNREFUSED + halt 500, 'VNF Provisioning unreachable' + rescue => e + logger.error e.response + halt e.response.code, e.response.body + end + + halt response.code, response.body + end + + # @method get_vnf_provisioning_vnf_instances + # @overload get '/vnf-provisioning/vnf-instances' + # Return all VNF Instances + # Return all VNF Instances + get '/vnf-instances' do + provisioner, errors = ServiceConfigurationHelper.get_module('vnf_provisioner') + halt 500, errors if errors + + # Send request to VNF Provisioning + begin + response = RestClient.get provisioner.host + '/vnf-provisioning/vnf-instances', 'X-Auth-Token' => provisioner.token + rescue Errno::ECONNREFUSED + halt 500, 'VNF Provisioning unreachable' + rescue => e + logger.error e.response + halt e.response.code, e.response.body + end - # @method get_vnf_provisioning_network_service_ns_id - # @overload get '/vnf-provisioning/network-service/:ns_id' - # Get all the VNFRs of a specific NS - # @param [Integer] ns_id the network service ID - # Get all the VNFRs of a specific NS - get '/network-service/:ns_id' do |ns_id| - - provisioner, errors = ServiceConfigurationHelper.get_module('vnf_provisioner') - halt 500, errors if errors - - # Forward the request to the VNF Provisioning - begin - response = RestClient.get provisioner.host + '/vnf-provisioning/network-service/' + ns_id, 'X-Auth-Token' => provisioner.token, :accept => :json - rescue Errno::ECONNREFUSED - halt 500, 'VNF Provisioning unreachable' - rescue => e - logger.error e.response - halt e.response.code, e.response.body - end - - halt response.code, response.body + halt response.code, response.body + end + + # @method get_vnf_provisioning_vnf_instances + # @overload get '/vnf-provisioning/vnf-instances' + # Return all VNF Instances + # Return all VNF Instances + get '/vnf-instances/:vnfr_id' do |vnfr_id| + provisioner, errors = ServiceConfigurationHelper.get_module('vnf_provisioner') + halt 500, errors if errors + + # Send request to VNF Provisioning + begin + response = RestClient.get provisioner.host + '/vnf-provisioning/vnf-instances/' + vnfr_id, 'X-Auth-Token' => provisioner.token + rescue Errno::ECONNREFUSED + halt 500, 'VNF Provisioning unreachable' + rescue => e + logger.error e.response + halt e.response.code, e.response.body end - # @method get_vnf_provisioning_vnf_instances - # @overload get '/vnf-provisioning/vnf-instances' - # Return all VNF Instances - # Return all VNF Instances - get '/vnf-instances' do - - provisioner, errors = ServiceConfigurationHelper.get_module('vnf_provisioner') - halt 500, errors if errors - - # Send request to VNF Provisioning - begin - response = RestClient.get provisioner.host + '/vnf-provisioning/vnf-instances', 'X-Auth-Token' => provisioner.token - rescue Errno::ECONNREFUSED - halt 500, 'VNF Provisioning unreachable' - rescue => e - logger.error e.response - halt e.response.code, e.response.body - end - - halt response.code, response.body + halt response.code, response.body + end + + # @method post_vnf_provisioning_vnf_instances + # @overload post '/vnf-provisioning/vnf-instances' + # Request the instantiation of a VNF + # @param [JSON] information about VIM and the VNFD ID + # Request the instantiation of a VNF + post '/vnf-instances' do + catalogue, errors = ServiceConfigurationHelper.get_module('vnf_catalogue') + halt 500, errors if errors + + provisioner, errors = ServiceConfigurationHelper.get_module('vnf_provisioner') + halt 500, errors if errors + + # Return if content-type is invalid + halt 415 unless request.content_type == 'application/json' + + # Validate JSON format + instantiation_info = parse_json(request.body.read) + + # Get VNF by id + begin + instantiation_info['vnf'] = parse_json(RestClient.get(catalogue.host + '/vnfs/' + instantiation_info['vnf_id'].to_s, 'X-Auth-Token' => catalogue.token, :accept => :json)) + rescue Errno::ECONNREFUSED + halt 500, 'VNF Catalogue unreachable' + rescue => e + logger.error e.response + halt e.response.code, e.response.body end - # @method get_vnf_provisioning_vnf_instances - # @overload get '/vnf-provisioning/vnf-instances' - # Return all VNF Instances - # Return all VNF Instances - get '/vnf-instances/:vnfr_id' do |vnfr_id| - - provisioner, errors = ServiceConfigurationHelper.get_module('vnf_provisioner') - halt 500, errors if errors - - # Send request to VNF Provisioning - begin - response = RestClient.get provisioner.host + '/vnf-provisioning/vnf-instances/' + vnfr_id, 'X-Auth-Token' => provisioner.token - rescue Errno::ECONNREFUSED - halt 500, 'VNF Provisioning unreachable' - rescue => e - logger.error e.response - halt e.response.code, e.response.body - end - - halt response.code, response.body + # Send provisioning info to VNF Provisioning + begin + response = RestClient.post provisioner.host + '/vnf-provisioning/vnf-instances', instantiation_info.to_json, 'X-Auth-Token' => provisioner.token, :content_type => :json + rescue Errno::ECONNREFUSED + halt 500, 'VNF Provisioning unreachable' + rescue => e + logger.error e.response + halt e.response.code, e.response.body end - # @method post_vnf_provisioning_vnf_instances - # @overload post '/vnf-provisioning/vnf-instances' - # Request the instantiation of a VNF - # @param [JSON] information about VIM and the VNFD ID - # Request the instantiation of a VNF - post '/vnf-instances' do - - catalogue, errors = ServiceConfigurationHelper.get_module('vnf_catalogue') - halt 500, errors if errors - - provisioner, errors = ServiceConfigurationHelper.get_module('vnf_provisioner') - halt 500, errors if errors - - # Return if content-type is invalid - halt 415 unless request.content_type == 'application/json' - - # Validate JSON format - instantiation_info = parse_json(request.body.read) - - # Get VNF by id - begin - instantiation_info['vnf'] = parse_json(RestClient.get catalogue.host + '/vnfs/' + instantiation_info['vnf_id'].to_s, 'X-Auth-Token' => catalogue.token, :accept => :json) - rescue Errno::ECONNREFUSED - halt 500, 'VNF Catalogue unreachable' - rescue => e - logger.error e.response - halt e.response.code, e.response.body - end - - # Send provisioning info to VNF Provisioning - begin - response = RestClient.post provisioner.host + '/vnf-provisioning/vnf-instances', instantiation_info.to_json, 'X-Auth-Token' => provisioner.token, :content_type => :json - rescue Errno::ECONNREFUSED - halt 500, 'VNF Provisioning unreachable' - rescue => e - logger.error e.response - halt e.response.code, e.response.body - end - - halt response.code, response.body + halt response.code, response.body + end + + # @method post_vnf_provisioning_vnf_instances_vnfr_id_destroy + # @overload post '/vnf-provisioning/vnf-instances/:vnfr_id/destroy' + # Request to de-allocate the resources of a VNF + # @param [String] vnfr_id the VNFR ID + # @param [JSON] information about VIM + # Request to de-allocate the resources of a VNF + post '/vnf-instances/:vnfr_id/destroy' do |vnfr_id| + # Return if content-type is invalid + halt 415 unless request.content_type == 'application/json' + + provisioner, errors = ServiceConfigurationHelper.get_module('vnf_provisioner') + halt 500, errors if errors + + monitoring, errors = ServiceConfigurationHelper.get_module('vnf_monitoring') + # halt 500, errors if errors + unless errors + begin + response = RestClient.delete monitoring.host + "/vnf-monitoring/subcription/#{vnfr_id}", 'X-Auth-Token' => monitoring.token, :content_type => :json, :accept => :json + rescue Errno::ECONNREFUSED + # halt 500, 'VNF Monitoring unreachable' + rescue => e + logger.error e + # logger.error e.response + # halt e.response.code, e.response.body + end end - # @method post_vnf_provisioning_vnf_instances_vnfr_id_destroy - # @overload post '/vnf-provisioning/vnf-instances/:vnfr_id/destroy' - # Request to de-allocate the resources of a VNF - # @param [String] vnfr_id the VNFR ID - # @param [JSON] information about VIM - # Request to de-allocate the resources of a VNF - post '/vnf-instances/:vnfr_id/destroy' do |vnfr_id| - - provisioner, errors = ServiceConfigurationHelper.get_module('vnf_provisioner') - halt 500, errors if errors - - monitoring, errors = ServiceConfigurationHelper.get_module('vnf_monitoring') - #halt 500, errors if errors - - # Return if content-type is invalid - halt 415 unless request.content_type == 'application/json' - - begin - response = RestClient.delete monitoring.host + "/vnf-monitoring/subcription/#{vnfr_id}", 'X-Auth-Token' => monitoring.token, :content_type => :json, :accept => :json - rescue Errno::ECONNREFUSED - #halt 500, 'VNF Monitoring unreachable' - rescue => e - logger.error e - #logger.error e.response - #halt e.response.code, e.response.body - end - - # Forward the request to the VNF Provisioning - begin - response = RestClient.post provisioner.host + "/vnf-provisioning/vnf-instances/#{vnfr_id}/destroy", request.body, 'X-Auth-Token' => provisioner.token, :content_type => :json - rescue Errno::ECONNREFUSED - halt 500, 'VNF Provisioning unreachable' - rescue => e - logger.error e - logger.error e.response - halt e.response.code, e.response.body - end - - halt response.code, response.body + # Forward the request to the VNF Provisioning + begin + response = RestClient.post provisioner.host + "/vnf-provisioning/vnf-instances/#{vnfr_id}/destroy", request.body, 'X-Auth-Token' => provisioner.token, :content_type => :json + rescue Errno::ECONNREFUSED + halt 500, 'VNF Provisioning unreachable' + rescue => e + logger.error e + logger.error e.response + halt e.response.code, e.response.body end - # @method post_vnf_rovisioning_vnf_instances_vnfr_id_config - # @overload post '/vnf-provisioning/vnf-instances/:vnfr_id/config' - # Request to execute a lifecycle event - # @param [String] vnfr_id the VNFR ID - # @param [JSON] information about VIM - # Request to execute a lifecycle event - put '/vnf-instances/:vnfr_id/config' do |vnfr_id| - - provisioner, errors = ServiceConfigurationHelper.get_module('vnf_provisioner') - halt 500, errors if errors - - # Return if content-type is invalid - halt 415 unless request.content_type == 'application/json' - - # Read request body - config_info = parse_json(request.body.read) - - # Forward the request to the VNF Provisioning - begin - response = RestClient.put provisioner.host + '/vnf-provisioning/vnf-instances/' + vnfr_id + '/config', config_info.to_json, 'X-Auth-Token' => provisioner.token, :content_type => :json - rescue Errno::ECONNREFUSED - halt 500, 'VNF Provisioning unreachable' - rescue => e - logger.error e.response - halt e.response.code, e.response.body - end - - halt response.code, response.body + halt response.code, response.body + end + + # @method post_vnf_rovisioning_vnf_instances_vnfr_id_config + # @overload post '/vnf-provisioning/vnf-instances/:vnfr_id/config' + # Request to execute a lifecycle event + # @param [String] vnfr_id the VNFR ID + # @param [JSON] information about VIM + # Request to execute a lifecycle event + put '/vnf-instances/:vnfr_id/config' do |vnfr_id| + provisioner, errors = ServiceConfigurationHelper.get_module('vnf_provisioner') + halt 500, errors if errors + + # Return if content-type is invalid + halt 415 unless request.content_type == 'application/json' + + # Read request body + config_info = parse_json(request.body.read) + + # Forward the request to the VNF Provisioning + begin + response = RestClient.put provisioner.host + '/vnf-provisioning/vnf-instances/' + vnfr_id + '/config', config_info.to_json, 'X-Auth-Token' => provisioner.token, :content_type => :json + rescue Errno::ECONNREFUSED + halt 500, 'VNF Provisioning unreachable' + rescue => e + logger.error e.response + halt e.response.code, e.response.body end + halt response.code, response.body + end end From 2aa83a8a05e0aa458062c12ad2b4056d2c1e9f20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Fri, 4 Nov 2016 12:22:25 +0100 Subject: [PATCH 17/35] Updated NS Provisioning and Monitoring in order to use the dependencies correctly --- ns-monitoring/helpers/monitoring.rb | 2 +- ns-provisioning/helpers/hot.rb | 5 +- ns-provisioning/helpers/mapping.rb | 48 ++++++++++++------ ns-provisioning/helpers/ns.rb | 76 ++++++++++++----------------- ns-provisioning/models/nsr.rb | 1 + ns-provisioning/routes/ns.rb | 10 ++-- 6 files changed, 73 insertions(+), 69 deletions(-) diff --git a/ns-monitoring/helpers/monitoring.rb b/ns-monitoring/helpers/monitoring.rb index 4a54431..54e386d 100644 --- a/ns-monitoring/helpers/monitoring.rb +++ b/ns-monitoring/helpers/monitoring.rb @@ -133,7 +133,7 @@ def self.subcriptionThread(monitoring) def self.startSubcription logger.info 'Getting list of instances...' begin - response = RestClient.get Sinatra::Application.settings.ns_provisioner + '/ns-instances', content_type: :json + response = RestClient.get Sinatra::Application.settings.manager + '/ns-instances', content_type: :json @ns_instances = JSON.parse(response) logger.info 'Creating a monitoring thread for each instance...' diff --git a/ns-provisioning/helpers/hot.rb b/ns-provisioning/helpers/hot.rb index bc4d688..2b19977 100644 --- a/ns-provisioning/helpers/hot.rb +++ b/ns-provisioning/helpers/hot.rb @@ -72,11 +72,8 @@ def sendStack(url, tenant_id, template, tenant_token) return 500, error rescue RestClient::ExceptionWithResponse => e logger.error e - logger.error e.response.body - return e.response.code, e.response.body - rescue RestClient::ExceptionWithResponse => e - # logger.error e logger.error e.response + logger.error e.response.body if e.response error = { 'info' => 'Error creating the network stack.' } return 500, error end diff --git a/ns-provisioning/helpers/mapping.rb b/ns-provisioning/helpers/mapping.rb index 33884d9..98bc688 100644 --- a/ns-provisioning/helpers/mapping.rb +++ b/ns-provisioning/helpers/mapping.rb @@ -22,17 +22,20 @@ module MappingHelper # @param [JSON] Microservice information # @return [Hash, nil] if the parsed message is a valid JSON # @return [Hash, String] if the parsed message is an invalid JSON - def callMapping(ms, _nsd) + def callMapping(mapping_host, ms, _nsd) begin - response = RestClient.post settings.mapping + '/mapper', ms.to_json, content_type: :json - rescue => e - logger.error e - if defined?(e.response).nil? - # halt 400, "NS-Mapping unavailable" - end - return 500, 'Service Mapping error.' - # halt e.response.code, e.response.body - end + response = RestClient.post mapping_host, ms.to_json, content_type: :json + # response = RestClient.post settings.mapping + '/mapper', ms.to_json, content_type: :json + rescue => e + logger.error e + if defined?(e.response).nil? + # halt 400, "NS-Mapping unavailable" + end + logger.error e.response + return 500, 'Service Mapping error.' + # halt e.response.code, e.response.body + end + logger.info response mapping, errors = parse_json(response.body) return 400, errors if errors @@ -50,14 +53,27 @@ def getMappingResponse(nsd, pop_id) mapping = { 'created_at' => 'Thu Nov 5 10:13:25 2015', 'links_mapping' => - [ - { - 'vld_id' => 'vld1', - 'maps_to_link' => '/pop/link/85b0bc34-dff0-4399-8435-4fb2ed65790a' - } - ], + [ + { + 'vld_id' => 'vld1', + 'maps_to_link' => '/pop/link/85b0bc34-dff0-4399-8435-4fb2ed65790a' + } + ], 'vnf_mapping' => vnf_mapping } mapping end + + def replace_pop_name_by_pop_id(mapping, pops) + mapping['vnf_mapping'].each do |m| + found_pops = pops.find{ |q| q['name'] == m['maps_to_PoP'].split("/pop/")[1] } + puts found_pops + if found_pops.nil? + return 400, "The PoP from Mapping cannot be matched to a PoP in TeNOR." + else + m['maps_to_PoP'] = "/pop/" + pops.find{ |q| q['name'] == m['maps_to_PoP'].split("/pop/")[1] }['id'].to_s + end + end + mapping + end end diff --git a/ns-provisioning/helpers/ns.rb b/ns-provisioning/helpers/ns.rb index bf6b66c..615ec9e 100644 --- a/ns-provisioning/helpers/ns.rb +++ b/ns-provisioning/helpers/ns.rb @@ -145,6 +145,7 @@ def recoverState(instance, _error) end logger.info 'REMOVED: User ' + auth_info['user_id'].to_s + " and tenant '" + auth_info['tenant_id'].to_s end + logger.debug "Tenants and users removed correctly." message = { code: 200, @@ -167,69 +168,53 @@ def instantiate(instance, nsd, instantiation_info) callback_url = @instance['notification'] flavour = @instance['service_deployment_flavour'] pop_list = instantiation_info['pop_list'] - # pop_id = instantiation_info['pop_id'] - mapping_id = instantiation_info['mapping_id'] + mapping_info = instantiation_info['mapping'] nap_id = instantiation_info['nap_id'] customer_id = instantiation_info['customer_id'] + infr_repo_url = instantiation_info['infr_repo_url'] slaInfo = nsd['sla'].find { |sla| sla['sla_key'] == flavour } if slaInfo.nil? - return generateMarketplaceResponse(callbackUrl, generateError(nsd['id'], 'FAILED', 'Internal error: SLA inconsistency')) + return handleError(@instance, 'Internal error: SLA inconsistency') end sla_id = nsd['sla'].find { |sla| sla['sla_key'] == flavour }['id'] logger.debug 'SLA id: ' + sla_id - infr_repo_url = if settings.environment == 'development' - { 'host' => '', 'port' => '' } - else - settings.infr_repository - end - - pop_list_ids = [] - pop_list.map do |hash| - pop_list_ids << { id: hash['id'] } - end - logger.info 'List of available PoPs: ' + pop_list_ids.to_s - if pop_list.size == 1 || mapping_id.nil? + if pop_list.size == 1 && mapping_info.empty? pop_id = pop_list[0]['id'] - elsif !mapping_id.nil? - # call specified mapping with the id - # TODO - end - - if !pop_id.nil? - logger.debug 'Deploy to PoP id: ' + pop_id.to_s + logger.info 'Deploy to PoP id: ' + pop_id.to_s mapping = getMappingResponse(nsd, pop_id) - else + elsif !mapping_info.empty? + logger.info "Calling Mapping algorithm " + logger.info mapping_info + if infr_repo_url.nil? + return handleError(@instance, 'Internal error: Infrastructure Repository not reachable.') + end + ms = { NS_id: nsd['id'], - tenor_api: settings.manager, - infr_repo_api: infr_repo_url, - development: true, NS_sla: sla_id, - overcommitting: 'true' + tenor_api: settings.manager, + infr_repo_api: infr_repo_url#, + #development: true, + #overcommitting: 'true' } - mapping, errors = callMapping(ms, nsd) - # mapping Mapper PoPs with gatekeeper PoPs. - return generateMarketplaceResponse(callback_url, generateError(nsd['id'], 'FAILED', 'Internal error: Mapping not reachable.')) if errors + logger.info ms + mapping, errors = callMapping(mapping_info, ms, nsd) + if mapping['vnf_mapping'] + mapping, errors = replace_pop_name_by_pop_id(mapping, pop_list) + return handleError(@instance, errors) if errors + else + return handleError(@instance, 'Internal error: Mapping: not enough resources.') + end + return handleError(@instance, 'Internal error: Mapping not reachable.') if errors end @instance.update_attribute('mapping_time', DateTime.now.iso8601(3).to_s) - - unless mapping['vnf_mapping'] - generateMarketplaceResponse(callback_url, generateError(nsd['id'], 'FAILED', 'Internal error: Mapping: not enough resources.')) - return - end - - if @instance.nil? - generateMarketplaceResponse(callback_url, generateError(nsd['id'], 'FAILED', 'Internal error: instance is null.')) - return - end - @instance.push(lifecycle_event_history: 'MAPPED FOUND') @instance['vnfrs'] = [] - @instance['authentication'] = [] + #@instance['authentication'] = [] # if mapping of all VNFs are in the same PoP. Create Authentication and network 1 time mapping['vnf_mapping'].each do |vnf| @@ -243,7 +228,8 @@ def instantiate(instance, nsd, instantiation_info) next unless authentication.nil? pop_auth, errors = create_authentication(@instance, nsd['id'], pop_info, callback_url) return handleError(@instance, errors) if errors - @instance['authentication'] << pop_auth + #@instance['authentication'] << pop_auth + @instance.push(authentication: pop_auth) end logger.info 'Authentication generated' @@ -330,7 +316,7 @@ def instantiate(instance, nsd, instantiation_info) hot, errors = generateNetworkHotTemplate(sla_id, hot_generator_message) return handleError(@instance, errors) if errors - logger.info 'Send network template to HEAT Orchestration' + logger.info 'Sending network template to HEAT Orchestration' stack_name = 'network_' + @instance['id'].to_s template = { stack_name: stack_name, template: hot } stack, errors = sendStack(popUrls[:orch], pop_auth['tenant_id'], template, tenant_token) @@ -390,9 +376,9 @@ def instantiate(instance, nsd, instantiation_info) @instance.push(resource_reservation: resource_reservation) end + #instantiate each VNF @instance.update_attribute('status', 'INSTANTIATING VNFs') vnfrs = [] - # for each VNF, instantiate mapping['vnf_mapping'].each do |vnf| response, errors = instantiate_vnf(@instance, nsd['id'], vnf, slaInfo) return handleError(@instance, errors) if errors diff --git a/ns-provisioning/models/nsr.rb b/ns-provisioning/models/nsr.rb index ec2324e..c928259 100644 --- a/ns-provisioning/models/nsr.rb +++ b/ns-provisioning/models/nsr.rb @@ -52,5 +52,6 @@ class Nsr field :mapping_time, type: Time field :instantiation_start_time, type: Time field :instantiation_end_time, type: Time + field :authentication, type: Array end diff --git a/ns-provisioning/routes/ns.rb b/ns-provisioning/routes/ns.rb index 95b9d42..1607e1c 100644 --- a/ns-provisioning/routes/ns.rb +++ b/ns-provisioning/routes/ns.rb @@ -81,7 +81,8 @@ class Provisioner < NsProvisioning notification: instantiation_info['callback_url'], lifecycle_event_history: ['INIT'], audit_log: [], - marketplace_callback: instantiation_info['callback_url'] + marketplace_callback: instantiation_info['callback_url'], + authentication: [] } @instance = Nsr.new(instance) @@ -140,14 +141,17 @@ class Provisioner < NsProvisioning logger.info 'Pop_id: ' + vnf['pop_id'].to_s raise 'VNF not defined' if vnf['pop_id'].nil? - popInfo, errors = getPopInfo(vnf['pop_id']) + pop_info, errors = getPopInfo(vnf['pop_id']) + logger.errors if errors raise 400, errors if errors - if popInfo == 400 + if pop_info == 400 logger.error 'Pop id no exists.' return end + logger.error @nsInstance['authentication'] + pop_auth = @nsInstance['authentication'].find { |pop| pop['pop_id'] == vnf['pop_id'] } popUrls = pop_auth['urls'] callback_url = settings.manager + '/ns-instances/' + @instance['id'] From 4c1e1c05cfabb300cbe52395e8c2a5364fe8bcce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Fri, 4 Nov 2016 13:06:10 +0100 Subject: [PATCH 18/35] VNF Provisining fix start when mapi is not reachable --- vnf-provisioning/routes/vnf.rb | 62 +++++++--------------------------- 1 file changed, 13 insertions(+), 49 deletions(-) diff --git a/vnf-provisioning/routes/vnf.rb b/vnf-provisioning/routes/vnf.rb index 6a5ead5..e71b773 100644 --- a/vnf-provisioning/routes/vnf.rb +++ b/vnf-provisioning/routes/vnf.rb @@ -133,13 +133,16 @@ class Provisioning < VnfProvisioning end hot_generator_message['flavours'] = flavors end + begin hot = parse_json(RestClient.post(settings.hot_generator + '/hot/' + vnf_flavour, hot_generator_message.to_json, content_type: :json, accept: :json)) rescue Errno::ECONNREFUSED halt 500, 'HOT Generator unreachable' rescue => e - logger.error e.response - halt e.response.code, e.response.body + logger.error e + logger.error e.response if e.response + halt e.response.code, e.response.body if e.response + halt 500, e end logger.debug 'HEAT template generated' @@ -148,14 +151,15 @@ class Provisioning < VnfProvisioning response = provision_vnf(vim_info, vnf['vnfd']['name'].delete(' ') + '_' + vnfr.id, hot) logger.debug 'Provision response: ' + response.to_json + # Update the VNFR + vnfr.push(lifecycle_event_history: 'CREATE_IN_PROGRESS') + + # save the VNF information into the VNFR vdu = [] vnf['vnfd']['vdu'].each do |v| vdu << { id: v['id'], alias: v['alias'] } end - # Update the VNFR - vnfr.push(lifecycle_event_history: 'CREATE_IN_PROGRESS') - vlrs = [] vnf['vnfd']['vlinks'].each do |vlink| vlrs << { id: vlink['id'], alias: vlink['alias'] } @@ -223,17 +227,9 @@ class Provisioning < VnfProvisioning callback_url = destroy_info['callback_url'] # if the stack contains nested templates, remove nesed before - # resources = getStackResources(vnfr.stack_url, auth_token) - # resources.each do |resource| - # next unless resource['resource_type'] == 'OS::Heat::AutoScalingGroup' - # next unless resource['links'].find { |link| link['rel'] == 'nested' } - # stack_url = resource['links'].find { |link| link['rel'] == 'nested' }['href'] - # response = delete_stack_with_wait(stack_url, auth_token) - # logger.debug 'VIM response to destroy the AutoScalingGroup: ' + response.to_json - # end vnfr['scale_resources'].each do |resource| stack_url = resource['stack_url'] - logger.info 'Sending request to Openstack for Remove scaled resources' + logger.info 'Sending request to Openstack for Remove scaled resource' response, errors = delete_stack_with_wait(stack_url, vim_info['token']) vnfr.pull(scale_resources: resource) logger.info 'Removed scaled resources.' @@ -288,7 +284,7 @@ class Provisioning < VnfProvisioning # Return if event doesn't have information halt 400, 'Event has no information' if vnfr.lifecycle_info['events'][config_info['event']].nil? - halt 200, 'mAPI not defined. No execution performed.' if settings.mapi.nil? + halt 400, 'mAPI not defined. No execution performed.' if settings.mapi.nil? # Build mAPI request mapi_request = { @@ -396,38 +392,6 @@ class Provisioning < VnfProvisioning private_key = output['output_value'] elsif output['output_key'] =~ /^.*#id$/i vms_id[output['output_key'].match(/^(.*)#id$/i)[1]] = output['output_value'] - # elsif output['output_key'] =~ /^.*#scale_in_url/i - # scale_resource = auto_scale_resources.find { |res| res[:vdu] == output['output_key'].match(/^(.*)#scale_in_url/i)[1] } - # if scale_resource.nil? - # auto_scale_resources << { vdu: output['output_key'].match(/^(.*)#scale_in_url/i)[1], scale_in: output['output_value'] } - # else - # scale_resource[:scale_in] = output['output_value'] - # end - # elsif output['output_key'] =~ /^.*#scale_out_url/i - # scale_resource = auto_scale_resources.find { |res| res[:vdu] == output['output_key'].match(/^(.*)#scale_out_url/i)[1] } - # if scale_resource.nil? - # auto_scale_resources << { vdu: output['output_key'].match(/^(.*)#scale_out_url/i)[1], scale_out: output['output_value'] } - # else - # scale_resource[:scale_out] = output['output_value'] - # end - # elsif output['output_key'] =~ /^.*#scale_group/i - # scale_resource = auto_scale_resources.find { |res| res[:vdu] == output['output_key'].match(/^(.*)#scale_group/i)[1] } - # if scale_resource.nil? - # auto_scale_resources << { vdu: output['output_key'].match(/^(.*)#scale_group/i)[1], id: output['output_value'] } - # else - # scale_resource[:id] = output['output_value'] - # end - # elsif output['output_key'] =~ /^.*#vdus/i - # vms_id[output['output_key']] = output['output_value'] - # elsif output['output_key'] =~ /^.*#networks/i - # # TODO - # # scale_resource = auto_scale_resources.find { |res| res[:vdu] == output['output_key'].match(/^(.*)#networks/i)[1] } - # # if scale_resource.nil? - # # auto_scale_resources << {:vdu => output['output_key'].match(/^(.*)#scale_out_url/i)[1], :networks => output['output_value']} - # # else - # # scale_resource[:networks] = output['output_value'] - # # end - # # vnf_addresses[output['output_key']] = output['output_value'] else if output['output_key'] =~ /^.*#PublicIp$/i @@ -438,11 +402,11 @@ class Provisioning < VnfProvisioning vnfr.lifecycle_info['events'].each do |event, event_info| next if event_info.nil? JSON.parse(event_info['template_file']).each do |id, parameter| - logger.debug parameter + #logger.debug parameter parameter_match = parameter.delete(' ').match(/^get_attr\[(.*)\]$/i).to_a string = parameter_match[1].split(',').map(&:strip) key_string = string.join('#') - logger.debug 'Key string: ' + key_string.to_s + '. Out_key: ' + output['output_key'].to_s + #logger.debug 'Key string: ' + key_string.to_s + '. Out_key: ' + output['output_key'].to_s if string[1] == 'PublicIp' # DEPRECATED: to be removed when all VNF developers uses the new form vnf_addresses[output['output_key']] = output['output_value'] lifecycle_events_values[event] = {} unless lifecycle_events_values.key?(event) From b954afdebdcbfce6961822ba6d609db50e4384c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Fri, 4 Nov 2016 13:38:21 +0100 Subject: [PATCH 19/35] Updated sample files with localhost config for rspec. Removed unused files --- ns-catalogue/config/config.yml.sample | 1 + ns-manager/routes/config.rb | 1 + ns-provisioning/config/config.yml.sample | 3 +++ tenor_install.sh | 1 + ui/app.rb | 5 +---- ui/app/scripts/controllers/popController.js | 9 ++++++++- vnf-catalogue/config/config.yml.sample | 1 + vnf-manager/models/service.rb | 3 +++ vnf-manager/models/serviceModel.rb | 11 ----------- vnf-manager/routes/configs.rb | 1 + 10 files changed, 20 insertions(+), 16 deletions(-) delete mode 100644 vnf-manager/models/serviceModel.rb diff --git a/ns-catalogue/config/config.yml.sample b/ns-catalogue/config/config.yml.sample index ffa69b8..3e0ee87 100644 --- a/ns-catalogue/config/config.yml.sample +++ b/ns-catalogue/config/config.yml.sample @@ -12,4 +12,5 @@ threaded: true logger_host: 127.0.0.1 logger_port: 24224 +nsd_validator: localhost:4015 dependencies: [nsd_validator] diff --git a/ns-manager/routes/config.rb b/ns-manager/routes/config.rb index 9656a14..0b4e9cd 100644 --- a/ns-manager/routes/config.rb +++ b/ns-manager/routes/config.rb @@ -94,6 +94,7 @@ class ServiceConfiguration < TnovaManager rescue Mongoid::Errors::DocumentNotFound => e Service.create!(serv) rescue => e + logger.error e logger.error 'Error saving service.' halt 404 end diff --git a/ns-provisioning/config/config.yml.sample b/ns-provisioning/config/config.yml.sample index 9c1ecbe..ef586e1 100644 --- a/ns-provisioning/config/config.yml.sample +++ b/ns-provisioning/config/config.yml.sample @@ -18,6 +18,9 @@ default_user_name: tenor_user default_user_password: secretsecret default_tenant_name: tenor_tenant +ns_monitoring: localhost:4014 +vnf_manager: localhost:4567 +hot_generator: localhost:4571 dependencies: [ns_monitoring, vnf_manager, wicm, mAPI, mapping, hot_generator, infr_repository, netfloc] netfloc: diff --git a/tenor_install.sh b/tenor_install.sh index e04d17a..f024472 100755 --- a/tenor_install.sh +++ b/tenor_install.sh @@ -241,6 +241,7 @@ configureFiles(){ configureIps $1 + printf "Removing old config files...." rm **/config/config.yml for folder in $(find . -type d \( -name "ns*" -o -name "vnf*" -o -name "hot-generator" \) ); do diff --git a/ui/app.rb b/ui/app.rb index 93e856a..2e9d154 100644 --- a/ui/app.rb +++ b/ui/app.rb @@ -8,8 +8,6 @@ class App < Sinatra::Base configure do #set :root, File.dirname(__FILE__) set :public_folder, 'app' - set :admin_user_uid, 1 - set :admin_user_passwd, "Eq7K8h9gpg" end configure :development do @@ -33,9 +31,8 @@ class App < Sinatra::Base end get '/bower_components/*' do - puts "Bower" tpl = 'bower_components/' + params[:splat][0] File.read(File.join('bower_components', params[:splat][0])) end -end \ No newline at end of file +end diff --git a/ui/app/scripts/controllers/popController.js b/ui/app/scripts/controllers/popController.js index c32d5be..b80ca44 100644 --- a/ui/app/scripts/controllers/popController.js +++ b/ui/app/scripts/controllers/popController.js @@ -16,10 +16,14 @@ angular.module('tNovaApp') $scope.neutron_version = "v2.0" $scope.openstack_ip = ""; + $scope.infr_repo_url = undefined tenorService.get("modules/services/type/infr_repo").then(function (data) { if (data === undefined) return; - $scope.infr_repo_url = data[0].host + ":" + data[0].port; + console.log(data); + if (data.length > 0){ + $scope.infr_repo_url = data[0].host + ":" + data[0].port; + } $scope.refreshPoPList(); }); @@ -34,6 +38,9 @@ angular.module('tNovaApp') }) });*/ console.log($scope.registeredDcList); + if ($scope.infr_repo_url == undefined){ + return; + } var url = 'pop/'; infrRepoService.get($scope.infr_repo_url, url).then(function (_data) { diff --git a/vnf-catalogue/config/config.yml.sample b/vnf-catalogue/config/config.yml.sample index 83ad67f..971fbda 100644 --- a/vnf-catalogue/config/config.yml.sample +++ b/vnf-catalogue/config/config.yml.sample @@ -12,4 +12,5 @@ threaded: true logger_host: 127.0.0.1 logger_port: 24224 +vnfd_validator: localhost:4570 dependencies: [vnfd_validator] diff --git a/vnf-manager/models/service.rb b/vnf-manager/models/service.rb index 9571f1d..f8161a4 100644 --- a/vnf-manager/models/service.rb +++ b/vnf-manager/models/service.rb @@ -5,6 +5,9 @@ class Service validates :name, presence: true, uniqueness: true field :host, type: String field :port, type: String + field :path, type: String field :token, type: String field :depends_on, type: Array, default: [] + field :type, type: String + field :status, type: String end diff --git a/vnf-manager/models/serviceModel.rb b/vnf-manager/models/serviceModel.rb deleted file mode 100644 index 707b164..0000000 --- a/vnf-manager/models/serviceModel.rb +++ /dev/null @@ -1,11 +0,0 @@ -class ServiceModel - - include Mongoid::Document - - field :name, type: String - field :host, type: String - field :port, type: String - field :path, type: String - field :service_key, type: String - index({:name => 1}, {unique: true}) -end diff --git a/vnf-manager/routes/configs.rb b/vnf-manager/routes/configs.rb index 0057883..ef5ef48 100644 --- a/vnf-manager/routes/configs.rb +++ b/vnf-manager/routes/configs.rb @@ -84,6 +84,7 @@ class ServiceConfiguration < VNFManager rescue Mongoid::Errors::DocumentNotFound => e Service.create!(serv) rescue => e + logger.error e logger.error 'Error saving service.' halt 404 end From bd01fb1ecfc5d400cb77e8056241243b1b37231b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Fri, 4 Nov 2016 14:14:02 +0100 Subject: [PATCH 20/35] Remove logger error in NS Provisioning --- ns-provisioning/routes/ns.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/ns-provisioning/routes/ns.rb b/ns-provisioning/routes/ns.rb index 1607e1c..e848e46 100644 --- a/ns-provisioning/routes/ns.rb +++ b/ns-provisioning/routes/ns.rb @@ -150,8 +150,6 @@ class Provisioner < NsProvisioning return end - logger.error @nsInstance['authentication'] - pop_auth = @nsInstance['authentication'].find { |pop| pop['pop_id'] == vnf['pop_id'] } popUrls = pop_auth['urls'] callback_url = settings.manager + '/ns-instances/' + @instance['id'] From 92d2c66a0068fb7fd2531e9803cafa1484d8ffd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Fri, 4 Nov 2016 14:14:48 +0100 Subject: [PATCH 21/35] End to end tests script updated --- end_to_end.rb | 11 ++- ns-provisioning/helpers/pop.rb | 20 ----- ui/apis/gk.rb | 144 --------------------------------- 3 files changed, 5 insertions(+), 170 deletions(-) delete mode 100644 ui/apis/gk.rb diff --git a/end_to_end.rb b/end_to_end.rb index 7be2b2c..348f1ae 100644 --- a/end_to_end.rb +++ b/end_to_end.rb @@ -13,7 +13,7 @@ @OPENSTACK_DNS = ENV['OPENSTACK_DNS'] if @OPENSTACK_HOST.nil? - puts "Execute the environment script! (. ./end_to_end_env.sh)" + puts "Execute the environment script! (. ./env_end_to_end.sh)" exit end @@ -41,7 +41,7 @@ def end_to_end_script() puts "Removing PoPs if exists...." pops_names = ["admin_v2", "admin_v3", "non_admin_v2", "non_admin_v3"] pops_names.each do |pop| - remove_pops_if_exists(pop) + #remove_pops_if_exists(pop) end puts "All PoPs are removed\n" @@ -121,6 +121,7 @@ def end_to_end_script() puts errors if errors recover_state(errors) if errors @e2e[:instances] << {:id => ns_instance_id, :status => "INIT"} + break end pop = @e2e[:pops].find { |p| p[:name] == "admin_v2"} #ns_instance, errors = create_instance(pop[:id]) @@ -150,7 +151,7 @@ def end_to_end_script() if @e2e[:instances].find {|ins| ins[:status] != "INSTANTIATED"} next else - puts "All instantiated???" + puts "All instances are INSTANTIATED" counter = 30 break end @@ -164,7 +165,7 @@ def end_to_end_script() puts "All instances created correctly..." - puts "Removing..." + puts "Start removing of instances..." @e2e[:instances].each do |instances| delete_instance(instances[:id]) @@ -300,8 +301,6 @@ def delete_descriptors() end puts "Remving VNFD...." if !@e2e[:vnfd_id].nil? - puts @e2e[:vnfd_id].to_s - puts "#{@tenor}/vnfs/" + @e2e[:vnfd_id].to_s begin response = RestClient.delete "#{@tenor}/vnfs/" + @e2e[:vnfd_id].to_s rescue => e diff --git a/ns-provisioning/helpers/pop.rb b/ns-provisioning/helpers/pop.rb index 78c0a88..bccf39d 100644 --- a/ns-provisioning/helpers/pop.rb +++ b/ns-provisioning/helpers/pop.rb @@ -68,26 +68,6 @@ def getPopUrls(extraInfo) popUrls end - # Returns all the registered PoPs - # - # @return [Hash, nil] if the parsed message is a valid JSON - # @return [Hash, String] if the parsed message is an invalid JSON - def getPops - begin - response = RestClient.get "#{settings.manager}/gatekeeper/dc", content_type: :json - rescue => e - logger.error e - logger.error 'PoP no exists?' - return 400, 'no exists' - end - popInfo, errors = parse_json(response) - return 400, errors if errors - - logger.error popInfo - - popInfo - end - # Returns an object with the properties of a PoP # @param [string] The extra information in string # @return [Hash] The PoP information in hash format diff --git a/ui/apis/gk.rb b/ui/apis/gk.rb deleted file mode 100644 index 9f2c899..0000000 --- a/ui/apis/gk.rb +++ /dev/null @@ -1,144 +0,0 @@ -require 'sinatra/base' -require 'json' -require 'rest-client' - -class App::Gk < Sinatra::Base - - get '/rest/gk/api/*' do - - host = request.env["HTTP_X_HOST"] - token = request.env["HTTP_X_AUTH_TOKEN"] - - begin - response = RestClient.get host + "/" + params[:splat][0], :content_type => :json, :'X-Auth-Token' => token - rescue Errno::ECONNREFUSED - halt 500, "Errno::ECONNREFUSED" - rescue RestClient::Unauthorized => e - puts e - halt 401, "Unauthorized" - rescue => e - puts "ERROR" - puts e - halt 400 - end - return response - end - - post '/rest/gk/api/token/' do - - host = request.env["HTTP_X_HOST"] - username = request.env["HTTP_X_AUTH_UID"] - passwd = request.env["HTTP_X_AUTH_PASSWORD"] - - #given user name, look database - admin_user = {:uid => App.admin_user_uid, :passwd => App.admin_user_passwd} - admin_token = loginToGk(host, admin_user) - users_list, users_ids = getListUsers(host, admin_token) - index_position = users_list.find_index { |name| name == username } - if index_position.nil? - puts "User not found." - halt 400, "User not found" - end - uid = users_ids[index_position] - - begin - response = RestClient.post host + "/token/", "", :content_type => :json, :'X-Auth-Uid' => uid, :'X-Auth-Password' => passwd - rescue Errno::ECONNREFUSED - halt 500, "Errno::ECONNREFUSED" - rescue => e - puts "ERROR" - puts e - halt 400, "Login failed." - end - response = JSON.parse(response) - response['uid'] = uid - return response.to_json - end - - post '/rest/gk/api/*' do - - host = request.env["HTTP_X_HOST"] - token = request.env["HTTP_X_AUTH_TOKEN"] - body = request.body.read - - begin - response = RestClient.post host + "/" + params[:splat][0], body, :content_type => :json, :'X-Auth-Token' => token - rescue Errno::ECONNREFUSED - halt 500, "Errno::ECONNREFUSED" - rescue => e - puts "ERROR" - puts e - halt e.response.code, e.response.body - end - return response - end - - put '/rest/gk/api/*' do - - host = request.env["HTTP_X_HOST"] - token = request.env["HTTP_X_AUTH_TOKEN"] - body = request.body.read - - begin - response = RestClient.put host + "/" + params[:splat][0], body, :content_type => :json, :'X-Auth-Token' => token - rescue Errno::ECONNREFUSED - halt 500, "Errno::ECONNREFUSED" - rescue => e - puts "ERROR" - puts e - halt 400 - end - return response - - end - - delete '/rest/gk/api/*' do - - host = request.env["HTTP_X_HOST"] - token = request.env["HTTP_X_AUTH_TOKEN"] - - begin - response = RestClient.delete host + "/" + params[:splat][0], :content_type => :json, :'X-Auth-Token' => token - rescue Errno::ECONNREFUSED - halt 500, "Errno::ECONNREFUSED" - rescue => e - puts "ERROR" - puts e - halt 400 - end - return response - - end - - def loginToGk(host, user) - puts host + "/token/" - puts user[:uid] - puts user[:passwd] - begin - response = RestClient.post host + "/token/", "", :content_type => :json, :'X-Auth-Uid' => user[:uid], :'X-Auth-Password' => user[:passwd] - rescue Errno::ECONNREFUSED - halt 500, "Errno::ECONNREFUSED" - rescue => e - puts "ERROR" - puts e.response - halt 400 - end - response = JSON.parse(response) - return response['token']['id'] - end - - def getListUsers(host, token) - begin - response = RestClient.get host + "/admin/user/", :content_type => :json, :'X-Auth-Token' => token - rescue Errno::ECONNREFUSED - halt 500, "Errno::ECONNREFUSED" - rescue => e - puts "ERROR" - puts e - halt 400 - end - response = JSON.parse(response) - return response['userlist'], response['userids'] - end - -end From 87dd76873c18fc5d774d21d20e10fed829017a0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Mon, 7 Nov 2016 10:36:22 +0100 Subject: [PATCH 22/35] UI: uploaded file can be edited in the modal. --- .../bower_components/jsoneditor/.bower.json | 43 + .../jsoneditor/CONTRIBUTING.md | 15 + ui/app/bower_components/jsoneditor/HISTORY.md | 563 + ui/app/bower_components/jsoneditor/LICENSE | 176 + ui/app/bower_components/jsoneditor/NOTICE | 17 + ui/app/bower_components/jsoneditor/README.md | 155 + ui/app/bower_components/jsoneditor/bower.json | 32 + .../jsoneditor/dist/img/jsoneditor-icons.svg | 893 + .../jsoneditor/dist/jsoneditor-minimalist.js | 9747 +++++ .../jsoneditor/dist/jsoneditor-minimalist.map | 1 + .../dist/jsoneditor-minimalist.min.js | 35 + .../jsoneditor/dist/jsoneditor.css | 929 + .../jsoneditor/dist/jsoneditor.js | 36373 ++++++++++++++++ .../jsoneditor/dist/jsoneditor.js.map | 1 + .../jsoneditor/dist/jsoneditor.map | 1 + .../jsoneditor/dist/jsoneditor.min.css | 1 + .../jsoneditor/dist/jsoneditor.min.js | 49 + .../jsoneditor/dist/which files do I need.md | 41 + .../bower_components/jsoneditor/docs/api.md | 294 + .../jsoneditor/docs/shortcut_keys.md | 38 + .../bower_components/jsoneditor/docs/usage.md | 117 + .../jsoneditor/examples/01_basic_usage.html | 49 + .../jsoneditor/examples/02_viewer.html | 44 + .../jsoneditor/examples/03_switch_mode.html | 66 + .../jsoneditor/examples/04_load_and_save.html | 75 + .../examples/05_custom_fields_editable.html | 63 + .../examples/06_custom_styling.html | 51 + .../examples/07_json_schema_validation.html | 71 + .../jsoneditor/examples/css/darktheme.css | 76 + .../requirejs_demo/requirejs_demo.html | 21 + .../examples/requirejs_demo/scripts/main.js | 25 + .../requirejs_demo/scripts/require.js | 36 + ui/app/bower_components/jsoneditor/index.js | 1 + .../bower_components/jsoneditor/package.json | 42 + .../jsoneditor/src/css/contextmenu.css | 244 + .../jsoneditor/src/css/img/description.txt | 14 + .../src/css/img/jsoneditor-icons.svg | 893 + .../jsoneditor/src/css/jsoneditor.css | 449 + .../jsoneditor/src/css/menu.css | 110 + .../jsoneditor/src/css/reset.css | 25 + .../jsoneditor/src/css/searchbox.css | 77 + .../src/docs/which files do I need.md | 41 + .../jsoneditor/src/js/ContextMenu.js | 460 + .../jsoneditor/src/js/Highlighter.js | 86 + .../jsoneditor/src/js/History.js | 267 + .../jsoneditor/src/js/JSONEditor.js | 385 + .../jsoneditor/src/js/ModeSwitcher.js | 115 + .../jsoneditor/src/js/Node.js | 3530 ++ .../jsoneditor/src/js/SearchBox.js | 316 + .../jsoneditor/src/js/ace/index.js | 9 + .../jsoneditor/src/js/ace/theme-jsoneditor.js | 144 + .../jsoneditor/src/js/appendNodeFactory.js | 229 + .../src/js/assets/jsonlint/README.md | 15 + .../src/js/assets/jsonlint/jsonlint.js | 418 + .../jsoneditor/src/js/header.js | 29 + .../jsoneditor/src/js/textmode.js | 491 + .../jsoneditor/src/js/treemode.js | 1198 + .../jsoneditor/src/js/util.js | 778 + .../ng-jsoneditor/.bower.json | 36 + ui/app/bower_components/ng-jsoneditor/LICENSE | 202 + .../bower_components/ng-jsoneditor/README.md | 98 + .../bower_components/ng-jsoneditor/bower.json | 25 + .../ng-jsoneditor/ng-jsoneditor.js | 105 + .../ng-jsoneditor/ng-jsoneditor.min.js | 1 + .../ng-jsoneditor/ng-jsoneditor.min.min.js | 1 + ui/app/index.html | 3 + ui/app/scripts/app.js | 2 +- ui/app/scripts/controllers/nsController.js | 25 +- ui/app/scripts/controllers/vnfController.js | 19 +- ui/app/scripts/directives/modalScroll.js | 8 +- ui/app/views/t-nova/modals/upload.html | 7 +- ui/bower.json | 4 +- 72 files changed, 60979 insertions(+), 21 deletions(-) create mode 100644 ui/app/bower_components/jsoneditor/.bower.json create mode 100644 ui/app/bower_components/jsoneditor/CONTRIBUTING.md create mode 100644 ui/app/bower_components/jsoneditor/HISTORY.md create mode 100644 ui/app/bower_components/jsoneditor/LICENSE create mode 100644 ui/app/bower_components/jsoneditor/NOTICE create mode 100644 ui/app/bower_components/jsoneditor/README.md create mode 100644 ui/app/bower_components/jsoneditor/bower.json create mode 100644 ui/app/bower_components/jsoneditor/dist/img/jsoneditor-icons.svg create mode 100644 ui/app/bower_components/jsoneditor/dist/jsoneditor-minimalist.js create mode 100644 ui/app/bower_components/jsoneditor/dist/jsoneditor-minimalist.map create mode 100644 ui/app/bower_components/jsoneditor/dist/jsoneditor-minimalist.min.js create mode 100644 ui/app/bower_components/jsoneditor/dist/jsoneditor.css create mode 100644 ui/app/bower_components/jsoneditor/dist/jsoneditor.js create mode 100644 ui/app/bower_components/jsoneditor/dist/jsoneditor.js.map create mode 100644 ui/app/bower_components/jsoneditor/dist/jsoneditor.map create mode 100644 ui/app/bower_components/jsoneditor/dist/jsoneditor.min.css create mode 100644 ui/app/bower_components/jsoneditor/dist/jsoneditor.min.js create mode 100644 ui/app/bower_components/jsoneditor/dist/which files do I need.md create mode 100644 ui/app/bower_components/jsoneditor/docs/api.md create mode 100644 ui/app/bower_components/jsoneditor/docs/shortcut_keys.md create mode 100644 ui/app/bower_components/jsoneditor/docs/usage.md create mode 100644 ui/app/bower_components/jsoneditor/examples/01_basic_usage.html create mode 100644 ui/app/bower_components/jsoneditor/examples/02_viewer.html create mode 100644 ui/app/bower_components/jsoneditor/examples/03_switch_mode.html create mode 100644 ui/app/bower_components/jsoneditor/examples/04_load_and_save.html create mode 100644 ui/app/bower_components/jsoneditor/examples/05_custom_fields_editable.html create mode 100644 ui/app/bower_components/jsoneditor/examples/06_custom_styling.html create mode 100644 ui/app/bower_components/jsoneditor/examples/07_json_schema_validation.html create mode 100644 ui/app/bower_components/jsoneditor/examples/css/darktheme.css create mode 100644 ui/app/bower_components/jsoneditor/examples/requirejs_demo/requirejs_demo.html create mode 100644 ui/app/bower_components/jsoneditor/examples/requirejs_demo/scripts/main.js create mode 100644 ui/app/bower_components/jsoneditor/examples/requirejs_demo/scripts/require.js create mode 100644 ui/app/bower_components/jsoneditor/index.js create mode 100644 ui/app/bower_components/jsoneditor/package.json create mode 100644 ui/app/bower_components/jsoneditor/src/css/contextmenu.css create mode 100644 ui/app/bower_components/jsoneditor/src/css/img/description.txt create mode 100644 ui/app/bower_components/jsoneditor/src/css/img/jsoneditor-icons.svg create mode 100644 ui/app/bower_components/jsoneditor/src/css/jsoneditor.css create mode 100644 ui/app/bower_components/jsoneditor/src/css/menu.css create mode 100644 ui/app/bower_components/jsoneditor/src/css/reset.css create mode 100644 ui/app/bower_components/jsoneditor/src/css/searchbox.css create mode 100644 ui/app/bower_components/jsoneditor/src/docs/which files do I need.md create mode 100644 ui/app/bower_components/jsoneditor/src/js/ContextMenu.js create mode 100644 ui/app/bower_components/jsoneditor/src/js/Highlighter.js create mode 100644 ui/app/bower_components/jsoneditor/src/js/History.js create mode 100644 ui/app/bower_components/jsoneditor/src/js/JSONEditor.js create mode 100644 ui/app/bower_components/jsoneditor/src/js/ModeSwitcher.js create mode 100644 ui/app/bower_components/jsoneditor/src/js/Node.js create mode 100644 ui/app/bower_components/jsoneditor/src/js/SearchBox.js create mode 100644 ui/app/bower_components/jsoneditor/src/js/ace/index.js create mode 100644 ui/app/bower_components/jsoneditor/src/js/ace/theme-jsoneditor.js create mode 100644 ui/app/bower_components/jsoneditor/src/js/appendNodeFactory.js create mode 100644 ui/app/bower_components/jsoneditor/src/js/assets/jsonlint/README.md create mode 100644 ui/app/bower_components/jsoneditor/src/js/assets/jsonlint/jsonlint.js create mode 100644 ui/app/bower_components/jsoneditor/src/js/header.js create mode 100644 ui/app/bower_components/jsoneditor/src/js/textmode.js create mode 100644 ui/app/bower_components/jsoneditor/src/js/treemode.js create mode 100644 ui/app/bower_components/jsoneditor/src/js/util.js create mode 100644 ui/app/bower_components/ng-jsoneditor/.bower.json create mode 100644 ui/app/bower_components/ng-jsoneditor/LICENSE create mode 100644 ui/app/bower_components/ng-jsoneditor/README.md create mode 100644 ui/app/bower_components/ng-jsoneditor/bower.json create mode 100644 ui/app/bower_components/ng-jsoneditor/ng-jsoneditor.js create mode 100644 ui/app/bower_components/ng-jsoneditor/ng-jsoneditor.min.js create mode 100644 ui/app/bower_components/ng-jsoneditor/ng-jsoneditor.min.min.js diff --git a/ui/app/bower_components/jsoneditor/.bower.json b/ui/app/bower_components/jsoneditor/.bower.json new file mode 100644 index 0000000..f3869a9 --- /dev/null +++ b/ui/app/bower_components/jsoneditor/.bower.json @@ -0,0 +1,43 @@ +{ + "name": "jsoneditor", + "description": "A web-based tool to view, edit and format JSON", + "tags": [ + "json", + "editor", + "viewer", + "formatter" + ], + "homepage": "http://jsoneditoronline.org/", + "repository": { + "type": "git", + "url": "https://github.com/josdejong/jsoneditor.git" + }, + "main": [ + "./dist/jsoneditor.min.js", + "./dist/jsoneditor.min.css" + ], + "bugs": "https://github.com/josdejong/jsoneditor/issues", + "ignore": [ + "misc", + "node_modules", + "test", + "tools", + "gulpfile.js", + "npm-debug.log", + ".idea", + ".npmignore", + ".gitignore" + ], + "dependencies": {}, + "version": "5.5.10", + "_release": "5.5.10", + "_resolution": { + "type": "version", + "tag": "v5.5.10", + "commit": "4bc339f6fe84afbb23413996d17ff0e9314ea7d8" + }, + "_source": "https://github.com/josdejong/jsoneditor.git", + "_target": "^5.5.10", + "_originalSource": "jsoneditor", + "_direct": true +} \ No newline at end of file diff --git a/ui/app/bower_components/jsoneditor/CONTRIBUTING.md b/ui/app/bower_components/jsoneditor/CONTRIBUTING.md new file mode 100644 index 0000000..110c5df --- /dev/null +++ b/ui/app/bower_components/jsoneditor/CONTRIBUTING.md @@ -0,0 +1,15 @@ +## Contributing + +Contributions to the `jsoneditor` library are very welcome! We can't do this +alone. You can contribute in different ways: spread the word, report bugs, come +up with ideas and suggestions, and contribute to the code. + +There are a few preferences regarding code contributions: + +- `jsoneditor` follows the node.js code style as described + [here](http://nodeguide.com/style.html). +- Send pull requests to the `develop` branch, not the `master` branch. +- Only commit changes done in the source files under `./src`, not to the builds + which are located under the `./dist` folder. + +Thanks! diff --git a/ui/app/bower_components/jsoneditor/HISTORY.md b/ui/app/bower_components/jsoneditor/HISTORY.md new file mode 100644 index 0000000..d651dbd --- /dev/null +++ b/ui/app/bower_components/jsoneditor/HISTORY.md @@ -0,0 +1,563 @@ +# JSON Editor - History + +https://github.com/josdejong/jsoneditor + + +## 2016-11-02, version 5.5.10 + +- Fixed #85: pressing enter in an input in a form containing a JSONEditor too + breaks submitting the form. + + +## 2016-10-17, version 5.5.9 + +- Fixed #329: Editor showing duplicate key warnings for keys defined on the + Object prototype, like `toString` and `watch`. + + +## 2016-09-27, version 5.5.8 + +- Fixed #314: JSON schema validation throwing an error "Unexpected token ' in + JSON at position 0" in specific cases. Thanks @apostrophest + + +## 2016-08-17, version 5.5.7 + +- Fixed #308: wrong positioning of label "empty array" when `onEditable` + returns false. + + +## 2016-06-15, version 5.5.6 + +- Fixed #303: editor contents collapsed when the parent div of the JSONEditor + has no height set. +- Improved example 04_load_and_save.html. Thanks @RDCH106. + + +## 2016-05-24, version 5.5.5 + +- Fixed #298: Switch mode button disappears when switching from text/code to + tree/form/view mode when the JSON contained errors. +- Fixed enum drop downs not working when the JSONEditor is configured with + a name. + + +## 2016-05-22, version 5.5.4 + +- Fixed #285: an issue with the enum drop down when having defined multiple + enums in a JSON schema. +- Fixed a (harmless) error in the console when clicking right from an enum + drop down. + + +## 2016-05-22, version 5.5.3 + +- Fixed #299: reverted the fix of #268 by trimming text in fields and values. + + +## 2016-04-18, version 5.5.2 + +- Fixed #294: Fields reset their caret location on every key press in Firefox. + + +## 2016-04-16, version 5.5.1 + +- Fixed enum select boxes not being rendered/removed when setting or removing + a JSON schema via `editor.setSchema(schema)`. + + +## 2016-04-16, version 5.5.0 + +- Implemented a dropdown for values having an JSON Schema enum. + Thanks @tdakanalis. +- Fixed #291, #292: Some CSS broken when using the editor in combination with + bootstrap. Thanks @nucleartide. + +## 2016-04-09, version 5.4.0 + +- Upgraded all dependencies (`ajv`, `brace`, etc). +- Fixed #289: Some CSS breaking when using the editor in combination with + materialize.css or bootstrap. +- Fixed #290: `setText()` not working in mode text or code. + + +## 2016-04-06, version 5.3.0 + +- Implemented support for sorting object keys naturally. Thanks @edufelipe. +- Sorting object keys or array items via the context menu is now also naturally + sorted. +- Fixed #283: improved JSON schema error message in case of no + additionalProperties. +- Fixed #286: Calling `get()` or `getText()` caused the editor to lose focus. + A regression introduced in v5.2.0. + + +## 2016-03-20, version 5.2.0 + +- Implemented method `editor.destroy()` to properly cleanup the editor (#278). +- Fixed #268: JSONEditor now trims text in fields and values. +- Fixed #280: Some CSS issues when used in combination with bootstrap. + + +## 2016-02-15, version 5.1.5 + +- Fixed #272: Checkbox for boolean values visible in view mode. + + +## 2016-02-13, version 5.1.4 + +- Fixed broken example 04_load_and_save.html. See #265. + + +## 2016-02-03, version 5.1.3 + +- Fixed #264: Clicking items in the context menu not working on Firefox. + + +## 2016-01-21, version 5.1.2 + +- Improvements in sanitizing invalid JSON. +- Updated dependencies to the latest version. +- Fixed clicking format/compact not triggering an onChange event. +- Fixed #259: when having a JSONEditor inside an HTML form, clicking an entry + in the context menu did submit the form. +- Fixed browserify build, see #260. Thanks @onip. + + +## 2016-01-16, version 5.1.1 + +- Fixed #257: Improving error messages for enum errors failed when the + schema contains references. +- Fixed #255: Removed wrong console warning about the option `search`. +- Fixed error thrown when option `search` is false (see #256). Thanks @MiroHibler. + + +## 2016-01-14, version 5.1.0 + +- Implemented support for JSON schema validation, powered by `ajv`. +- Implemented #197: display an error in case of duplicate keys in an object. +- Implemented #183: display a checkbox left from boolean values, so you can + easily switch between true/false. +- Implemented debouncing of keyboard input, resulting in much less history + actions whilst typing. +- Added a minimalist bundle to the `dist` folder, excluding `ace` and `ajv`. +- Fixed #222: editor throwing `onChange` events when switching mode. +- Fixed an error throw when switching to mode "code" via the menu. +- Fixed interfering shortcut keys: changed quick keys to select multiple fields + from `Shift+Arrow Up/Down` to `Ctrl+Shift+Arrow Up/Down`. + + + +## 2015-12-31, version 5.0.1 + +- Fixed a bug in positioning of the context menu for multiple selected nodes. +- Fixed #130: option `onEditable` not available in mode `form`. +- Fixed #202: removed `version` field from bower.json. + + +## 2015-12-31, version 5.0.0 + +- New design. +- Implemented selection of multiple nodes, allowing to move/duplicate/remove + multiple nodes at once (See #106). +- Implemented a new option `escapeUnicode`, which will show the hexadecimal + unicode instead of the character itself. (See #93 and #230). +- Implemented method `getMode`. +- Implemented option `onModeChange(oldMode, newMode)`. +- Implemented #203: Objects and arrays in mode `form` and `view` are now + expandable by clicking the field names too. +- Replaced the PNG icon images with SVG. Thanks @1j01. +- Renamed all CSS classes They now have prefixes `.jsoneditor-` to prevent + name collisions with css frameworks like bootstrap. +- Renamed options `change`, `editable`, `error` to respectively `onChange`, + `onEditable`, and `onError`. Old options are still working and give a + deprecation warning. +- Colors of values are now customizable using CSS. +- JSONEditor new throws a warning in the console in case of unknown options. +- Fixed #93 and #227: html codes like `&` not escaped. +- Fixed #149: Memory leak when switching mode from/to `code` mode, web worker + of Ace editor wasn't cleaned up. +- Fixed #234: Remove dependency on a fork of the `jsonlint` project on github. +- Fixed: disabled `Ctrl+L` quick key to go to a line, instead use the default + browser behavior of selecting the address bar. +- Fixed #38: clear search results after a new JSON object is set. +- Fixed #242: row stays highlighted when dragging outside editor. +- Fixed quick-keys Shift+Alt+Arrows not registering actions in history. +- Fixed #104: context menus are now positioned relative to the elements of the + editor instead of an absolute position in the window. + + +## 2015-06-13, version 4.2.1 + +- Fixed #161: Cannot select text in Ace editor on systems using Chinese fonts. + + +## 2015-05-14, version 4.2.0 + +- Implemented option `theme`, allowing to set a custom theme for the Ace + editor. Thanks @nfvs. +- Implemented option `ace`, which allows to pass a custom instance of the Ace + instead of the embedded version. +- Fixed #186: binding issue to `jsonlint.parse`. +- Fixed `editor.get()` manipulating the code when containing an error. + + +## 2015-03-15, version 4.1.1 + +- Added missing file `index.js` to the bower package. + + +## 2015-03-15, version 4.1.0 + +- Implemented a function `focus()` for modes tree, view, and form. +- Added `./src` folder to the distributed package, needed for usage via + node.js/browserify. + + +## 2015-02-28, version 4.0.0 + +- Ace editor and jsonlint are now packed with jsoneditor.js by default. + This makes the library about 4 times larger. If Ace is not needed, a custom + build of the library can be done. +- The distribution files are now moved from the root to the `/dist` folder. +- Reworked the source code to CommonJS modules, using `brace` to load Ace. +- JSONP is now automatically stripped from JSON. Thanks @yanivefraim. +- Fixed bugs in the JSON sanitizer, no longer manipulating JSON-like structures + inside strings. + + +## 2015-01-25, version 3.2.0 + +- Implemented shortcut keys `Ctrl+\` to format and `Ctrl+Shift+\` to compact + JSON when in mode `text` or `code`. +- Before an error is thrown because of invalid text, the editor first tries to + sanitize the text (replace JavaScript notation with JSON notation), and only + after that throws the error. +- Fixed Node.path() not working for a JSON Object `""`. Thanks @tomalec. +- Minor styling improvements. +- Fixed configured indentation not being applied to Ace editor. + + +## 2014-09-03, version 3.1.2 + +- Some fixes/improvements in `parseJS` (to parse a JSON object from a JavaScript + object). +- Fixed the lack of a semi colon at end of the bundled files. + + +## 2014-08-01, version 3.1.1 + +- Replaced parsing of JavaScript objects into JSON from `eval` to a dedicated + `parseJS` function. + + +## 2014-07-28, version 3.1.0 + +- JSONEditor now accepts JavaScript objects as input, and can turn them into + valid JSON. For example `{a:2,b:'str'}` can be turned into `{"a":2,"b":"str"}`. +- Implemented an option `editable`, a callback function, which allows to set + individual nodes (their field and/or value) editable or read-only. +- Fixed: shortcut keys to manipulate the nodes are now disabled when mode + is `form` or `view`. + + +## 2014-05-31, version 3.0.0 + +- Large code reorganization. +- Editor must be loaded as `new JSONEditor(...)` instead of + `new jsoneditor.JSONEditor(...)`. +- Css is not automatically loaded anymore when using AMD. +- Web application has been moved to another project. + + +## 2014-01-03, version 2.3.6 + +- Fixed positioning issue of the action menu. + + +## 2013-12-09, version 2.3.5 + +- Fixed a positioning issue of the action menu again. +- Fixed an issue with non-breaking space characters. + + +## 2013-11-19, version 2.3.4 + +- Dropped support for IE8, cleaned up legacy code for old browsers. +- Disabled saving files using HTML5 on Firefox to prevent a Firefox bug + blocking cut/paste functionality in editable divs after using a.download. + + +## 2013-10-17, version 2.3.3 + +- Added support for search (Ctrl+F) in the code editor Ace. +- Fixed a positioning issue of the action menu when in bootstrap modal. + (thanks tsash). + + +## 2013-09-26, version 2.3.2 + +- The web application is now available offline. Thanks ayanamist. + + +## 2013-09-24, version 2.3.1 + +- Fixed non-working action menu when in bootstrap modal (z-index issue). +- Fixed missing main field in package.json. + + +## 2013-09-13, version 2.3.0 + +- Implemented an option `modes`, which creates a menu in the editor + where the user can switch between the selected editor modes. +- Fixed wrong title on fields with value `null`. +- Fixed buggy loading of files in the web application. + + +## 2013-08-01, version 2.2.2 + +- Fixed non working option `indentation`. +- Fixed css not being loaded with AMD in case of multiple scripts. +- Fixed a security error in the server side file retriever script of + the web application. + + +## 2013-05-27, version 2.2.1 + +- Fixed undefined options in TextEditor. Thanks Wiseon3. +- Fixed non-working save function on Firefox 21. Thanks youxiachai. + + +## 2013-05-04, version 2.2.0 + +- Unified JSONFormatter and JSONEditor in one editor with a switchable mode. +- Urls are navigable now. +- Improved error and log handling. +- Added jsoneditor to package managers npm and bower. + + +## 2013-03-11, version 2.1.1 + +- Fixed an issue with console outputs on IE8, causing the editor not to work + at all on IE8. + + +## 2013-03-08, version 2.1.0 + +- Replaced the plain text editor with code editor Ace, which brings in syntax + highlighting and code inspection. +- Improved the splitter between the two panels. Panels can be hided. + + +## 2013-02-26, version 2.0.2 + +- Fixed: dragarea of the root node was wrongly visible is removed now. + + +## 2013-02-21, version 2.0.1 + +- Fixed undefined variable in the redo method. +- Removed the "hide ads" button. Not allowed by Google AdSense, sorry. + + +## 2013-02-09, version 2.0.0 + +- Implemented a context menu, replacing the action buttons on the right side of + the editor and the inline action buttons. This gives a cleaner interface, + more space for the actual contents, and more room for new controls (like + insert and sort). +- Implemented shortcut keys. The JSON Editor can be used with just a keyboard. +- Implemented sort action, which sorts the childs of an array or object. +- Implemented auto scrolling up and down when dragging a node and reaching + the top or bottom of the editor. +- Added support for CommonJS and RequireJS. +- Added more examples. +- Improved performance and memory usage. +- Implemented a new mode 'form', in which only values are editable and the + fields are fixed. +- Minor improvements and bug fixes. + + +## 2012-12-08, version 1.7.0 + +- Implemented two modes: 'editor' (default), and 'viewer'. In viewer mode, + the data and datastructure is read-only. +- Implemented methods set(json, name), setName(name), and getName(), which + allows for setting and getting the field name of the root node. +- Fixed an issue where the search bar does not work when there is no global + window.editor object. + + +## 2012-11-26, version 1.6.2 + +- Fixed a bug in the change callback handler, resulting in an infinite loop + when requesting the contents of the editor inside the callback (issue #19). + + +## 2012-11-21, version 1.6.1 + +- Added a request header "Accept: application/json" when loading files and urls. + + +## 2012-11-03, version 1.6.0 + +- Added feature to the web application to load and save files from disk and url. +- Improved error messages in the web application using JSONLint. +- Made the web application pass the W3C markup validation service. +- Added option 'change' to both editor and formatter, which allows to set a + callback which is triggered when the contents of the editor or formatter + changes. +- Changed the default indentation of the JSONFormatter to 4 spaces. +- Renamed options 'enableSearch' and 'enableHistory' to 'search' and 'history' + respectively. +- Added parameter 'json' to the JSONFormatter constructor. +- Added option 'indentation' to the JSONFormatter. + + +## 2012-10-08, version 1.5.1 + +- Replaced the paid Chrome App with a free, hosted Chrome App (with ads). + + +## 2012-10-02, version 1.5.0 + +- Implemented history: undo/redo all actions. +- Created menu icons (instead of text buttons). +- Cleaned up the code (removed unused params, improved comments, etc). +- Minor performance improvements. + + +## 2012-08-31, version 1.4.4 + +- Changed: description of advertisement now gives information about the Chrome + App (without ads). +- Changed: Chrome App is now configured to be available offline. +- Fixed: When zooming your browser window, the fields/values did get wrapped + on Chrome (thanks Henri Gourvest), and on Firefox sometimes the jsoneditor + disappeared due to wrapping of the interface contents. + + +## 2012-08-25, version 1.4.3 + +- Changed: changed code for the buttons to copy from formatter to editor and + vice versa, no inline javascript (gives security policy errors in chrome app). + + +## 2012-08-25, version 1.4.2 + +- Changed: other bootstrapping mechanism for the chrome app, in a separate + javascript file, as inline javascript is not allowed (security policy). +- Fixed: drop down menu for changing the field type did throw javascript errors + (did not break any functionality though). + + +## 2012-08-23, version 1.4.1 + +- New: Chrome app created. + + +## 2012-08-23, version 1.4.0 + +- New: Improved icon, logo, and interface header. + + +## 2012-08-19, version 1.3.0 + +- New: Added buttons next and previous to the search box in the upper right. +- New: Escape characters are automatically inserted before " and \ missing + and escape character, making the string contents valid JSON. New lines are + automatically replaced with \n. (Thanks Steve Clay) +- Changed: all icons have been put in a single sprite. This will improve page + load times as there are much less server requests needed to load the editor. + + +## 2012-08-12, version 1.2.0 + +- New: Added search functionality. Search results are expanded and highlighed. + Quickkeys in the search box: Enter (next), Shift+Enter (previous), Ctrl+Enter + (search again). +- New: The position of the vertical separator between left and right panel is + stored. +- New: Link to the sourcecode on github added at the bottom of the page. +- Changed: Refinements in the layout: fonts, colors, icons. +- Fixed: leading an trailing spaces not being displayed in the editor. +- Fixed: wrapping of long words and urls in Chrome. +- Fixed: ignoring functions and undefined values in the loaded JSON object + (they where interpreted as empty object and string instead of being ignored). + + +## 2012-07-01, version 1.1.1 + +- Fixed global event listener for the focus/blur events, causing changes in + fields and values not always being registered. +- Fixed a css issue with Firefox (box-sizing of the editor). + + +## 2012-04-24, version 1.1 + +- Fixed a bug. Dragging an object down which has been expanded and collapsed + again did not work. +- Using a minified version of jsoneditor.js, to improve page load time and + save bandwidth. + + +## 2012-04-21, version 1.0 + +- Values are no longer aligned in one global column, but placed directly right + from the field. Having field and value close together improves readability, + especially in case of deeply nested data. +- Values are colorized by their type: strings are green, values read, booleans + blue, and null is purple. +- Font is changed to a monotype font for better readability. +- Special characters like \t are now handled nicely. +- Overall performance and memory usage improved. +- When clicking on whitespace, focus is set to the closest field or value. +- some other small interface tweaks. +- Fixed a bug with casting a value from type auto to string and vice versa + (the value was not casted at all). + + +## 2012-03-01, version 0.9.10 + +- Nicer looking select box for the field types, with icons. +- Improved drag and drop: better visualized, and now working in all browers. +- Previous values will be restored after changing the type of a field. When + changing the type back, the previous value or childs will be restored. +- When hovering buttons (fieldtype, duplicate, delete, add) or when dragging + a field, corresponding field including its childs is highlighted. This makes + it easier to see what part of the data will be edited. +- Errors are now displayed in a message window on top of the page instead of + an alert which pops up. +- Fixed a bug with displaying enters in fields. +- Fixed a bug where the last trailing enter was removed when setting json + in the editor. +- Added a fix to get around Internet Explorer 8 issues with vertical scrollbars. + + +## 2012-01-29, version 0.9.9 + +- Fields can be duplicated +- Support for drag and drop: + - fields in the editor itself can be moved via drag and drop + - fields can be exported from the editor as JSON + - external JSON can be dropped inside the editor +- When changing type from array to object and vice versa, childs will be + maintained instead of removed. +- Updated interface. Works now in IE8 too. + + +## 2012-01-16, version 0.9.8 + +- Improved the performance of expanding a node with all its childs. + + +## 2012-01-09, version 0.9.7 + +- Added functionallity to expand/collapse a node and all its childs. Click + the expand button of a node while holding Ctrl down. +- Small interface improvements + + +## 2011-11-28, version 0.9.6 + +- First fully usable version of the JSON editor diff --git a/ui/app/bower_components/jsoneditor/LICENSE b/ui/app/bower_components/jsoneditor/LICENSE new file mode 100644 index 0000000..ea2712c --- /dev/null +++ b/ui/app/bower_components/jsoneditor/LICENSE @@ -0,0 +1,176 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/ui/app/bower_components/jsoneditor/NOTICE b/ui/app/bower_components/jsoneditor/NOTICE new file mode 100644 index 0000000..ff2aa45 --- /dev/null +++ b/ui/app/bower_components/jsoneditor/NOTICE @@ -0,0 +1,17 @@ +JSON Editor +https://github.com/josdejong/jsoneditor + +Copyright (C) 2011-2015 Jos de Jong + + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/ui/app/bower_components/jsoneditor/README.md b/ui/app/bower_components/jsoneditor/README.md new file mode 100644 index 0000000..43b5c45 --- /dev/null +++ b/ui/app/bower_components/jsoneditor/README.md @@ -0,0 +1,155 @@ +# JSON Editor + +JSON Editor is a web-based tool to view, edit, format, and validate JSON. +It has various modes such as a tree editor, a code editor, and a plain text +editor. + +The editor can be used as a component in your own web application. The library +can be loaded as CommonJS module, AMD module, or as a regular javascript file. + +Supported browsers: Chrome, Firefox, Safari, Opera, Internet Explorer 9+. + +json editor   code editor + + +## Features + +### Tree editor +- Edit, add, move, remove, and duplicate fields and values. +- Change type of values. +- Sort arrays and objects. +- Colorized code. +- Search & highlight text in the tree view. +- Undo and redo all actions. +- JSON schema validation (powered by [ajv](https://github.com/epoberezkin/ajv)). + +### Code editor +- Colorized code (powered by [Ace](https://ace.c9.io)). +- Inspect JSON (powered by [Ace](https://ace.c9.io)). +- Format and compact JSON. +- JSON schema validation (powered by [ajv](https://github.com/epoberezkin/ajv)). + +### Text editor +- Format and compact JSON. +- JSON schema validation (powered by [ajv](https://github.com/epoberezkin/ajv)). + + +## Documentation + +- Documentation: + - [API](https://github.com/josdejong/jsoneditor/tree/master/docs/api.md) + - [Usage](https://github.com/josdejong/jsoneditor/tree/master/docs/usage.md) + - [Shortcut keys](https://github.com/josdejong/jsoneditor/tree/master/docs/shortcut_keys.md) +- [Examples](https://github.com/josdejong/jsoneditor/tree/master/examples) +- [Source](https://github.com/josdejong/jsoneditor) +- [History](https://github.com/josdejong/jsoneditor/blob/master/HISTORY.md) + + +## Install + +with npm (recommended): + + npm install jsoneditor + +with bower: + + bower install jsoneditor + + +#### More + +There is a directive available for using JSONEditor in Angular.js: + +[https://github.com/angular-tools/ng-jsoneditor](https://github.com/angular-tools/ng-jsoneditor) + + +## Use + +```html + + + + + + + + + + +
+ + + + +``` + + +## Build + +The code of the JSON Editor is located in the folder `./src`. To build +jsoneditor: + +- Install dependencies: + + ``` + npm install + ``` + +- Build JSON Editor: + + ``` + npm run build + ``` + + This will generate the files `./jsoneditor.js`, `./jsoneditor.css`, and + minified versions in the dist of the project. + +- To automatically build when a source file has changed: + + ``` + npm run watch + ``` + + This will update `./jsoneditor.js` and `./jsoneditor.css` in the dist folder + on every change, but it will **NOT** update the minified versions as that's + an expensive operation. + + +## Custom builds + +The source code of JSONEditor consists of CommonJS modules. JSONEditor can be bundled in a customized way using a module bundler like [browserify](http://browserify.org/) or [webpack](http://webpack.github.io/). First, install all dependencies of jsoneditor: + + npm install + +To create a custom bundle of the source code using browserify: + + browserify ./index.js -o ./jsoneditor.custom.js -s JSONEditor + +The Ace editor, used in mode `code`, accounts for about 75% of the total +size of the library. To exclude the Ace editor from the bundle: + + browserify ./index.js -o ./jsoneditor.custom.js -s JSONEditor -x brace -x brace/mode/json -x brace/ext/searchbox + +To minify the generated bundle, use [uglifyjs](https://github.com/mishoo/UglifyJS2): + + uglifyjs ./jsoneditor.custom.js -o ./jsoneditor.custom.min.js -m -c + diff --git a/ui/app/bower_components/jsoneditor/bower.json b/ui/app/bower_components/jsoneditor/bower.json new file mode 100644 index 0000000..933e66d --- /dev/null +++ b/ui/app/bower_components/jsoneditor/bower.json @@ -0,0 +1,32 @@ +{ + "name": "jsoneditor", + "description": "A web-based tool to view, edit and format JSON", + "tags": [ + "json", + "editor", + "viewer", + "formatter" + ], + "homepage": "http://jsoneditoronline.org/", + "repository": { + "type": "git", + "url": "https://github.com/josdejong/jsoneditor.git" + }, + "main": [ + "./dist/jsoneditor.min.js", + "./dist/jsoneditor.min.css" + ], + "bugs": "https://github.com/josdejong/jsoneditor/issues", + "ignore": [ + "misc", + "node_modules", + "test", + "tools", + "gulpfile.js", + "npm-debug.log", + ".idea", + ".npmignore", + ".gitignore" + ], + "dependencies": {} +} diff --git a/ui/app/bower_components/jsoneditor/dist/img/jsoneditor-icons.svg b/ui/app/bower_components/jsoneditor/dist/img/jsoneditor-icons.svg new file mode 100644 index 0000000..1b40068 --- /dev/null +++ b/ui/app/bower_components/jsoneditor/dist/img/jsoneditor-icons.svg @@ -0,0 +1,893 @@ + + + JSON Editor Icons + + + + image/svg+xml + + JSON Editor Icons + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ui/app/bower_components/jsoneditor/dist/jsoneditor-minimalist.js b/ui/app/bower_components/jsoneditor/dist/jsoneditor-minimalist.js new file mode 100644 index 0000000..c205716 --- /dev/null +++ b/ui/app/bower_components/jsoneditor/dist/jsoneditor-minimalist.js @@ -0,0 +1,9747 @@ +/*! + * jsoneditor.js + * + * @brief + * JSONEditor is a web-based tool to view, edit, format, and validate JSON. + * It has various modes such as a tree editor, a code editor, and a plain text + * editor. + * + * Supported browsers: Chrome, Firefox, Safari, Opera, Internet Explorer 8+ + * + * @license + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + * + * Copyright (c) 2011-2016 Jos de Jong, http://jsoneditoronline.org + * + * @author Jos de Jong, + * @version 5.5.10 + * @date 2016-11-02 + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports["JSONEditor"] = factory(); + else + root["JSONEditor"] = factory(); +})(this, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; + +/******/ // The require function +/******/ function __webpack_require__(moduleId) { + +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; + +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; + +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + +/******/ // Flag the module as loaded +/******/ module.loaded = true; + +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } + + +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; + +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; + +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; + +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var Ajv; + try { + Ajv = __webpack_require__(!(function webpackMissingModule() { var e = new Error("Cannot find module \"ajv\""); e.code = 'MODULE_NOT_FOUND'; throw e; }())); + } + catch (err) { + // no problem... when we need Ajv we will throw a neat exception + } + + var treemode = __webpack_require__(1); + var textmode = __webpack_require__(12); + var util = __webpack_require__(4); + + /** + * @constructor JSONEditor + * @param {Element} container Container element + * @param {Object} [options] Object with options. available options: + * {String} mode Editor mode. Available values: + * 'tree' (default), 'view', + * 'form', 'text', and 'code'. + * {function} onChange Callback method, triggered + * on change of contents + * {function} onError Callback method, triggered + * when an error occurs + * {Boolean} search Enable search box. + * True by default + * Only applicable for modes + * 'tree', 'view', and 'form' + * {Boolean} history Enable history (undo/redo). + * True by default + * Only applicable for modes + * 'tree', 'view', and 'form' + * {String} name Field name for the root node. + * Only applicable for modes + * 'tree', 'view', and 'form' + * {Number} indentation Number of indentation + * spaces. 4 by default. + * Only applicable for + * modes 'text' and 'code' + * {boolean} escapeUnicode If true, unicode + * characters are escaped. + * false by default. + * {boolean} sortObjectKeys If true, object keys are + * sorted before display. + * false by default. + * @param {Object | undefined} json JSON object + */ + function JSONEditor (container, options, json) { + if (!(this instanceof JSONEditor)) { + throw new Error('JSONEditor constructor called without "new".'); + } + + // check for unsupported browser (IE8 and older) + var ieVersion = util.getInternetExplorerVersion(); + if (ieVersion != -1 && ieVersion < 9) { + throw new Error('Unsupported browser, IE9 or newer required. ' + + 'Please install the newest version of your browser.'); + } + + if (options) { + // check for deprecated options + if (options.error) { + console.warn('Option "error" has been renamed to "onError"'); + options.onError = options.error; + delete options.error; + } + if (options.change) { + console.warn('Option "change" has been renamed to "onChange"'); + options.onChange = options.change; + delete options.change; + } + if (options.editable) { + console.warn('Option "editable" has been renamed to "onEditable"'); + options.onEditable = options.editable; + delete options.editable; + } + + // validate options + if (options) { + var VALID_OPTIONS = [ + 'ace', 'theme', + 'ajv', 'schema', + 'onChange', 'onEditable', 'onError', 'onModeChange', + 'escapeUnicode', 'history', 'search', 'mode', 'modes', 'name', 'indentation', 'sortObjectKeys' + ]; + + Object.keys(options).forEach(function (option) { + if (VALID_OPTIONS.indexOf(option) === -1) { + console.warn('Unknown option "' + option + '". This option will be ignored'); + } + }); + } + } + + if (arguments.length) { + this._create(container, options, json); + } + } + + /** + * Configuration for all registered modes. Example: + * { + * tree: { + * mixin: TreeEditor, + * data: 'json' + * }, + * text: { + * mixin: TextEditor, + * data: 'text' + * } + * } + * + * @type { Object. } + */ + JSONEditor.modes = {}; + + // debounce interval for JSON schema vaidation in milliseconds + JSONEditor.prototype.DEBOUNCE_INTERVAL = 150; + + /** + * Create the JSONEditor + * @param {Element} container Container element + * @param {Object} [options] See description in constructor + * @param {Object | undefined} json JSON object + * @private + */ + JSONEditor.prototype._create = function (container, options, json) { + this.container = container; + this.options = options || {}; + this.json = json || {}; + + var mode = this.options.mode || 'tree'; + this.setMode(mode); + }; + + /** + * Destroy the editor. Clean up DOM, event listeners, and web workers. + */ + JSONEditor.prototype.destroy = function () {}; + + /** + * Set JSON object in editor + * @param {Object | undefined} json JSON data + */ + JSONEditor.prototype.set = function (json) { + this.json = json; + }; + + /** + * Get JSON from the editor + * @returns {Object} json + */ + JSONEditor.prototype.get = function () { + return this.json; + }; + + /** + * Set string containing JSON for the editor + * @param {String | undefined} jsonText + */ + JSONEditor.prototype.setText = function (jsonText) { + this.json = util.parse(jsonText); + }; + + /** + * Get stringified JSON contents from the editor + * @returns {String} jsonText + */ + JSONEditor.prototype.getText = function () { + return JSON.stringify(this.json); + }; + + /** + * Set a field name for the root node. + * @param {String | undefined} name + */ + JSONEditor.prototype.setName = function (name) { + if (!this.options) { + this.options = {}; + } + this.options.name = name; + }; + + /** + * Get the field name for the root node. + * @return {String | undefined} name + */ + JSONEditor.prototype.getName = function () { + return this.options && this.options.name; + }; + + /** + * Change the mode of the editor. + * JSONEditor will be extended with all methods needed for the chosen mode. + * @param {String} mode Available modes: 'tree' (default), 'view', 'form', + * 'text', and 'code'. + */ + JSONEditor.prototype.setMode = function (mode) { + var container = this.container; + var options = util.extend({}, this.options); + var oldMode = options.mode; + var data; + var name; + + options.mode = mode; + var config = JSONEditor.modes[mode]; + if (config) { + try { + var asText = (config.data == 'text'); + name = this.getName(); + data = this[asText ? 'getText' : 'get'](); // get text or json + + this.destroy(); + util.clear(this); + util.extend(this, config.mixin); + this.create(container, options); + + this.setName(name); + this[asText ? 'setText' : 'set'](data); // set text or json + + if (typeof config.load === 'function') { + try { + config.load.call(this); + } + catch (err) { + console.error(err); + } + } + + if (typeof options.onModeChange === 'function' && mode !== oldMode) { + try { + options.onModeChange(mode, oldMode); + } + catch (err) { + console.error(err); + } + } + } + catch (err) { + this._onError(err); + } + } + else { + throw new Error('Unknown mode "' + options.mode + '"'); + } + }; + + /** + * Get the current mode + * @return {string} + */ + JSONEditor.prototype.getMode = function () { + return this.options.mode; + }; + + /** + * Throw an error. If an error callback is configured in options.error, this + * callback will be invoked. Else, a regular error is thrown. + * @param {Error} err + * @private + */ + JSONEditor.prototype._onError = function(err) { + if (this.options && typeof this.options.onError === 'function') { + this.options.onError(err); + } + else { + throw err; + } + }; + + /** + * Set a JSON schema for validation of the JSON object. + * To remove the schema, call JSONEditor.setSchema(null) + * @param {Object | null} schema + */ + JSONEditor.prototype.setSchema = function (schema) { + // compile a JSON schema validator if a JSON schema is provided + if (schema) { + var ajv; + try { + // grab ajv from options if provided, else create a new instance + ajv = this.options.ajv || Ajv({ allErrors: true, verbose: true }); + + } + catch (err) { + console.warn('Failed to create an instance of Ajv, JSON Schema validation is not available. Please use a JSONEditor bundle including Ajv, or pass an instance of Ajv as via the configuration option `ajv`.'); + } + + if (ajv) { + this.validateSchema = ajv.compile(schema); + + // add schema to the options, so that when switching to an other mode, + // the set schema is not lost + this.options.schema = schema; + + // validate now + this.validate(); + } + + this.refresh(); // update DOM + } + else { + // remove current schema + this.validateSchema = null; + this.options.schema = null; + this.validate(); // to clear current error messages + this.refresh(); // update DOM + } + }; + + /** + * Validate current JSON object against the configured JSON schema + * Throws an exception when no JSON schema is configured + */ + JSONEditor.prototype.validate = function () { + // must be implemented by treemode and textmode + }; + + /** + * Refresh the rendered contents + */ + JSONEditor.prototype.refresh = function () { + // can be implemented by treemode and textmode + }; + + /** + * Register a plugin with one ore multiple modes for the JSON Editor. + * + * A mode is described as an object with properties: + * + * - `mode: String` The name of the mode. + * - `mixin: Object` An object containing the mixin functions which + * will be added to the JSONEditor. Must contain functions + * create, get, getText, set, and setText. May have + * additional functions. + * When the JSONEditor switches to a mixin, all mixin + * functions are added to the JSONEditor, and then + * the function `create(container, options)` is executed. + * - `data: 'text' | 'json'` The type of data that will be used to load the mixin. + * - `[load: function]` An optional function called after the mixin + * has been loaded. + * + * @param {Object | Array} mode A mode object or an array with multiple mode objects. + */ + JSONEditor.registerMode = function (mode) { + var i, prop; + + if (util.isArray(mode)) { + // multiple modes + for (i = 0; i < mode.length; i++) { + JSONEditor.registerMode(mode[i]); + } + } + else { + // validate the new mode + if (!('mode' in mode)) throw new Error('Property "mode" missing'); + if (!('mixin' in mode)) throw new Error('Property "mixin" missing'); + if (!('data' in mode)) throw new Error('Property "data" missing'); + var name = mode.mode; + if (name in JSONEditor.modes) { + throw new Error('Mode "' + name + '" already registered'); + } + + // validate the mixin + if (typeof mode.mixin.create !== 'function') { + throw new Error('Required function "create" missing on mixin'); + } + var reserved = ['setMode', 'registerMode', 'modes']; + for (i = 0; i < reserved.length; i++) { + prop = reserved[i]; + if (prop in mode.mixin) { + throw new Error('Reserved property "' + prop + '" not allowed in mixin'); + } + } + + JSONEditor.modes[name] = mode; + } + }; + + // register tree and text modes + JSONEditor.registerMode(treemode); + JSONEditor.registerMode(textmode); + + module.exports = JSONEditor; + + +/***/ }, +/* 1 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + var Highlighter = __webpack_require__(2); + var History = __webpack_require__(3); + var SearchBox = __webpack_require__(6); + var ContextMenu = __webpack_require__(7); + var Node = __webpack_require__(8); + var ModeSwitcher = __webpack_require__(11); + var util = __webpack_require__(4); + + // create a mixin with the functions for tree mode + var treemode = {}; + + /** + * Create a tree editor + * @param {Element} container Container element + * @param {Object} [options] Object with options. available options: + * {String} mode Editor mode. Available values: + * 'tree' (default), 'view', + * and 'form'. + * {Boolean} search Enable search box. + * True by default + * {Boolean} history Enable history (undo/redo). + * True by default + * {function} onChange Callback method, triggered + * on change of contents + * {String} name Field name for the root node. + * {boolean} escapeUnicode If true, unicode + * characters are escaped. + * false by default. + * {Object} schema A JSON Schema for validation + * @private + */ + treemode.create = function (container, options) { + if (!container) { + throw new Error('No container element provided.'); + } + this.container = container; + this.dom = {}; + this.highlighter = new Highlighter(); + this.selection = undefined; // will hold the last input selection + this.multiselection = { + nodes: [] + }; + this.validateSchema = null; // will be set in .setSchema(schema) + this.errorNodes = []; + + this.node = null; + this.focusTarget = null; + + this._setOptions(options); + + if (this.options.history && this.options.mode !== 'view') { + this.history = new History(this); + } + + this._createFrame(); + this._createTable(); + }; + + /** + * Destroy the editor. Clean up DOM, event listeners, and web workers. + */ + treemode.destroy = function () { + if (this.frame && this.container && this.frame.parentNode == this.container) { + this.container.removeChild(this.frame); + this.frame = null; + } + this.container = null; + + this.dom = null; + + this.clear(); + this.node = null; + this.focusTarget = null; + this.selection = null; + this.multiselection = null; + this.errorNodes = null; + this.validateSchema = null; + this._debouncedValidate = null; + + if (this.history) { + this.history.destroy(); + this.history = null; + } + + if (this.searchBox) { + this.searchBox.destroy(); + this.searchBox = null; + } + + if (this.modeSwitcher) { + this.modeSwitcher.destroy(); + this.modeSwitcher = null; + } + }; + + /** + * Initialize and set default options + * @param {Object} [options] See description in constructor + * @private + */ + treemode._setOptions = function (options) { + this.options = { + search: true, + history: true, + mode: 'tree', + name: undefined, // field name of root node + schema: null + }; + + // copy all options + if (options) { + for (var prop in options) { + if (options.hasOwnProperty(prop)) { + this.options[prop] = options[prop]; + } + } + } + + // compile a JSON schema validator if a JSON schema is provided + this.setSchema(this.options.schema); + + // create a debounced validate function + this._debouncedValidate = util.debounce(this.validate.bind(this), this.DEBOUNCE_INTERVAL); + }; + + /** + * Set JSON object in editor + * @param {Object | undefined} json JSON data + * @param {String} [name] Optional field name for the root node. + * Can also be set using setName(name). + */ + treemode.set = function (json, name) { + // adjust field name for root node + if (name) { + // TODO: deprecated since version 2.2.0. Cleanup some day. + console.warn('Second parameter "name" is deprecated. Use setName(name) instead.'); + this.options.name = name; + } + + // verify if json is valid JSON, ignore when a function + if (json instanceof Function || (json === undefined)) { + this.clear(); + } + else { + this.content.removeChild(this.table); // Take the table offline + + // replace the root node + var params = { + field: this.options.name, + value: json + }; + var node = new Node(this, params); + this._setRoot(node); + + // validate JSON schema (if configured) + this.validate(); + + // expand + var recurse = false; + this.node.expand(recurse); + + this.content.appendChild(this.table); // Put the table online again + } + + // TODO: maintain history, store last state and previous document + if (this.history) { + this.history.clear(); + } + + // clear search + if (this.searchBox) { + this.searchBox.clear(); + } + }; + + /** + * Get JSON object from editor + * @return {Object | undefined} json + */ + treemode.get = function () { + // remove focus from currently edited node + if (this.focusTarget) { + var node = Node.getNodeFromTarget(this.focusTarget); + if (node) { + node.blur(); + } + } + + if (this.node) { + return this.node.getValue(); + } + else { + return undefined; + } + }; + + /** + * Get the text contents of the editor + * @return {String} jsonText + */ + treemode.getText = function() { + return JSON.stringify(this.get()); + }; + + /** + * Set the text contents of the editor + * @param {String} jsonText + */ + treemode.setText = function(jsonText) { + this.set(util.parse(jsonText)); + }; + + /** + * Set a field name for the root node. + * @param {String | undefined} name + */ + treemode.setName = function (name) { + this.options.name = name; + if (this.node) { + this.node.updateField(this.options.name); + } + }; + + /** + * Get the field name for the root node. + * @return {String | undefined} name + */ + treemode.getName = function () { + return this.options.name; + }; + + /** + * Set focus to the editor. Focus will be set to: + * - the first editable field or value, or else + * - to the expand button of the root node, or else + * - to the context menu button of the root node, or else + * - to the first button in the top menu + */ + treemode.focus = function () { + var input = this.content.querySelector('[contenteditable=true]'); + if (input) { + input.focus(); + } + else if (this.node.dom.expand) { + this.node.dom.expand.focus(); + } + else if (this.node.dom.menu) { + this.node.dom.menu.focus(); + } + else { + // focus to the first button in the menu + input = this.frame.querySelector('button'); + if (input) { + input.focus(); + } + } + }; + + /** + * Remove the root node from the editor + */ + treemode.clear = function () { + if (this.node) { + this.node.collapse(); + this.tbody.removeChild(this.node.getDom()); + delete this.node; + } + }; + + /** + * Set the root node for the json editor + * @param {Node} node + * @private + */ + treemode._setRoot = function (node) { + this.clear(); + + this.node = node; + + // append to the dom + this.tbody.appendChild(node.getDom()); + }; + + /** + * Search text in all nodes + * The nodes will be expanded when the text is found one of its childs, + * else it will be collapsed. Searches are case insensitive. + * @param {String} text + * @return {Object[]} results Array with nodes containing the search results + * The result objects contains fields: + * - {Node} node, + * - {String} elem the dom element name where + * the result is found ('field' or + * 'value') + */ + treemode.search = function (text) { + var results; + if (this.node) { + this.content.removeChild(this.table); // Take the table offline + results = this.node.search(text); + this.content.appendChild(this.table); // Put the table online again + } + else { + results = []; + } + + return results; + }; + + /** + * Expand all nodes + */ + treemode.expandAll = function () { + if (this.node) { + this.content.removeChild(this.table); // Take the table offline + this.node.expand(); + this.content.appendChild(this.table); // Put the table online again + } + }; + + /** + * Collapse all nodes + */ + treemode.collapseAll = function () { + if (this.node) { + this.content.removeChild(this.table); // Take the table offline + this.node.collapse(); + this.content.appendChild(this.table); // Put the table online again + } + }; + + /** + * The method onChange is called whenever a field or value is changed, created, + * deleted, duplicated, etc. + * @param {String} action Change action. Available values: "editField", + * "editValue", "changeType", "appendNode", + * "removeNode", "duplicateNode", "moveNode", "expand", + * "collapse". + * @param {Object} params Object containing parameters describing the change. + * The parameters in params depend on the action (for + * example for "editValue" the Node, old value, and new + * value are provided). params contains all information + * needed to undo or redo the action. + * @private + */ + treemode._onAction = function (action, params) { + // add an action to the history + if (this.history) { + this.history.add(action, params); + } + + this._onChange(); + }; + + /** + * Handle a change: + * - Validate JSON schema + * - Send a callback to the onChange listener if provided + * @private + */ + treemode._onChange = function () { + // validate JSON schema (if configured) + this._debouncedValidate(); + + // trigger the onChange callback + if (this.options.onChange) { + try { + this.options.onChange(); + } + catch (err) { + console.error('Error in onChange callback: ', err); + } + } + }; + + /** + * Validate current JSON object against the configured JSON schema + * Throws an exception when no JSON schema is configured + */ + treemode.validate = function () { + // clear all current errors + if (this.errorNodes) { + this.errorNodes.forEach(function (node) { + node.setError(null); + }); + } + + var root = this.node; + if (!root) { // TODO: this should be redundant but is needed on mode switch + return; + } + + // check for duplicate keys + var duplicateErrors = root.validate(); + + // validate the JSON + var schemaErrors = []; + if (this.validateSchema) { + var valid = this.validateSchema(root.getValue()); + if (!valid) { + // apply all new errors + schemaErrors = this.validateSchema.errors + .map(function (error) { + return util.improveSchemaError(error); + }) + .map(function findNode (error) { + return { + node: root.findNode(error.dataPath), + error: error + } + }) + .filter(function hasNode (entry) { + return entry.node != null + }); + } + } + + // display the error in the nodes with a problem + this.errorNodes = duplicateErrors + .concat(schemaErrors) + .reduce(function expandParents (all, entry) { + // expand parents, then merge such that parents come first and + // original entries last + return entry.node + .findParents() + .map(function (parent) { + return { + node: parent, + child: entry.node, + error: { + message: parent.type === 'object' + ? 'Contains invalid properties' // object + : 'Contains invalid items' // array + } + }; + }) + .concat(all, [entry]); + }, []) + // TODO: dedupe the parent nodes + .map(function setError (entry) { + entry.node.setError(entry.error, entry.child); + return entry.node; + }); + }; + + /** + * Refresh the rendered contents + */ + treemode.refresh = function () { + if (this.node) { + this.node.updateDom({recurse: true}); + } + }; + + /** + * Start autoscrolling when given mouse position is above the top of the + * editor contents, or below the bottom. + * @param {Number} mouseY Absolute mouse position in pixels + */ + treemode.startAutoScroll = function (mouseY) { + var me = this; + var content = this.content; + var top = util.getAbsoluteTop(content); + var height = content.clientHeight; + var bottom = top + height; + var margin = 24; + var interval = 50; // ms + + if ((mouseY < top + margin) && content.scrollTop > 0) { + this.autoScrollStep = ((top + margin) - mouseY) / 3; + } + else if (mouseY > bottom - margin && + height + content.scrollTop < content.scrollHeight) { + this.autoScrollStep = ((bottom - margin) - mouseY) / 3; + } + else { + this.autoScrollStep = undefined; + } + + if (this.autoScrollStep) { + if (!this.autoScrollTimer) { + this.autoScrollTimer = setInterval(function () { + if (me.autoScrollStep) { + content.scrollTop -= me.autoScrollStep; + } + else { + me.stopAutoScroll(); + } + }, interval); + } + } + else { + this.stopAutoScroll(); + } + }; + + /** + * Stop auto scrolling. Only applicable when scrolling + */ + treemode.stopAutoScroll = function () { + if (this.autoScrollTimer) { + clearTimeout(this.autoScrollTimer); + delete this.autoScrollTimer; + } + if (this.autoScrollStep) { + delete this.autoScrollStep; + } + }; + + + /** + * Set the focus to an element in the editor, set text selection, and + * set scroll position. + * @param {Object} selection An object containing fields: + * {Element | undefined} dom The dom element + * which has focus + * {Range | TextRange} range A text selection + * {Node[]} nodes Nodes in case of multi selection + * {Number} scrollTop Scroll position + */ + treemode.setSelection = function (selection) { + if (!selection) { + return; + } + + if ('scrollTop' in selection && this.content) { + // TODO: animated scroll + this.content.scrollTop = selection.scrollTop; + } + if (selection.nodes) { + // multi-select + this.select(selection.nodes); + } + if (selection.range) { + util.setSelectionOffset(selection.range); + } + if (selection.dom) { + selection.dom.focus(); + } + }; + + /** + * Get the current focus + * @return {Object} selection An object containing fields: + * {Element | undefined} dom The dom element + * which has focus + * {Range | TextRange} range A text selection + * {Node[]} nodes Nodes in case of multi selection + * {Number} scrollTop Scroll position + */ + treemode.getSelection = function () { + var range = util.getSelectionOffset(); + if (range && range.container.nodeName !== 'DIV') { // filter on (editable) divs) + range = null; + } + + return { + dom: this.focusTarget, + range: range, + nodes: this.multiselection.nodes.slice(0), + scrollTop: this.content ? this.content.scrollTop : 0 + }; + }; + + /** + * Adjust the scroll position such that given top position is shown at 1/4 + * of the window height. + * @param {Number} top + * @param {function(boolean)} [callback] Callback, executed when animation is + * finished. The callback returns true + * when animation is finished, or false + * when not. + */ + treemode.scrollTo = function (top, callback) { + var content = this.content; + if (content) { + var editor = this; + // cancel any running animation + if (editor.animateTimeout) { + clearTimeout(editor.animateTimeout); + delete editor.animateTimeout; + } + if (editor.animateCallback) { + editor.animateCallback(false); + delete editor.animateCallback; + } + + // calculate final scroll position + var height = content.clientHeight; + var bottom = content.scrollHeight - height; + var finalScrollTop = Math.min(Math.max(top - height / 4, 0), bottom); + + // animate towards the new scroll position + var animate = function () { + var scrollTop = content.scrollTop; + var diff = (finalScrollTop - scrollTop); + if (Math.abs(diff) > 3) { + content.scrollTop += diff / 3; + editor.animateCallback = callback; + editor.animateTimeout = setTimeout(animate, 50); + } + else { + // finished + if (callback) { + callback(true); + } + content.scrollTop = finalScrollTop; + delete editor.animateTimeout; + delete editor.animateCallback; + } + }; + animate(); + } + else { + if (callback) { + callback(false); + } + } + }; + + /** + * Create main frame + * @private + */ + treemode._createFrame = function () { + // create the frame + this.frame = document.createElement('div'); + this.frame.className = 'jsoneditor jsoneditor-mode-' + this.options.mode; + this.container.appendChild(this.frame); + + // create one global event listener to handle all events from all nodes + var editor = this; + function onEvent(event) { + // when switching to mode "code" or "text" via the menu, some events + // are still fired whilst the _onEvent methods is already removed. + if (editor._onEvent) { + editor._onEvent(event); + } + } + this.frame.onclick = function (event) { + var target = event.target;// || event.srcElement; + + onEvent(event); + + // prevent default submit action of buttons when editor is located + // inside a form + if (target.nodeName == 'BUTTON') { + event.preventDefault(); + } + }; + this.frame.oninput = onEvent; + this.frame.onchange = onEvent; + this.frame.onkeydown = onEvent; + this.frame.onkeyup = onEvent; + this.frame.oncut = onEvent; + this.frame.onpaste = onEvent; + this.frame.onmousedown = onEvent; + this.frame.onmouseup = onEvent; + this.frame.onmouseover = onEvent; + this.frame.onmouseout = onEvent; + // Note: focus and blur events do not propagate, therefore they defined + // using an eventListener with useCapture=true + // see http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html + util.addEventListener(this.frame, 'focus', onEvent, true); + util.addEventListener(this.frame, 'blur', onEvent, true); + this.frame.onfocusin = onEvent; // for IE + this.frame.onfocusout = onEvent; // for IE + + // create menu + this.menu = document.createElement('div'); + this.menu.className = 'jsoneditor-menu'; + this.frame.appendChild(this.menu); + + // create expand all button + var expandAll = document.createElement('button'); + expandAll.type = 'button'; + expandAll.className = 'jsoneditor-expand-all'; + expandAll.title = 'Expand all fields'; + expandAll.onclick = function () { + editor.expandAll(); + }; + this.menu.appendChild(expandAll); + + // create expand all button + var collapseAll = document.createElement('button'); + collapseAll.type = 'button'; + collapseAll.title = 'Collapse all fields'; + collapseAll.className = 'jsoneditor-collapse-all'; + collapseAll.onclick = function () { + editor.collapseAll(); + }; + this.menu.appendChild(collapseAll); + + // create undo/redo buttons + if (this.history) { + // create undo button + var undo = document.createElement('button'); + undo.type = 'button'; + undo.className = 'jsoneditor-undo jsoneditor-separator'; + undo.title = 'Undo last action (Ctrl+Z)'; + undo.onclick = function () { + editor._onUndo(); + }; + this.menu.appendChild(undo); + this.dom.undo = undo; + + // create redo button + var redo = document.createElement('button'); + redo.type = 'button'; + redo.className = 'jsoneditor-redo'; + redo.title = 'Redo (Ctrl+Shift+Z)'; + redo.onclick = function () { + editor._onRedo(); + }; + this.menu.appendChild(redo); + this.dom.redo = redo; + + // register handler for onchange of history + this.history.onChange = function () { + undo.disabled = !editor.history.canUndo(); + redo.disabled = !editor.history.canRedo(); + }; + this.history.onChange(); + } + + // create mode box + if (this.options && this.options.modes && this.options.modes.length) { + var me = this; + this.modeSwitcher = new ModeSwitcher(this.menu, this.options.modes, this.options.mode, function onSwitch(mode) { + me.modeSwitcher.destroy(); + + // switch mode and restore focus + me.setMode(mode); + me.modeSwitcher.focus(); + }); + } + + // create search box + if (this.options.search) { + this.searchBox = new SearchBox(this, this.menu); + } + }; + + /** + * Perform an undo action + * @private + */ + treemode._onUndo = function () { + if (this.history) { + // undo last action + this.history.undo(); + + // fire change event + this._onChange(); + } + }; + + /** + * Perform a redo action + * @private + */ + treemode._onRedo = function () { + if (this.history) { + // redo last action + this.history.redo(); + + // fire change event + this._onChange(); + } + }; + + /** + * Event handler + * @param event + * @private + */ + treemode._onEvent = function (event) { + if (event.type == 'keydown') { + this._onKeyDown(event); + } + + if (event.type == 'focus') { + this.focusTarget = event.target; + } + + if (event.type == 'mousedown') { + this._startDragDistance(event); + } + if (event.type == 'mousemove' || event.type == 'mouseup' || event.type == 'click') { + this._updateDragDistance(event); + } + + var node = Node.getNodeFromTarget(event.target); + + if (node && node.selected) { + if (event.type == 'click') { + if (event.target == node.dom.menu) { + this.showContextMenu(event.target); + + // stop propagation (else we will open the context menu of a single node) + return; + } + + // deselect a multi selection + if (!event.hasMoved) { + this.deselect(); + } + } + + if (event.type == 'mousedown') { + // drag multiple nodes + Node.onDragStart(this.multiselection.nodes, event); + } + } + else { + if (event.type == 'mousedown') { + this.deselect(); + + if (node && event.target == node.dom.drag) { + // drag a singe node + Node.onDragStart(node, event); + } + else if (!node || (event.target != node.dom.field && event.target != node.dom.value && event.target != node.dom.select)) { + // select multiple nodes + this._onMultiSelectStart(event); + } + } + } + + if (node) { + node.onEvent(event); + } + }; + + treemode._startDragDistance = function (event) { + this.dragDistanceEvent = { + initialTarget: event.target, + initialPageX: event.pageX, + initialPageY: event.pageY, + dragDistance: 0, + hasMoved: false + }; + }; + + treemode._updateDragDistance = function (event) { + if (!this.dragDistanceEvent) { + this._startDragDistance(event); + } + + var diffX = event.pageX - this.dragDistanceEvent.initialPageX; + var diffY = event.pageY - this.dragDistanceEvent.initialPageY; + + this.dragDistanceEvent.dragDistance = Math.sqrt(diffX * diffX + diffY * diffY); + this.dragDistanceEvent.hasMoved = + this.dragDistanceEvent.hasMoved || this.dragDistanceEvent.dragDistance > 10; + + event.dragDistance = this.dragDistanceEvent.dragDistance; + event.hasMoved = this.dragDistanceEvent.hasMoved; + + return event.dragDistance; + }; + + /** + * Start multi selection of nodes by dragging the mouse + * @param event + * @private + */ + treemode._onMultiSelectStart = function (event) { + var node = Node.getNodeFromTarget(event.target); + + if (this.options.mode !== 'tree' || this.options.onEditable !== undefined) { + // dragging not allowed in modes 'view' and 'form' + // TODO: allow multiselection of items when option onEditable is specified + return; + } + + this.multiselection = { + start: node || null, + end: null, + nodes: [] + }; + + this._startDragDistance(event); + + var editor = this; + if (!this.mousemove) { + this.mousemove = util.addEventListener(window, 'mousemove', function (event) { + editor._onMultiSelect(event); + }); + } + if (!this.mouseup) { + this.mouseup = util.addEventListener(window, 'mouseup', function (event ) { + editor._onMultiSelectEnd(event); + }); + } + + }; + + /** + * Multiselect nodes by dragging + * @param event + * @private + */ + treemode._onMultiSelect = function (event) { + event.preventDefault(); + + this._updateDragDistance(event); + if (!event.hasMoved) { + return; + } + + var node = Node.getNodeFromTarget(event.target); + + if (node) { + if (this.multiselection.start == null) { + this.multiselection.start = node; + } + this.multiselection.end = node; + } + + // deselect previous selection + this.deselect(); + + // find the selected nodes in the range from first to last + var start = this.multiselection.start; + var end = this.multiselection.end || this.multiselection.start; + if (start && end) { + // find the top level childs, all having the same parent + this.multiselection.nodes = this._findTopLevelNodes(start, end); + this.select(this.multiselection.nodes); + } + }; + + /** + * End of multiselect nodes by dragging + * @param event + * @private + */ + treemode._onMultiSelectEnd = function (event) { + // set focus to the context menu button of the first node + if (this.multiselection.nodes[0]) { + this.multiselection.nodes[0].dom.menu.focus(); + } + + this.multiselection.start = null; + this.multiselection.end = null; + + // cleanup global event listeners + if (this.mousemove) { + util.removeEventListener(window, 'mousemove', this.mousemove); + delete this.mousemove; + } + if (this.mouseup) { + util.removeEventListener(window, 'mouseup', this.mouseup); + delete this.mouseup; + } + }; + + /** + * deselect currently selected nodes + * @param {boolean} [clearStartAndEnd=false] If true, the `start` and `end` + * state is cleared too. + */ + treemode.deselect = function (clearStartAndEnd) { + this.multiselection.nodes.forEach(function (node) { + node.setSelected(false); + }); + this.multiselection.nodes = []; + + if (clearStartAndEnd) { + this.multiselection.start = null; + this.multiselection.end = null; + } + }; + + /** + * select nodes + * @param {Node[] | Node} nodes + */ + treemode.select = function (nodes) { + if (!Array.isArray(nodes)) { + return this.select([nodes]); + } + + if (nodes) { + this.deselect(); + + this.multiselection.nodes = nodes.slice(0); + + var first = nodes[0]; + nodes.forEach(function (node) { + node.setSelected(true, node === first); + }); + } + }; + + /** + * From two arbitrary selected nodes, find their shared parent node. + * From that parent node, select the two child nodes in the brances going to + * nodes `start` and `end`, and select all childs in between. + * @param {Node} start + * @param {Node} end + * @return {Array.} Returns an ordered list with child nodes + * @private + */ + treemode._findTopLevelNodes = function (start, end) { + var startPath = start.getNodePath(); + var endPath = end.getNodePath(); + var i = 0; + while (i < startPath.length && startPath[i] === endPath[i]) { + i++; + } + var root = startPath[i - 1]; + var startChild = startPath[i]; + var endChild = endPath[i]; + + if (!startChild || !endChild) { + if (root.parent) { + // startChild is a parent of endChild or vice versa + startChild = root; + endChild = root; + root = root.parent + } + else { + // we have selected the root node (which doesn't have a parent) + startChild = root.childs[0]; + endChild = root.childs[root.childs.length - 1]; + } + } + + if (root && startChild && endChild) { + var startIndex = root.childs.indexOf(startChild); + var endIndex = root.childs.indexOf(endChild); + var firstIndex = Math.min(startIndex, endIndex); + var lastIndex = Math.max(startIndex, endIndex); + + return root.childs.slice(firstIndex, lastIndex + 1); + } + else { + return []; + } + }; + + /** + * Event handler for keydown. Handles shortcut keys + * @param {Event} event + * @private + */ + treemode._onKeyDown = function (event) { + var keynum = event.which || event.keyCode; + var ctrlKey = event.ctrlKey; + var shiftKey = event.shiftKey; + var handled = false; + + if (keynum == 9) { // Tab or Shift+Tab + var me = this; + setTimeout(function () { + // select all text when moving focus to an editable div + util.selectContentEditable(me.focusTarget); + }, 0); + } + + if (this.searchBox) { + if (ctrlKey && keynum == 70) { // Ctrl+F + this.searchBox.dom.search.focus(); + this.searchBox.dom.search.select(); + handled = true; + } + else if (keynum == 114 || (ctrlKey && keynum == 71)) { // F3 or Ctrl+G + var focus = true; + if (!shiftKey) { + // select next search result (F3 or Ctrl+G) + this.searchBox.next(focus); + } + else { + // select previous search result (Shift+F3 or Ctrl+Shift+G) + this.searchBox.previous(focus); + } + + handled = true; + } + } + + if (this.history) { + if (ctrlKey && !shiftKey && keynum == 90) { // Ctrl+Z + // undo + this._onUndo(); + handled = true; + } + else if (ctrlKey && shiftKey && keynum == 90) { // Ctrl+Shift+Z + // redo + this._onRedo(); + handled = true; + } + } + + if (handled) { + event.preventDefault(); + event.stopPropagation(); + } + }; + + /** + * Create main table + * @private + */ + treemode._createTable = function () { + var contentOuter = document.createElement('div'); + contentOuter.className = 'jsoneditor-outer'; + this.contentOuter = contentOuter; + + this.content = document.createElement('div'); + this.content.className = 'jsoneditor-tree'; + contentOuter.appendChild(this.content); + + this.table = document.createElement('table'); + this.table.className = 'jsoneditor-tree'; + this.content.appendChild(this.table); + + // create colgroup where the first two columns don't have a fixed + // width, and the edit columns do have a fixed width + var col; + this.colgroupContent = document.createElement('colgroup'); + if (this.options.mode === 'tree') { + col = document.createElement('col'); + col.width = "24px"; + this.colgroupContent.appendChild(col); + } + col = document.createElement('col'); + col.width = "24px"; + this.colgroupContent.appendChild(col); + col = document.createElement('col'); + this.colgroupContent.appendChild(col); + this.table.appendChild(this.colgroupContent); + + this.tbody = document.createElement('tbody'); + this.table.appendChild(this.tbody); + + this.frame.appendChild(contentOuter); + }; + + /** + * Show a contextmenu for this node. + * Used for multiselection + * @param {HTMLElement} anchor Anchor element to attache the context menu to. + * @param {function} [onClose] Callback method called when the context menu + * is being closed. + */ + treemode.showContextMenu = function (anchor, onClose) { + var items = []; + var editor = this; + + // create duplicate button + items.push({ + text: 'Duplicate', + title: 'Duplicate selected fields (Ctrl+D)', + className: 'jsoneditor-duplicate', + click: function () { + Node.onDuplicate(editor.multiselection.nodes); + } + }); + + // create remove button + items.push({ + text: 'Remove', + title: 'Remove selected fields (Ctrl+Del)', + className: 'jsoneditor-remove', + click: function () { + Node.onRemove(editor.multiselection.nodes); + } + }); + + var menu = new ContextMenu(items, {close: onClose}); + menu.show(anchor, this.content); + }; + + + // define modes + module.exports = [ + { + mode: 'tree', + mixin: treemode, + data: 'json' + }, + { + mode: 'view', + mixin: treemode, + data: 'json' + }, + { + mode: 'form', + mixin: treemode, + data: 'json' + } + ]; + + +/***/ }, +/* 2 */ +/***/ function(module, exports) { + + 'use strict'; + + /** + * The highlighter can highlight/unhighlight a node, and + * animate the visibility of a context menu. + * @constructor Highlighter + */ + function Highlighter () { + this.locked = false; + } + + /** + * Hightlight given node and its childs + * @param {Node} node + */ + Highlighter.prototype.highlight = function (node) { + if (this.locked) { + return; + } + + if (this.node != node) { + // unhighlight current node + if (this.node) { + this.node.setHighlight(false); + } + + // highlight new node + this.node = node; + this.node.setHighlight(true); + } + + // cancel any current timeout + this._cancelUnhighlight(); + }; + + /** + * Unhighlight currently highlighted node. + * Will be done after a delay + */ + Highlighter.prototype.unhighlight = function () { + if (this.locked) { + return; + } + + var me = this; + if (this.node) { + this._cancelUnhighlight(); + + // do the unhighlighting after a small delay, to prevent re-highlighting + // the same node when moving from the drag-icon to the contextmenu-icon + // or vice versa. + this.unhighlightTimer = setTimeout(function () { + me.node.setHighlight(false); + me.node = undefined; + me.unhighlightTimer = undefined; + }, 0); + } + }; + + /** + * Cancel an unhighlight action (if before the timeout of the unhighlight action) + * @private + */ + Highlighter.prototype._cancelUnhighlight = function () { + if (this.unhighlightTimer) { + clearTimeout(this.unhighlightTimer); + this.unhighlightTimer = undefined; + } + }; + + /** + * Lock highlighting or unhighlighting nodes. + * methods highlight and unhighlight do not work while locked. + */ + Highlighter.prototype.lock = function () { + this.locked = true; + }; + + /** + * Unlock highlighting or unhighlighting nodes + */ + Highlighter.prototype.unlock = function () { + this.locked = false; + }; + + module.exports = Highlighter; + + +/***/ }, +/* 3 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var util = __webpack_require__(4); + + /** + * @constructor History + * Store action history, enables undo and redo + * @param {JSONEditor} editor + */ + function History (editor) { + this.editor = editor; + this.history = []; + this.index = -1; + + this.clear(); + + // map with all supported actions + this.actions = { + 'editField': { + 'undo': function (params) { + params.node.updateField(params.oldValue); + }, + 'redo': function (params) { + params.node.updateField(params.newValue); + } + }, + 'editValue': { + 'undo': function (params) { + params.node.updateValue(params.oldValue); + }, + 'redo': function (params) { + params.node.updateValue(params.newValue); + } + }, + 'changeType': { + 'undo': function (params) { + params.node.changeType(params.oldType); + }, + 'redo': function (params) { + params.node.changeType(params.newType); + } + }, + + 'appendNodes': { + 'undo': function (params) { + params.nodes.forEach(function (node) { + params.parent.removeChild(node); + }); + }, + 'redo': function (params) { + params.nodes.forEach(function (node) { + params.parent.appendChild(node); + }); + } + }, + 'insertBeforeNodes': { + 'undo': function (params) { + params.nodes.forEach(function (node) { + params.parent.removeChild(node); + }); + }, + 'redo': function (params) { + params.nodes.forEach(function (node) { + params.parent.insertBefore(node, params.beforeNode); + }); + } + }, + 'insertAfterNodes': { + 'undo': function (params) { + params.nodes.forEach(function (node) { + params.parent.removeChild(node); + }); + }, + 'redo': function (params) { + var afterNode = params.afterNode; + params.nodes.forEach(function (node) { + params.parent.insertAfter(params.node, afterNode); + afterNode = node; + }); + } + }, + 'removeNodes': { + 'undo': function (params) { + var parent = params.parent; + var beforeNode = parent.childs[params.index] || parent.append; + params.nodes.forEach(function (node) { + parent.insertBefore(node, beforeNode); + }); + }, + 'redo': function (params) { + params.nodes.forEach(function (node) { + params.parent.removeChild(node); + }); + } + }, + 'duplicateNodes': { + 'undo': function (params) { + params.nodes.forEach(function (node) { + params.parent.removeChild(node); + }); + }, + 'redo': function (params) { + var afterNode = params.afterNode; + params.nodes.forEach(function (node) { + params.parent.insertAfter(node, afterNode); + afterNode = node; + }); + } + }, + 'moveNodes': { + 'undo': function (params) { + params.nodes.forEach(function (node) { + params.oldBeforeNode.parent.moveBefore(node, params.oldBeforeNode); + }); + }, + 'redo': function (params) { + params.nodes.forEach(function (node) { + params.newBeforeNode.parent.moveBefore(node, params.newBeforeNode); + }); + } + }, + + 'sort': { + 'undo': function (params) { + var node = params.node; + node.hideChilds(); + node.sort = params.oldSort; + node.childs = params.oldChilds; + node.showChilds(); + }, + 'redo': function (params) { + var node = params.node; + node.hideChilds(); + node.sort = params.newSort; + node.childs = params.newChilds; + node.showChilds(); + } + } + + // TODO: restore the original caret position and selection with each undo + // TODO: implement history for actions "expand", "collapse", "scroll", "setDocument" + }; + } + + /** + * The method onChange is executed when the History is changed, and can + * be overloaded. + */ + History.prototype.onChange = function () {}; + + /** + * Add a new action to the history + * @param {String} action The executed action. Available actions: "editField", + * "editValue", "changeType", "appendNode", + * "removeNode", "duplicateNode", "moveNode" + * @param {Object} params Object containing parameters describing the change. + * The parameters in params depend on the action (for + * example for "editValue" the Node, old value, and new + * value are provided). params contains all information + * needed to undo or redo the action. + */ + History.prototype.add = function (action, params) { + this.index++; + this.history[this.index] = { + 'action': action, + 'params': params, + 'timestamp': new Date() + }; + + // remove redo actions which are invalid now + if (this.index < this.history.length - 1) { + this.history.splice(this.index + 1, this.history.length - this.index - 1); + } + + // fire onchange event + this.onChange(); + }; + + /** + * Clear history + */ + History.prototype.clear = function () { + this.history = []; + this.index = -1; + + // fire onchange event + this.onChange(); + }; + + /** + * Check if there is an action available for undo + * @return {Boolean} canUndo + */ + History.prototype.canUndo = function () { + return (this.index >= 0); + }; + + /** + * Check if there is an action available for redo + * @return {Boolean} canRedo + */ + History.prototype.canRedo = function () { + return (this.index < this.history.length - 1); + }; + + /** + * Undo the last action + */ + History.prototype.undo = function () { + if (this.canUndo()) { + var obj = this.history[this.index]; + if (obj) { + var action = this.actions[obj.action]; + if (action && action.undo) { + action.undo(obj.params); + if (obj.params.oldSelection) { + this.editor.setSelection(obj.params.oldSelection); + } + } + else { + console.error(new Error('unknown action "' + obj.action + '"')); + } + } + this.index--; + + // fire onchange event + this.onChange(); + } + }; + + /** + * Redo the last action + */ + History.prototype.redo = function () { + if (this.canRedo()) { + this.index++; + + var obj = this.history[this.index]; + if (obj) { + var action = this.actions[obj.action]; + if (action && action.redo) { + action.redo(obj.params); + if (obj.params.newSelection) { + this.editor.setSelection(obj.params.newSelection); + } + } + else { + console.error(new Error('unknown action "' + obj.action + '"')); + } + } + + // fire onchange event + this.onChange(); + } + }; + + /** + * Destroy history + */ + History.prototype.destroy = function () { + this.editor = null; + + this.history = []; + this.index = -1; + }; + + module.exports = History; + + +/***/ }, +/* 4 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var jsonlint = __webpack_require__(5); + + /** + * Parse JSON using the parser built-in in the browser. + * On exception, the jsonString is validated and a detailed error is thrown. + * @param {String} jsonString + * @return {JSON} json + */ + exports.parse = function parse(jsonString) { + try { + return JSON.parse(jsonString); + } + catch (err) { + // try to throw a more detailed error message using validate + exports.validate(jsonString); + + // rethrow the original error + throw err; + } + }; + + /** + * Sanitize a JSON-like string containing. For example changes JavaScript + * notation into JSON notation. + * This function for example changes a string like "{a: 2, 'b': {c: 'd'}" + * into '{"a": 2, "b": {"c": "d"}' + * @param {string} jsString + * @returns {string} json + */ + exports.sanitize = function (jsString) { + // escape all single and double quotes inside strings + var chars = []; + var i = 0; + + //If JSON starts with a function (characters/digits/"_-"), remove this function. + //This is useful for "stripping" JSONP objects to become JSON + //For example: /* some comment */ function_12321321 ( [{"a":"b"}] ); => [{"a":"b"}] + var match = jsString.match(/^\s*(\/\*(.|[\r\n])*?\*\/)?\s*[\da-zA-Z_$]+\s*\(([\s\S]*)\)\s*;?\s*$/); + if (match) { + jsString = match[3]; + } + + // helper functions to get the current/prev/next character + function curr () { return jsString.charAt(i); } + function next() { return jsString.charAt(i + 1); } + function prev() { return jsString.charAt(i - 1); } + + // get the last parsed non-whitespace character + function lastNonWhitespace () { + var p = chars.length - 1; + + while (p >= 0) { + var pp = chars[p]; + if (pp !== ' ' && pp !== '\n' && pp !== '\r' && pp !== '\t') { // non whitespace + return pp; + } + p--; + } + + return ''; + } + + // skip a block comment '/* ... */' + function skipBlockComment () { + i += 2; + while (i < jsString.length && (curr() !== '*' || next() !== '/')) { + i++; + } + i += 2; + } + + // skip a comment '// ...' + function skipComment () { + i += 2; + while (i < jsString.length && (curr() !== '\n')) { + i++; + } + } + + // parse single or double quoted string + function parseString(quote) { + chars.push('"'); + i++; + var c = curr(); + while (i < jsString.length && c !== quote) { + if (c === '"' && prev() !== '\\') { + // unescaped double quote, escape it + chars.push('\\'); + } + + // handle escape character + if (c === '\\') { + i++; + c = curr(); + + // remove the escape character when followed by a single quote ', not needed + if (c !== '\'') { + chars.push('\\'); + } + } + chars.push(c); + + i++; + c = curr(); + } + if (c === quote) { + chars.push('"'); + i++; + } + } + + // parse an unquoted key + function parseKey() { + var specialValues = ['null', 'true', 'false']; + var key = ''; + var c = curr(); + + var regexp = /[a-zA-Z_$\d]/; // letter, number, underscore, dollar character + while (regexp.test(c)) { + key += c; + i++; + c = curr(); + } + + if (specialValues.indexOf(key) === -1) { + chars.push('"' + key + '"'); + } + else { + chars.push(key); + } + } + + while(i < jsString.length) { + var c = curr(); + + if (c === '/' && next() === '*') { + skipBlockComment(); + } + else if (c === '/' && next() === '/') { + skipComment(); + } + else if (c === '\'' || c === '"') { + parseString(c); + } + else if (/[a-zA-Z_$]/.test(c) && ['{', ','].indexOf(lastNonWhitespace()) !== -1) { + // an unquoted object key (like a in '{a:2}') + parseKey(); + } + else { + chars.push(c); + i++; + } + } + + return chars.join(''); + }; + + /** + * Escape unicode characters. + * For example input '\u2661' (length 1) will output '\\u2661' (length 5). + * @param {string} text + * @return {string} + */ + exports.escapeUnicodeChars = function (text) { + // see https://www.wikiwand.com/en/UTF-16 + // note: we leave surrogate pairs as two individual chars, + // as JSON doesn't interpret them as a single unicode char. + return text.replace(/[\u007F-\uFFFF]/g, function(c) { + return '\\u'+('0000' + c.charCodeAt(0).toString(16)).slice(-4); + }) + }; + + /** + * Validate a string containing a JSON object + * This method uses JSONLint to validate the String. If JSONLint is not + * available, the built-in JSON parser of the browser is used. + * @param {String} jsonString String with an (invalid) JSON object + * @throws Error + */ + exports.validate = function validate(jsonString) { + if (typeof(jsonlint) != 'undefined') { + jsonlint.parse(jsonString); + } + else { + JSON.parse(jsonString); + } + }; + + /** + * Extend object a with the properties of object b + * @param {Object} a + * @param {Object} b + * @return {Object} a + */ + exports.extend = function extend(a, b) { + for (var prop in b) { + if (b.hasOwnProperty(prop)) { + a[prop] = b[prop]; + } + } + return a; + }; + + /** + * Remove all properties from object a + * @param {Object} a + * @return {Object} a + */ + exports.clear = function clear (a) { + for (var prop in a) { + if (a.hasOwnProperty(prop)) { + delete a[prop]; + } + } + return a; + }; + + /** + * Get the type of an object + * @param {*} object + * @return {String} type + */ + exports.type = function type (object) { + if (object === null) { + return 'null'; + } + if (object === undefined) { + return 'undefined'; + } + if ((object instanceof Number) || (typeof object === 'number')) { + return 'number'; + } + if ((object instanceof String) || (typeof object === 'string')) { + return 'string'; + } + if ((object instanceof Boolean) || (typeof object === 'boolean')) { + return 'boolean'; + } + if ((object instanceof RegExp) || (typeof object === 'regexp')) { + return 'regexp'; + } + if (exports.isArray(object)) { + return 'array'; + } + + return 'object'; + }; + + /** + * Test whether a text contains a url (matches when a string starts + * with 'http://*' or 'https://*' and has no whitespace characters) + * @param {String} text + */ + var isUrlRegex = /^https?:\/\/\S+$/; + exports.isUrl = function isUrl (text) { + return (typeof text == 'string' || text instanceof String) && + isUrlRegex.test(text); + }; + + /** + * Tes whether given object is an Array + * @param {*} obj + * @returns {boolean} returns true when obj is an array + */ + exports.isArray = function (obj) { + return Object.prototype.toString.call(obj) === '[object Array]'; + }; + + /** + * Retrieve the absolute left value of a DOM element + * @param {Element} elem A dom element, for example a div + * @return {Number} left The absolute left position of this element + * in the browser page. + */ + exports.getAbsoluteLeft = function getAbsoluteLeft(elem) { + var rect = elem.getBoundingClientRect(); + return rect.left + window.pageXOffset || document.scrollLeft || 0; + }; + + /** + * Retrieve the absolute top value of a DOM element + * @param {Element} elem A dom element, for example a div + * @return {Number} top The absolute top position of this element + * in the browser page. + */ + exports.getAbsoluteTop = function getAbsoluteTop(elem) { + var rect = elem.getBoundingClientRect(); + return rect.top + window.pageYOffset || document.scrollTop || 0; + }; + + /** + * add a className to the given elements style + * @param {Element} elem + * @param {String} className + */ + exports.addClassName = function addClassName(elem, className) { + var classes = elem.className.split(' '); + if (classes.indexOf(className) == -1) { + classes.push(className); // add the class to the array + elem.className = classes.join(' '); + } + }; + + /** + * add a className to the given elements style + * @param {Element} elem + * @param {String} className + */ + exports.removeClassName = function removeClassName(elem, className) { + var classes = elem.className.split(' '); + var index = classes.indexOf(className); + if (index != -1) { + classes.splice(index, 1); // remove the class from the array + elem.className = classes.join(' '); + } + }; + + /** + * Strip the formatting from the contents of a div + * the formatting from the div itself is not stripped, only from its childs. + * @param {Element} divElement + */ + exports.stripFormatting = function stripFormatting(divElement) { + var childs = divElement.childNodes; + for (var i = 0, iMax = childs.length; i < iMax; i++) { + var child = childs[i]; + + // remove the style + if (child.style) { + // TODO: test if child.attributes does contain style + child.removeAttribute('style'); + } + + // remove all attributes + var attributes = child.attributes; + if (attributes) { + for (var j = attributes.length - 1; j >= 0; j--) { + var attribute = attributes[j]; + if (attribute.specified === true) { + child.removeAttribute(attribute.name); + } + } + } + + // recursively strip childs + exports.stripFormatting(child); + } + }; + + /** + * Set focus to the end of an editable div + * code from Nico Burns + * http://stackoverflow.com/users/140293/nico-burns + * http://stackoverflow.com/questions/1125292/how-to-move-cursor-to-end-of-contenteditable-entity + * @param {Element} contentEditableElement A content editable div + */ + exports.setEndOfContentEditable = function setEndOfContentEditable(contentEditableElement) { + var range, selection; + if(document.createRange) { + range = document.createRange();//Create a range (a range is a like the selection but invisible) + range.selectNodeContents(contentEditableElement);//Select the entire contents of the element with the range + range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start + selection = window.getSelection();//get the selection object (allows you to change selection) + selection.removeAllRanges();//remove any selections already made + selection.addRange(range);//make the range you have just created the visible selection + } + }; + + /** + * Select all text of a content editable div. + * http://stackoverflow.com/a/3806004/1262753 + * @param {Element} contentEditableElement A content editable div + */ + exports.selectContentEditable = function selectContentEditable(contentEditableElement) { + if (!contentEditableElement || contentEditableElement.nodeName != 'DIV') { + return; + } + + var sel, range; + if (window.getSelection && document.createRange) { + range = document.createRange(); + range.selectNodeContents(contentEditableElement); + sel = window.getSelection(); + sel.removeAllRanges(); + sel.addRange(range); + } + }; + + /** + * Get text selection + * http://stackoverflow.com/questions/4687808/contenteditable-selected-text-save-and-restore + * @return {Range | TextRange | null} range + */ + exports.getSelection = function getSelection() { + if (window.getSelection) { + var sel = window.getSelection(); + if (sel.getRangeAt && sel.rangeCount) { + return sel.getRangeAt(0); + } + } + return null; + }; + + /** + * Set text selection + * http://stackoverflow.com/questions/4687808/contenteditable-selected-text-save-and-restore + * @param {Range | TextRange | null} range + */ + exports.setSelection = function setSelection(range) { + if (range) { + if (window.getSelection) { + var sel = window.getSelection(); + sel.removeAllRanges(); + sel.addRange(range); + } + } + }; + + /** + * Get selected text range + * @return {Object} params object containing parameters: + * {Number} startOffset + * {Number} endOffset + * {Element} container HTML element holding the + * selected text element + * Returns null if no text selection is found + */ + exports.getSelectionOffset = function getSelectionOffset() { + var range = exports.getSelection(); + + if (range && 'startOffset' in range && 'endOffset' in range && + range.startContainer && (range.startContainer == range.endContainer)) { + return { + startOffset: range.startOffset, + endOffset: range.endOffset, + container: range.startContainer.parentNode + }; + } + + return null; + }; + + /** + * Set selected text range in given element + * @param {Object} params An object containing: + * {Element} container + * {Number} startOffset + * {Number} endOffset + */ + exports.setSelectionOffset = function setSelectionOffset(params) { + if (document.createRange && window.getSelection) { + var selection = window.getSelection(); + if(selection) { + var range = document.createRange(); + + if (!params.container.firstChild) { + params.container.appendChild(document.createTextNode('')); + } + + // TODO: do not suppose that the first child of the container is a textnode, + // but recursively find the textnodes + range.setStart(params.container.firstChild, params.startOffset); + range.setEnd(params.container.firstChild, params.endOffset); + + exports.setSelection(range); + } + } + }; + + /** + * Get the inner text of an HTML element (for example a div element) + * @param {Element} element + * @param {Object} [buffer] + * @return {String} innerText + */ + exports.getInnerText = function getInnerText(element, buffer) { + var first = (buffer == undefined); + if (first) { + buffer = { + 'text': '', + 'flush': function () { + var text = this.text; + this.text = ''; + return text; + }, + 'set': function (text) { + this.text = text; + } + }; + } + + // text node + if (element.nodeValue) { + return buffer.flush() + element.nodeValue; + } + + // divs or other HTML elements + if (element.hasChildNodes()) { + var childNodes = element.childNodes; + var innerText = ''; + + for (var i = 0, iMax = childNodes.length; i < iMax; i++) { + var child = childNodes[i]; + + if (child.nodeName == 'DIV' || child.nodeName == 'P') { + var prevChild = childNodes[i - 1]; + var prevName = prevChild ? prevChild.nodeName : undefined; + if (prevName && prevName != 'DIV' && prevName != 'P' && prevName != 'BR') { + innerText += '\n'; + buffer.flush(); + } + innerText += exports.getInnerText(child, buffer); + buffer.set('\n'); + } + else if (child.nodeName == 'BR') { + innerText += buffer.flush(); + buffer.set('\n'); + } + else { + innerText += exports.getInnerText(child, buffer); + } + } + + return innerText; + } + else { + if (element.nodeName == 'P' && exports.getInternetExplorerVersion() != -1) { + // On Internet Explorer, a

with hasChildNodes()==false is + // rendered with a new line. Note that a

with + // hasChildNodes()==true is rendered without a new line + // Other browsers always ensure there is a
inside the

, + // and if not, the

does not render a new line + return buffer.flush(); + } + } + + // br or unknown + return ''; + }; + + /** + * Returns the version of Internet Explorer or a -1 + * (indicating the use of another browser). + * Source: http://msdn.microsoft.com/en-us/library/ms537509(v=vs.85).aspx + * @return {Number} Internet Explorer version, or -1 in case of an other browser + */ + exports.getInternetExplorerVersion = function getInternetExplorerVersion() { + if (_ieVersion == -1) { + var rv = -1; // Return value assumes failure. + if (navigator.appName == 'Microsoft Internet Explorer') + { + var ua = navigator.userAgent; + var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})"); + if (re.exec(ua) != null) { + rv = parseFloat( RegExp.$1 ); + } + } + + _ieVersion = rv; + } + + return _ieVersion; + }; + + /** + * Test whether the current browser is Firefox + * @returns {boolean} isFirefox + */ + exports.isFirefox = function isFirefox () { + return (navigator.userAgent.indexOf("Firefox") != -1); + }; + + /** + * cached internet explorer version + * @type {Number} + * @private + */ + var _ieVersion = -1; + + /** + * Add and event listener. Works for all browsers + * @param {Element} element An html element + * @param {string} action The action, for example "click", + * without the prefix "on" + * @param {function} listener The callback function to be executed + * @param {boolean} [useCapture] false by default + * @return {function} the created event listener + */ + exports.addEventListener = function addEventListener(element, action, listener, useCapture) { + if (element.addEventListener) { + if (useCapture === undefined) + useCapture = false; + + if (action === "mousewheel" && exports.isFirefox()) { + action = "DOMMouseScroll"; // For Firefox + } + + element.addEventListener(action, listener, useCapture); + return listener; + } else if (element.attachEvent) { + // Old IE browsers + var f = function () { + return listener.call(element, window.event); + }; + element.attachEvent("on" + action, f); + return f; + } + }; + + /** + * Remove an event listener from an element + * @param {Element} element An html dom element + * @param {string} action The name of the event, for example "mousedown" + * @param {function} listener The listener function + * @param {boolean} [useCapture] false by default + */ + exports.removeEventListener = function removeEventListener(element, action, listener, useCapture) { + if (element.removeEventListener) { + if (useCapture === undefined) + useCapture = false; + + if (action === "mousewheel" && exports.isFirefox()) { + action = "DOMMouseScroll"; // For Firefox + } + + element.removeEventListener(action, listener, useCapture); + } else if (element.detachEvent) { + // Old IE browsers + element.detachEvent("on" + action, listener); + } + }; + + /** + * Parse a JSON path like '.items[3].name' into an array + * @param {string} jsonPath + * @return {Array} + */ + exports.parsePath = function parsePath(jsonPath) { + var prop, remainder; + + if (jsonPath.length === 0) { + return []; + } + + // find a match like '.prop' + var match = jsonPath.match(/^\.(\w+)/); + if (match) { + prop = match[1]; + remainder = jsonPath.substr(prop.length + 1); + } + else if (jsonPath[0] === '[') { + // find a match like + var end = jsonPath.indexOf(']'); + if (end === -1) { + throw new SyntaxError('Character ] expected in path'); + } + if (end === 1) { + throw new SyntaxError('Index expected after ['); + } + + var value = jsonPath.substring(1, end); + if (value[0] === '\'') { + // ajv produces string prop names with single quotes, so we need + // to reformat them into valid double-quoted JSON strings + value = '\"' + value.substring(1, value.length - 1) + '\"'; + } + + prop = value === '*' ? value : JSON.parse(value); // parse string and number + remainder = jsonPath.substr(end + 1); + } + else { + throw new SyntaxError('Failed to parse path'); + } + + return [prop].concat(parsePath(remainder)) + }; + + /** + * Improve the error message of a JSON schema error + * @param {Object} error + * @return {Object} The error + */ + exports.improveSchemaError = function (error) { + if (error.keyword === 'enum' && Array.isArray(error.schema)) { + var enums = error.schema; + if (enums) { + enums = enums.map(function (value) { + return JSON.stringify(value); + }); + + if (enums.length > 5) { + var more = ['(' + (enums.length - 5) + ' more...)']; + enums = enums.slice(0, 5); + enums.push(more); + } + error.message = 'should be equal to one of: ' + enums.join(', '); + } + } + + if (error.keyword === 'additionalProperties') { + error.message = 'should NOT have additional property: ' + error.params.additionalProperty; + } + + return error; + }; + + /** + * Test whether the child rect fits completely inside the parent rect. + * @param {ClientRect} parent + * @param {ClientRect} child + * @param {number} margin + */ + exports.insideRect = function (parent, child, margin) { + var _margin = margin !== undefined ? margin : 0; + return child.left - _margin >= parent.left + && child.right + _margin <= parent.right + && child.top - _margin >= parent.top + && child.bottom + _margin <= parent.bottom; + }; + + /** + * Returns a function, that, as long as it continues to be invoked, will not + * be triggered. The function will be called after it stops being called for + * N milliseconds. + * + * Source: https://davidwalsh.name/javascript-debounce-function + * + * @param {function} func + * @param {number} wait Number in milliseconds + * @param {boolean} [immediate=false] If `immediate` is passed, trigger the + * function on the leading edge, instead + * of the trailing. + * @return {function} Return the debounced function + */ + exports.debounce = function debounce(func, wait, immediate) { + var timeout; + return function() { + var context = this, args = arguments; + var later = function() { + timeout = null; + if (!immediate) func.apply(context, args); + }; + var callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) func.apply(context, args); + }; + }; + + /** + * Determines the difference between two texts. + * Can only detect one removed or inserted block of characters. + * @param {string} oldText + * @param {string} newText + * @return {{start: number, end: number}} Returns the start and end + * of the changed part in newText. + */ + exports.textDiff = function textDiff(oldText, newText) { + var len = newText.length; + var start = 0; + var oldEnd = oldText.length; + var newEnd = newText.length; + + while (newText.charAt(start) === oldText.charAt(start) + && start < len) { + start++; + } + + while (newText.charAt(newEnd - 1) === oldText.charAt(oldEnd - 1) + && newEnd > start && oldEnd > 0) { + newEnd--; + oldEnd--; + } + + return {start: start, end: newEnd}; + }; + + +/***/ }, +/* 5 */ +/***/ function(module, exports, __webpack_require__) { + + /* Jison generated parser */ + var jsonlint = (function(){ + var parser = {trace: function trace() { }, + yy: {}, + symbols_: {"error":2,"JSONString":3,"STRING":4,"JSONNumber":5,"NUMBER":6,"JSONNullLiteral":7,"NULL":8,"JSONBooleanLiteral":9,"TRUE":10,"FALSE":11,"JSONText":12,"JSONValue":13,"EOF":14,"JSONObject":15,"JSONArray":16,"{":17,"}":18,"JSONMemberList":19,"JSONMember":20,":":21,",":22,"[":23,"]":24,"JSONElementList":25,"$accept":0,"$end":1}, + terminals_: {2:"error",4:"STRING",6:"NUMBER",8:"NULL",10:"TRUE",11:"FALSE",14:"EOF",17:"{",18:"}",21:":",22:",",23:"[",24:"]"}, + productions_: [0,[3,1],[5,1],[7,1],[9,1],[9,1],[12,2],[13,1],[13,1],[13,1],[13,1],[13,1],[13,1],[15,2],[15,3],[20,3],[19,1],[19,3],[16,2],[16,3],[25,1],[25,3]], + performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) { + + var $0 = $$.length - 1; + switch (yystate) { + case 1: // replace escaped characters with actual character + this.$ = yytext.replace(/\\(\\|")/g, "$"+"1") + .replace(/\\n/g,'\n') + .replace(/\\r/g,'\r') + .replace(/\\t/g,'\t') + .replace(/\\v/g,'\v') + .replace(/\\f/g,'\f') + .replace(/\\b/g,'\b'); + + break; + case 2:this.$ = Number(yytext); + break; + case 3:this.$ = null; + break; + case 4:this.$ = true; + break; + case 5:this.$ = false; + break; + case 6:return this.$ = $$[$0-1]; + break; + case 13:this.$ = {}; + break; + case 14:this.$ = $$[$0-1]; + break; + case 15:this.$ = [$$[$0-2], $$[$0]]; + break; + case 16:this.$ = {}; this.$[$$[$0][0]] = $$[$0][1]; + break; + case 17:this.$ = $$[$0-2]; $$[$0-2][$$[$0][0]] = $$[$0][1]; + break; + case 18:this.$ = []; + break; + case 19:this.$ = $$[$0-1]; + break; + case 20:this.$ = [$$[$0]]; + break; + case 21:this.$ = $$[$0-2]; $$[$0-2].push($$[$0]); + break; + } + }, + table: [{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],12:1,13:2,15:7,16:8,17:[1,14],23:[1,15]},{1:[3]},{14:[1,16]},{14:[2,7],18:[2,7],22:[2,7],24:[2,7]},{14:[2,8],18:[2,8],22:[2,8],24:[2,8]},{14:[2,9],18:[2,9],22:[2,9],24:[2,9]},{14:[2,10],18:[2,10],22:[2,10],24:[2,10]},{14:[2,11],18:[2,11],22:[2,11],24:[2,11]},{14:[2,12],18:[2,12],22:[2,12],24:[2,12]},{14:[2,3],18:[2,3],22:[2,3],24:[2,3]},{14:[2,4],18:[2,4],22:[2,4],24:[2,4]},{14:[2,5],18:[2,5],22:[2,5],24:[2,5]},{14:[2,1],18:[2,1],21:[2,1],22:[2,1],24:[2,1]},{14:[2,2],18:[2,2],22:[2,2],24:[2,2]},{3:20,4:[1,12],18:[1,17],19:18,20:19},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:23,15:7,16:8,17:[1,14],23:[1,15],24:[1,21],25:22},{1:[2,6]},{14:[2,13],18:[2,13],22:[2,13],24:[2,13]},{18:[1,24],22:[1,25]},{18:[2,16],22:[2,16]},{21:[1,26]},{14:[2,18],18:[2,18],22:[2,18],24:[2,18]},{22:[1,28],24:[1,27]},{22:[2,20],24:[2,20]},{14:[2,14],18:[2,14],22:[2,14],24:[2,14]},{3:20,4:[1,12],20:29},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:30,15:7,16:8,17:[1,14],23:[1,15]},{14:[2,19],18:[2,19],22:[2,19],24:[2,19]},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:31,15:7,16:8,17:[1,14],23:[1,15]},{18:[2,17],22:[2,17]},{18:[2,15],22:[2,15]},{22:[2,21],24:[2,21]}], + defaultActions: {16:[2,6]}, + parseError: function parseError(str, hash) { + throw new Error(str); + }, + parse: function parse(input) { + var self = this, + stack = [0], + vstack = [null], // semantic value stack + lstack = [], // location stack + table = this.table, + yytext = '', + yylineno = 0, + yyleng = 0, + recovering = 0, + TERROR = 2, + EOF = 1; + + //this.reductionCount = this.shiftCount = 0; + + this.lexer.setInput(input); + this.lexer.yy = this.yy; + this.yy.lexer = this.lexer; + if (typeof this.lexer.yylloc == 'undefined') + this.lexer.yylloc = {}; + var yyloc = this.lexer.yylloc; + lstack.push(yyloc); + + if (typeof this.yy.parseError === 'function') + this.parseError = this.yy.parseError; + + function popStack (n) { + stack.length = stack.length - 2*n; + vstack.length = vstack.length - n; + lstack.length = lstack.length - n; + } + + function lex() { + var token; + token = self.lexer.lex() || 1; // $end = 1 + // if token isn't its numeric value, convert + if (typeof token !== 'number') { + token = self.symbols_[token] || token; + } + return token; + } + + var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected; + while (true) { + // retreive state number from top of stack + state = stack[stack.length-1]; + + // use default actions if available + if (this.defaultActions[state]) { + action = this.defaultActions[state]; + } else { + if (symbol == null) + symbol = lex(); + // read action for current state and first input + action = table[state] && table[state][symbol]; + } + + // handle parse error + _handle_error: + if (typeof action === 'undefined' || !action.length || !action[0]) { + + if (!recovering) { + // Report error + expected = []; + for (p in table[state]) if (this.terminals_[p] && p > 2) { + expected.push("'"+this.terminals_[p]+"'"); + } + var errStr = ''; + if (this.lexer.showPosition) { + errStr = 'Parse error on line '+(yylineno+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+expected.join(', ') + ", got '" + this.terminals_[symbol]+ "'"; + } else { + errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " + + (symbol == 1 /*EOF*/ ? "end of input" : + ("'"+(this.terminals_[symbol] || symbol)+"'")); + } + this.parseError(errStr, + {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected}); + } + + // just recovered from another error + if (recovering == 3) { + if (symbol == EOF) { + throw new Error(errStr || 'Parsing halted.'); + } + + // discard current lookahead and grab another + yyleng = this.lexer.yyleng; + yytext = this.lexer.yytext; + yylineno = this.lexer.yylineno; + yyloc = this.lexer.yylloc; + symbol = lex(); + } + + // try to recover from error + while (1) { + // check for error recovery rule in this state + if ((TERROR.toString()) in table[state]) { + break; + } + if (state == 0) { + throw new Error(errStr || 'Parsing halted.'); + } + popStack(1); + state = stack[stack.length-1]; + } + + preErrorSymbol = symbol; // save the lookahead token + symbol = TERROR; // insert generic error symbol as new lookahead + state = stack[stack.length-1]; + action = table[state] && table[state][TERROR]; + recovering = 3; // allow 3 real symbols to be shifted before reporting a new error + } + + // this shouldn't happen, unless resolve defaults are off + if (action[0] instanceof Array && action.length > 1) { + throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol); + } + + switch (action[0]) { + + case 1: // shift + //this.shiftCount++; + + stack.push(symbol); + vstack.push(this.lexer.yytext); + lstack.push(this.lexer.yylloc); + stack.push(action[1]); // push state + symbol = null; + if (!preErrorSymbol) { // normal execution/no error + yyleng = this.lexer.yyleng; + yytext = this.lexer.yytext; + yylineno = this.lexer.yylineno; + yyloc = this.lexer.yylloc; + if (recovering > 0) + recovering--; + } else { // error just occurred, resume old lookahead f/ before error + symbol = preErrorSymbol; + preErrorSymbol = null; + } + break; + + case 2: // reduce + //this.reductionCount++; + + len = this.productions_[action[1]][1]; + + // perform semantic action + yyval.$ = vstack[vstack.length-len]; // default to $$ = $1 + // default location, uses first token for firsts, last for lasts + yyval._$ = { + first_line: lstack[lstack.length-(len||1)].first_line, + last_line: lstack[lstack.length-1].last_line, + first_column: lstack[lstack.length-(len||1)].first_column, + last_column: lstack[lstack.length-1].last_column + }; + r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); + + if (typeof r !== 'undefined') { + return r; + } + + // pop off stack + if (len) { + stack = stack.slice(0,-1*len*2); + vstack = vstack.slice(0, -1*len); + lstack = lstack.slice(0, -1*len); + } + + stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce) + vstack.push(yyval.$); + lstack.push(yyval._$); + // goto new state = table[STATE][NONTERMINAL] + newState = table[stack[stack.length-2]][stack[stack.length-1]]; + stack.push(newState); + break; + + case 3: // accept + return true; + } + + } + + return true; + }}; + /* Jison generated lexer */ + var lexer = (function(){ + var lexer = ({EOF:1, + parseError:function parseError(str, hash) { + if (this.yy.parseError) { + this.yy.parseError(str, hash); + } else { + throw new Error(str); + } + }, + setInput:function (input) { + this._input = input; + this._more = this._less = this.done = false; + this.yylineno = this.yyleng = 0; + this.yytext = this.matched = this.match = ''; + this.conditionStack = ['INITIAL']; + this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0}; + return this; + }, + input:function () { + var ch = this._input[0]; + this.yytext+=ch; + this.yyleng++; + this.match+=ch; + this.matched+=ch; + var lines = ch.match(/\n/); + if (lines) this.yylineno++; + this._input = this._input.slice(1); + return ch; + }, + unput:function (ch) { + this._input = ch + this._input; + return this; + }, + more:function () { + this._more = true; + return this; + }, + less:function (n) { + this._input = this.match.slice(n) + this._input; + }, + pastInput:function () { + var past = this.matched.substr(0, this.matched.length - this.match.length); + return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, ""); + }, + upcomingInput:function () { + var next = this.match; + if (next.length < 20) { + next += this._input.substr(0, 20-next.length); + } + return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, ""); + }, + showPosition:function () { + var pre = this.pastInput(); + var c = new Array(pre.length + 1).join("-"); + return pre + this.upcomingInput() + "\n" + c+"^"; + }, + next:function () { + if (this.done) { + return this.EOF; + } + if (!this._input) this.done = true; + + var token, + match, + tempMatch, + index, + col, + lines; + if (!this._more) { + this.yytext = ''; + this.match = ''; + } + var rules = this._currentRules(); + for (var i=0;i < rules.length; i++) { + tempMatch = this._input.match(this.rules[rules[i]]); + if (tempMatch && (!match || tempMatch[0].length > match[0].length)) { + match = tempMatch; + index = i; + if (!this.options.flex) break; + } + } + if (match) { + lines = match[0].match(/\n.*/g); + if (lines) this.yylineno += lines.length; + this.yylloc = {first_line: this.yylloc.last_line, + last_line: this.yylineno+1, + first_column: this.yylloc.last_column, + last_column: lines ? lines[lines.length-1].length-1 : this.yylloc.last_column + match[0].length} + this.yytext += match[0]; + this.match += match[0]; + this.yyleng = this.yytext.length; + this._more = false; + this._input = this._input.slice(match[0].length); + this.matched += match[0]; + token = this.performAction.call(this, this.yy, this, rules[index],this.conditionStack[this.conditionStack.length-1]); + if (this.done && this._input) this.done = false; + if (token) return token; + else return; + } + if (this._input === "") { + return this.EOF; + } else { + this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(), + {text: "", token: null, line: this.yylineno}); + } + }, + lex:function lex() { + var r = this.next(); + if (typeof r !== 'undefined') { + return r; + } else { + return this.lex(); + } + }, + begin:function begin(condition) { + this.conditionStack.push(condition); + }, + popState:function popState() { + return this.conditionStack.pop(); + }, + _currentRules:function _currentRules() { + return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules; + }, + topState:function () { + return this.conditionStack[this.conditionStack.length-2]; + }, + pushState:function begin(condition) { + this.begin(condition); + }}); + lexer.options = {}; + lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) { + + var YYSTATE=YY_START + switch($avoiding_name_collisions) { + case 0:/* skip whitespace */ + break; + case 1:return 6 + break; + case 2:yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2); return 4 + break; + case 3:return 17 + break; + case 4:return 18 + break; + case 5:return 23 + break; + case 6:return 24 + break; + case 7:return 22 + break; + case 8:return 21 + break; + case 9:return 10 + break; + case 10:return 11 + break; + case 11:return 8 + break; + case 12:return 14 + break; + case 13:return 'INVALID' + break; + } + }; + lexer.rules = [/^(?:\s+)/,/^(?:(-?([0-9]|[1-9][0-9]+))(\.[0-9]+)?([eE][-+]?[0-9]+)?\b)/,/^(?:"(?:\\[\\"bfnrt/]|\\u[a-fA-F0-9]{4}|[^\\\0-\x09\x0a-\x1f"])*")/,/^(?:\{)/,/^(?:\})/,/^(?:\[)/,/^(?:\])/,/^(?:,)/,/^(?::)/,/^(?:true\b)/,/^(?:false\b)/,/^(?:null\b)/,/^(?:$)/,/^(?:.)/]; + lexer.conditions = {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13],"inclusive":true}}; + + + ; + return lexer;})() + parser.lexer = lexer; + return parser; + })(); + if (true) { + exports.parser = jsonlint; + exports.parse = jsonlint.parse.bind(jsonlint); + } + +/***/ }, +/* 6 */ +/***/ function(module, exports) { + + 'use strict'; + + /** + * @constructor SearchBox + * Create a search box in given HTML container + * @param {JSONEditor} editor The JSON Editor to attach to + * @param {Element} container HTML container element of where to + * create the search box + */ + function SearchBox (editor, container) { + var searchBox = this; + + this.editor = editor; + this.timeout = undefined; + this.delay = 200; // ms + this.lastText = undefined; + + this.dom = {}; + this.dom.container = container; + + var table = document.createElement('table'); + this.dom.table = table; + table.className = 'jsoneditor-search'; + container.appendChild(table); + var tbody = document.createElement('tbody'); + this.dom.tbody = tbody; + table.appendChild(tbody); + var tr = document.createElement('tr'); + tbody.appendChild(tr); + + var td = document.createElement('td'); + tr.appendChild(td); + var results = document.createElement('div'); + this.dom.results = results; + results.className = 'jsoneditor-results'; + td.appendChild(results); + + td = document.createElement('td'); + tr.appendChild(td); + var divInput = document.createElement('div'); + this.dom.input = divInput; + divInput.className = 'jsoneditor-frame'; + divInput.title = 'Search fields and values'; + td.appendChild(divInput); + + // table to contain the text input and search button + var tableInput = document.createElement('table'); + divInput.appendChild(tableInput); + var tbodySearch = document.createElement('tbody'); + tableInput.appendChild(tbodySearch); + tr = document.createElement('tr'); + tbodySearch.appendChild(tr); + + var refreshSearch = document.createElement('button'); + refreshSearch.type = 'button'; + refreshSearch.className = 'jsoneditor-refresh'; + td = document.createElement('td'); + td.appendChild(refreshSearch); + tr.appendChild(td); + + var search = document.createElement('input'); + // search.type = 'button'; + this.dom.search = search; + search.oninput = function (event) { + searchBox._onDelayedSearch(event); + }; + search.onchange = function (event) { // For IE 9 + searchBox._onSearch(); + }; + search.onkeydown = function (event) { + searchBox._onKeyDown(event); + }; + search.onkeyup = function (event) { + searchBox._onKeyUp(event); + }; + refreshSearch.onclick = function (event) { + search.select(); + }; + + // TODO: ESC in FF restores the last input, is a FF bug, https://bugzilla.mozilla.org/show_bug.cgi?id=598819 + td = document.createElement('td'); + td.appendChild(search); + tr.appendChild(td); + + var searchNext = document.createElement('button'); + searchNext.type = 'button'; + searchNext.title = 'Next result (Enter)'; + searchNext.className = 'jsoneditor-next'; + searchNext.onclick = function () { + searchBox.next(); + }; + td = document.createElement('td'); + td.appendChild(searchNext); + tr.appendChild(td); + + var searchPrevious = document.createElement('button'); + searchPrevious.type = 'button'; + searchPrevious.title = 'Previous result (Shift+Enter)'; + searchPrevious.className = 'jsoneditor-previous'; + searchPrevious.onclick = function () { + searchBox.previous(); + }; + td = document.createElement('td'); + td.appendChild(searchPrevious); + tr.appendChild(td); + } + + /** + * Go to the next search result + * @param {boolean} [focus] If true, focus will be set to the next result + * focus is false by default. + */ + SearchBox.prototype.next = function(focus) { + if (this.results != undefined) { + var index = (this.resultIndex != undefined) ? this.resultIndex + 1 : 0; + if (index > this.results.length - 1) { + index = 0; + } + this._setActiveResult(index, focus); + } + }; + + /** + * Go to the prevous search result + * @param {boolean} [focus] If true, focus will be set to the next result + * focus is false by default. + */ + SearchBox.prototype.previous = function(focus) { + if (this.results != undefined) { + var max = this.results.length - 1; + var index = (this.resultIndex != undefined) ? this.resultIndex - 1 : max; + if (index < 0) { + index = max; + } + this._setActiveResult(index, focus); + } + }; + + /** + * Set new value for the current active result + * @param {Number} index + * @param {boolean} [focus] If true, focus will be set to the next result. + * focus is false by default. + * @private + */ + SearchBox.prototype._setActiveResult = function(index, focus) { + // de-activate current active result + if (this.activeResult) { + var prevNode = this.activeResult.node; + var prevElem = this.activeResult.elem; + if (prevElem == 'field') { + delete prevNode.searchFieldActive; + } + else { + delete prevNode.searchValueActive; + } + prevNode.updateDom(); + } + + if (!this.results || !this.results[index]) { + // out of range, set to undefined + this.resultIndex = undefined; + this.activeResult = undefined; + return; + } + + this.resultIndex = index; + + // set new node active + var node = this.results[this.resultIndex].node; + var elem = this.results[this.resultIndex].elem; + if (elem == 'field') { + node.searchFieldActive = true; + } + else { + node.searchValueActive = true; + } + this.activeResult = this.results[this.resultIndex]; + node.updateDom(); + + // TODO: not so nice that the focus is only set after the animation is finished + node.scrollTo(function () { + if (focus) { + node.focus(elem); + } + }); + }; + + /** + * Cancel any running onDelayedSearch. + * @private + */ + SearchBox.prototype._clearDelay = function() { + if (this.timeout != undefined) { + clearTimeout(this.timeout); + delete this.timeout; + } + }; + + /** + * Start a timer to execute a search after a short delay. + * Used for reducing the number of searches while typing. + * @param {Event} event + * @private + */ + SearchBox.prototype._onDelayedSearch = function (event) { + // execute the search after a short delay (reduces the number of + // search actions while typing in the search text box) + this._clearDelay(); + var searchBox = this; + this.timeout = setTimeout(function (event) { + searchBox._onSearch(); + }, + this.delay); + }; + + /** + * Handle onSearch event + * @param {boolean} [forceSearch] If true, search will be executed again even + * when the search text is not changed. + * Default is false. + * @private + */ + SearchBox.prototype._onSearch = function (forceSearch) { + this._clearDelay(); + + var value = this.dom.search.value; + var text = (value.length > 0) ? value : undefined; + if (text != this.lastText || forceSearch) { + // only search again when changed + this.lastText = text; + this.results = this.editor.search(text); + this._setActiveResult(undefined); + + // display search results + if (text != undefined) { + var resultCount = this.results.length; + switch (resultCount) { + case 0: this.dom.results.innerHTML = 'no results'; break; + case 1: this.dom.results.innerHTML = '1 result'; break; + default: this.dom.results.innerHTML = resultCount + ' results'; break; + } + } + else { + this.dom.results.innerHTML = ''; + } + } + }; + + /** + * Handle onKeyDown event in the input box + * @param {Event} event + * @private + */ + SearchBox.prototype._onKeyDown = function (event) { + var keynum = event.which; + if (keynum == 27) { // ESC + this.dom.search.value = ''; // clear search + this._onSearch(); + event.preventDefault(); + event.stopPropagation(); + } + else if (keynum == 13) { // Enter + if (event.ctrlKey) { + // force to search again + this._onSearch(true); + } + else if (event.shiftKey) { + // move to the previous search result + this.previous(); + } + else { + // move to the next search result + this.next(); + } + event.preventDefault(); + event.stopPropagation(); + } + }; + + /** + * Handle onKeyUp event in the input box + * @param {Event} event + * @private + */ + SearchBox.prototype._onKeyUp = function (event) { + var keynum = event.keyCode; + if (keynum != 27 && keynum != 13) { // !show and !Enter + this._onDelayedSearch(event); // For IE 9 + } + }; + + /** + * Clear the search results + */ + SearchBox.prototype.clear = function () { + this.dom.search.value = ''; + this._onSearch(); + }; + + /** + * Destroy the search box + */ + SearchBox.prototype.destroy = function () { + this.editor = null; + this.dom.container.removeChild(this.dom.table); + this.dom = null; + + this.results = null; + this.activeResult = null; + + this._clearDelay(); + + }; + + module.exports = SearchBox; + + +/***/ }, +/* 7 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var util = __webpack_require__(4); + + /** + * A context menu + * @param {Object[]} items Array containing the menu structure + * TODO: describe structure + * @param {Object} [options] Object with options. Available options: + * {function} close Callback called when the + * context menu is being closed. + * @constructor + */ + function ContextMenu (items, options) { + this.dom = {}; + + var me = this; + var dom = this.dom; + this.anchor = undefined; + this.items = items; + this.eventListeners = {}; + this.selection = undefined; // holds the selection before the menu was opened + this.onClose = options ? options.close : undefined; + + // create root element + var root = document.createElement('div'); + root.className = 'jsoneditor-contextmenu-root'; + dom.root = root; + + // create a container element + var menu = document.createElement('div'); + menu.className = 'jsoneditor-contextmenu'; + dom.menu = menu; + root.appendChild(menu); + + // create a list to hold the menu items + var list = document.createElement('ul'); + list.className = 'jsoneditor-menu'; + menu.appendChild(list); + dom.list = list; + dom.items = []; // list with all buttons + + // create a (non-visible) button to set the focus to the menu + var focusButton = document.createElement('button'); + focusButton.type = 'button'; + dom.focusButton = focusButton; + var li = document.createElement('li'); + li.style.overflow = 'hidden'; + li.style.height = '0'; + li.appendChild(focusButton); + list.appendChild(li); + + function createMenuItems (list, domItems, items) { + items.forEach(function (item) { + if (item.type == 'separator') { + // create a separator + var separator = document.createElement('div'); + separator.className = 'jsoneditor-separator'; + li = document.createElement('li'); + li.appendChild(separator); + list.appendChild(li); + } + else { + var domItem = {}; + + // create a menu item + var li = document.createElement('li'); + list.appendChild(li); + + // create a button in the menu item + var button = document.createElement('button'); + button.type = 'button'; + button.className = item.className; + domItem.button = button; + if (item.title) { + button.title = item.title; + } + if (item.click) { + button.onclick = function (event) { + event.preventDefault(); + me.hide(); + item.click(); + }; + } + li.appendChild(button); + + // create the contents of the button + if (item.submenu) { + // add the icon to the button + var divIcon = document.createElement('div'); + divIcon.className = 'jsoneditor-icon'; + button.appendChild(divIcon); + button.appendChild(document.createTextNode(item.text)); + + var buttonSubmenu; + if (item.click) { + // submenu and a button with a click handler + button.className += ' jsoneditor-default'; + + var buttonExpand = document.createElement('button'); + buttonExpand.type = 'button'; + domItem.buttonExpand = buttonExpand; + buttonExpand.className = 'jsoneditor-expand'; + buttonExpand.innerHTML = '

'; + li.appendChild(buttonExpand); + if (item.submenuTitle) { + buttonExpand.title = item.submenuTitle; + } + + buttonSubmenu = buttonExpand; + } + else { + // submenu and a button without a click handler + var divExpand = document.createElement('div'); + divExpand.className = 'jsoneditor-expand'; + button.appendChild(divExpand); + + buttonSubmenu = button; + } + + // attach a handler to expand/collapse the submenu + buttonSubmenu.onclick = function (event) { + event.preventDefault(); + me._onExpandItem(domItem); + buttonSubmenu.focus(); + }; + + // create the submenu + var domSubItems = []; + domItem.subItems = domSubItems; + var ul = document.createElement('ul'); + domItem.ul = ul; + ul.className = 'jsoneditor-menu'; + ul.style.height = '0'; + li.appendChild(ul); + createMenuItems(ul, domSubItems, item.submenu); + } + else { + // no submenu, just a button with clickhandler + button.innerHTML = '
' + item.text; + } + + domItems.push(domItem); + } + }); + } + createMenuItems(list, this.dom.items, items); + + // TODO: when the editor is small, show the submenu on the right instead of inline? + + // calculate the max height of the menu with one submenu expanded + this.maxHeight = 0; // height in pixels + items.forEach(function (item) { + var height = (items.length + (item.submenu ? item.submenu.length : 0)) * 24; + me.maxHeight = Math.max(me.maxHeight, height); + }); + } + + /** + * Get the currently visible buttons + * @return {Array.} buttons + * @private + */ + ContextMenu.prototype._getVisibleButtons = function () { + var buttons = []; + var me = this; + this.dom.items.forEach(function (item) { + buttons.push(item.button); + if (item.buttonExpand) { + buttons.push(item.buttonExpand); + } + if (item.subItems && item == me.expandedItem) { + item.subItems.forEach(function (subItem) { + buttons.push(subItem.button); + if (subItem.buttonExpand) { + buttons.push(subItem.buttonExpand); + } + // TODO: change to fully recursive method + }); + } + }); + + return buttons; + }; + + // currently displayed context menu, a singleton. We may only have one visible context menu + ContextMenu.visibleMenu = undefined; + + /** + * Attach the menu to an anchor + * @param {HTMLElement} anchor Anchor where the menu will be attached + * as sibling. + * @param {HTMLElement} [contentWindow] The DIV with with the (scrollable) contents + */ + ContextMenu.prototype.show = function (anchor, contentWindow) { + this.hide(); + + // determine whether to display the menu below or above the anchor + var showBelow = true; + if (contentWindow) { + var anchorRect = anchor.getBoundingClientRect(); + var contentRect = contentWindow.getBoundingClientRect(); + + if (anchorRect.bottom + this.maxHeight < contentRect.bottom) { + // fits below -> show below + } + else if (anchorRect.top - this.maxHeight > contentRect.top) { + // fits above -> show above + showBelow = false; + } + else { + // doesn't fit above nor below -> show below + } + } + + // position the menu + if (showBelow) { + // display the menu below the anchor + var anchorHeight = anchor.offsetHeight; + this.dom.menu.style.left = '0px'; + this.dom.menu.style.top = anchorHeight + 'px'; + this.dom.menu.style.bottom = ''; + } + else { + // display the menu above the anchor + this.dom.menu.style.left = '0px'; + this.dom.menu.style.top = ''; + this.dom.menu.style.bottom = '0px'; + } + + // attach the menu to the parent of the anchor + var parent = anchor.parentNode; + parent.insertBefore(this.dom.root, parent.firstChild); + + // create and attach event listeners + var me = this; + var list = this.dom.list; + this.eventListeners.mousedown = util.addEventListener(window, 'mousedown', function (event) { + // hide menu on click outside of the menu + var target = event.target; + if ((target != list) && !me._isChildOf(target, list)) { + me.hide(); + event.stopPropagation(); + event.preventDefault(); + } + }); + this.eventListeners.keydown = util.addEventListener(window, 'keydown', function (event) { + me._onKeyDown(event); + }); + + // move focus to the first button in the context menu + this.selection = util.getSelection(); + this.anchor = anchor; + setTimeout(function () { + me.dom.focusButton.focus(); + }, 0); + + if (ContextMenu.visibleMenu) { + ContextMenu.visibleMenu.hide(); + } + ContextMenu.visibleMenu = this; + }; + + /** + * Hide the context menu if visible + */ + ContextMenu.prototype.hide = function () { + // remove the menu from the DOM + if (this.dom.root.parentNode) { + this.dom.root.parentNode.removeChild(this.dom.root); + if (this.onClose) { + this.onClose(); + } + } + + // remove all event listeners + // all event listeners are supposed to be attached to document. + for (var name in this.eventListeners) { + if (this.eventListeners.hasOwnProperty(name)) { + var fn = this.eventListeners[name]; + if (fn) { + util.removeEventListener(window, name, fn); + } + delete this.eventListeners[name]; + } + } + + if (ContextMenu.visibleMenu == this) { + ContextMenu.visibleMenu = undefined; + } + }; + + /** + * Expand a submenu + * Any currently expanded submenu will be hided. + * @param {Object} domItem + * @private + */ + ContextMenu.prototype._onExpandItem = function (domItem) { + var me = this; + var alreadyVisible = (domItem == this.expandedItem); + + // hide the currently visible submenu + var expandedItem = this.expandedItem; + if (expandedItem) { + //var ul = expandedItem.ul; + expandedItem.ul.style.height = '0'; + expandedItem.ul.style.padding = ''; + setTimeout(function () { + if (me.expandedItem != expandedItem) { + expandedItem.ul.style.display = ''; + util.removeClassName(expandedItem.ul.parentNode, 'jsoneditor-selected'); + } + }, 300); // timeout duration must match the css transition duration + this.expandedItem = undefined; + } + + if (!alreadyVisible) { + var ul = domItem.ul; + ul.style.display = 'block'; + var height = ul.clientHeight; // force a reflow in Firefox + setTimeout(function () { + if (me.expandedItem == domItem) { + ul.style.height = (ul.childNodes.length * 24) + 'px'; + ul.style.padding = '5px 10px'; + } + }, 0); + util.addClassName(ul.parentNode, 'jsoneditor-selected'); + this.expandedItem = domItem; + } + }; + + /** + * Handle onkeydown event + * @param {Event} event + * @private + */ + ContextMenu.prototype._onKeyDown = function (event) { + var target = event.target; + var keynum = event.which; + var handled = false; + var buttons, targetIndex, prevButton, nextButton; + + if (keynum == 27) { // ESC + // hide the menu on ESC key + + // restore previous selection and focus + if (this.selection) { + util.setSelection(this.selection); + } + if (this.anchor) { + this.anchor.focus(); + } + + this.hide(); + + handled = true; + } + else if (keynum == 9) { // Tab + if (!event.shiftKey) { // Tab + buttons = this._getVisibleButtons(); + targetIndex = buttons.indexOf(target); + if (targetIndex == buttons.length - 1) { + // move to first button + buttons[0].focus(); + handled = true; + } + } + else { // Shift+Tab + buttons = this._getVisibleButtons(); + targetIndex = buttons.indexOf(target); + if (targetIndex == 0) { + // move to last button + buttons[buttons.length - 1].focus(); + handled = true; + } + } + } + else if (keynum == 37) { // Arrow Left + if (target.className == 'jsoneditor-expand') { + buttons = this._getVisibleButtons(); + targetIndex = buttons.indexOf(target); + prevButton = buttons[targetIndex - 1]; + if (prevButton) { + prevButton.focus(); + } + } + handled = true; + } + else if (keynum == 38) { // Arrow Up + buttons = this._getVisibleButtons(); + targetIndex = buttons.indexOf(target); + prevButton = buttons[targetIndex - 1]; + if (prevButton && prevButton.className == 'jsoneditor-expand') { + // skip expand button + prevButton = buttons[targetIndex - 2]; + } + if (!prevButton) { + // move to last button + prevButton = buttons[buttons.length - 1]; + } + if (prevButton) { + prevButton.focus(); + } + handled = true; + } + else if (keynum == 39) { // Arrow Right + buttons = this._getVisibleButtons(); + targetIndex = buttons.indexOf(target); + nextButton = buttons[targetIndex + 1]; + if (nextButton && nextButton.className == 'jsoneditor-expand') { + nextButton.focus(); + } + handled = true; + } + else if (keynum == 40) { // Arrow Down + buttons = this._getVisibleButtons(); + targetIndex = buttons.indexOf(target); + nextButton = buttons[targetIndex + 1]; + if (nextButton && nextButton.className == 'jsoneditor-expand') { + // skip expand button + nextButton = buttons[targetIndex + 2]; + } + if (!nextButton) { + // move to first button + nextButton = buttons[0]; + } + if (nextButton) { + nextButton.focus(); + handled = true; + } + handled = true; + } + // TODO: arrow left and right + + if (handled) { + event.stopPropagation(); + event.preventDefault(); + } + }; + + /** + * Test if an element is a child of a parent element. + * @param {Element} child + * @param {Element} parent + * @return {boolean} isChild + */ + ContextMenu.prototype._isChildOf = function (child, parent) { + var e = child.parentNode; + while (e) { + if (e == parent) { + return true; + } + e = e.parentNode; + } + + return false; + }; + + module.exports = ContextMenu; + + +/***/ }, +/* 8 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var naturalSort = __webpack_require__(9); + var ContextMenu = __webpack_require__(7); + var appendNodeFactory = __webpack_require__(10); + var util = __webpack_require__(4); + + /** + * @constructor Node + * Create a new Node + * @param {./treemode} editor + * @param {Object} [params] Can contain parameters: + * {string} field + * {boolean} fieldEditable + * {*} value + * {String} type Can have values 'auto', 'array', + * 'object', or 'string'. + */ + function Node (editor, params) { + /** @type {./treemode} */ + this.editor = editor; + this.dom = {}; + this.expanded = false; + + if(params && (params instanceof Object)) { + this.setField(params.field, params.fieldEditable); + this.setValue(params.value, params.type); + } + else { + this.setField(''); + this.setValue(null); + } + + this._debouncedOnChangeValue = util.debounce(this._onChangeValue.bind(this), Node.prototype.DEBOUNCE_INTERVAL); + this._debouncedOnChangeField = util.debounce(this._onChangeField.bind(this), Node.prototype.DEBOUNCE_INTERVAL); + } + + // debounce interval for keyboard input in milliseconds + Node.prototype.DEBOUNCE_INTERVAL = 150; + + /** + * Determine whether the field and/or value of this node are editable + * @private + */ + Node.prototype._updateEditability = function () { + this.editable = { + field: true, + value: true + }; + + if (this.editor) { + this.editable.field = this.editor.options.mode === 'tree'; + this.editable.value = this.editor.options.mode !== 'view'; + + if ((this.editor.options.mode === 'tree' || this.editor.options.mode === 'form') && + (typeof this.editor.options.onEditable === 'function')) { + var editable = this.editor.options.onEditable({ + field: this.field, + value: this.value, + path: this.getPath() + }); + + if (typeof editable === 'boolean') { + this.editable.field = editable; + this.editable.value = editable; + } + else { + if (typeof editable.field === 'boolean') this.editable.field = editable.field; + if (typeof editable.value === 'boolean') this.editable.value = editable.value; + } + } + } + }; + + /** + * Get the path of this node + * @return {String[]} Array containing the path to this node + */ + Node.prototype.getPath = function () { + var node = this; + var path = []; + while (node) { + var field = !node.parent + ? undefined // do not add an (optional) field name of the root node + : (node.parent.type != 'array') + ? node.field + : node.index; + + if (field !== undefined) { + path.unshift(field); + } + node = node.parent; + } + return path; + }; + + /** + * Find a Node from a JSON path like '.items[3].name' + * @param {string} jsonPath + * @return {Node | null} Returns the Node when found, returns null if not found + */ + Node.prototype.findNode = function (jsonPath) { + var path = util.parsePath(jsonPath); + var node = this; + while (node && path.length > 0) { + var prop = path.shift(); + if (typeof prop === 'number') { + if (node.type !== 'array') { + throw new Error('Cannot get child node at index ' + prop + ': node is no array'); + } + node = node.childs[prop]; + } + else { // string + if (node.type !== 'object') { + throw new Error('Cannot get child node ' + prop + ': node is no object'); + } + node = node.childs.filter(function (child) { + return child.field === prop; + })[0]; + } + } + + return node; + }; + + /** + * Find all parents of this node. The parents are ordered from root node towards + * the original node. + * @return {Array.} + */ + Node.prototype.findParents = function () { + var parents = []; + var parent = this.parent; + while (parent) { + parents.unshift(parent); + parent = parent.parent; + } + return parents; + }; + + /** + * + * @param {{dataPath: string, keyword: string, message: string, params: Object, schemaPath: string} | null} error + * @param {Node} [child] When this is the error of a parent node, pointing + * to an invalid child node, the child node itself + * can be provided. If provided, clicking the error + * icon will set focus to the invalid child node. + */ + Node.prototype.setError = function (error, child) { + // ensure the dom exists + this.getDom(); + + this.error = error; + var tdError = this.dom.tdError; + if (error) { + if (!tdError) { + tdError = document.createElement('td'); + this.dom.tdError = tdError; + this.dom.tdValue.parentNode.appendChild(tdError); + } + + var popover = document.createElement('div'); + popover.className = 'jsoneditor-popover jsoneditor-right'; + popover.appendChild(document.createTextNode(error.message)); + + var button = document.createElement('button'); + button.type = 'button'; + button.className = 'jsoneditor-schema-error'; + button.appendChild(popover); + + // update the direction of the popover + button.onmouseover = button.onfocus = function updateDirection() { + var directions = ['right', 'above', 'below', 'left']; + for (var i = 0; i < directions.length; i++) { + var direction = directions[i]; + popover.className = 'jsoneditor-popover jsoneditor-' + direction; + + var contentRect = this.editor.content.getBoundingClientRect(); + var popoverRect = popover.getBoundingClientRect(); + var margin = 20; // account for a scroll bar + var fit = util.insideRect(contentRect, popoverRect, margin); + + if (fit) { + break; + } + } + }.bind(this); + + // when clicking the error icon, expand all nodes towards the invalid + // child node, and set focus to the child node + if (child) { + button.onclick = function showInvalidNode() { + child.findParents().forEach(function (parent) { + parent.expand(false); + }); + + child.scrollTo(function () { + child.focus(); + }); + }; + } + + // apply the error message to the node + while (tdError.firstChild) { + tdError.removeChild(tdError.firstChild); + } + tdError.appendChild(button); + } + else { + if (tdError) { + this.dom.tdError.parentNode.removeChild(this.dom.tdError); + delete this.dom.tdError; + } + } + }; + + /** + * Get the index of this node: the index in the list of childs where this + * node is part of + * @return {number} Returns the index, or -1 if this is the root node + */ + Node.prototype.getIndex = function () { + return this.parent ? this.parent.childs.indexOf(this) : -1; + }; + + /** + * Set parent node + * @param {Node} parent + */ + Node.prototype.setParent = function(parent) { + this.parent = parent; + }; + + /** + * Set field + * @param {String} field + * @param {boolean} [fieldEditable] + */ + Node.prototype.setField = function(field, fieldEditable) { + this.field = field; + this.previousField = field; + this.fieldEditable = (fieldEditable === true); + }; + + /** + * Get field + * @return {String} + */ + Node.prototype.getField = function() { + if (this.field === undefined) { + this._getDomField(); + } + + return this.field; + }; + + /** + * Set value. Value is a JSON structure or an element String, Boolean, etc. + * @param {*} value + * @param {String} [type] Specify the type of the value. Can be 'auto', + * 'array', 'object', or 'string' + */ + Node.prototype.setValue = function(value, type) { + var childValue, child; + + // first clear all current childs (if any) + var childs = this.childs; + if (childs) { + while (childs.length) { + this.removeChild(childs[0]); + } + } + + // TODO: remove the DOM of this Node + + this.type = this._getType(value); + + // check if type corresponds with the provided type + if (type && type != this.type) { + if (type == 'string' && this.type == 'auto') { + this.type = type; + } + else { + throw new Error('Type mismatch: ' + + 'cannot cast value of type "' + this.type + + ' to the specified type "' + type + '"'); + } + } + + if (this.type == 'array') { + // array + this.childs = []; + for (var i = 0, iMax = value.length; i < iMax; i++) { + childValue = value[i]; + if (childValue !== undefined && !(childValue instanceof Function)) { + // ignore undefined and functions + child = new Node(this.editor, { + value: childValue + }); + this.appendChild(child); + } + } + this.value = ''; + } + else if (this.type == 'object') { + // object + this.childs = []; + for (var childField in value) { + if (value.hasOwnProperty(childField)) { + childValue = value[childField]; + if (childValue !== undefined && !(childValue instanceof Function)) { + // ignore undefined and functions + child = new Node(this.editor, { + field: childField, + value: childValue + }); + this.appendChild(child); + } + } + } + this.value = ''; + + // sort object keys + if (this.editor.options.sortObjectKeys === true) { + this.sort('asc'); + } + } + else { + // value + this.childs = undefined; + this.value = value; + } + + this.previousValue = this.value; + }; + + /** + * Get value. Value is a JSON structure + * @return {*} value + */ + Node.prototype.getValue = function() { + //var childs, i, iMax; + + if (this.type == 'array') { + var arr = []; + this.childs.forEach (function (child) { + arr.push(child.getValue()); + }); + return arr; + } + else if (this.type == 'object') { + var obj = {}; + this.childs.forEach (function (child) { + obj[child.getField()] = child.getValue(); + }); + return obj; + } + else { + if (this.value === undefined) { + this._getDomValue(); + } + + return this.value; + } + }; + + /** + * Get the nesting level of this node + * @return {Number} level + */ + Node.prototype.getLevel = function() { + return (this.parent ? this.parent.getLevel() + 1 : 0); + }; + + /** + * Get path of the root node till the current node + * @return {Node[]} Returns an array with nodes + */ + Node.prototype.getNodePath = function() { + var path = this.parent ? this.parent.getNodePath() : []; + path.push(this); + return path; + }; + + /** + * Create a clone of a node + * The complete state of a clone is copied, including whether it is expanded or + * not. The DOM elements are not cloned. + * @return {Node} clone + */ + Node.prototype.clone = function() { + var clone = new Node(this.editor); + clone.type = this.type; + clone.field = this.field; + clone.fieldInnerText = this.fieldInnerText; + clone.fieldEditable = this.fieldEditable; + clone.value = this.value; + clone.valueInnerText = this.valueInnerText; + clone.expanded = this.expanded; + + if (this.childs) { + // an object or array + var cloneChilds = []; + this.childs.forEach(function (child) { + var childClone = child.clone(); + childClone.setParent(clone); + cloneChilds.push(childClone); + }); + clone.childs = cloneChilds; + } + else { + // a value + clone.childs = undefined; + } + + return clone; + }; + + /** + * Expand this node and optionally its childs. + * @param {boolean} [recurse] Optional recursion, true by default. When + * true, all childs will be expanded recursively + */ + Node.prototype.expand = function(recurse) { + if (!this.childs) { + return; + } + + // set this node expanded + this.expanded = true; + if (this.dom.expand) { + this.dom.expand.className = 'jsoneditor-expanded'; + } + + this.showChilds(); + + if (recurse !== false) { + this.childs.forEach(function (child) { + child.expand(recurse); + }); + } + }; + + /** + * Collapse this node and optionally its childs. + * @param {boolean} [recurse] Optional recursion, true by default. When + * true, all childs will be collapsed recursively + */ + Node.prototype.collapse = function(recurse) { + if (!this.childs) { + return; + } + + this.hideChilds(); + + // collapse childs in case of recurse + if (recurse !== false) { + this.childs.forEach(function (child) { + child.collapse(recurse); + }); + + } + + // make this node collapsed + if (this.dom.expand) { + this.dom.expand.className = 'jsoneditor-collapsed'; + } + this.expanded = false; + }; + + /** + * Recursively show all childs when they are expanded + */ + Node.prototype.showChilds = function() { + var childs = this.childs; + if (!childs) { + return; + } + if (!this.expanded) { + return; + } + + var tr = this.dom.tr; + var table = tr ? tr.parentNode : undefined; + if (table) { + // show row with append button + var append = this.getAppend(); + var nextTr = tr.nextSibling; + if (nextTr) { + table.insertBefore(append, nextTr); + } + else { + table.appendChild(append); + } + + // show childs + this.childs.forEach(function (child) { + table.insertBefore(child.getDom(), append); + child.showChilds(); + }); + } + }; + + /** + * Hide the node with all its childs + */ + Node.prototype.hide = function() { + var tr = this.dom.tr; + var table = tr ? tr.parentNode : undefined; + if (table) { + table.removeChild(tr); + } + this.hideChilds(); + }; + + + /** + * Recursively hide all childs + */ + Node.prototype.hideChilds = function() { + var childs = this.childs; + if (!childs) { + return; + } + if (!this.expanded) { + return; + } + + // hide append row + var append = this.getAppend(); + if (append.parentNode) { + append.parentNode.removeChild(append); + } + + // hide childs + this.childs.forEach(function (child) { + child.hide(); + }); + }; + + + /** + * Add a new child to the node. + * Only applicable when Node value is of type array or object + * @param {Node} node + */ + Node.prototype.appendChild = function(node) { + if (this._hasChilds()) { + // adjust the link to the parent + node.setParent(this); + node.fieldEditable = (this.type == 'object'); + if (this.type == 'array') { + node.index = this.childs.length; + } + this.childs.push(node); + + if (this.expanded) { + // insert into the DOM, before the appendRow + var newTr = node.getDom(); + var appendTr = this.getAppend(); + var table = appendTr ? appendTr.parentNode : undefined; + if (appendTr && table) { + table.insertBefore(newTr, appendTr); + } + + node.showChilds(); + } + + this.updateDom({'updateIndexes': true}); + node.updateDom({'recurse': true}); + } + }; + + + /** + * Move a node from its current parent to this node + * Only applicable when Node value is of type array or object + * @param {Node} node + * @param {Node} beforeNode + */ + Node.prototype.moveBefore = function(node, beforeNode) { + if (this._hasChilds()) { + // create a temporary row, to prevent the scroll position from jumping + // when removing the node + var tbody = (this.dom.tr) ? this.dom.tr.parentNode : undefined; + if (tbody) { + var trTemp = document.createElement('tr'); + trTemp.style.height = tbody.clientHeight + 'px'; + tbody.appendChild(trTemp); + } + + if (node.parent) { + node.parent.removeChild(node); + } + + if (beforeNode instanceof AppendNode) { + this.appendChild(node); + } + else { + this.insertBefore(node, beforeNode); + } + + if (tbody) { + tbody.removeChild(trTemp); + } + } + }; + + /** + * Move a node from its current parent to this node + * Only applicable when Node value is of type array or object. + * If index is out of range, the node will be appended to the end + * @param {Node} node + * @param {Number} index + */ + Node.prototype.moveTo = function (node, index) { + if (node.parent == this) { + // same parent + var currentIndex = this.childs.indexOf(node); + if (currentIndex < index) { + // compensate the index for removal of the node itself + index++; + } + } + + var beforeNode = this.childs[index] || this.append; + this.moveBefore(node, beforeNode); + }; + + /** + * Insert a new child before a given node + * Only applicable when Node value is of type array or object + * @param {Node} node + * @param {Node} beforeNode + */ + Node.prototype.insertBefore = function(node, beforeNode) { + if (this._hasChilds()) { + if (beforeNode == this.append) { + // append to the child nodes + + // adjust the link to the parent + node.setParent(this); + node.fieldEditable = (this.type == 'object'); + this.childs.push(node); + } + else { + // insert before a child node + var index = this.childs.indexOf(beforeNode); + if (index == -1) { + throw new Error('Node not found'); + } + + // adjust the link to the parent + node.setParent(this); + node.fieldEditable = (this.type == 'object'); + this.childs.splice(index, 0, node); + } + + if (this.expanded) { + // insert into the DOM + var newTr = node.getDom(); + var nextTr = beforeNode.getDom(); + var table = nextTr ? nextTr.parentNode : undefined; + if (nextTr && table) { + table.insertBefore(newTr, nextTr); + } + + node.showChilds(); + } + + this.updateDom({'updateIndexes': true}); + node.updateDom({'recurse': true}); + } + }; + + /** + * Insert a new child before a given node + * Only applicable when Node value is of type array or object + * @param {Node} node + * @param {Node} afterNode + */ + Node.prototype.insertAfter = function(node, afterNode) { + if (this._hasChilds()) { + var index = this.childs.indexOf(afterNode); + var beforeNode = this.childs[index + 1]; + if (beforeNode) { + this.insertBefore(node, beforeNode); + } + else { + this.appendChild(node); + } + } + }; + + /** + * Search in this node + * The node will be expanded when the text is found one of its childs, else + * it will be collapsed. Searches are case insensitive. + * @param {String} text + * @return {Node[]} results Array with nodes containing the search text + */ + Node.prototype.search = function(text) { + var results = []; + var index; + var search = text ? text.toLowerCase() : undefined; + + // delete old search data + delete this.searchField; + delete this.searchValue; + + // search in field + if (this.field != undefined) { + var field = String(this.field).toLowerCase(); + index = field.indexOf(search); + if (index != -1) { + this.searchField = true; + results.push({ + 'node': this, + 'elem': 'field' + }); + } + + // update dom + this._updateDomField(); + } + + // search in value + if (this._hasChilds()) { + // array, object + + // search the nodes childs + if (this.childs) { + var childResults = []; + this.childs.forEach(function (child) { + childResults = childResults.concat(child.search(text)); + }); + results = results.concat(childResults); + } + + // update dom + if (search != undefined) { + var recurse = false; + if (childResults.length == 0) { + this.collapse(recurse); + } + else { + this.expand(recurse); + } + } + } + else { + // string, auto + if (this.value != undefined ) { + var value = String(this.value).toLowerCase(); + index = value.indexOf(search); + if (index != -1) { + this.searchValue = true; + results.push({ + 'node': this, + 'elem': 'value' + }); + } + } + + // update dom + this._updateDomValue(); + } + + return results; + }; + + /** + * Move the scroll position such that this node is in the visible area. + * The node will not get the focus + * @param {function(boolean)} [callback] + */ + Node.prototype.scrollTo = function(callback) { + if (!this.dom.tr || !this.dom.tr.parentNode) { + // if the node is not visible, expand its parents + var parent = this.parent; + var recurse = false; + while (parent) { + parent.expand(recurse); + parent = parent.parent; + } + } + + if (this.dom.tr && this.dom.tr.parentNode) { + this.editor.scrollTo(this.dom.tr.offsetTop, callback); + } + }; + + + // stores the element name currently having the focus + Node.focusElement = undefined; + + /** + * Set focus to this node + * @param {String} [elementName] The field name of the element to get the + * focus available values: 'drag', 'menu', + * 'expand', 'field', 'value' (default) + */ + Node.prototype.focus = function(elementName) { + Node.focusElement = elementName; + + if (this.dom.tr && this.dom.tr.parentNode) { + var dom = this.dom; + + switch (elementName) { + case 'drag': + if (dom.drag) { + dom.drag.focus(); + } + else { + dom.menu.focus(); + } + break; + + case 'menu': + dom.menu.focus(); + break; + + case 'expand': + if (this._hasChilds()) { + dom.expand.focus(); + } + else if (dom.field && this.fieldEditable) { + dom.field.focus(); + util.selectContentEditable(dom.field); + } + else if (dom.value && !this._hasChilds()) { + dom.value.focus(); + util.selectContentEditable(dom.value); + } + else { + dom.menu.focus(); + } + break; + + case 'field': + if (dom.field && this.fieldEditable) { + dom.field.focus(); + util.selectContentEditable(dom.field); + } + else if (dom.value && !this._hasChilds()) { + dom.value.focus(); + util.selectContentEditable(dom.value); + } + else if (this._hasChilds()) { + dom.expand.focus(); + } + else { + dom.menu.focus(); + } + break; + + case 'value': + default: + if (dom.value && !this._hasChilds()) { + dom.value.focus(); + util.selectContentEditable(dom.value); + } + else if (dom.field && this.fieldEditable) { + dom.field.focus(); + util.selectContentEditable(dom.field); + } + else if (this._hasChilds()) { + dom.expand.focus(); + } + else { + dom.menu.focus(); + } + break; + } + } + }; + + /** + * Select all text in an editable div after a delay of 0 ms + * @param {Element} editableDiv + */ + Node.select = function(editableDiv) { + setTimeout(function () { + util.selectContentEditable(editableDiv); + }, 0); + }; + + /** + * Update the values from the DOM field and value of this node + */ + Node.prototype.blur = function() { + // retrieve the actual field and value from the DOM. + this._getDomValue(false); + this._getDomField(false); + }; + + /** + * Check if given node is a child. The method will check recursively to find + * this node. + * @param {Node} node + * @return {boolean} containsNode + */ + Node.prototype.containsNode = function(node) { + if (this == node) { + return true; + } + + var childs = this.childs; + if (childs) { + // TODO: use the js5 Array.some() here? + for (var i = 0, iMax = childs.length; i < iMax; i++) { + if (childs[i].containsNode(node)) { + return true; + } + } + } + + return false; + }; + + /** + * Move given node into this node + * @param {Node} node the childNode to be moved + * @param {Node} beforeNode node will be inserted before given + * node. If no beforeNode is given, + * the node is appended at the end + * @private + */ + Node.prototype._move = function(node, beforeNode) { + if (node == beforeNode) { + // nothing to do... + return; + } + + // check if this node is not a child of the node to be moved here + if (node.containsNode(this)) { + throw new Error('Cannot move a field into a child of itself'); + } + + // remove the original node + if (node.parent) { + node.parent.removeChild(node); + } + + // create a clone of the node + var clone = node.clone(); + node.clearDom(); + + // insert or append the node + if (beforeNode) { + this.insertBefore(clone, beforeNode); + } + else { + this.appendChild(clone); + } + + /* TODO: adjust the field name (to prevent equal field names) + if (this.type == 'object') { + } + */ + }; + + /** + * Remove a child from the node. + * Only applicable when Node value is of type array or object + * @param {Node} node The child node to be removed; + * @return {Node | undefined} node The removed node on success, + * else undefined + */ + Node.prototype.removeChild = function(node) { + if (this.childs) { + var index = this.childs.indexOf(node); + + if (index != -1) { + node.hide(); + + // delete old search results + delete node.searchField; + delete node.searchValue; + + var removedNode = this.childs.splice(index, 1)[0]; + removedNode.parent = null; + + this.updateDom({'updateIndexes': true}); + + return removedNode; + } + } + + return undefined; + }; + + /** + * Remove a child node node from this node + * This method is equal to Node.removeChild, except that _remove fire an + * onChange event. + * @param {Node} node + * @private + */ + Node.prototype._remove = function (node) { + this.removeChild(node); + }; + + /** + * Change the type of the value of this Node + * @param {String} newType + */ + Node.prototype.changeType = function (newType) { + var oldType = this.type; + + if (oldType == newType) { + // type is not changed + return; + } + + if ((newType == 'string' || newType == 'auto') && + (oldType == 'string' || oldType == 'auto')) { + // this is an easy change + this.type = newType; + } + else { + // change from array to object, or from string/auto to object/array + var table = this.dom.tr ? this.dom.tr.parentNode : undefined; + var lastTr; + if (this.expanded) { + lastTr = this.getAppend(); + } + else { + lastTr = this.getDom(); + } + var nextTr = (lastTr && lastTr.parentNode) ? lastTr.nextSibling : undefined; + + // hide current field and all its childs + this.hide(); + this.clearDom(); + + // adjust the field and the value + this.type = newType; + + // adjust childs + if (newType == 'object') { + if (!this.childs) { + this.childs = []; + } + + this.childs.forEach(function (child, index) { + child.clearDom(); + delete child.index; + child.fieldEditable = true; + if (child.field == undefined) { + child.field = ''; + } + }); + + if (oldType == 'string' || oldType == 'auto') { + this.expanded = true; + } + } + else if (newType == 'array') { + if (!this.childs) { + this.childs = []; + } + + this.childs.forEach(function (child, index) { + child.clearDom(); + child.fieldEditable = false; + child.index = index; + }); + + if (oldType == 'string' || oldType == 'auto') { + this.expanded = true; + } + } + else { + this.expanded = false; + } + + // create new DOM + if (table) { + if (nextTr) { + table.insertBefore(this.getDom(), nextTr); + } + else { + table.appendChild(this.getDom()); + } + } + this.showChilds(); + } + + if (newType == 'auto' || newType == 'string') { + // cast value to the correct type + if (newType == 'string') { + this.value = String(this.value); + } + else { + this.value = this._stringCast(String(this.value)); + } + + this.focus(); + } + + this.updateDom({'updateIndexes': true}); + }; + + /** + * Retrieve value from DOM + * @param {boolean} [silent] If true (default), no errors will be thrown in + * case of invalid data + * @private + */ + Node.prototype._getDomValue = function(silent) { + if (this.dom.value && this.type != 'array' && this.type != 'object') { + this.valueInnerText = util.getInnerText(this.dom.value); + } + + if (this.valueInnerText != undefined) { + try { + // retrieve the value + var value; + if (this.type == 'string') { + value = this._unescapeHTML(this.valueInnerText); + } + else { + var str = this._unescapeHTML(this.valueInnerText); + value = this._stringCast(str); + } + if (value !== this.value) { + this.value = value; + this._debouncedOnChangeValue(); + } + } + catch (err) { + this.value = undefined; + // TODO: sent an action with the new, invalid value? + if (silent !== true) { + throw err; + } + } + } + }; + + /** + * Handle a changed value + * @private + */ + Node.prototype._onChangeValue = function () { + // get current selection, then override the range such that we can select + // the added/removed text on undo/redo + var oldSelection = this.editor.getSelection(); + if (oldSelection.range) { + var undoDiff = util.textDiff(String(this.value), String(this.previousValue)); + oldSelection.range.startOffset = undoDiff.start; + oldSelection.range.endOffset = undoDiff.end; + } + var newSelection = this.editor.getSelection(); + if (newSelection.range) { + var redoDiff = util.textDiff(String(this.previousValue), String(this.value)); + newSelection.range.startOffset = redoDiff.start; + newSelection.range.endOffset = redoDiff.end; + } + + this.editor._onAction('editValue', { + node: this, + oldValue: this.previousValue, + newValue: this.value, + oldSelection: oldSelection, + newSelection: newSelection + }); + + this.previousValue = this.value; + }; + + /** + * Handle a changed field + * @private + */ + Node.prototype._onChangeField = function () { + // get current selection, then override the range such that we can select + // the added/removed text on undo/redo + var oldSelection = this.editor.getSelection(); + if (oldSelection.range) { + var undoDiff = util.textDiff(this.field, this.previousField); + oldSelection.range.startOffset = undoDiff.start; + oldSelection.range.endOffset = undoDiff.end; + } + var newSelection = this.editor.getSelection(); + if (newSelection.range) { + var redoDiff = util.textDiff(this.previousField, this.field); + newSelection.range.startOffset = redoDiff.start; + newSelection.range.endOffset = redoDiff.end; + } + + this.editor._onAction('editField', { + node: this, + oldValue: this.previousField, + newValue: this.field, + oldSelection: oldSelection, + newSelection: newSelection + }); + + this.previousField = this.field; + }; + + /** + * Update dom value: + * - the text color of the value, depending on the type of the value + * - the height of the field, depending on the width + * - background color in case it is empty + * @private + */ + Node.prototype._updateDomValue = function () { + var domValue = this.dom.value; + if (domValue) { + var classNames = ['jsoneditor-value']; + + + // set text color depending on value type + var value = this.value; + var type = (this.type == 'auto') ? util.type(value) : this.type; + var isUrl = type == 'string' && util.isUrl(value); + classNames.push('jsoneditor-' + type); + if (isUrl) { + classNames.push('jsoneditor-url'); + } + + // visual styling when empty + var isEmpty = (String(this.value) == '' && this.type != 'array' && this.type != 'object'); + if (isEmpty) { + classNames.push('jsoneditor-empty'); + } + + // highlight when there is a search result + if (this.searchValueActive) { + classNames.push('jsoneditor-highlight-active'); + } + if (this.searchValue) { + classNames.push('jsoneditor-highlight'); + } + + domValue.className = classNames.join(' '); + + // update title + if (type == 'array' || type == 'object') { + var count = this.childs ? this.childs.length : 0; + domValue.title = this.type + ' containing ' + count + ' items'; + } + else if (isUrl && this.editable.value) { + domValue.title = 'Ctrl+Click or Ctrl+Enter to open url in new window'; + } + else { + domValue.title = ''; + } + + // show checkbox when the value is a boolean + if (type === 'boolean' && this.editable.value) { + if (!this.dom.checkbox) { + this.dom.checkbox = document.createElement('input'); + this.dom.checkbox.type = 'checkbox'; + this.dom.tdCheckbox = document.createElement('td'); + this.dom.tdCheckbox.className = 'jsoneditor-tree'; + this.dom.tdCheckbox.appendChild(this.dom.checkbox); + + this.dom.tdValue.parentNode.insertBefore(this.dom.tdCheckbox, this.dom.tdValue); + } + + this.dom.checkbox.checked = this.value; + } + else { + // cleanup checkbox when displayed + if (this.dom.tdCheckbox) { + this.dom.tdCheckbox.parentNode.removeChild(this.dom.tdCheckbox); + delete this.dom.tdCheckbox; + delete this.dom.checkbox; + } + } + + if (this.enum && this.editable.value) { + // create select box when this node has an enum object + if (!this.dom.select) { + this.dom.select = document.createElement('select'); + this.id = this.field + "_" + new Date().getUTCMilliseconds(); + this.dom.select.id = this.id; + this.dom.select.name = this.dom.select.id; + + //Create the default empty option + this.dom.select.option = document.createElement('option'); + this.dom.select.option.value = ''; + this.dom.select.option.innerHTML = '--'; + this.dom.select.appendChild(this.dom.select.option); + + //Iterate all enum values and add them as options + for(var i = 0; i < this.enum.length; i++) { + this.dom.select.option = document.createElement('option'); + this.dom.select.option.value = this.enum[i]; + this.dom.select.option.innerHTML = this.enum[i]; + if(this.dom.select.option.value == this.value){ + this.dom.select.option.selected = true; + } + this.dom.select.appendChild(this.dom.select.option); + } + + this.dom.tdSelect = document.createElement('td'); + this.dom.tdSelect.className = 'jsoneditor-tree'; + this.dom.tdSelect.appendChild(this.dom.select); + this.dom.tdValue.parentNode.insertBefore(this.dom.tdSelect, this.dom.tdValue); + } + + // If the enum is inside a composite type display + // both the simple input and the dropdown field + if(this.schema && ( + !this.schema.hasOwnProperty("oneOf") && + !this.schema.hasOwnProperty("anyOf") && + !this.schema.hasOwnProperty("allOf")) + ) { + this.valueFieldHTML = this.dom.tdValue.innerHTML; + this.dom.tdValue.style.visibility = 'hidden'; + this.dom.tdValue.innerHTML = ''; + } else { + delete this.valueFieldHTML; + } + } + else { + // cleanup select box when displayed + if (this.dom.tdSelect) { + this.dom.tdSelect.parentNode.removeChild(this.dom.tdSelect); + delete this.dom.tdSelect; + delete this.dom.select; + this.dom.tdValue.innerHTML = this.valueFieldHTML; + this.dom.tdValue.style.visibility = ''; + delete this.valueFieldHTML; + } + } + + // strip formatting from the contents of the editable div + util.stripFormatting(domValue); + } + }; + + /** + * Update dom field: + * - the text color of the field, depending on the text + * - the height of the field, depending on the width + * - background color in case it is empty + * @private + */ + Node.prototype._updateDomField = function () { + var domField = this.dom.field; + if (domField) { + // make backgound color lightgray when empty + var isEmpty = (String(this.field) == '' && this.parent.type != 'array'); + if (isEmpty) { + util.addClassName(domField, 'jsoneditor-empty'); + } + else { + util.removeClassName(domField, 'jsoneditor-empty'); + } + + // highlight when there is a search result + if (this.searchFieldActive) { + util.addClassName(domField, 'jsoneditor-highlight-active'); + } + else { + util.removeClassName(domField, 'jsoneditor-highlight-active'); + } + if (this.searchField) { + util.addClassName(domField, 'jsoneditor-highlight'); + } + else { + util.removeClassName(domField, 'jsoneditor-highlight'); + } + + // strip formatting from the contents of the editable div + util.stripFormatting(domField); + } + }; + + /** + * Retrieve field from DOM + * @param {boolean} [silent] If true (default), no errors will be thrown in + * case of invalid data + * @private + */ + Node.prototype._getDomField = function(silent) { + if (this.dom.field && this.fieldEditable) { + this.fieldInnerText = util.getInnerText(this.dom.field); + } + + if (this.fieldInnerText != undefined) { + try { + var field = this._unescapeHTML(this.fieldInnerText); + + if (field !== this.field) { + this.field = field; + this._debouncedOnChangeField(); + } + } + catch (err) { + this.field = undefined; + // TODO: sent an action here, with the new, invalid value? + if (silent !== true) { + throw err; + } + } + } + }; + + /** + * Validate this node and all it's childs + * @return {Array.<{node: Node, error: {message: string}}>} Returns a list with duplicates + */ + Node.prototype.validate = function () { + var errors = []; + + // find duplicate keys + if (this.type === 'object') { + var keys = {}; + var duplicateKeys = []; + for (var i = 0; i < this.childs.length; i++) { + var child = this.childs[i]; + if (keys.hasOwnProperty(child.field)) { + duplicateKeys.push(child.field); + } + keys[child.field] = true; + } + + if (duplicateKeys.length > 0) { + errors = this.childs + .filter(function (node) { + return duplicateKeys.indexOf(node.field) !== -1; + }) + .map(function (node) { + return { + node: node, + error: { + message: 'duplicate key "' + node.field + '"' + } + } + }); + } + } + + // recurse over the childs + if (this.childs) { + for (var i = 0; i < this.childs.length; i++) { + var e = this.childs[i].validate(); + if (e.length > 0) { + errors = errors.concat(e); + } + } + } + + return errors; + }; + + /** + * Clear the dom of the node + */ + Node.prototype.clearDom = function() { + // TODO: hide the node first? + //this.hide(); + // TODO: recursively clear dom? + + this.dom = {}; + }; + + /** + * Get the HTML DOM TR element of the node. + * The dom will be generated when not yet created + * @return {Element} tr HTML DOM TR Element + */ + Node.prototype.getDom = function() { + var dom = this.dom; + if (dom.tr) { + return dom.tr; + } + + this._updateEditability(); + + // create row + dom.tr = document.createElement('tr'); + dom.tr.node = this; + + if (this.editor.options.mode === 'tree') { // note: we take here the global setting + var tdDrag = document.createElement('td'); + if (this.editable.field) { + // create draggable area + if (this.parent) { + var domDrag = document.createElement('button'); + domDrag.type = 'button'; + dom.drag = domDrag; + domDrag.className = 'jsoneditor-dragarea'; + domDrag.title = 'Drag to move this field (Alt+Shift+Arrows)'; + tdDrag.appendChild(domDrag); + } + } + dom.tr.appendChild(tdDrag); + + // create context menu + var tdMenu = document.createElement('td'); + var menu = document.createElement('button'); + menu.type = 'button'; + dom.menu = menu; + menu.className = 'jsoneditor-contextmenu'; + menu.title = 'Click to open the actions menu (Ctrl+M)'; + tdMenu.appendChild(dom.menu); + dom.tr.appendChild(tdMenu); + } + + // create tree and field + var tdField = document.createElement('td'); + dom.tr.appendChild(tdField); + dom.tree = this._createDomTree(); + tdField.appendChild(dom.tree); + + this.updateDom({'updateIndexes': true}); + + return dom.tr; + }; + + /** + * DragStart event, fired on mousedown on the dragarea at the left side of a Node + * @param {Node[] | Node} nodes + * @param {Event} event + */ + Node.onDragStart = function (nodes, event) { + if (!Array.isArray(nodes)) { + return Node.onDragStart([nodes], event); + } + if (nodes.length === 0) { + return; + } + + var firstNode = nodes[0]; + var lastNode = nodes[nodes.length - 1]; + var draggedNode = Node.getNodeFromTarget(event.target); + var beforeNode = lastNode._nextSibling(); + var editor = firstNode.editor; + + // in case of multiple selected nodes, offsetY prevents the selection from + // jumping when you start dragging one of the lower down nodes in the selection + var offsetY = util.getAbsoluteTop(draggedNode.dom.tr) - util.getAbsoluteTop(firstNode.dom.tr); + + if (!editor.mousemove) { + editor.mousemove = util.addEventListener(window, 'mousemove', function (event) { + Node.onDrag(nodes, event); + }); + } + + if (!editor.mouseup) { + editor.mouseup = util.addEventListener(window, 'mouseup',function (event ) { + Node.onDragEnd(nodes, event); + }); + } + + editor.highlighter.lock(); + editor.drag = { + oldCursor: document.body.style.cursor, + oldSelection: editor.getSelection(), + oldBeforeNode: beforeNode, + mouseX: event.pageX, + offsetY: offsetY, + level: firstNode.getLevel() + }; + document.body.style.cursor = 'move'; + + event.preventDefault(); + }; + + /** + * Drag event, fired when moving the mouse while dragging a Node + * @param {Node[] | Node} nodes + * @param {Event} event + */ + Node.onDrag = function (nodes, event) { + if (!Array.isArray(nodes)) { + return Node.onDrag([nodes], event); + } + if (nodes.length === 0) { + return; + } + + // TODO: this method has grown too large. Split it in a number of methods + var editor = nodes[0].editor; + var mouseY = event.pageY - editor.drag.offsetY; + var mouseX = event.pageX; + var trThis, trPrev, trNext, trFirst, trLast, trRoot; + var nodePrev, nodeNext; + var topThis, topPrev, topFirst, heightThis, bottomNext, heightNext; + var moved = false; + + // TODO: add an ESC option, which resets to the original position + + // move up/down + var firstNode = nodes[0]; + trThis = firstNode.dom.tr; + topThis = util.getAbsoluteTop(trThis); + heightThis = trThis.offsetHeight; + if (mouseY < topThis) { + // move up + trPrev = trThis; + do { + trPrev = trPrev.previousSibling; + nodePrev = Node.getNodeFromTarget(trPrev); + topPrev = trPrev ? util.getAbsoluteTop(trPrev) : 0; + } + while (trPrev && mouseY < topPrev); + + if (nodePrev && !nodePrev.parent) { + nodePrev = undefined; + } + + if (!nodePrev) { + // move to the first node + trRoot = trThis.parentNode.firstChild; + trPrev = trRoot ? trRoot.nextSibling : undefined; + nodePrev = Node.getNodeFromTarget(trPrev); + if (nodePrev == firstNode) { + nodePrev = undefined; + } + } + + if (nodePrev) { + // check if mouseY is really inside the found node + trPrev = nodePrev.dom.tr; + topPrev = trPrev ? util.getAbsoluteTop(trPrev) : 0; + if (mouseY > topPrev + heightThis) { + nodePrev = undefined; + } + } + + if (nodePrev) { + nodes.forEach(function (node) { + nodePrev.parent.moveBefore(node, nodePrev); + }); + moved = true; + } + } + else { + // move down + var lastNode = nodes[nodes.length - 1]; + trLast = (lastNode.expanded && lastNode.append) ? lastNode.append.getDom() : lastNode.dom.tr; + trFirst = trLast ? trLast.nextSibling : undefined; + if (trFirst) { + topFirst = util.getAbsoluteTop(trFirst); + trNext = trFirst; + do { + nodeNext = Node.getNodeFromTarget(trNext); + if (trNext) { + bottomNext = trNext.nextSibling ? + util.getAbsoluteTop(trNext.nextSibling) : 0; + heightNext = trNext ? (bottomNext - topFirst) : 0; + + if (nodeNext.parent.childs.length == nodes.length && + nodeNext.parent.childs[nodes.length - 1] == lastNode) { + // We are about to remove the last child of this parent, + // which will make the parents appendNode visible. + topThis += 27; + // TODO: dangerous to suppose the height of the appendNode a constant of 27 px. + } + } + + trNext = trNext.nextSibling; + } + while (trNext && mouseY > topThis + heightNext); + + if (nodeNext && nodeNext.parent) { + // calculate the desired level + var diffX = (mouseX - editor.drag.mouseX); + var diffLevel = Math.round(diffX / 24 / 2); + var level = editor.drag.level + diffLevel; // desired level + var levelNext = nodeNext.getLevel(); // level to be + + // find the best fitting level (move upwards over the append nodes) + trPrev = nodeNext.dom.tr.previousSibling; + while (levelNext < level && trPrev) { + nodePrev = Node.getNodeFromTarget(trPrev); + + var isDraggedNode = nodes.some(function (node) { + return node === nodePrev || nodePrev._isChildOf(node); + }); + + if (isDraggedNode) { + // neglect the dragged nodes themselves and their childs + } + else if (nodePrev instanceof AppendNode) { + var childs = nodePrev.parent.childs; + if (childs.length != nodes.length || childs[nodes.length - 1] != lastNode) { + // non-visible append node of a list of childs + // consisting of not only this node (else the + // append node will change into a visible "empty" + // text when removing this node). + nodeNext = Node.getNodeFromTarget(trPrev); + levelNext = nodeNext.getLevel(); + } + else { + break; + } + } + else { + break; + } + + trPrev = trPrev.previousSibling; + } + + // move the node when its position is changed + if (trLast.nextSibling != nodeNext.dom.tr) { + nodes.forEach(function (node) { + nodeNext.parent.moveBefore(node, nodeNext); + }); + moved = true; + } + } + } + } + + if (moved) { + // update the dragging parameters when moved + editor.drag.mouseX = mouseX; + editor.drag.level = firstNode.getLevel(); + } + + // auto scroll when hovering around the top of the editor + editor.startAutoScroll(mouseY); + + event.preventDefault(); + }; + + /** + * Drag event, fired on mouseup after having dragged a node + * @param {Node[] | Node} nodes + * @param {Event} event + */ + Node.onDragEnd = function (nodes, event) { + if (!Array.isArray(nodes)) { + return Node.onDrag([nodes], event); + } + if (nodes.length === 0) { + return; + } + + var firstNode = nodes[0]; + var editor = firstNode.editor; + var parent = firstNode.parent; + var firstIndex = parent.childs.indexOf(firstNode); + var beforeNode = parent.childs[firstIndex + nodes.length] || parent.append; + + // set focus to the context menu button of the first node + if (nodes[0]) { + nodes[0].dom.menu.focus(); + } + + var params = { + nodes: nodes, + oldSelection: editor.drag.oldSelection, + newSelection: editor.getSelection(), + oldBeforeNode: editor.drag.oldBeforeNode, + newBeforeNode: beforeNode + }; + + if (params.oldBeforeNode != params.newBeforeNode) { + // only register this action if the node is actually moved to another place + editor._onAction('moveNodes', params); + } + + document.body.style.cursor = editor.drag.oldCursor; + editor.highlighter.unlock(); + nodes.forEach(function (node) { + if (event.target !== node.dom.drag && event.target !== node.dom.menu) { + editor.highlighter.unhighlight(); + } + }); + delete editor.drag; + + if (editor.mousemove) { + util.removeEventListener(window, 'mousemove', editor.mousemove); + delete editor.mousemove; + } + if (editor.mouseup) { + util.removeEventListener(window, 'mouseup', editor.mouseup); + delete editor.mouseup; + } + + // Stop any running auto scroll + editor.stopAutoScroll(); + + event.preventDefault(); + }; + + /** + * Test if this node is a child of an other node + * @param {Node} node + * @return {boolean} isChild + * @private + */ + Node.prototype._isChildOf = function (node) { + var n = this.parent; + while (n) { + if (n == node) { + return true; + } + n = n.parent; + } + + return false; + }; + + /** + * Create an editable field + * @return {Element} domField + * @private + */ + Node.prototype._createDomField = function () { + return document.createElement('div'); + }; + + /** + * Set highlighting for this node and all its childs. + * Only applied to the currently visible (expanded childs) + * @param {boolean} highlight + */ + Node.prototype.setHighlight = function (highlight) { + if (this.dom.tr) { + if (highlight) { + util.addClassName(this.dom.tr, 'jsoneditor-highlight'); + } + else { + util.removeClassName(this.dom.tr, 'jsoneditor-highlight'); + } + + if (this.append) { + this.append.setHighlight(highlight); + } + + if (this.childs) { + this.childs.forEach(function (child) { + child.setHighlight(highlight); + }); + } + } + }; + + /** + * Select or deselect a node + * @param {boolean} selected + * @param {boolean} [isFirst] + */ + Node.prototype.setSelected = function (selected, isFirst) { + this.selected = selected; + + if (this.dom.tr) { + if (selected) { + util.addClassName(this.dom.tr, 'jsoneditor-selected'); + } + else { + util.removeClassName(this.dom.tr, 'jsoneditor-selected'); + } + + if (isFirst) { + util.addClassName(this.dom.tr, 'jsoneditor-first'); + } + else { + util.removeClassName(this.dom.tr, 'jsoneditor-first'); + } + + if (this.append) { + this.append.setSelected(selected); + } + + if (this.childs) { + this.childs.forEach(function (child) { + child.setSelected(selected); + }); + } + } + }; + + /** + * Update the value of the node. Only primitive types are allowed, no Object + * or Array is allowed. + * @param {String | Number | Boolean | null} value + */ + Node.prototype.updateValue = function (value) { + this.value = value; + this.updateDom(); + }; + + /** + * Update the field of the node. + * @param {String} field + */ + Node.prototype.updateField = function (field) { + this.field = field; + this.updateDom(); + }; + + /** + * Update the HTML DOM, optionally recursing through the childs + * @param {Object} [options] Available parameters: + * {boolean} [recurse] If true, the + * DOM of the childs will be updated recursively. + * False by default. + * {boolean} [updateIndexes] If true, the childs + * indexes of the node will be updated too. False by + * default. + */ + Node.prototype.updateDom = function (options) { + // update level indentation + var domTree = this.dom.tree; + if (domTree) { + domTree.style.marginLeft = this.getLevel() * 24 + 'px'; + } + + // apply field to DOM + var domField = this.dom.field; + if (domField) { + if (this.fieldEditable) { + // parent is an object + domField.contentEditable = this.editable.field; + domField.spellcheck = false; + domField.className = 'jsoneditor-field'; + } + else { + // parent is an array this is the root node + domField.className = 'jsoneditor-readonly'; + } + + var fieldText; + if (this.index != undefined) { + fieldText = this.index; + } + else if (this.field != undefined) { + fieldText = this.field; + } + else if (this._hasChilds()) { + fieldText = this.type; + } + else { + fieldText = ''; + } + domField.innerHTML = this._escapeHTML(fieldText); + + this._updateSchema(); + } + + // apply value to DOM + var domValue = this.dom.value; + if (domValue) { + var count = this.childs ? this.childs.length : 0; + if (this.type == 'array') { + domValue.innerHTML = '[' + count + ']'; + util.addClassName(this.dom.tr, 'jsoneditor-expandable'); + } + else if (this.type == 'object') { + domValue.innerHTML = '{' + count + '}'; + util.addClassName(this.dom.tr, 'jsoneditor-expandable'); + } + else { + domValue.innerHTML = this._escapeHTML(this.value); + util.removeClassName(this.dom.tr, 'jsoneditor-expandable'); + } + } + + // update field and value + this._updateDomField(); + this._updateDomValue(); + + // update childs indexes + if (options && options.updateIndexes === true) { + // updateIndexes is true or undefined + this._updateDomIndexes(); + } + + if (options && options.recurse === true) { + // recurse is true or undefined. update childs recursively + if (this.childs) { + this.childs.forEach(function (child) { + child.updateDom(options); + }); + } + } + + // update row with append button + if (this.append) { + this.append.updateDom(); + } + }; + + /** + * Locate the JSON schema of the node and check for any enum type + * @private + */ + Node.prototype._updateSchema = function () { + //Locating the schema of the node and checking for any enum type + if(this.editor && this.editor.options) { + // find the part of the json schema matching this nodes path + this.schema = Node._findSchema(this.editor.options.schema, this.getPath()); + if (this.schema) { + this.enum = Node._findEnum(this.schema); + } + else { + delete this.enum; + } + } + }; + + /** + * find an enum definition in a JSON schema, as property `enum` or inside + * one of the schemas composites (`oneOf`, `anyOf`, `allOf`) + * @param {Object} schema + * @return {Array | null} Returns the enum when found, null otherwise. + * @private + */ + Node._findEnum = function (schema) { + if (schema.enum) { + return schema.enum; + } + + var composite = schema.oneOf || schema.anyOf || schema.allOf; + if (composite) { + var match = composite.filter(function (entry) {return entry.enum}); + if (match.length > 0) { + return match[0].enum; + } + } + + return null + }; + + /** + * Return the part of a JSON schema matching given path. + * @param {Object} schema + * @param {Array.} path + * @return {Object | null} + * @private + */ + Node._findSchema = function (schema, path) { + var childSchema = schema; + + for (var i = 0; i < path.length && childSchema; i++) { + var key = path[i]; + if (typeof key === 'string' && childSchema.properties) { + childSchema = childSchema.properties[key] || null + } + else if (typeof key === 'number' && childSchema.items) { + childSchema = childSchema.items + } + } + + return childSchema + }; + + /** + * Update the DOM of the childs of a node: update indexes and undefined field + * names. + * Only applicable when structure is an array or object + * @private + */ + Node.prototype._updateDomIndexes = function () { + var domValue = this.dom.value; + var childs = this.childs; + if (domValue && childs) { + if (this.type == 'array') { + childs.forEach(function (child, index) { + child.index = index; + var childField = child.dom.field; + if (childField) { + childField.innerHTML = index; + } + }); + } + else if (this.type == 'object') { + childs.forEach(function (child) { + if (child.index != undefined) { + delete child.index; + + if (child.field == undefined) { + child.field = ''; + } + } + }); + } + } + }; + + /** + * Create an editable value + * @private + */ + Node.prototype._createDomValue = function () { + var domValue; + + if (this.type == 'array') { + domValue = document.createElement('div'); + domValue.innerHTML = '[...]'; + } + else if (this.type == 'object') { + domValue = document.createElement('div'); + domValue.innerHTML = '{...}'; + } + else { + if (!this.editable.value && util.isUrl(this.value)) { + // create a link in case of read-only editor and value containing an url + domValue = document.createElement('a'); + domValue.href = this.value; + domValue.target = '_blank'; + domValue.innerHTML = this._escapeHTML(this.value); + } + else { + // create an editable or read-only div + domValue = document.createElement('div'); + domValue.contentEditable = this.editable.value; + domValue.spellcheck = false; + domValue.innerHTML = this._escapeHTML(this.value); + } + } + + return domValue; + }; + + /** + * Create an expand/collapse button + * @return {Element} expand + * @private + */ + Node.prototype._createDomExpandButton = function () { + // create expand button + var expand = document.createElement('button'); + expand.type = 'button'; + if (this._hasChilds()) { + expand.className = this.expanded ? 'jsoneditor-expanded' : 'jsoneditor-collapsed'; + expand.title = + 'Click to expand/collapse this field (Ctrl+E). \n' + + 'Ctrl+Click to expand/collapse including all childs.'; + } + else { + expand.className = 'jsoneditor-invisible'; + expand.title = ''; + } + + return expand; + }; + + + /** + * Create a DOM tree element, containing the expand/collapse button + * @return {Element} domTree + * @private + */ + Node.prototype._createDomTree = function () { + var dom = this.dom; + var domTree = document.createElement('table'); + var tbody = document.createElement('tbody'); + domTree.style.borderCollapse = 'collapse'; // TODO: put in css + domTree.className = 'jsoneditor-values'; + domTree.appendChild(tbody); + var tr = document.createElement('tr'); + tbody.appendChild(tr); + + // create expand button + var tdExpand = document.createElement('td'); + tdExpand.className = 'jsoneditor-tree'; + tr.appendChild(tdExpand); + dom.expand = this._createDomExpandButton(); + tdExpand.appendChild(dom.expand); + dom.tdExpand = tdExpand; + + // create the field + var tdField = document.createElement('td'); + tdField.className = 'jsoneditor-tree'; + tr.appendChild(tdField); + dom.field = this._createDomField(); + tdField.appendChild(dom.field); + dom.tdField = tdField; + + // create a separator + var tdSeparator = document.createElement('td'); + tdSeparator.className = 'jsoneditor-tree'; + tr.appendChild(tdSeparator); + if (this.type != 'object' && this.type != 'array') { + tdSeparator.appendChild(document.createTextNode(':')); + tdSeparator.className = 'jsoneditor-separator'; + } + dom.tdSeparator = tdSeparator; + + // create the value + var tdValue = document.createElement('td'); + tdValue.className = 'jsoneditor-tree'; + tr.appendChild(tdValue); + dom.value = this._createDomValue(); + tdValue.appendChild(dom.value); + dom.tdValue = tdValue; + + return domTree; + }; + + /** + * Handle an event. The event is caught centrally by the editor + * @param {Event} event + */ + Node.prototype.onEvent = function (event) { + var type = event.type, + target = event.target || event.srcElement, + dom = this.dom, + node = this, + expandable = this._hasChilds(); + + // check if mouse is on menu or on dragarea. + // If so, highlight current row and its childs + if (target == dom.drag || target == dom.menu) { + if (type == 'mouseover') { + this.editor.highlighter.highlight(this); + } + else if (type == 'mouseout') { + this.editor.highlighter.unhighlight(); + } + } + + // context menu events + if (type == 'click' && target == dom.menu) { + var highlighter = node.editor.highlighter; + highlighter.highlight(node); + highlighter.lock(); + util.addClassName(dom.menu, 'jsoneditor-selected'); + this.showContextMenu(dom.menu, function () { + util.removeClassName(dom.menu, 'jsoneditor-selected'); + highlighter.unlock(); + highlighter.unhighlight(); + }); + } + + // expand events + if (type == 'click') { + if (target == dom.expand || + ((node.editor.options.mode === 'view' || node.editor.options.mode === 'form') && target.nodeName === 'DIV')) { + if (expandable) { + var recurse = event.ctrlKey; // with ctrl-key, expand/collapse all + this._onExpand(recurse); + } + } + } + + // swap the value of a boolean when the checkbox displayed left is clicked + if (type == 'change' && target == dom.checkbox) { + this.dom.value.innerHTML = !this.value; + this._getDomValue(); + } + + // update the value of the node based on the selected option + if (type == 'change' && target == dom.select) { + this.dom.value.innerHTML = dom.select.value; + this._getDomValue(); + this._updateDomValue(); + } + + // value events + var domValue = dom.value; + if (target == domValue) { + //noinspection FallthroughInSwitchStatementJS + switch (type) { + case 'blur': + case 'change': + this._getDomValue(true); + this._updateDomValue(); + if (this.value) { + domValue.innerHTML = this._escapeHTML(this.value); + } + break; + + case 'input': + //this._debouncedGetDomValue(true); // TODO + this._getDomValue(true); + this._updateDomValue(); + break; + + case 'keydown': + case 'mousedown': + // TODO: cleanup + this.editor.selection = this.editor.getSelection(); + break; + + case 'click': + if (event.ctrlKey || !this.editable.value) { + if (util.isUrl(this.value)) { + window.open(this.value, '_blank'); + } + } + break; + + case 'keyup': + //this._debouncedGetDomValue(true); // TODO + this._getDomValue(true); + this._updateDomValue(); + break; + + case 'cut': + case 'paste': + setTimeout(function () { + node._getDomValue(true); + node._updateDomValue(); + }, 1); + break; + } + } + + // field events + var domField = dom.field; + if (target == domField) { + switch (type) { + case 'blur': + case 'change': + this._getDomField(true); + this._updateDomField(); + if (this.field) { + domField.innerHTML = this._escapeHTML(this.field); + } + break; + + case 'input': + this._getDomField(true); + this._updateSchema(); + this._updateDomField(); + this._updateDomValue(); + break; + + case 'keydown': + case 'mousedown': + this.editor.selection = this.editor.getSelection(); + break; + + case 'keyup': + this._getDomField(true); + this._updateDomField(); + break; + + case 'cut': + case 'paste': + setTimeout(function () { + node._getDomField(true); + node._updateDomField(); + }, 1); + break; + } + } + + // focus + // when clicked in whitespace left or right from the field or value, set focus + var domTree = dom.tree; + if (target == domTree.parentNode && type == 'click' && !event.hasMoved) { + var left = (event.offsetX != undefined) ? + (event.offsetX < (this.getLevel() + 1) * 24) : + (event.pageX < util.getAbsoluteLeft(dom.tdSeparator));// for FF + if (left || expandable) { + // node is expandable when it is an object or array + if (domField) { + util.setEndOfContentEditable(domField); + domField.focus(); + } + } + else { + if (domValue && !this.enum) { + util.setEndOfContentEditable(domValue); + domValue.focus(); + } + } + } + if (((target == dom.tdExpand && !expandable) || target == dom.tdField || target == dom.tdSeparator) && + (type == 'click' && !event.hasMoved)) { + if (domField) { + util.setEndOfContentEditable(domField); + domField.focus(); + } + } + + if (type == 'keydown') { + this.onKeyDown(event); + } + }; + + /** + * Key down event handler + * @param {Event} event + */ + Node.prototype.onKeyDown = function (event) { + var keynum = event.which || event.keyCode; + var target = event.target || event.srcElement; + var ctrlKey = event.ctrlKey; + var shiftKey = event.shiftKey; + var altKey = event.altKey; + var handled = false; + var prevNode, nextNode, nextDom, nextDom2; + var editable = this.editor.options.mode === 'tree'; + var oldSelection; + var oldBeforeNode; + var nodes; + var multiselection; + var selectedNodes = this.editor.multiselection.nodes.length > 0 + ? this.editor.multiselection.nodes + : [this]; + var firstNode = selectedNodes[0]; + var lastNode = selectedNodes[selectedNodes.length - 1]; + + // console.log(ctrlKey, keynum, event.charCode); // TODO: cleanup + if (keynum == 13) { // Enter + if (target == this.dom.value) { + if (!this.editable.value || event.ctrlKey) { + if (util.isUrl(this.value)) { + window.open(this.value, '_blank'); + handled = true; + } + } + } + else if (target == this.dom.expand) { + var expandable = this._hasChilds(); + if (expandable) { + var recurse = event.ctrlKey; // with ctrl-key, expand/collapse all + this._onExpand(recurse); + target.focus(); + handled = true; + } + } + } + else if (keynum == 68) { // D + if (ctrlKey && editable) { // Ctrl+D + Node.onDuplicate(selectedNodes); + handled = true; + } + } + else if (keynum == 69) { // E + if (ctrlKey) { // Ctrl+E and Ctrl+Shift+E + this._onExpand(shiftKey); // recurse = shiftKey + target.focus(); // TODO: should restore focus in case of recursing expand (which takes DOM offline) + handled = true; + } + } + else if (keynum == 77 && editable) { // M + if (ctrlKey) { // Ctrl+M + this.showContextMenu(target); + handled = true; + } + } + else if (keynum == 46 && editable) { // Del + if (ctrlKey) { // Ctrl+Del + Node.onRemove(selectedNodes); + handled = true; + } + } + else if (keynum == 45 && editable) { // Ins + if (ctrlKey && !shiftKey) { // Ctrl+Ins + this._onInsertBefore(); + handled = true; + } + else if (ctrlKey && shiftKey) { // Ctrl+Shift+Ins + this._onInsertAfter(); + handled = true; + } + } + else if (keynum == 35) { // End + if (altKey) { // Alt+End + // find the last node + var endNode = this._lastNode(); + if (endNode) { + endNode.focus(Node.focusElement || this._getElementName(target)); + } + handled = true; + } + } + else if (keynum == 36) { // Home + if (altKey) { // Alt+Home + // find the first node + var homeNode = this._firstNode(); + if (homeNode) { + homeNode.focus(Node.focusElement || this._getElementName(target)); + } + handled = true; + } + } + else if (keynum == 37) { // Arrow Left + if (altKey && !shiftKey) { // Alt + Arrow Left + // move to left element + var prevElement = this._previousElement(target); + if (prevElement) { + this.focus(this._getElementName(prevElement)); + } + handled = true; + } + else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow left + if (lastNode.expanded) { + var appendDom = lastNode.getAppend(); + nextDom = appendDom ? appendDom.nextSibling : undefined; + } + else { + var dom = lastNode.getDom(); + nextDom = dom.nextSibling; + } + if (nextDom) { + nextNode = Node.getNodeFromTarget(nextDom); + nextDom2 = nextDom.nextSibling; + nextNode2 = Node.getNodeFromTarget(nextDom2); + if (nextNode && nextNode instanceof AppendNode && + !(lastNode.parent.childs.length == 1) && + nextNode2 && nextNode2.parent) { + oldSelection = this.editor.getSelection(); + oldBeforeNode = lastNode._nextSibling(); + + selectedNodes.forEach(function (node) { + nextNode2.parent.moveBefore(node, nextNode2); + }); + this.focus(Node.focusElement || this._getElementName(target)); + + this.editor._onAction('moveNodes', { + nodes: selectedNodes, + oldBeforeNode: oldBeforeNode, + newBeforeNode: nextNode2, + oldSelection: oldSelection, + newSelection: this.editor.getSelection() + }); + } + } + } + } + else if (keynum == 38) { // Arrow Up + if (altKey && !shiftKey) { // Alt + Arrow Up + // find the previous node + prevNode = this._previousNode(); + if (prevNode) { + this.editor.deselect(true); + prevNode.focus(Node.focusElement || this._getElementName(target)); + } + handled = true; + } + else if (!altKey && ctrlKey && shiftKey && editable) { // Ctrl + Shift + Arrow Up + // select multiple nodes + prevNode = this._previousNode(); + if (prevNode) { + multiselection = this.editor.multiselection; + multiselection.start = multiselection.start || this; + multiselection.end = prevNode; + nodes = this.editor._findTopLevelNodes(multiselection.start, multiselection.end); + + this.editor.select(nodes); + prevNode.focus('field'); // select field as we know this always exists + } + handled = true; + } + else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow Up + // find the previous node + prevNode = firstNode._previousNode(); + if (prevNode && prevNode.parent) { + oldSelection = this.editor.getSelection(); + oldBeforeNode = lastNode._nextSibling(); + + selectedNodes.forEach(function (node) { + prevNode.parent.moveBefore(node, prevNode); + }); + this.focus(Node.focusElement || this._getElementName(target)); + + this.editor._onAction('moveNodes', { + nodes: selectedNodes, + oldBeforeNode: oldBeforeNode, + newBeforeNode: prevNode, + oldSelection: oldSelection, + newSelection: this.editor.getSelection() + }); + } + handled = true; + } + } + else if (keynum == 39) { // Arrow Right + if (altKey && !shiftKey) { // Alt + Arrow Right + // move to right element + var nextElement = this._nextElement(target); + if (nextElement) { + this.focus(this._getElementName(nextElement)); + } + handled = true; + } + else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow Right + dom = firstNode.getDom(); + var prevDom = dom.previousSibling; + if (prevDom) { + prevNode = Node.getNodeFromTarget(prevDom); + if (prevNode && prevNode.parent && + (prevNode instanceof AppendNode) + && !prevNode.isVisible()) { + oldSelection = this.editor.getSelection(); + oldBeforeNode = lastNode._nextSibling(); + + selectedNodes.forEach(function (node) { + prevNode.parent.moveBefore(node, prevNode); + }); + this.focus(Node.focusElement || this._getElementName(target)); + + this.editor._onAction('moveNodes', { + nodes: selectedNodes, + oldBeforeNode: oldBeforeNode, + newBeforeNode: prevNode, + oldSelection: oldSelection, + newSelection: this.editor.getSelection() + }); + } + } + } + } + else if (keynum == 40) { // Arrow Down + if (altKey && !shiftKey) { // Alt + Arrow Down + // find the next node + nextNode = this._nextNode(); + if (nextNode) { + this.editor.deselect(true); + nextNode.focus(Node.focusElement || this._getElementName(target)); + } + handled = true; + } + else if (!altKey && ctrlKey && shiftKey && editable) { // Ctrl + Shift + Arrow Down + // select multiple nodes + nextNode = this._nextNode(); + if (nextNode) { + multiselection = this.editor.multiselection; + multiselection.start = multiselection.start || this; + multiselection.end = nextNode; + nodes = this.editor._findTopLevelNodes(multiselection.start, multiselection.end); + + this.editor.select(nodes); + nextNode.focus('field'); // select field as we know this always exists + } + handled = true; + } + else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow Down + // find the 2nd next node and move before that one + if (lastNode.expanded) { + nextNode = lastNode.append ? lastNode.append._nextNode() : undefined; + } + else { + nextNode = lastNode._nextNode(); + } + var nextNode2 = nextNode && (nextNode._nextNode() || nextNode.parent.append); + if (nextNode2 && nextNode2.parent) { + oldSelection = this.editor.getSelection(); + oldBeforeNode = lastNode._nextSibling(); + + selectedNodes.forEach(function (node) { + nextNode2.parent.moveBefore(node, nextNode2); + }); + this.focus(Node.focusElement || this._getElementName(target)); + + this.editor._onAction('moveNodes', { + nodes: selectedNodes, + oldBeforeNode: oldBeforeNode, + newBeforeNode: nextNode2, + oldSelection: oldSelection, + newSelection: this.editor.getSelection() + }); + } + handled = true; + } + } + + if (handled) { + event.preventDefault(); + event.stopPropagation(); + } + }; + + /** + * Handle the expand event, when clicked on the expand button + * @param {boolean} recurse If true, child nodes will be expanded too + * @private + */ + Node.prototype._onExpand = function (recurse) { + if (recurse) { + // Take the table offline + var table = this.dom.tr.parentNode; // TODO: not nice to access the main table like this + var frame = table.parentNode; + var scrollTop = frame.scrollTop; + frame.removeChild(table); + } + + if (this.expanded) { + this.collapse(recurse); + } + else { + this.expand(recurse); + } + + if (recurse) { + // Put the table online again + frame.appendChild(table); + frame.scrollTop = scrollTop; + } + }; + + /** + * Remove nodes + * @param {Node[] | Node} nodes + */ + Node.onRemove = function(nodes) { + if (!Array.isArray(nodes)) { + return Node.onRemove([nodes]); + } + + if (nodes && nodes.length > 0) { + var firstNode = nodes[0]; + var parent = firstNode.parent; + var editor = firstNode.editor; + var firstIndex = firstNode.getIndex(); + editor.highlighter.unhighlight(); + + // adjust the focus + var oldSelection = editor.getSelection(); + Node.blurNodes(nodes); + var newSelection = editor.getSelection(); + + // remove the nodes + nodes.forEach(function (node) { + node.parent._remove(node); + }); + + // store history action + editor._onAction('removeNodes', { + nodes: nodes.slice(0), // store a copy of the array! + parent: parent, + index: firstIndex, + oldSelection: oldSelection, + newSelection: newSelection + }); + } + }; + + + /** + * Duplicate nodes + * duplicated nodes will be added right after the original nodes + * @param {Node[] | Node} nodes + */ + Node.onDuplicate = function(nodes) { + if (!Array.isArray(nodes)) { + return Node.onDuplicate([nodes]); + } + + if (nodes && nodes.length > 0) { + var lastNode = nodes[nodes.length - 1]; + var parent = lastNode.parent; + var editor = lastNode.editor; + + editor.deselect(editor.multiselection.nodes); + + // duplicate the nodes + var oldSelection = editor.getSelection(); + var afterNode = lastNode; + var clones = nodes.map(function (node) { + var clone = node.clone(); + parent.insertAfter(clone, afterNode); + afterNode = clone; + return clone; + }); + + // set selection to the duplicated nodes + if (nodes.length === 1) { + clones[0].focus(); + } + else { + editor.select(clones); + } + var newSelection = editor.getSelection(); + + editor._onAction('duplicateNodes', { + afterNode: lastNode, + nodes: clones, + parent: parent, + oldSelection: oldSelection, + newSelection: newSelection + }); + } + }; + + /** + * Handle insert before event + * @param {String} [field] + * @param {*} [value] + * @param {String} [type] Can be 'auto', 'array', 'object', or 'string' + * @private + */ + Node.prototype._onInsertBefore = function (field, value, type) { + var oldSelection = this.editor.getSelection(); + + var newNode = new Node(this.editor, { + field: (field != undefined) ? field : '', + value: (value != undefined) ? value : '', + type: type + }); + newNode.expand(true); + this.parent.insertBefore(newNode, this); + this.editor.highlighter.unhighlight(); + newNode.focus('field'); + var newSelection = this.editor.getSelection(); + + this.editor._onAction('insertBeforeNodes', { + nodes: [newNode], + beforeNode: this, + parent: this.parent, + oldSelection: oldSelection, + newSelection: newSelection + }); + }; + + /** + * Handle insert after event + * @param {String} [field] + * @param {*} [value] + * @param {String} [type] Can be 'auto', 'array', 'object', or 'string' + * @private + */ + Node.prototype._onInsertAfter = function (field, value, type) { + var oldSelection = this.editor.getSelection(); + + var newNode = new Node(this.editor, { + field: (field != undefined) ? field : '', + value: (value != undefined) ? value : '', + type: type + }); + newNode.expand(true); + this.parent.insertAfter(newNode, this); + this.editor.highlighter.unhighlight(); + newNode.focus('field'); + var newSelection = this.editor.getSelection(); + + this.editor._onAction('insertAfterNodes', { + nodes: [newNode], + afterNode: this, + parent: this.parent, + oldSelection: oldSelection, + newSelection: newSelection + }); + }; + + /** + * Handle append event + * @param {String} [field] + * @param {*} [value] + * @param {String} [type] Can be 'auto', 'array', 'object', or 'string' + * @private + */ + Node.prototype._onAppend = function (field, value, type) { + var oldSelection = this.editor.getSelection(); + + var newNode = new Node(this.editor, { + field: (field != undefined) ? field : '', + value: (value != undefined) ? value : '', + type: type + }); + newNode.expand(true); + this.parent.appendChild(newNode); + this.editor.highlighter.unhighlight(); + newNode.focus('field'); + var newSelection = this.editor.getSelection(); + + this.editor._onAction('appendNodes', { + nodes: [newNode], + parent: this.parent, + oldSelection: oldSelection, + newSelection: newSelection + }); + }; + + /** + * Change the type of the node's value + * @param {String} newType + * @private + */ + Node.prototype._onChangeType = function (newType) { + var oldType = this.type; + if (newType != oldType) { + var oldSelection = this.editor.getSelection(); + this.changeType(newType); + var newSelection = this.editor.getSelection(); + + this.editor._onAction('changeType', { + node: this, + oldType: oldType, + newType: newType, + oldSelection: oldSelection, + newSelection: newSelection + }); + } + }; + + /** + * Sort the child's of the node. Only applicable when the node has type 'object' + * or 'array'. + * @param {String} direction Sorting direction. Available values: "asc", "desc" + * @private + */ + Node.prototype.sort = function (direction) { + if (!this._hasChilds()) { + return; + } + + var order = (direction == 'desc') ? -1 : 1; + var prop = (this.type == 'array') ? 'value': 'field'; + this.hideChilds(); + + var oldChilds = this.childs; + var oldSortOrder = this.sortOrder; + + // copy the array (the old one will be kept for an undo action + this.childs = this.childs.concat(); + + // sort the arrays + this.childs.sort(function (a, b) { + return order * naturalSort(a[prop], b[prop]); + }); + this.sortOrder = (order == 1) ? 'asc' : 'desc'; + + this.editor._onAction('sort', { + node: this, + oldChilds: oldChilds, + oldSort: oldSortOrder, + newChilds: this.childs, + newSort: this.sortOrder + }); + + this.showChilds(); + }; + + /** + * Create a table row with an append button. + * @return {HTMLElement | undefined} buttonAppend or undefined when inapplicable + */ + Node.prototype.getAppend = function () { + if (!this.append) { + this.append = new AppendNode(this.editor); + this.append.setParent(this); + } + return this.append.getDom(); + }; + + /** + * Find the node from an event target + * @param {Node} target + * @return {Node | undefined} node or undefined when not found + * @static + */ + Node.getNodeFromTarget = function (target) { + while (target) { + if (target.node) { + return target.node; + } + target = target.parentNode; + } + + return undefined; + }; + + /** + * Remove the focus of given nodes, and move the focus to the (a) node before, + * (b) the node after, or (c) the parent node. + * @param {Array. | Node} nodes + */ + Node.blurNodes = function (nodes) { + if (!Array.isArray(nodes)) { + Node.blurNodes([nodes]); + return; + } + + var firstNode = nodes[0]; + var parent = firstNode.parent; + var firstIndex = firstNode.getIndex(); + + if (parent.childs[firstIndex + nodes.length]) { + parent.childs[firstIndex + nodes.length].focus(); + } + else if (parent.childs[firstIndex - 1]) { + parent.childs[firstIndex - 1].focus(); + } + else { + parent.focus(); + } + }; + + /** + * Get the next sibling of current node + * @return {Node} nextSibling + * @private + */ + Node.prototype._nextSibling = function () { + var index = this.parent.childs.indexOf(this); + return this.parent.childs[index + 1] || this.parent.append; + }; + + /** + * Get the previously rendered node + * @return {Node | null} previousNode + * @private + */ + Node.prototype._previousNode = function () { + var prevNode = null; + var dom = this.getDom(); + if (dom && dom.parentNode) { + // find the previous field + var prevDom = dom; + do { + prevDom = prevDom.previousSibling; + prevNode = Node.getNodeFromTarget(prevDom); + } + while (prevDom && (prevNode instanceof AppendNode && !prevNode.isVisible())); + } + return prevNode; + }; + + /** + * Get the next rendered node + * @return {Node | null} nextNode + * @private + */ + Node.prototype._nextNode = function () { + var nextNode = null; + var dom = this.getDom(); + if (dom && dom.parentNode) { + // find the previous field + var nextDom = dom; + do { + nextDom = nextDom.nextSibling; + nextNode = Node.getNodeFromTarget(nextDom); + } + while (nextDom && (nextNode instanceof AppendNode && !nextNode.isVisible())); + } + + return nextNode; + }; + + /** + * Get the first rendered node + * @return {Node | null} firstNode + * @private + */ + Node.prototype._firstNode = function () { + var firstNode = null; + var dom = this.getDom(); + if (dom && dom.parentNode) { + var firstDom = dom.parentNode.firstChild; + firstNode = Node.getNodeFromTarget(firstDom); + } + + return firstNode; + }; + + /** + * Get the last rendered node + * @return {Node | null} lastNode + * @private + */ + Node.prototype._lastNode = function () { + var lastNode = null; + var dom = this.getDom(); + if (dom && dom.parentNode) { + var lastDom = dom.parentNode.lastChild; + lastNode = Node.getNodeFromTarget(lastDom); + while (lastDom && (lastNode instanceof AppendNode && !lastNode.isVisible())) { + lastDom = lastDom.previousSibling; + lastNode = Node.getNodeFromTarget(lastDom); + } + } + return lastNode; + }; + + /** + * Get the next element which can have focus. + * @param {Element} elem + * @return {Element | null} nextElem + * @private + */ + Node.prototype._previousElement = function (elem) { + var dom = this.dom; + // noinspection FallthroughInSwitchStatementJS + switch (elem) { + case dom.value: + if (this.fieldEditable) { + return dom.field; + } + // intentional fall through + case dom.field: + if (this._hasChilds()) { + return dom.expand; + } + // intentional fall through + case dom.expand: + return dom.menu; + case dom.menu: + if (dom.drag) { + return dom.drag; + } + // intentional fall through + default: + return null; + } + }; + + /** + * Get the next element which can have focus. + * @param {Element} elem + * @return {Element | null} nextElem + * @private + */ + Node.prototype._nextElement = function (elem) { + var dom = this.dom; + // noinspection FallthroughInSwitchStatementJS + switch (elem) { + case dom.drag: + return dom.menu; + case dom.menu: + if (this._hasChilds()) { + return dom.expand; + } + // intentional fall through + case dom.expand: + if (this.fieldEditable) { + return dom.field; + } + // intentional fall through + case dom.field: + if (!this._hasChilds()) { + return dom.value; + } + default: + return null; + } + }; + + /** + * Get the dom name of given element. returns null if not found. + * For example when element == dom.field, "field" is returned. + * @param {Element} element + * @return {String | null} elementName Available elements with name: 'drag', + * 'menu', 'expand', 'field', 'value' + * @private + */ + Node.prototype._getElementName = function (element) { + var dom = this.dom; + for (var name in dom) { + if (dom.hasOwnProperty(name)) { + if (dom[name] == element) { + return name; + } + } + } + return null; + }; + + /** + * Test if this node has childs. This is the case when the node is an object + * or array. + * @return {boolean} hasChilds + * @private + */ + Node.prototype._hasChilds = function () { + return this.type == 'array' || this.type == 'object'; + }; + + // titles with explanation for the different types + Node.TYPE_TITLES = { + 'auto': 'Field type "auto". ' + + 'The field type is automatically determined from the value ' + + 'and can be a string, number, boolean, or null.', + 'object': 'Field type "object". ' + + 'An object contains an unordered set of key/value pairs.', + 'array': 'Field type "array". ' + + 'An array contains an ordered collection of values.', + 'string': 'Field type "string". ' + + 'Field type is not determined from the value, ' + + 'but always returned as string.' + }; + + /** + * Show a contextmenu for this node + * @param {HTMLElement} anchor Anchor element to attach the context menu to + * as sibling. + * @param {function} [onClose] Callback method called when the context menu + * is being closed. + */ + Node.prototype.showContextMenu = function (anchor, onClose) { + var node = this; + var titles = Node.TYPE_TITLES; + var items = []; + + if (this.editable.value) { + items.push({ + text: 'Type', + title: 'Change the type of this field', + className: 'jsoneditor-type-' + this.type, + submenu: [ + { + text: 'Auto', + className: 'jsoneditor-type-auto' + + (this.type == 'auto' ? ' jsoneditor-selected' : ''), + title: titles.auto, + click: function () { + node._onChangeType('auto'); + } + }, + { + text: 'Array', + className: 'jsoneditor-type-array' + + (this.type == 'array' ? ' jsoneditor-selected' : ''), + title: titles.array, + click: function () { + node._onChangeType('array'); + } + }, + { + text: 'Object', + className: 'jsoneditor-type-object' + + (this.type == 'object' ? ' jsoneditor-selected' : ''), + title: titles.object, + click: function () { + node._onChangeType('object'); + } + }, + { + text: 'String', + className: 'jsoneditor-type-string' + + (this.type == 'string' ? ' jsoneditor-selected' : ''), + title: titles.string, + click: function () { + node._onChangeType('string'); + } + } + ] + }); + } + + if (this._hasChilds()) { + var direction = ((this.sortOrder == 'asc') ? 'desc': 'asc'); + items.push({ + text: 'Sort', + title: 'Sort the childs of this ' + this.type, + className: 'jsoneditor-sort-' + direction, + click: function () { + node.sort(direction); + }, + submenu: [ + { + text: 'Ascending', + className: 'jsoneditor-sort-asc', + title: 'Sort the childs of this ' + this.type + ' in ascending order', + click: function () { + node.sort('asc'); + } + }, + { + text: 'Descending', + className: 'jsoneditor-sort-desc', + title: 'Sort the childs of this ' + this.type +' in descending order', + click: function () { + node.sort('desc'); + } + } + ] + }); + } + + if (this.parent && this.parent._hasChilds()) { + if (items.length) { + // create a separator + items.push({ + 'type': 'separator' + }); + } + + // create append button (for last child node only) + var childs = node.parent.childs; + if (node == childs[childs.length - 1]) { + items.push({ + text: 'Append', + title: 'Append a new field with type \'auto\' after this field (Ctrl+Shift+Ins)', + submenuTitle: 'Select the type of the field to be appended', + className: 'jsoneditor-append', + click: function () { + node._onAppend('', '', 'auto'); + }, + submenu: [ + { + text: 'Auto', + className: 'jsoneditor-type-auto', + title: titles.auto, + click: function () { + node._onAppend('', '', 'auto'); + } + }, + { + text: 'Array', + className: 'jsoneditor-type-array', + title: titles.array, + click: function () { + node._onAppend('', []); + } + }, + { + text: 'Object', + className: 'jsoneditor-type-object', + title: titles.object, + click: function () { + node._onAppend('', {}); + } + }, + { + text: 'String', + className: 'jsoneditor-type-string', + title: titles.string, + click: function () { + node._onAppend('', '', 'string'); + } + } + ] + }); + } + + // create insert button + items.push({ + text: 'Insert', + title: 'Insert a new field with type \'auto\' before this field (Ctrl+Ins)', + submenuTitle: 'Select the type of the field to be inserted', + className: 'jsoneditor-insert', + click: function () { + node._onInsertBefore('', '', 'auto'); + }, + submenu: [ + { + text: 'Auto', + className: 'jsoneditor-type-auto', + title: titles.auto, + click: function () { + node._onInsertBefore('', '', 'auto'); + } + }, + { + text: 'Array', + className: 'jsoneditor-type-array', + title: titles.array, + click: function () { + node._onInsertBefore('', []); + } + }, + { + text: 'Object', + className: 'jsoneditor-type-object', + title: titles.object, + click: function () { + node._onInsertBefore('', {}); + } + }, + { + text: 'String', + className: 'jsoneditor-type-string', + title: titles.string, + click: function () { + node._onInsertBefore('', '', 'string'); + } + } + ] + }); + + if (this.editable.field) { + // create duplicate button + items.push({ + text: 'Duplicate', + title: 'Duplicate this field (Ctrl+D)', + className: 'jsoneditor-duplicate', + click: function () { + Node.onDuplicate(node); + } + }); + + // create remove button + items.push({ + text: 'Remove', + title: 'Remove this field (Ctrl+Del)', + className: 'jsoneditor-remove', + click: function () { + Node.onRemove(node); + } + }); + } + } + + var menu = new ContextMenu(items, {close: onClose}); + menu.show(anchor, this.editor.content); + }; + + /** + * get the type of a value + * @param {*} value + * @return {String} type Can be 'object', 'array', 'string', 'auto' + * @private + */ + Node.prototype._getType = function(value) { + if (value instanceof Array) { + return 'array'; + } + if (value instanceof Object) { + return 'object'; + } + if (typeof(value) == 'string' && typeof(this._stringCast(value)) != 'string') { + return 'string'; + } + + return 'auto'; + }; + + /** + * cast contents of a string to the correct type. This can be a string, + * a number, a boolean, etc + * @param {String} str + * @return {*} castedStr + * @private + */ + Node.prototype._stringCast = function(str) { + var lower = str.toLowerCase(), + num = Number(str), // will nicely fail with '123ab' + numFloat = parseFloat(str); // will nicely fail with ' ' + + if (str == '') { + return ''; + } + else if (lower == 'null') { + return null; + } + else if (lower == 'true') { + return true; + } + else if (lower == 'false') { + return false; + } + else if (!isNaN(num) && !isNaN(numFloat)) { + return num; + } + else { + return str; + } + }; + + /** + * escape a text, such that it can be displayed safely in an HTML element + * @param {String} text + * @return {String} escapedText + * @private + */ + Node.prototype._escapeHTML = function (text) { + if (typeof text !== 'string') { + return String(text); + } + else { + var htmlEscaped = String(text) + .replace(/&/g, '&') // must be replaced first! + .replace(//g, '>') + .replace(/ /g, '  ') // replace double space with an nbsp and space + .replace(/^ /, ' ') // space at start + .replace(/ $/, ' '); // space at end + + var json = JSON.stringify(htmlEscaped); + var html = json.substring(1, json.length - 1); + if (this.editor.options.escapeUnicode === true) { + html = util.escapeUnicodeChars(html); + } + return html; + } + }; + + /** + * unescape a string. + * @param {String} escapedText + * @return {String} text + * @private + */ + Node.prototype._unescapeHTML = function (escapedText) { + var json = '"' + this._escapeJSON(escapedText) + '"'; + var htmlEscaped = util.parse(json); + + return htmlEscaped + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/ |\u00A0/g, ' ') + .replace(/&/g, '&'); // must be replaced last + }; + + /** + * escape a text to make it a valid JSON string. The method will: + * - replace unescaped double quotes with '\"' + * - replace unescaped backslash with '\\' + * - replace returns with '\n' + * @param {String} text + * @return {String} escapedText + * @private + */ + Node.prototype._escapeJSON = function (text) { + // TODO: replace with some smart regex (only when a new solution is faster!) + var escaped = ''; + var i = 0; + while (i < text.length) { + var c = text.charAt(i); + if (c == '\n') { + escaped += '\\n'; + } + else if (c == '\\') { + escaped += c; + i++; + + c = text.charAt(i); + if (c === '' || '"\\/bfnrtu'.indexOf(c) == -1) { + escaped += '\\'; // no valid escape character + } + escaped += c; + } + else if (c == '"') { + escaped += '\\"'; + } + else { + escaped += c; + } + i++; + } + + return escaped; + }; + + // TODO: find a nicer solution to resolve this circular dependency between Node and AppendNode + var AppendNode = appendNodeFactory(Node); + + module.exports = Node; + + +/***/ }, +/* 9 */ +/***/ function(module, exports) { + + /* + * Natural Sort algorithm for Javascript - Version 0.7 - Released under MIT license + * Author: Jim Palmer (based on chunking idea from Dave Koelle) + */ + /*jshint unused:false */ + module.exports = function naturalSort (a, b) { + "use strict"; + var re = /(^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi, + sre = /(^[ ]*|[ ]*$)/g, + dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/, + hre = /^0x[0-9a-f]+$/i, + ore = /^0/, + i = function(s) { return naturalSort.insensitive && ('' + s).toLowerCase() || '' + s; }, + // convert all to strings strip whitespace + x = i(a).replace(sre, '') || '', + y = i(b).replace(sre, '') || '', + // chunk/tokenize + xN = x.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'), + yN = y.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'), + // numeric, hex or date detection + xD = parseInt(x.match(hre), 16) || (xN.length !== 1 && x.match(dre) && Date.parse(x)), + yD = parseInt(y.match(hre), 16) || xD && y.match(dre) && Date.parse(y) || null, + oFxNcL, oFyNcL; + // first try and sort Hex codes or Dates + if (yD) { + if ( xD < yD ) { return -1; } + else if ( xD > yD ) { return 1; } + } + // natural sorting through split numeric strings and default strings + for(var cLoc=0, numS=Math.max(xN.length, yN.length); cLoc < numS; cLoc++) { + // find floats not starting with '0', string or 0 if not defined (Clint Priest) + oFxNcL = !(xN[cLoc] || '').match(ore) && parseFloat(xN[cLoc]) || xN[cLoc] || 0; + oFyNcL = !(yN[cLoc] || '').match(ore) && parseFloat(yN[cLoc]) || yN[cLoc] || 0; + // handle numeric vs string comparison - number < string - (Kyle Adams) + if (isNaN(oFxNcL) !== isNaN(oFyNcL)) { return (isNaN(oFxNcL)) ? 1 : -1; } + // rely on string comparison if different types - i.e. '02' < 2 != '02' < '2' + else if (typeof oFxNcL !== typeof oFyNcL) { + oFxNcL += ''; + oFyNcL += ''; + } + if (oFxNcL < oFyNcL) { return -1; } + if (oFxNcL > oFyNcL) { return 1; } + } + return 0; + }; + + +/***/ }, +/* 10 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var util = __webpack_require__(4); + var ContextMenu = __webpack_require__(7); + + /** + * A factory function to create an AppendNode, which depends on a Node + * @param {Node} Node + */ + function appendNodeFactory(Node) { + /** + * @constructor AppendNode + * @extends Node + * @param {TreeEditor} editor + * Create a new AppendNode. This is a special node which is created at the + * end of the list with childs for an object or array + */ + function AppendNode (editor) { + /** @type {TreeEditor} */ + this.editor = editor; + this.dom = {}; + } + + AppendNode.prototype = new Node(); + + /** + * Return a table row with an append button. + * @return {Element} dom TR element + */ + AppendNode.prototype.getDom = function () { + // TODO: implement a new solution for the append node + var dom = this.dom; + + if (dom.tr) { + return dom.tr; + } + + this._updateEditability(); + + // a row for the append button + var trAppend = document.createElement('tr'); + trAppend.node = this; + dom.tr = trAppend; + + // TODO: consistent naming + + if (this.editor.options.mode === 'tree') { + // a cell for the dragarea column + dom.tdDrag = document.createElement('td'); + + // create context menu + var tdMenu = document.createElement('td'); + dom.tdMenu = tdMenu; + var menu = document.createElement('button'); + menu.type = 'button'; + menu.className = 'jsoneditor-contextmenu'; + menu.title = 'Click to open the actions menu (Ctrl+M)'; + dom.menu = menu; + tdMenu.appendChild(dom.menu); + } + + // a cell for the contents (showing text 'empty') + var tdAppend = document.createElement('td'); + var domText = document.createElement('div'); + domText.innerHTML = '(empty)'; + domText.className = 'jsoneditor-readonly'; + tdAppend.appendChild(domText); + dom.td = tdAppend; + dom.text = domText; + + this.updateDom(); + + return trAppend; + }; + + /** + * Update the HTML dom of the Node + */ + AppendNode.prototype.updateDom = function () { + var dom = this.dom; + var tdAppend = dom.td; + if (tdAppend) { + tdAppend.style.paddingLeft = (this.getLevel() * 24 + 26) + 'px'; + // TODO: not so nice hard coded offset + } + + var domText = dom.text; + if (domText) { + domText.innerHTML = '(empty ' + this.parent.type + ')'; + } + + // attach or detach the contents of the append node: + // hide when the parent has childs, show when the parent has no childs + var trAppend = dom.tr; + if (!this.isVisible()) { + if (dom.tr.firstChild) { + if (dom.tdDrag) { + trAppend.removeChild(dom.tdDrag); + } + if (dom.tdMenu) { + trAppend.removeChild(dom.tdMenu); + } + trAppend.removeChild(tdAppend); + } + } + else { + if (!dom.tr.firstChild) { + if (dom.tdDrag) { + trAppend.appendChild(dom.tdDrag); + } + if (dom.tdMenu) { + trAppend.appendChild(dom.tdMenu); + } + trAppend.appendChild(tdAppend); + } + } + }; + + /** + * Check whether the AppendNode is currently visible. + * the AppendNode is visible when its parent has no childs (i.e. is empty). + * @return {boolean} isVisible + */ + AppendNode.prototype.isVisible = function () { + return (this.parent.childs.length == 0); + }; + + /** + * Show a contextmenu for this node + * @param {HTMLElement} anchor The element to attach the menu to. + * @param {function} [onClose] Callback method called when the context menu + * is being closed. + */ + AppendNode.prototype.showContextMenu = function (anchor, onClose) { + var node = this; + var titles = Node.TYPE_TITLES; + var items = [ + // create append button + { + 'text': 'Append', + 'title': 'Append a new field with type \'auto\' (Ctrl+Shift+Ins)', + 'submenuTitle': 'Select the type of the field to be appended', + 'className': 'jsoneditor-insert', + 'click': function () { + node._onAppend('', '', 'auto'); + }, + 'submenu': [ + { + 'text': 'Auto', + 'className': 'jsoneditor-type-auto', + 'title': titles.auto, + 'click': function () { + node._onAppend('', '', 'auto'); + } + }, + { + 'text': 'Array', + 'className': 'jsoneditor-type-array', + 'title': titles.array, + 'click': function () { + node._onAppend('', []); + } + }, + { + 'text': 'Object', + 'className': 'jsoneditor-type-object', + 'title': titles.object, + 'click': function () { + node._onAppend('', {}); + } + }, + { + 'text': 'String', + 'className': 'jsoneditor-type-string', + 'title': titles.string, + 'click': function () { + node._onAppend('', '', 'string'); + } + } + ] + } + ]; + + var menu = new ContextMenu(items, {close: onClose}); + menu.show(anchor, this.editor.content); + }; + + /** + * Handle an event. The event is catched centrally by the editor + * @param {Event} event + */ + AppendNode.prototype.onEvent = function (event) { + var type = event.type; + var target = event.target || event.srcElement; + var dom = this.dom; + + // highlight the append nodes parent + var menu = dom.menu; + if (target == menu) { + if (type == 'mouseover') { + this.editor.highlighter.highlight(this.parent); + } + else if (type == 'mouseout') { + this.editor.highlighter.unhighlight(); + } + } + + // context menu events + if (type == 'click' && target == dom.menu) { + var highlighter = this.editor.highlighter; + highlighter.highlight(this.parent); + highlighter.lock(); + util.addClassName(dom.menu, 'jsoneditor-selected'); + this.showContextMenu(dom.menu, function () { + util.removeClassName(dom.menu, 'jsoneditor-selected'); + highlighter.unlock(); + highlighter.unhighlight(); + }); + } + + if (type == 'keydown') { + this.onKeyDown(event); + } + }; + + return AppendNode; + } + + module.exports = appendNodeFactory; + + +/***/ }, +/* 11 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var ContextMenu = __webpack_require__(7); + + /** + * Create a select box to be used in the editor menu's, which allows to switch mode + * @param {HTMLElement} container + * @param {String[]} modes Available modes: 'code', 'form', 'text', 'tree', 'view' + * @param {String} current Available modes: 'code', 'form', 'text', 'tree', 'view' + * @param {function(mode: string)} onSwitch Callback invoked on switch + * @constructor + */ + function ModeSwitcher(container, modes, current, onSwitch) { + // available modes + var availableModes = { + code: { + 'text': 'Code', + 'title': 'Switch to code highlighter', + 'click': function () { + onSwitch('code') + } + }, + form: { + 'text': 'Form', + 'title': 'Switch to form editor', + 'click': function () { + onSwitch('form'); + } + }, + text: { + 'text': 'Text', + 'title': 'Switch to plain text editor', + 'click': function () { + onSwitch('text'); + } + }, + tree: { + 'text': 'Tree', + 'title': 'Switch to tree editor', + 'click': function () { + onSwitch('tree'); + } + }, + view: { + 'text': 'View', + 'title': 'Switch to tree view', + 'click': function () { + onSwitch('view'); + } + } + }; + + // list the selected modes + var items = []; + for (var i = 0; i < modes.length; i++) { + var mode = modes[i]; + var item = availableModes[mode]; + if (!item) { + throw new Error('Unknown mode "' + mode + '"'); + } + + item.className = 'jsoneditor-type-modes' + ((current == mode) ? ' jsoneditor-selected' : ''); + items.push(item); + } + + // retrieve the title of current mode + var currentMode = availableModes[current]; + if (!currentMode) { + throw new Error('Unknown mode "' + current + '"'); + } + var currentTitle = currentMode.text; + + // create the html element + var box = document.createElement('button'); + box.type = 'button'; + box.className = 'jsoneditor-modes jsoneditor-separator'; + box.innerHTML = currentTitle + ' ▾'; + box.title = 'Switch editor mode'; + box.onclick = function () { + var menu = new ContextMenu(items); + menu.show(box); + }; + + var frame = document.createElement('div'); + frame.className = 'jsoneditor-modes'; + frame.style.position = 'relative'; + frame.appendChild(box); + + container.appendChild(frame); + + this.dom = { + container: container, + box: box, + frame: frame + }; + } + + /** + * Set focus to switcher + */ + ModeSwitcher.prototype.focus = function () { + this.dom.box.focus(); + }; + + /** + * Destroy the ModeSwitcher, remove from DOM + */ + ModeSwitcher.prototype.destroy = function () { + if (this.dom && this.dom.frame && this.dom.frame.parentNode) { + this.dom.frame.parentNode.removeChild(this.dom.frame); + } + this.dom = null; + }; + + module.exports = ModeSwitcher; + + +/***/ }, +/* 12 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var ace; + try { + ace = __webpack_require__(13); + } + catch (err) { + // failed to load ace, no problem, we will fall back to plain text + } + + var ModeSwitcher = __webpack_require__(11); + var util = __webpack_require__(4); + + // create a mixin with the functions for text mode + var textmode = {}; + + var MAX_ERRORS = 3; // maximum number of displayed errors at the bottom + + /** + * Create a text editor + * @param {Element} container + * @param {Object} [options] Object with options. available options: + * {String} mode Available values: + * "text" (default) + * or "code". + * {Number} indentation Number of indentation + * spaces. 2 by default. + * {function} onChange Callback method + * triggered on change + * {function} onModeChange Callback method + * triggered after setMode + * {Object} ace A custom instance of + * Ace editor. + * {boolean} escapeUnicode If true, unicode + * characters are escaped. + * false by default. + * @private + */ + textmode.create = function (container, options) { + // read options + options = options || {}; + this.options = options; + + // indentation + if (options.indentation) { + this.indentation = Number(options.indentation); + } + else { + this.indentation = 2; // number of spaces + } + + // grab ace from options if provided + var _ace = options.ace ? options.ace : ace; + + // determine mode + this.mode = (options.mode == 'code') ? 'code' : 'text'; + if (this.mode == 'code') { + // verify whether Ace editor is available and supported + if (typeof _ace === 'undefined') { + this.mode = 'text'; + console.warn('Failed to load Ace editor, falling back to plain text mode. Please use a JSONEditor bundle including Ace, or pass Ace as via the configuration option `ace`.'); + } + } + + // determine theme + this.theme = options.theme || 'ace/theme/jsoneditor'; + + var me = this; + this.container = container; + this.dom = {}; + this.aceEditor = undefined; // ace code editor + this.textarea = undefined; // plain text editor (fallback when Ace is not available) + this.validateSchema = null; + + // create a debounced validate function + this._debouncedValidate = util.debounce(this.validate.bind(this), this.DEBOUNCE_INTERVAL); + + this.width = container.clientWidth; + this.height = container.clientHeight; + + this.frame = document.createElement('div'); + this.frame.className = 'jsoneditor jsoneditor-mode-' + this.options.mode; + this.frame.onclick = function (event) { + // prevent default submit action when the editor is located inside a form + event.preventDefault(); + }; + this.frame.onkeydown = function (event) { + me._onKeyDown(event); + }; + + // create menu + this.menu = document.createElement('div'); + this.menu.className = 'jsoneditor-menu'; + this.frame.appendChild(this.menu); + + // create format button + var buttonFormat = document.createElement('button'); + buttonFormat.type = 'button'; + buttonFormat.className = 'jsoneditor-format'; + buttonFormat.title = 'Format JSON data, with proper indentation and line feeds (Ctrl+\\)'; + this.menu.appendChild(buttonFormat); + buttonFormat.onclick = function () { + try { + me.format(); + me._onChange(); + } + catch (err) { + me._onError(err); + } + }; + + // create compact button + var buttonCompact = document.createElement('button'); + buttonCompact.type = 'button'; + buttonCompact.className = 'jsoneditor-compact'; + buttonCompact.title = 'Compact JSON data, remove all whitespaces (Ctrl+Shift+\\)'; + this.menu.appendChild(buttonCompact); + buttonCompact.onclick = function () { + try { + me.compact(); + me._onChange(); + } + catch (err) { + me._onError(err); + } + }; + + // create mode box + if (this.options && this.options.modes && this.options.modes.length) { + this.modeSwitcher = new ModeSwitcher(this.menu, this.options.modes, this.options.mode, function onSwitch(mode) { + // switch mode and restore focus + me.setMode(mode); + me.modeSwitcher.focus(); + }); + } + + this.content = document.createElement('div'); + this.content.className = 'jsoneditor-outer'; + this.frame.appendChild(this.content); + + this.container.appendChild(this.frame); + + if (this.mode == 'code') { + this.editorDom = document.createElement('div'); + this.editorDom.style.height = '100%'; // TODO: move to css + this.editorDom.style.width = '100%'; // TODO: move to css + this.content.appendChild(this.editorDom); + + var aceEditor = _ace.edit(this.editorDom); + aceEditor.$blockScrolling = Infinity; + aceEditor.setTheme(this.theme); + aceEditor.setShowPrintMargin(false); + aceEditor.setFontSize(13); + aceEditor.getSession().setMode('ace/mode/json'); + aceEditor.getSession().setTabSize(this.indentation); + aceEditor.getSession().setUseSoftTabs(true); + aceEditor.getSession().setUseWrapMode(true); + aceEditor.commands.bindKey('Ctrl-L', null); // disable Ctrl+L (is used by the browser to select the address bar) + aceEditor.commands.bindKey('Command-L', null); // disable Ctrl+L (is used by the browser to select the address bar) + this.aceEditor = aceEditor; + + // TODO: deprecated since v5.0.0. Cleanup backward compatibility some day + if (!this.hasOwnProperty('editor')) { + Object.defineProperty(this, 'editor', { + get: function () { + console.warn('Property "editor" has been renamed to "aceEditor".'); + return me.aceEditor; + }, + set: function (aceEditor) { + console.warn('Property "editor" has been renamed to "aceEditor".'); + me.aceEditor = aceEditor; + } + }); + } + + var poweredBy = document.createElement('a'); + poweredBy.appendChild(document.createTextNode('powered by ace')); + poweredBy.href = 'http://ace.ajax.org'; + poweredBy.target = '_blank'; + poweredBy.className = 'jsoneditor-poweredBy'; + poweredBy.onclick = function () { + // TODO: this anchor falls below the margin of the content, + // therefore the normal a.href does not work. We use a click event + // for now, but this should be fixed. + window.open(poweredBy.href, poweredBy.target); + }; + this.menu.appendChild(poweredBy); + + // register onchange event + aceEditor.on('change', this._onChange.bind(this)); + } + else { + // load a plain text textarea + var textarea = document.createElement('textarea'); + textarea.className = 'jsoneditor-text'; + textarea.spellcheck = false; + this.content.appendChild(textarea); + this.textarea = textarea; + + // register onchange event + if (this.textarea.oninput === null) { + this.textarea.oninput = this._onChange.bind(this); + } + else { + // oninput is undefined. For IE8- + this.textarea.onchange = this._onChange.bind(this); + } + } + + this.setSchema(this.options.schema); + }; + + /** + * Handle a change: + * - Validate JSON schema + * - Send a callback to the onChange listener if provided + * @private + */ + textmode._onChange = function () { + // validate JSON schema (if configured) + this._debouncedValidate(); + + // trigger the onChange callback + if (this.options.onChange) { + try { + this.options.onChange(); + } + catch (err) { + console.error('Error in onChange callback: ', err); + } + } + }; + + /** + * Event handler for keydown. Handles shortcut keys + * @param {Event} event + * @private + */ + textmode._onKeyDown = function (event) { + var keynum = event.which || event.keyCode; + var handled = false; + + if (keynum == 220 && event.ctrlKey) { + if (event.shiftKey) { // Ctrl+Shift+\ + this.compact(); + this._onChange(); + } + else { // Ctrl+\ + this.format(); + this._onChange(); + } + handled = true; + } + + if (handled) { + event.preventDefault(); + event.stopPropagation(); + } + }; + + /** + * Destroy the editor. Clean up DOM, event listeners, and web workers. + */ + textmode.destroy = function () { + // remove old ace editor + if (this.aceEditor) { + this.aceEditor.destroy(); + this.aceEditor = null; + } + + if (this.frame && this.container && this.frame.parentNode == this.container) { + this.container.removeChild(this.frame); + } + + if (this.modeSwitcher) { + this.modeSwitcher.destroy(); + this.modeSwitcher = null; + } + + this.textarea = null; + + this._debouncedValidate = null; + }; + + /** + * Compact the code in the formatter + */ + textmode.compact = function () { + var json = this.get(); + var text = JSON.stringify(json); + this.setText(text); + }; + + /** + * Format the code in the formatter + */ + textmode.format = function () { + var json = this.get(); + var text = JSON.stringify(json, null, this.indentation); + this.setText(text); + }; + + /** + * Set focus to the formatter + */ + textmode.focus = function () { + if (this.textarea) { + this.textarea.focus(); + } + if (this.aceEditor) { + this.aceEditor.focus(); + } + }; + + /** + * Resize the formatter + */ + textmode.resize = function () { + if (this.aceEditor) { + var force = false; + this.aceEditor.resize(force); + } + }; + + /** + * Set json data in the formatter + * @param {Object} json + */ + textmode.set = function(json) { + this.setText(JSON.stringify(json, null, this.indentation)); + }; + + /** + * Get json data from the formatter + * @return {Object} json + */ + textmode.get = function() { + var text = this.getText(); + var json; + + try { + json = util.parse(text); // this can throw an error + } + catch (err) { + // try to sanitize json, replace JavaScript notation with JSON notation + text = util.sanitize(text); + + // try to parse again + json = util.parse(text); // this can throw an error + } + + return json; + }; + + /** + * Get the text contents of the editor + * @return {String} jsonText + */ + textmode.getText = function() { + if (this.textarea) { + return this.textarea.value; + } + if (this.aceEditor) { + return this.aceEditor.getValue(); + } + return ''; + }; + + /** + * Set the text contents of the editor + * @param {String} jsonText + */ + textmode.setText = function(jsonText) { + var text; + + if (this.options.escapeUnicode === true) { + text = util.escapeUnicodeChars(jsonText); + } + else { + text = jsonText; + } + + if (this.textarea) { + this.textarea.value = text; + } + if (this.aceEditor) { + // prevent emitting onChange events while setting new text + var originalOnChange = this.options.onChange; + this.options.onChange = null; + + this.aceEditor.setValue(text, -1); + + this.options.onChange = originalOnChange; + } + + // validate JSON schema + this.validate(); + }; + + /** + * Validate current JSON object against the configured JSON schema + * Throws an exception when no JSON schema is configured + */ + textmode.validate = function () { + // clear all current errors + if (this.dom.validationErrors) { + this.dom.validationErrors.parentNode.removeChild(this.dom.validationErrors); + this.dom.validationErrors = null; + + this.content.style.marginBottom = ''; + this.content.style.paddingBottom = ''; + } + + var doValidate = false; + var errors = []; + var json; + try { + json = this.get(); // this can fail when there is no valid json + doValidate = true; + } + catch (err) { + // no valid JSON, don't validate + } + + // only validate the JSON when parsing the JSON succeeded + if (doValidate && this.validateSchema) { + var valid = this.validateSchema(json); + if (!valid) { + errors = this.validateSchema.errors.map(function (error) { + return util.improveSchemaError(error); + }); + } + } + + if (errors.length > 0) { + // limit the number of displayed errors + var limit = errors.length > MAX_ERRORS; + if (limit) { + errors = errors.slice(0, MAX_ERRORS); + var hidden = this.validateSchema.errors.length - MAX_ERRORS; + errors.push('(' + hidden + ' more errors...)') + } + + var validationErrors = document.createElement('div'); + validationErrors.innerHTML = '' + + '' + + errors.map(function (error) { + var message; + if (typeof error === 'string') { + message = ''; + } + else { + message = '' + + ''; + } + + return '' + message + '' + }).join('') + + '' + + '
' + error + '
' + error.dataPath + '' + error.message + '
'; + + this.dom.validationErrors = validationErrors; + this.frame.appendChild(validationErrors); + + var height = validationErrors.clientHeight; + this.content.style.marginBottom = (-height) + 'px'; + this.content.style.paddingBottom = height + 'px'; + } + + // update the height of the ace editor + if (this.aceEditor) { + var force = false; + this.aceEditor.resize(force); + } + }; + + // define modes + module.exports = [ + { + mode: 'text', + mixin: textmode, + data: 'text', + load: textmode.format + }, + { + mode: 'code', + mixin: textmode, + data: 'text', + load: textmode.format + } + ]; + + +/***/ }, +/* 13 */ +/***/ function(module, exports, __webpack_require__) { + + // load brace + var ace = __webpack_require__(!(function webpackMissingModule() { var e = new Error("Cannot find module \"brace\""); e.code = 'MODULE_NOT_FOUND'; throw e; }())); + + // load required ace modules + __webpack_require__(14); + __webpack_require__(16); + __webpack_require__(17); + + module.exports = ace; + + +/***/ }, +/* 14 */ +/***/ function(module, exports, __webpack_require__) { + + ace.define("ace/mode/json_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("../lib/oop"); + var TextHighlightRules = acequire("./text_highlight_rules").TextHighlightRules; + + var JsonHighlightRules = function() { + this.$rules = { + "start" : [ + { + token : "variable", // single line + regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]\\s*(?=:)' + }, { + token : "string", // single line + regex : '"', + next : "string" + }, { + token : "constant.numeric", // hex + regex : "0[xX][0-9a-fA-F]+\\b" + }, { + token : "constant.numeric", // float + regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b" + }, { + token : "constant.language.boolean", + regex : "(?:true|false)\\b" + }, { + token : "invalid.illegal", // single quoted strings are not allowed + regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']" + }, { + token : "invalid.illegal", // comments are not allowed + regex : "\\/\\/.*$" + }, { + token : "paren.lparen", + regex : "[[({]" + }, { + token : "paren.rparen", + regex : "[\\])}]" + }, { + token : "text", + regex : "\\s+" + } + ], + "string" : [ + { + token : "constant.language.escape", + regex : /\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|["\\\/bfnrt])/ + }, { + token : "string", + regex : '[^"\\\\]+' + }, { + token : "string", + regex : '"', + next : "start" + }, { + token : "string", + regex : "", + next : "start" + } + ] + }; + + }; + + oop.inherits(JsonHighlightRules, TextHighlightRules); + + exports.JsonHighlightRules = JsonHighlightRules; + }); + + ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"], function(acequire, exports, module) { + "use strict"; + + var Range = acequire("../range").Range; + + var MatchingBraceOutdent = function() {}; + + (function() { + + this.checkOutdent = function(line, input) { + if (! /^\s+$/.test(line)) + return false; + + return /^\s*\}/.test(input); + }; + + this.autoOutdent = function(doc, row) { + var line = doc.getLine(row); + var match = line.match(/^(\s*\})/); + + if (!match) return 0; + + var column = match[1].length; + var openBracePos = doc.findMatchingBracket({row: row, column: column}); + + if (!openBracePos || openBracePos.row == row) return 0; + + var indent = this.$getIndent(doc.getLine(openBracePos.row)); + doc.replace(new Range(row, 0, row, column-1), indent); + }; + + this.$getIndent = function(line) { + return line.match(/^\s*/)[0]; + }; + + }).call(MatchingBraceOutdent.prototype); + + exports.MatchingBraceOutdent = MatchingBraceOutdent; + }); + + ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("../../lib/oop"); + var Behaviour = acequire("../behaviour").Behaviour; + var TokenIterator = acequire("../../token_iterator").TokenIterator; + var lang = acequire("../../lib/lang"); + + var SAFE_INSERT_IN_TOKENS = + ["text", "paren.rparen", "punctuation.operator"]; + var SAFE_INSERT_BEFORE_TOKENS = + ["text", "paren.rparen", "punctuation.operator", "comment"]; + + var context; + var contextCache = {}; + var initContext = function(editor) { + var id = -1; + if (editor.multiSelect) { + id = editor.selection.index; + if (contextCache.rangeCount != editor.multiSelect.rangeCount) + contextCache = {rangeCount: editor.multiSelect.rangeCount}; + } + if (contextCache[id]) + return context = contextCache[id]; + context = contextCache[id] = { + autoInsertedBrackets: 0, + autoInsertedRow: -1, + autoInsertedLineEnd: "", + maybeInsertedBrackets: 0, + maybeInsertedRow: -1, + maybeInsertedLineStart: "", + maybeInsertedLineEnd: "" + }; + }; + + var getWrapped = function(selection, selected, opening, closing) { + var rowDiff = selection.end.row - selection.start.row; + return { + text: opening + selected + closing, + selection: [ + 0, + selection.start.column + 1, + rowDiff, + selection.end.column + (rowDiff ? 0 : 1) + ] + }; + }; + + var CstyleBehaviour = function() { + this.add("braces", "insertion", function(state, action, editor, session, text) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + if (text == '{') { + initContext(editor); + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && selected !== "{" && editor.getWrapBehavioursEnabled()) { + return getWrapped(selection, selected, '{', '}'); + } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { + if (/[\]\}\)]/.test(line[cursor.column]) || editor.inMultiSelectMode) { + CstyleBehaviour.recordAutoInsert(editor, session, "}"); + return { + text: '{}', + selection: [1, 1] + }; + } else { + CstyleBehaviour.recordMaybeInsert(editor, session, "{"); + return { + text: '{', + selection: [1, 1] + }; + } + } + } else if (text == '}') { + initContext(editor); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == '}') { + var matching = session.$findOpeningBracket('}', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) { + CstyleBehaviour.popAutoInsertedClosing(); + return { + text: '', + selection: [1, 1] + }; + } + } + } else if (text == "\n" || text == "\r\n") { + initContext(editor); + var closing = ""; + if (CstyleBehaviour.isMaybeInsertedClosing(cursor, line)) { + closing = lang.stringRepeat("}", context.maybeInsertedBrackets); + CstyleBehaviour.clearMaybeInsertedClosing(); + } + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar === '}') { + var openBracePos = session.findMatchingBracket({row: cursor.row, column: cursor.column+1}, '}'); + if (!openBracePos) + return null; + var next_indent = this.$getIndent(session.getLine(openBracePos.row)); + } else if (closing) { + var next_indent = this.$getIndent(line); + } else { + CstyleBehaviour.clearMaybeInsertedClosing(); + return; + } + var indent = next_indent + session.getTabString(); + + return { + text: '\n' + indent + '\n' + next_indent + closing, + selection: [1, indent.length, 1, indent.length] + }; + } else { + CstyleBehaviour.clearMaybeInsertedClosing(); + } + }); + + this.add("braces", "deletion", function(state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '{') { + initContext(editor); + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.end.column, range.end.column + 1); + if (rightChar == '}') { + range.end.column++; + return range; + } else { + context.maybeInsertedBrackets--; + } + } + }); + + this.add("parens", "insertion", function(state, action, editor, session, text) { + if (text == '(') { + initContext(editor); + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && editor.getWrapBehavioursEnabled()) { + return getWrapped(selection, selected, '(', ')'); + } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { + CstyleBehaviour.recordAutoInsert(editor, session, ")"); + return { + text: '()', + selection: [1, 1] + }; + } + } else if (text == ')') { + initContext(editor); + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == ')') { + var matching = session.$findOpeningBracket(')', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) { + CstyleBehaviour.popAutoInsertedClosing(); + return { + text: '', + selection: [1, 1] + }; + } + } + } + }); + + this.add("parens", "deletion", function(state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '(') { + initContext(editor); + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == ')') { + range.end.column++; + return range; + } + } + }); + + this.add("brackets", "insertion", function(state, action, editor, session, text) { + if (text == '[') { + initContext(editor); + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && editor.getWrapBehavioursEnabled()) { + return getWrapped(selection, selected, '[', ']'); + } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { + CstyleBehaviour.recordAutoInsert(editor, session, "]"); + return { + text: '[]', + selection: [1, 1] + }; + } + } else if (text == ']') { + initContext(editor); + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == ']') { + var matching = session.$findOpeningBracket(']', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) { + CstyleBehaviour.popAutoInsertedClosing(); + return { + text: '', + selection: [1, 1] + }; + } + } + } + }); + + this.add("brackets", "deletion", function(state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '[') { + initContext(editor); + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == ']') { + range.end.column++; + return range; + } + } + }); + + this.add("string_dquotes", "insertion", function(state, action, editor, session, text) { + if (text == '"' || text == "'") { + initContext(editor); + var quote = text; + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && selected !== "'" && selected != '"' && editor.getWrapBehavioursEnabled()) { + return getWrapped(selection, selected, quote, quote); + } else if (!selected) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var leftChar = line.substring(cursor.column-1, cursor.column); + var rightChar = line.substring(cursor.column, cursor.column + 1); + + var token = session.getTokenAt(cursor.row, cursor.column); + var rightToken = session.getTokenAt(cursor.row, cursor.column + 1); + if (leftChar == "\\" && token && /escape/.test(token.type)) + return null; + + var stringBefore = token && /string|escape/.test(token.type); + var stringAfter = !rightToken || /string|escape/.test(rightToken.type); + + var pair; + if (rightChar == quote) { + pair = stringBefore !== stringAfter; + } else { + if (stringBefore && !stringAfter) + return null; // wrap string with different quote + if (stringBefore && stringAfter) + return null; // do not pair quotes inside strings + var wordRe = session.$mode.tokenRe; + wordRe.lastIndex = 0; + var isWordBefore = wordRe.test(leftChar); + wordRe.lastIndex = 0; + var isWordAfter = wordRe.test(leftChar); + if (isWordBefore || isWordAfter) + return null; // before or after alphanumeric + if (rightChar && !/[\s;,.})\]\\]/.test(rightChar)) + return null; // there is rightChar and it isn't closing + pair = true; + } + return { + text: pair ? quote + quote : "", + selection: [1,1] + }; + } + } + }); + + this.add("string_dquotes", "deletion", function(state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && (selected == '"' || selected == "'")) { + initContext(editor); + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == selected) { + range.end.column++; + return range; + } + } + }); + + }; + + + CstyleBehaviour.isSaneInsertion = function(editor, session) { + var cursor = editor.getCursorPosition(); + var iterator = new TokenIterator(session, cursor.row, cursor.column); + if (!this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) { + var iterator2 = new TokenIterator(session, cursor.row, cursor.column + 1); + if (!this.$matchTokenType(iterator2.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) + return false; + } + iterator.stepForward(); + return iterator.getCurrentTokenRow() !== cursor.row || + this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_BEFORE_TOKENS); + }; + + CstyleBehaviour.$matchTokenType = function(token, types) { + return types.indexOf(token.type || token) > -1; + }; + + CstyleBehaviour.recordAutoInsert = function(editor, session, bracket) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + if (!this.isAutoInsertedClosing(cursor, line, context.autoInsertedLineEnd[0])) + context.autoInsertedBrackets = 0; + context.autoInsertedRow = cursor.row; + context.autoInsertedLineEnd = bracket + line.substr(cursor.column); + context.autoInsertedBrackets++; + }; + + CstyleBehaviour.recordMaybeInsert = function(editor, session, bracket) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + if (!this.isMaybeInsertedClosing(cursor, line)) + context.maybeInsertedBrackets = 0; + context.maybeInsertedRow = cursor.row; + context.maybeInsertedLineStart = line.substr(0, cursor.column) + bracket; + context.maybeInsertedLineEnd = line.substr(cursor.column); + context.maybeInsertedBrackets++; + }; + + CstyleBehaviour.isAutoInsertedClosing = function(cursor, line, bracket) { + return context.autoInsertedBrackets > 0 && + cursor.row === context.autoInsertedRow && + bracket === context.autoInsertedLineEnd[0] && + line.substr(cursor.column) === context.autoInsertedLineEnd; + }; + + CstyleBehaviour.isMaybeInsertedClosing = function(cursor, line) { + return context.maybeInsertedBrackets > 0 && + cursor.row === context.maybeInsertedRow && + line.substr(cursor.column) === context.maybeInsertedLineEnd && + line.substr(0, cursor.column) == context.maybeInsertedLineStart; + }; + + CstyleBehaviour.popAutoInsertedClosing = function() { + context.autoInsertedLineEnd = context.autoInsertedLineEnd.substr(1); + context.autoInsertedBrackets--; + }; + + CstyleBehaviour.clearMaybeInsertedClosing = function() { + if (context) { + context.maybeInsertedBrackets = 0; + context.maybeInsertedRow = -1; + } + }; + + + + oop.inherits(CstyleBehaviour, Behaviour); + + exports.CstyleBehaviour = CstyleBehaviour; + }); + + ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("../../lib/oop"); + var Range = acequire("../../range").Range; + var BaseFoldMode = acequire("./fold_mode").FoldMode; + + var FoldMode = exports.FoldMode = function(commentRegex) { + if (commentRegex) { + this.foldingStartMarker = new RegExp( + this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start) + ); + this.foldingStopMarker = new RegExp( + this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end) + ); + } + }; + oop.inherits(FoldMode, BaseFoldMode); + + (function() { + + this.foldingStartMarker = /(\{|\[)[^\}\]]*$|^\s*(\/\*)/; + this.foldingStopMarker = /^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/; + this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/; + this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/; + this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/; + this._getFoldWidgetBase = this.getFoldWidget; + this.getFoldWidget = function(session, foldStyle, row) { + var line = session.getLine(row); + + if (this.singleLineBlockCommentRe.test(line)) { + if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line)) + return ""; + } + + var fw = this._getFoldWidgetBase(session, foldStyle, row); + + if (!fw && this.startRegionRe.test(line)) + return "start"; // lineCommentRegionStart + + return fw; + }; + + this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) { + var line = session.getLine(row); + + if (this.startRegionRe.test(line)) + return this.getCommentRegionBlock(session, line, row); + + var match = line.match(this.foldingStartMarker); + if (match) { + var i = match.index; + + if (match[1]) + return this.openingBracketBlock(session, match[1], row, i); + + var range = session.getCommentFoldRange(row, i + match[0].length, 1); + + if (range && !range.isMultiLine()) { + if (forceMultiline) { + range = this.getSectionRange(session, row); + } else if (foldStyle != "all") + range = null; + } + + return range; + } + + if (foldStyle === "markbegin") + return; + + var match = line.match(this.foldingStopMarker); + if (match) { + var i = match.index + match[0].length; + + if (match[1]) + return this.closingBracketBlock(session, match[1], row, i); + + return session.getCommentFoldRange(row, i, -1); + } + }; + + this.getSectionRange = function(session, row) { + var line = session.getLine(row); + var startIndent = line.search(/\S/); + var startRow = row; + var startColumn = line.length; + row = row + 1; + var endRow = row; + var maxRow = session.getLength(); + while (++row < maxRow) { + line = session.getLine(row); + var indent = line.search(/\S/); + if (indent === -1) + continue; + if (startIndent > indent) + break; + var subRange = this.getFoldWidgetRange(session, "all", row); + + if (subRange) { + if (subRange.start.row <= startRow) { + break; + } else if (subRange.isMultiLine()) { + row = subRange.end.row; + } else if (startIndent == indent) { + break; + } + } + endRow = row; + } + + return new Range(startRow, startColumn, endRow, session.getLine(endRow).length); + }; + this.getCommentRegionBlock = function(session, line, row) { + var startColumn = line.search(/\s*$/); + var maxRow = session.getLength(); + var startRow = row; + + var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/; + var depth = 1; + while (++row < maxRow) { + line = session.getLine(row); + var m = re.exec(line); + if (!m) continue; + if (m[1]) depth--; + else depth++; + + if (!depth) break; + } + + var endRow = row; + if (endRow > startRow) { + return new Range(startRow, startColumn, endRow, line.length); + } + }; + + }).call(FoldMode.prototype); + + }); + + ace.define("ace/mode/json",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/json_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle","ace/worker/worker_client"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("../lib/oop"); + var TextMode = acequire("./text").Mode; + var HighlightRules = acequire("./json_highlight_rules").JsonHighlightRules; + var MatchingBraceOutdent = acequire("./matching_brace_outdent").MatchingBraceOutdent; + var CstyleBehaviour = acequire("./behaviour/cstyle").CstyleBehaviour; + var CStyleFoldMode = acequire("./folding/cstyle").FoldMode; + var WorkerClient = acequire("../worker/worker_client").WorkerClient; + + var Mode = function() { + this.HighlightRules = HighlightRules; + this.$outdent = new MatchingBraceOutdent(); + this.$behaviour = new CstyleBehaviour(); + this.foldingRules = new CStyleFoldMode(); + }; + oop.inherits(Mode, TextMode); + + (function() { + + this.getNextLineIndent = function(state, line, tab) { + var indent = this.$getIndent(line); + + if (state == "start") { + var match = line.match(/^.*[\{\(\[]\s*$/); + if (match) { + indent += tab; + } + } + + return indent; + }; + + this.checkOutdent = function(state, line, input) { + return this.$outdent.checkOutdent(line, input); + }; + + this.autoOutdent = function(state, doc, row) { + this.$outdent.autoOutdent(doc, row); + }; + + this.createWorker = function(session) { + var worker = new WorkerClient(["ace"], __webpack_require__(15), "JsonWorker"); + worker.attachToDocument(session.getDocument()); + + worker.on("annotate", function(e) { + session.setAnnotations(e.data); + }); + + worker.on("terminate", function() { + session.clearAnnotations(); + }); + + return worker; + }; + + + this.$id = "ace/mode/json"; + }).call(Mode.prototype); + + exports.Mode = Mode; + }); + + +/***/ }, +/* 15 */ +/***/ function(module, exports) { + + module.exports.id = 'ace/mode/json_worker'; + module.exports.src = "\"no use strict\";(function(window){function resolveModuleId(id,paths){for(var testPath=id,tail=\"\";testPath;){var alias=paths[testPath];if(\"string\"==typeof alias)return alias+tail;if(alias)return alias.location.replace(/\\/*$/,\"/\")+(tail||alias.main||alias.name);if(alias===!1)return\"\";var i=testPath.lastIndexOf(\"/\");if(-1===i)break;tail=testPath.substr(i)+tail,testPath=testPath.slice(0,i)}return id}if(!(void 0!==window.window&&window.document||window.acequire&&window.define)){window.console||(window.console=function(){var msgs=Array.prototype.slice.call(arguments,0);postMessage({type:\"log\",data:msgs})},window.console.error=window.console.warn=window.console.log=window.console.trace=window.console),window.window=window,window.ace=window,window.onerror=function(message,file,line,col,err){postMessage({type:\"error\",data:{message:message,data:err.data,file:file,line:line,col:col,stack:err.stack}})},window.normalizeModule=function(parentId,moduleName){if(-1!==moduleName.indexOf(\"!\")){var chunks=moduleName.split(\"!\");return window.normalizeModule(parentId,chunks[0])+\"!\"+window.normalizeModule(parentId,chunks[1])}if(\".\"==moduleName.charAt(0)){var base=parentId.split(\"/\").slice(0,-1).join(\"/\");for(moduleName=(base?base+\"/\":\"\")+moduleName;-1!==moduleName.indexOf(\".\")&&previous!=moduleName;){var previous=moduleName;moduleName=moduleName.replace(/^\\.\\//,\"\").replace(/\\/\\.\\//,\"/\").replace(/[^\\/]+\\/\\.\\.\\//,\"\")}}return moduleName},window.acequire=function acequire(parentId,id){if(id||(id=parentId,parentId=null),!id.charAt)throw Error(\"worker.js acequire() accepts only (parentId, id) as arguments\");id=window.normalizeModule(parentId,id);var module=window.acequire.modules[id];if(module)return module.initialized||(module.initialized=!0,module.exports=module.factory().exports),module.exports;if(!window.acequire.tlns)return console.log(\"unable to load \"+id);var path=resolveModuleId(id,window.acequire.tlns);return\".js\"!=path.slice(-3)&&(path+=\".js\"),window.acequire.id=id,window.acequire.modules[id]={},importScripts(path),window.acequire(parentId,id)},window.acequire.modules={},window.acequire.tlns={},window.define=function(id,deps,factory){if(2==arguments.length?(factory=deps,\"string\"!=typeof id&&(deps=id,id=window.acequire.id)):1==arguments.length&&(factory=id,deps=[],id=window.acequire.id),\"function\"!=typeof factory)return window.acequire.modules[id]={exports:factory,initialized:!0},void 0;deps.length||(deps=[\"require\",\"exports\",\"module\"]);var req=function(childId){return window.acequire(id,childId)};window.acequire.modules[id]={exports:{},factory:function(){var module=this,returnExports=factory.apply(this,deps.map(function(dep){switch(dep){case\"require\":return req;case\"exports\":return module.exports;case\"module\":return module;default:return req(dep)}}));return returnExports&&(module.exports=returnExports),module}}},window.define.amd={},acequire.tlns={},window.initBaseUrls=function(topLevelNamespaces){for(var i in topLevelNamespaces)acequire.tlns[i]=topLevelNamespaces[i]},window.initSender=function(){var EventEmitter=window.acequire(\"ace/lib/event_emitter\").EventEmitter,oop=window.acequire(\"ace/lib/oop\"),Sender=function(){};return function(){oop.implement(this,EventEmitter),this.callback=function(data,callbackId){postMessage({type:\"call\",id:callbackId,data:data})},this.emit=function(name,data){postMessage({type:\"event\",name:name,data:data})}}.call(Sender.prototype),new Sender};var main=window.main=null,sender=window.sender=null;window.onmessage=function(e){var msg=e.data;if(msg.event&&sender)sender._signal(msg.event,msg.data);else if(msg.command)if(main[msg.command])main[msg.command].apply(main,msg.args);else{if(!window[msg.command])throw Error(\"Unknown command:\"+msg.command);window[msg.command].apply(window,msg.args)}else if(msg.init){window.initBaseUrls(msg.tlns),acequire(\"ace/lib/es5-shim\"),sender=window.sender=window.initSender();var clazz=acequire(msg.module)[msg.classname];main=window.main=new clazz(sender)}}}})(this),ace.define(\"ace/lib/oop\",[\"require\",\"exports\",\"module\"],function(acequire,exports){\"use strict\";exports.inherits=function(ctor,superCtor){ctor.super_=superCtor,ctor.prototype=Object.create(superCtor.prototype,{constructor:{value:ctor,enumerable:!1,writable:!0,configurable:!0}})},exports.mixin=function(obj,mixin){for(var key in mixin)obj[key]=mixin[key];return obj},exports.implement=function(proto,mixin){exports.mixin(proto,mixin)}}),ace.define(\"ace/range\",[\"require\",\"exports\",\"module\"],function(acequire,exports){\"use strict\";var comparePoints=function(p1,p2){return p1.row-p2.row||p1.column-p2.column},Range=function(startRow,startColumn,endRow,endColumn){this.start={row:startRow,column:startColumn},this.end={row:endRow,column:endColumn}};(function(){this.isEqual=function(range){return this.start.row===range.start.row&&this.end.row===range.end.row&&this.start.column===range.start.column&&this.end.column===range.end.column},this.toString=function(){return\"Range: [\"+this.start.row+\"/\"+this.start.column+\"] -> [\"+this.end.row+\"/\"+this.end.column+\"]\"},this.contains=function(row,column){return 0==this.compare(row,column)},this.compareRange=function(range){var cmp,end=range.end,start=range.start;return cmp=this.compare(end.row,end.column),1==cmp?(cmp=this.compare(start.row,start.column),1==cmp?2:0==cmp?1:0):-1==cmp?-2:(cmp=this.compare(start.row,start.column),-1==cmp?-1:1==cmp?42:0)},this.comparePoint=function(p){return this.compare(p.row,p.column)},this.containsRange=function(range){return 0==this.comparePoint(range.start)&&0==this.comparePoint(range.end)},this.intersects=function(range){var cmp=this.compareRange(range);return-1==cmp||0==cmp||1==cmp},this.isEnd=function(row,column){return this.end.row==row&&this.end.column==column},this.isStart=function(row,column){return this.start.row==row&&this.start.column==column},this.setStart=function(row,column){\"object\"==typeof row?(this.start.column=row.column,this.start.row=row.row):(this.start.row=row,this.start.column=column)},this.setEnd=function(row,column){\"object\"==typeof row?(this.end.column=row.column,this.end.row=row.row):(this.end.row=row,this.end.column=column)},this.inside=function(row,column){return 0==this.compare(row,column)?this.isEnd(row,column)||this.isStart(row,column)?!1:!0:!1},this.insideStart=function(row,column){return 0==this.compare(row,column)?this.isEnd(row,column)?!1:!0:!1},this.insideEnd=function(row,column){return 0==this.compare(row,column)?this.isStart(row,column)?!1:!0:!1},this.compare=function(row,column){return this.isMultiLine()||row!==this.start.row?this.start.row>row?-1:row>this.end.row?1:this.start.row===row?column>=this.start.column?0:-1:this.end.row===row?this.end.column>=column?0:1:0:this.start.column>column?-1:column>this.end.column?1:0},this.compareStart=function(row,column){return this.start.row==row&&this.start.column==column?-1:this.compare(row,column)},this.compareEnd=function(row,column){return this.end.row==row&&this.end.column==column?1:this.compare(row,column)},this.compareInside=function(row,column){return this.end.row==row&&this.end.column==column?1:this.start.row==row&&this.start.column==column?-1:this.compare(row,column)},this.clipRows=function(firstRow,lastRow){if(this.end.row>lastRow)var end={row:lastRow+1,column:0};else if(firstRow>this.end.row)var end={row:firstRow,column:0};if(this.start.row>lastRow)var start={row:lastRow+1,column:0};else if(firstRow>this.start.row)var start={row:firstRow,column:0};return Range.fromPoints(start||this.start,end||this.end)},this.extend=function(row,column){var cmp=this.compare(row,column);if(0==cmp)return this;if(-1==cmp)var start={row:row,column:column};else var end={row:row,column:column};return Range.fromPoints(start||this.start,end||this.end)},this.isEmpty=function(){return this.start.row===this.end.row&&this.start.column===this.end.column},this.isMultiLine=function(){return this.start.row!==this.end.row},this.clone=function(){return Range.fromPoints(this.start,this.end)},this.collapseRows=function(){return 0==this.end.column?new Range(this.start.row,0,Math.max(this.start.row,this.end.row-1),0):new Range(this.start.row,0,this.end.row,0)},this.toScreenRange=function(session){var screenPosStart=session.documentToScreenPosition(this.start),screenPosEnd=session.documentToScreenPosition(this.end);return new Range(screenPosStart.row,screenPosStart.column,screenPosEnd.row,screenPosEnd.column)},this.moveBy=function(row,column){this.start.row+=row,this.start.column+=column,this.end.row+=row,this.end.column+=column}}).call(Range.prototype),Range.fromPoints=function(start,end){return new Range(start.row,start.column,end.row,end.column)},Range.comparePoints=comparePoints,Range.comparePoints=function(p1,p2){return p1.row-p2.row||p1.column-p2.column},exports.Range=Range}),ace.define(\"ace/apply_delta\",[\"require\",\"exports\",\"module\"],function(acequire,exports){\"use strict\";exports.applyDelta=function(docLines,delta){var row=delta.start.row,startColumn=delta.start.column,line=docLines[row]||\"\";switch(delta.action){case\"insert\":var lines=delta.lines;if(1===lines.length)docLines[row]=line.substring(0,startColumn)+delta.lines[0]+line.substring(startColumn);else{var args=[row,1].concat(delta.lines);docLines.splice.apply(docLines,args),docLines[row]=line.substring(0,startColumn)+docLines[row],docLines[row+delta.lines.length-1]+=line.substring(startColumn)}break;case\"remove\":var endColumn=delta.end.column,endRow=delta.end.row;row===endRow?docLines[row]=line.substring(0,startColumn)+line.substring(endColumn):docLines.splice(row,endRow-row+1,line.substring(0,startColumn)+docLines[endRow].substring(endColumn))}}}),ace.define(\"ace/lib/event_emitter\",[\"require\",\"exports\",\"module\"],function(acequire,exports){\"use strict\";var EventEmitter={},stopPropagation=function(){this.propagationStopped=!0},preventDefault=function(){this.defaultPrevented=!0};EventEmitter._emit=EventEmitter._dispatchEvent=function(eventName,e){this._eventRegistry||(this._eventRegistry={}),this._defaultHandlers||(this._defaultHandlers={});var listeners=this._eventRegistry[eventName]||[],defaultHandler=this._defaultHandlers[eventName];if(listeners.length||defaultHandler){\"object\"==typeof e&&e||(e={}),e.type||(e.type=eventName),e.stopPropagation||(e.stopPropagation=stopPropagation),e.preventDefault||(e.preventDefault=preventDefault),listeners=listeners.slice();for(var i=0;listeners.length>i&&(listeners[i](e,this),!e.propagationStopped);i++);return defaultHandler&&!e.defaultPrevented?defaultHandler(e,this):void 0}},EventEmitter._signal=function(eventName,e){var listeners=(this._eventRegistry||{})[eventName];if(listeners){listeners=listeners.slice();for(var i=0;listeners.length>i;i++)listeners[i](e,this)}},EventEmitter.once=function(eventName,callback){var _self=this;callback&&this.addEventListener(eventName,function newCallback(){_self.removeEventListener(eventName,newCallback),callback.apply(null,arguments)})},EventEmitter.setDefaultHandler=function(eventName,callback){var handlers=this._defaultHandlers;if(handlers||(handlers=this._defaultHandlers={_disabled_:{}}),handlers[eventName]){var old=handlers[eventName],disabled=handlers._disabled_[eventName];disabled||(handlers._disabled_[eventName]=disabled=[]),disabled.push(old);var i=disabled.indexOf(callback);-1!=i&&disabled.splice(i,1)}handlers[eventName]=callback},EventEmitter.removeDefaultHandler=function(eventName,callback){var handlers=this._defaultHandlers;if(handlers){var disabled=handlers._disabled_[eventName];if(handlers[eventName]==callback)handlers[eventName],disabled&&this.setDefaultHandler(eventName,disabled.pop());else if(disabled){var i=disabled.indexOf(callback);-1!=i&&disabled.splice(i,1)}}},EventEmitter.on=EventEmitter.addEventListener=function(eventName,callback,capturing){this._eventRegistry=this._eventRegistry||{};var listeners=this._eventRegistry[eventName];return listeners||(listeners=this._eventRegistry[eventName]=[]),-1==listeners.indexOf(callback)&&listeners[capturing?\"unshift\":\"push\"](callback),callback},EventEmitter.off=EventEmitter.removeListener=EventEmitter.removeEventListener=function(eventName,callback){this._eventRegistry=this._eventRegistry||{};var listeners=this._eventRegistry[eventName];if(listeners){var index=listeners.indexOf(callback);-1!==index&&listeners.splice(index,1)}},EventEmitter.removeAllListeners=function(eventName){this._eventRegistry&&(this._eventRegistry[eventName]=[])},exports.EventEmitter=EventEmitter}),ace.define(\"ace/anchor\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/event_emitter\"],function(acequire,exports){\"use strict\";var oop=acequire(\"./lib/oop\"),EventEmitter=acequire(\"./lib/event_emitter\").EventEmitter,Anchor=exports.Anchor=function(doc,row,column){this.$onChange=this.onChange.bind(this),this.attach(doc),column===void 0?this.setPosition(row.row,row.column):this.setPosition(row,column)};(function(){function $pointsInOrder(point1,point2,equalPointsInOrder){var bColIsAfter=equalPointsInOrder?point1.column<=point2.column:point1.columnthis.row)){var point=$getTransformedPoint(delta,{row:this.row,column:this.column},this.$insertRight);this.setPosition(point.row,point.column,!0)}},this.setPosition=function(row,column,noClip){var pos;if(pos=noClip?{row:row,column:column}:this.$clipPositionToDocument(row,column),this.row!=pos.row||this.column!=pos.column){var old={row:this.row,column:this.column};this.row=pos.row,this.column=pos.column,this._signal(\"change\",{old:old,value:pos})}},this.detach=function(){this.document.removeEventListener(\"change\",this.$onChange)},this.attach=function(doc){this.document=doc||this.document,this.document.on(\"change\",this.$onChange)},this.$clipPositionToDocument=function(row,column){var pos={};return row>=this.document.getLength()?(pos.row=Math.max(0,this.document.getLength()-1),pos.column=this.document.getLine(pos.row).length):0>row?(pos.row=0,pos.column=0):(pos.row=row,pos.column=Math.min(this.document.getLine(pos.row).length,Math.max(0,column))),0>column&&(pos.column=0),pos}}).call(Anchor.prototype)}),ace.define(\"ace/document\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/apply_delta\",\"ace/lib/event_emitter\",\"ace/range\",\"ace/anchor\"],function(acequire,exports){\"use strict\";var oop=acequire(\"./lib/oop\"),applyDelta=acequire(\"./apply_delta\").applyDelta,EventEmitter=acequire(\"./lib/event_emitter\").EventEmitter,Range=acequire(\"./range\").Range,Anchor=acequire(\"./anchor\").Anchor,Document=function(textOrLines){this.$lines=[\"\"],0===textOrLines.length?this.$lines=[\"\"]:Array.isArray(textOrLines)?this.insertMergedLines({row:0,column:0},textOrLines):this.insert({row:0,column:0},textOrLines)};(function(){oop.implement(this,EventEmitter),this.setValue=function(text){var len=this.getLength()-1;this.remove(new Range(0,0,len,this.getLine(len).length)),this.insert({row:0,column:0},text)},this.getValue=function(){return this.getAllLines().join(this.getNewLineCharacter())},this.createAnchor=function(row,column){return new Anchor(this,row,column)},this.$split=0===\"aaa\".split(/a/).length?function(text){return text.replace(/\\r\\n|\\r/g,\"\\n\").split(\"\\n\")}:function(text){return text.split(/\\r\\n|\\r|\\n/)},this.$detectNewLine=function(text){var match=text.match(/^.*?(\\r\\n|\\r|\\n)/m);this.$autoNewLine=match?match[1]:\"\\n\",this._signal(\"changeNewLineMode\")},this.getNewLineCharacter=function(){switch(this.$newLineMode){case\"windows\":return\"\\r\\n\";case\"unix\":return\"\\n\";default:return this.$autoNewLine||\"\\n\"}},this.$autoNewLine=\"\",this.$newLineMode=\"auto\",this.setNewLineMode=function(newLineMode){this.$newLineMode!==newLineMode&&(this.$newLineMode=newLineMode,this._signal(\"changeNewLineMode\"))},this.getNewLineMode=function(){return this.$newLineMode},this.isNewLine=function(text){return\"\\r\\n\"==text||\"\\r\"==text||\"\\n\"==text},this.getLine=function(row){return this.$lines[row]||\"\"},this.getLines=function(firstRow,lastRow){return this.$lines.slice(firstRow,lastRow+1)},this.getAllLines=function(){return this.getLines(0,this.getLength())},this.getLength=function(){return this.$lines.length},this.getTextRange=function(range){return this.getLinesForRange(range).join(this.getNewLineCharacter())},this.getLinesForRange=function(range){var lines;if(range.start.row===range.end.row)lines=[this.getLine(range.start.row).substring(range.start.column,range.end.column)];else{lines=this.getLines(range.start.row,range.end.row),lines[0]=(lines[0]||\"\").substring(range.start.column);var l=lines.length-1;range.end.row-range.start.row==l&&(lines[l]=lines[l].substring(0,range.end.column))}return lines},this.insertLines=function(row,lines){return console.warn(\"Use of document.insertLines is deprecated. Use the insertFullLines method instead.\"),this.insertFullLines(row,lines)},this.removeLines=function(firstRow,lastRow){return console.warn(\"Use of document.removeLines is deprecated. Use the removeFullLines method instead.\"),this.removeFullLines(firstRow,lastRow)},this.insertNewLine=function(position){return console.warn(\"Use of document.insertNewLine is deprecated. Use insertMergedLines(position, ['', '']) instead.\"),this.insertMergedLines(position,[\"\",\"\"])},this.insert=function(position,text){return 1>=this.getLength()&&this.$detectNewLine(text),this.insertMergedLines(position,this.$split(text))},this.insertInLine=function(position,text){var start=this.clippedPos(position.row,position.column),end=this.pos(position.row,position.column+text.length);return this.applyDelta({start:start,end:end,action:\"insert\",lines:[text]},!0),this.clonePos(end)},this.clippedPos=function(row,column){var length=this.getLength();void 0===row?row=length:0>row?row=0:row>=length&&(row=length-1,column=void 0);var line=this.getLine(row);return void 0==column&&(column=line.length),column=Math.min(Math.max(column,0),line.length),{row:row,column:column}},this.clonePos=function(pos){return{row:pos.row,column:pos.column}},this.pos=function(row,column){return{row:row,column:column}},this.$clipPosition=function(position){var length=this.getLength();return position.row>=length?(position.row=Math.max(0,length-1),position.column=this.getLine(length-1).length):(position.row=Math.max(0,position.row),position.column=Math.min(Math.max(position.column,0),this.getLine(position.row).length)),position},this.insertFullLines=function(row,lines){row=Math.min(Math.max(row,0),this.getLength());var column=0;this.getLength()>row?(lines=lines.concat([\"\"]),column=0):(lines=[\"\"].concat(lines),row--,column=this.$lines[row].length),this.insertMergedLines({row:row,column:column},lines)},this.insertMergedLines=function(position,lines){var start=this.clippedPos(position.row,position.column),end={row:start.row+lines.length-1,column:(1==lines.length?start.column:0)+lines[lines.length-1].length};return this.applyDelta({start:start,end:end,action:\"insert\",lines:lines}),this.clonePos(end)},this.remove=function(range){var start=this.clippedPos(range.start.row,range.start.column),end=this.clippedPos(range.end.row,range.end.column);return this.applyDelta({start:start,end:end,action:\"remove\",lines:this.getLinesForRange({start:start,end:end})}),this.clonePos(start)},this.removeInLine=function(row,startColumn,endColumn){var start=this.clippedPos(row,startColumn),end=this.clippedPos(row,endColumn);return this.applyDelta({start:start,end:end,action:\"remove\",lines:this.getLinesForRange({start:start,end:end})},!0),this.clonePos(start)},this.removeFullLines=function(firstRow,lastRow){firstRow=Math.min(Math.max(0,firstRow),this.getLength()-1),lastRow=Math.min(Math.max(0,lastRow),this.getLength()-1);var deleteFirstNewLine=lastRow==this.getLength()-1&&firstRow>0,deleteLastNewLine=this.getLength()-1>lastRow,startRow=deleteFirstNewLine?firstRow-1:firstRow,startCol=deleteFirstNewLine?this.getLine(startRow).length:0,endRow=deleteLastNewLine?lastRow+1:lastRow,endCol=deleteLastNewLine?0:this.getLine(endRow).length,range=new Range(startRow,startCol,endRow,endCol),deletedLines=this.$lines.slice(firstRow,lastRow+1);return this.applyDelta({start:range.start,end:range.end,action:\"remove\",lines:this.getLinesForRange(range)}),deletedLines},this.removeNewLine=function(row){this.getLength()-1>row&&row>=0&&this.applyDelta({start:this.pos(row,this.getLine(row).length),end:this.pos(row+1,0),action:\"remove\",lines:[\"\",\"\"]})},this.replace=function(range,text){if(range instanceof Range||(range=Range.fromPoints(range.start,range.end)),0===text.length&&range.isEmpty())return range.start;if(text==this.getTextRange(range))return range.end;this.remove(range);var end;return end=text?this.insert(range.start,text):range.start},this.applyDeltas=function(deltas){for(var i=0;deltas.length>i;i++)this.applyDelta(deltas[i])},this.revertDeltas=function(deltas){for(var i=deltas.length-1;i>=0;i--)this.revertDelta(deltas[i])},this.applyDelta=function(delta,doNotValidate){var isInsert=\"insert\"==delta.action;(isInsert?1>=delta.lines.length&&!delta.lines[0]:!Range.comparePoints(delta.start,delta.end))||(isInsert&&delta.lines.length>2e4&&this.$splitAndapplyLargeDelta(delta,2e4),applyDelta(this.$lines,delta,doNotValidate),this._signal(\"change\",delta))},this.$splitAndapplyLargeDelta=function(delta,MAX){for(var lines=delta.lines,l=lines.length,row=delta.start.row,column=delta.start.column,from=0,to=0;;){from=to,to+=MAX-1;var chunk=lines.slice(from,to);if(to>l){delta.lines=chunk,delta.start.row=row+from,delta.start.column=column;break}chunk.push(\"\"),this.applyDelta({start:this.pos(row+from,column),end:this.pos(row+to,column=0),action:delta.action,lines:chunk},!0)}},this.revertDelta=function(delta){this.applyDelta({start:this.clonePos(delta.start),end:this.clonePos(delta.end),action:\"insert\"==delta.action?\"remove\":\"insert\",lines:delta.lines.slice()})},this.indexToPosition=function(index,startRow){for(var lines=this.$lines||this.getAllLines(),newlineLength=this.getNewLineCharacter().length,i=startRow||0,l=lines.length;l>i;i++)if(index-=lines[i].length+newlineLength,0>index)return{row:i,column:index+lines[i].length+newlineLength};return{row:l-1,column:lines[l-1].length}},this.positionToIndex=function(pos,startRow){for(var lines=this.$lines||this.getAllLines(),newlineLength=this.getNewLineCharacter().length,index=0,row=Math.min(pos.row,lines.length),i=startRow||0;row>i;++i)index+=lines[i].length+newlineLength;return index+pos.column}}).call(Document.prototype),exports.Document=Document}),ace.define(\"ace/lib/lang\",[\"require\",\"exports\",\"module\"],function(acequire,exports){\"use strict\";exports.last=function(a){return a[a.length-1]},exports.stringReverse=function(string){return string.split(\"\").reverse().join(\"\")},exports.stringRepeat=function(string,count){for(var result=\"\";count>0;)1&count&&(result+=string),(count>>=1)&&(string+=string);return result};var trimBeginRegexp=/^\\s\\s*/,trimEndRegexp=/\\s\\s*$/;exports.stringTrimLeft=function(string){return string.replace(trimBeginRegexp,\"\")},exports.stringTrimRight=function(string){return string.replace(trimEndRegexp,\"\")},exports.copyObject=function(obj){var copy={};for(var key in obj)copy[key]=obj[key];return copy},exports.copyArray=function(array){for(var copy=[],i=0,l=array.length;l>i;i++)copy[i]=array[i]&&\"object\"==typeof array[i]?this.copyObject(array[i]):array[i];return copy},exports.deepCopy=function deepCopy(obj){if(\"object\"!=typeof obj||!obj)return obj;var copy;if(Array.isArray(obj)){copy=[];for(var key=0;obj.length>key;key++)copy[key]=deepCopy(obj[key]);return copy}var cons=obj.constructor;if(cons===RegExp)return obj;copy=cons();for(var key in obj)copy[key]=deepCopy(obj[key]);return copy},exports.arrayToMap=function(arr){for(var map={},i=0;arr.length>i;i++)map[arr[i]]=1;return map},exports.createMap=function(props){var map=Object.create(null);for(var i in props)map[i]=props[i];return map},exports.arrayRemove=function(array,value){for(var i=0;array.length>=i;i++)value===array[i]&&array.splice(i,1)},exports.escapeRegExp=function(str){return str.replace(/([.*+?^${}()|[\\]\\/\\\\])/g,\"\\\\$1\")},exports.escapeHTML=function(str){return str.replace(/&/g,\"&\").replace(/\"/g,\""\").replace(/'/g,\"'\").replace(/i;i+=2){if(Array.isArray(data[i+1]))var d={action:\"insert\",start:data[i],lines:data[i+1]};else var d={action:\"remove\",start:data[i],end:data[i+1]};doc.applyDelta(d,!0)}return _self.$timeout?deferredUpdate.schedule(_self.$timeout):(_self.onUpdate(),void 0)})};(function(){this.$timeout=500,this.setTimeout=function(timeout){this.$timeout=timeout},this.setValue=function(value){this.doc.setValue(value),this.deferredUpdate.schedule(this.$timeout)},this.getValue=function(callbackId){this.sender.callback(this.doc.getValue(),callbackId)},this.onUpdate=function(){},this.isPending=function(){return this.deferredUpdate.isPending()}}).call(Mirror.prototype)}),ace.define(\"ace/mode/json/json_parse\",[\"require\",\"exports\",\"module\"],function(){\"use strict\";var at,ch,text,value,escapee={'\"':'\"',\"\\\\\":\"\\\\\",\"/\":\"/\",b:\"\\b\",f:\"\\f\",n:\"\\n\",r:\"\\r\",t:\"\t\"},error=function(m){throw{name:\"SyntaxError\",message:m,at:at,text:text}},next=function(c){return c&&c!==ch&&error(\"Expected '\"+c+\"' instead of '\"+ch+\"'\"),ch=text.charAt(at),at+=1,ch},number=function(){var number,string=\"\";for(\"-\"===ch&&(string=\"-\",next(\"-\"));ch>=\"0\"&&\"9\">=ch;)string+=ch,next();if(\".\"===ch)for(string+=\".\";next()&&ch>=\"0\"&&\"9\">=ch;)string+=ch;if(\"e\"===ch||\"E\"===ch)for(string+=ch,next(),(\"-\"===ch||\"+\"===ch)&&(string+=ch,next());ch>=\"0\"&&\"9\">=ch;)string+=ch,next();return number=+string,isNaN(number)?(error(\"Bad number\"),void 0):number},string=function(){var hex,i,uffff,string=\"\";if('\"'===ch)for(;next();){if('\"'===ch)return next(),string;if(\"\\\\\"===ch)if(next(),\"u\"===ch){for(uffff=0,i=0;4>i&&(hex=parseInt(next(),16),isFinite(hex));i+=1)uffff=16*uffff+hex;string+=String.fromCharCode(uffff)}else{if(\"string\"!=typeof escapee[ch])break;string+=escapee[ch]}else string+=ch}error(\"Bad string\")},white=function(){for(;ch&&\" \">=ch;)next()},word=function(){switch(ch){case\"t\":return next(\"t\"),next(\"r\"),next(\"u\"),next(\"e\"),!0;case\"f\":return next(\"f\"),next(\"a\"),next(\"l\"),next(\"s\"),next(\"e\"),!1;case\"n\":return next(\"n\"),next(\"u\"),next(\"l\"),next(\"l\"),null}error(\"Unexpected '\"+ch+\"'\")},array=function(){var array=[];if(\"[\"===ch){if(next(\"[\"),white(),\"]\"===ch)return next(\"]\"),array;for(;ch;){if(array.push(value()),white(),\"]\"===ch)return next(\"]\"),array;next(\",\"),white()}}error(\"Bad array\")},object=function(){var key,object={};if(\"{\"===ch){if(next(\"{\"),white(),\"}\"===ch)return next(\"}\"),object;for(;ch;){if(key=string(),white(),next(\":\"),Object.hasOwnProperty.call(object,key)&&error('Duplicate key \"'+key+'\"'),object[key]=value(),white(),\"}\"===ch)return next(\"}\"),object;next(\",\"),white()}}error(\"Bad object\")};return value=function(){switch(white(),ch){case\"{\":return object();case\"[\":return array();case'\"':return string();case\"-\":return number();default:return ch>=\"0\"&&\"9\">=ch?number():word()}},function(source,reviver){var result;return text=source,at=0,ch=\" \",result=value(),white(),ch&&error(\"Syntax error\"),\"function\"==typeof reviver?function walk(holder,key){var k,v,value=holder[key];if(value&&\"object\"==typeof value)for(k in value)Object.hasOwnProperty.call(value,k)&&(v=walk(value,k),void 0!==v?value[k]=v:delete value[k]);return reviver.call(holder,key,value)}({\"\":result},\"\"):result}}),ace.define(\"ace/mode/json_worker\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/worker/mirror\",\"ace/mode/json/json_parse\"],function(acequire,exports){\"use strict\";var oop=acequire(\"../lib/oop\"),Mirror=acequire(\"../worker/mirror\").Mirror,parse=acequire(\"./json/json_parse\"),JsonWorker=exports.JsonWorker=function(sender){Mirror.call(this,sender),this.setTimeout(200)};oop.inherits(JsonWorker,Mirror),function(){this.onUpdate=function(){var value=this.doc.getValue(),errors=[];try{value&&parse(value)}catch(e){var pos=this.doc.indexToPosition(e.at-1);errors.push({row:pos.row,column:pos.column,text:e.message,type:\"error\"})}this.sender.emit(\"annotate\",errors)}}.call(JsonWorker.prototype)}),ace.define(\"ace/lib/es5-shim\",[\"require\",\"exports\",\"module\"],function(){function Empty(){}function doesDefinePropertyWork(object){try{return Object.defineProperty(object,\"sentinel\",{}),\"sentinel\"in object}catch(exception){}}function toInteger(n){return n=+n,n!==n?n=0:0!==n&&n!==1/0&&n!==-(1/0)&&(n=(n>0||-1)*Math.floor(Math.abs(n))),n}Function.prototype.bind||(Function.prototype.bind=function(that){var target=this;if(\"function\"!=typeof target)throw new TypeError(\"Function.prototype.bind called on incompatible \"+target);var args=slice.call(arguments,1),bound=function(){if(this instanceof bound){var result=target.apply(this,args.concat(slice.call(arguments)));return Object(result)===result?result:this}return target.apply(that,args.concat(slice.call(arguments)))};return target.prototype&&(Empty.prototype=target.prototype,bound.prototype=new Empty,Empty.prototype=null),bound});var defineGetter,defineSetter,lookupGetter,lookupSetter,supportsAccessors,call=Function.prototype.call,prototypeOfArray=Array.prototype,prototypeOfObject=Object.prototype,slice=prototypeOfArray.slice,_toString=call.bind(prototypeOfObject.toString),owns=call.bind(prototypeOfObject.hasOwnProperty);if((supportsAccessors=owns(prototypeOfObject,\"__defineGetter__\"))&&(defineGetter=call.bind(prototypeOfObject.__defineGetter__),defineSetter=call.bind(prototypeOfObject.__defineSetter__),lookupGetter=call.bind(prototypeOfObject.__lookupGetter__),lookupSetter=call.bind(prototypeOfObject.__lookupSetter__)),2!=[1,2].splice(0).length)if(function(){function makeArray(l){var a=Array(l+2);return a[0]=a[1]=0,a}var lengthBefore,array=[];return array.splice.apply(array,makeArray(20)),array.splice.apply(array,makeArray(26)),lengthBefore=array.length,array.splice(5,0,\"XXX\"),lengthBefore+1==array.length,lengthBefore+1==array.length?!0:void 0\n}()){var array_splice=Array.prototype.splice;Array.prototype.splice=function(start,deleteCount){return arguments.length?array_splice.apply(this,[void 0===start?0:start,void 0===deleteCount?this.length-start:deleteCount].concat(slice.call(arguments,2))):[]}}else Array.prototype.splice=function(pos,removeCount){var length=this.length;pos>0?pos>length&&(pos=length):void 0==pos?pos=0:0>pos&&(pos=Math.max(length+pos,0)),length>pos+removeCount||(removeCount=length-pos);var removed=this.slice(pos,pos+removeCount),insert=slice.call(arguments,2),add=insert.length;if(pos===length)add&&this.push.apply(this,insert);else{var remove=Math.min(removeCount,length-pos),tailOldPos=pos+remove,tailNewPos=tailOldPos+add-remove,tailCount=length-tailOldPos,lengthAfterRemove=length-remove;if(tailOldPos>tailNewPos)for(var i=0;tailCount>i;++i)this[tailNewPos+i]=this[tailOldPos+i];else if(tailNewPos>tailOldPos)for(i=tailCount;i--;)this[tailNewPos+i]=this[tailOldPos+i];if(add&&pos===lengthAfterRemove)this.length=lengthAfterRemove,this.push.apply(this,insert);else for(this.length=lengthAfterRemove+add,i=0;add>i;++i)this[pos+i]=insert[i]}return removed};Array.isArray||(Array.isArray=function(obj){return\"[object Array]\"==_toString(obj)});var boxedString=Object(\"a\"),splitString=\"a\"!=boxedString[0]||!(0 in boxedString);if(Array.prototype.forEach||(Array.prototype.forEach=function(fun){var object=toObject(this),self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):object,thisp=arguments[1],i=-1,length=self.length>>>0;if(\"[object Function]\"!=_toString(fun))throw new TypeError;for(;length>++i;)i in self&&fun.call(thisp,self[i],i,object)}),Array.prototype.map||(Array.prototype.map=function(fun){var object=toObject(this),self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):object,length=self.length>>>0,result=Array(length),thisp=arguments[1];if(\"[object Function]\"!=_toString(fun))throw new TypeError(fun+\" is not a function\");for(var i=0;length>i;i++)i in self&&(result[i]=fun.call(thisp,self[i],i,object));return result}),Array.prototype.filter||(Array.prototype.filter=function(fun){var value,object=toObject(this),self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):object,length=self.length>>>0,result=[],thisp=arguments[1];if(\"[object Function]\"!=_toString(fun))throw new TypeError(fun+\" is not a function\");for(var i=0;length>i;i++)i in self&&(value=self[i],fun.call(thisp,value,i,object)&&result.push(value));return result}),Array.prototype.every||(Array.prototype.every=function(fun){var object=toObject(this),self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):object,length=self.length>>>0,thisp=arguments[1];if(\"[object Function]\"!=_toString(fun))throw new TypeError(fun+\" is not a function\");for(var i=0;length>i;i++)if(i in self&&!fun.call(thisp,self[i],i,object))return!1;return!0}),Array.prototype.some||(Array.prototype.some=function(fun){var object=toObject(this),self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):object,length=self.length>>>0,thisp=arguments[1];if(\"[object Function]\"!=_toString(fun))throw new TypeError(fun+\" is not a function\");for(var i=0;length>i;i++)if(i in self&&fun.call(thisp,self[i],i,object))return!0;return!1}),Array.prototype.reduce||(Array.prototype.reduce=function(fun){var object=toObject(this),self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):object,length=self.length>>>0;if(\"[object Function]\"!=_toString(fun))throw new TypeError(fun+\" is not a function\");if(!length&&1==arguments.length)throw new TypeError(\"reduce of empty array with no initial value\");var result,i=0;if(arguments.length>=2)result=arguments[1];else for(;;){if(i in self){result=self[i++];break}if(++i>=length)throw new TypeError(\"reduce of empty array with no initial value\")}for(;length>i;i++)i in self&&(result=fun.call(void 0,result,self[i],i,object));return result}),Array.prototype.reduceRight||(Array.prototype.reduceRight=function(fun){var object=toObject(this),self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):object,length=self.length>>>0;if(\"[object Function]\"!=_toString(fun))throw new TypeError(fun+\" is not a function\");if(!length&&1==arguments.length)throw new TypeError(\"reduceRight of empty array with no initial value\");var result,i=length-1;if(arguments.length>=2)result=arguments[1];else for(;;){if(i in self){result=self[i--];break}if(0>--i)throw new TypeError(\"reduceRight of empty array with no initial value\")}do i in this&&(result=fun.call(void 0,result,self[i],i,object));while(i--);return result}),Array.prototype.indexOf&&-1==[0,1].indexOf(1,2)||(Array.prototype.indexOf=function(sought){var self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):toObject(this),length=self.length>>>0;if(!length)return-1;var i=0;for(arguments.length>1&&(i=toInteger(arguments[1])),i=i>=0?i:Math.max(0,length+i);length>i;i++)if(i in self&&self[i]===sought)return i;return-1}),Array.prototype.lastIndexOf&&-1==[0,1].lastIndexOf(0,-3)||(Array.prototype.lastIndexOf=function(sought){var self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):toObject(this),length=self.length>>>0;if(!length)return-1;var i=length-1;for(arguments.length>1&&(i=Math.min(i,toInteger(arguments[1]))),i=i>=0?i:length-Math.abs(i);i>=0;i--)if(i in self&&sought===self[i])return i;return-1}),Object.getPrototypeOf||(Object.getPrototypeOf=function(object){return object.__proto__||(object.constructor?object.constructor.prototype:prototypeOfObject)}),!Object.getOwnPropertyDescriptor){var ERR_NON_OBJECT=\"Object.getOwnPropertyDescriptor called on a non-object: \";Object.getOwnPropertyDescriptor=function(object,property){if(\"object\"!=typeof object&&\"function\"!=typeof object||null===object)throw new TypeError(ERR_NON_OBJECT+object);if(owns(object,property)){var descriptor,getter,setter;if(descriptor={enumerable:!0,configurable:!0},supportsAccessors){var prototype=object.__proto__;object.__proto__=prototypeOfObject;var getter=lookupGetter(object,property),setter=lookupSetter(object,property);if(object.__proto__=prototype,getter||setter)return getter&&(descriptor.get=getter),setter&&(descriptor.set=setter),descriptor}return descriptor.value=object[property],descriptor}}}if(Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(object){return Object.keys(object)}),!Object.create){var createEmpty;createEmpty=null===Object.prototype.__proto__?function(){return{__proto__:null}}:function(){var empty={};for(var i in empty)empty[i]=null;return empty.constructor=empty.hasOwnProperty=empty.propertyIsEnumerable=empty.isPrototypeOf=empty.toLocaleString=empty.toString=empty.valueOf=empty.__proto__=null,empty},Object.create=function(prototype,properties){var object;if(null===prototype)object=createEmpty();else{if(\"object\"!=typeof prototype)throw new TypeError(\"typeof prototype[\"+typeof prototype+\"] != 'object'\");var Type=function(){};Type.prototype=prototype,object=new Type,object.__proto__=prototype}return void 0!==properties&&Object.defineProperties(object,properties),object}}if(Object.defineProperty){var definePropertyWorksOnObject=doesDefinePropertyWork({}),definePropertyWorksOnDom=\"undefined\"==typeof document||doesDefinePropertyWork(document.createElement(\"div\"));if(!definePropertyWorksOnObject||!definePropertyWorksOnDom)var definePropertyFallback=Object.defineProperty}if(!Object.defineProperty||definePropertyFallback){var ERR_NON_OBJECT_DESCRIPTOR=\"Property description must be an object: \",ERR_NON_OBJECT_TARGET=\"Object.defineProperty called on non-object: \",ERR_ACCESSORS_NOT_SUPPORTED=\"getters & setters can not be defined on this javascript engine\";Object.defineProperty=function(object,property,descriptor){if(\"object\"!=typeof object&&\"function\"!=typeof object||null===object)throw new TypeError(ERR_NON_OBJECT_TARGET+object);if(\"object\"!=typeof descriptor&&\"function\"!=typeof descriptor||null===descriptor)throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR+descriptor);if(definePropertyFallback)try{return definePropertyFallback.call(Object,object,property,descriptor)}catch(exception){}if(owns(descriptor,\"value\"))if(supportsAccessors&&(lookupGetter(object,property)||lookupSetter(object,property))){var prototype=object.__proto__;object.__proto__=prototypeOfObject,delete object[property],object[property]=descriptor.value,object.__proto__=prototype}else object[property]=descriptor.value;else{if(!supportsAccessors)throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);owns(descriptor,\"get\")&&defineGetter(object,property,descriptor.get),owns(descriptor,\"set\")&&defineSetter(object,property,descriptor.set)}return object}}Object.defineProperties||(Object.defineProperties=function(object,properties){for(var property in properties)owns(properties,property)&&Object.defineProperty(object,property,properties[property]);return object}),Object.seal||(Object.seal=function(object){return object}),Object.freeze||(Object.freeze=function(object){return object});try{Object.freeze(function(){})}catch(exception){Object.freeze=function(freezeObject){return function(object){return\"function\"==typeof object?object:freezeObject(object)}}(Object.freeze)}if(Object.preventExtensions||(Object.preventExtensions=function(object){return object}),Object.isSealed||(Object.isSealed=function(){return!1}),Object.isFrozen||(Object.isFrozen=function(){return!1}),Object.isExtensible||(Object.isExtensible=function(object){if(Object(object)===object)throw new TypeError;for(var name=\"\";owns(object,name);)name+=\"?\";object[name]=!0;var returnValue=owns(object,name);return delete object[name],returnValue}),!Object.keys){var hasDontEnumBug=!0,dontEnums=[\"toString\",\"toLocaleString\",\"valueOf\",\"hasOwnProperty\",\"isPrototypeOf\",\"propertyIsEnumerable\",\"constructor\"],dontEnumsLength=dontEnums.length;for(var key in{toString:null})hasDontEnumBug=!1;Object.keys=function(object){if(\"object\"!=typeof object&&\"function\"!=typeof object||null===object)throw new TypeError(\"Object.keys called on a non-object\");var keys=[];for(var name in object)owns(object,name)&&keys.push(name);if(hasDontEnumBug)for(var i=0,ii=dontEnumsLength;ii>i;i++){var dontEnum=dontEnums[i];owns(object,dontEnum)&&keys.push(dontEnum)}return keys}}Date.now||(Date.now=function(){return(new Date).getTime()});var ws=\"\t\\n\u000b\\f\\r   ᠎              \\u2028\\u2029\";if(!String.prototype.trim||ws.trim()){ws=\"[\"+ws+\"]\";var trimBeginRegexp=RegExp(\"^\"+ws+ws+\"*\"),trimEndRegexp=RegExp(ws+ws+\"*$\");String.prototype.trim=function(){return(this+\"\").replace(trimBeginRegexp,\"\").replace(trimEndRegexp,\"\")}}var toObject=function(o){if(null==o)throw new TypeError(\"can't convert \"+o+\" to object\");return Object(o)}});"; + +/***/ }, +/* 16 */ +/***/ function(module, exports) { + + ace.define("ace/ext/searchbox",["require","exports","module","ace/lib/dom","ace/lib/lang","ace/lib/event","ace/keyboard/hash_handler","ace/lib/keys"], function(acequire, exports, module) { + "use strict"; + + var dom = acequire("../lib/dom"); + var lang = acequire("../lib/lang"); + var event = acequire("../lib/event"); + var searchboxCss = "\ + .ace_search {\ + background-color: #ddd;\ + border: 1px solid #cbcbcb;\ + border-top: 0 none;\ + max-width: 325px;\ + overflow: hidden;\ + margin: 0;\ + padding: 4px;\ + padding-right: 6px;\ + padding-bottom: 0;\ + position: absolute;\ + top: 0px;\ + z-index: 99;\ + white-space: normal;\ + }\ + .ace_search.left {\ + border-left: 0 none;\ + border-radius: 0px 0px 5px 0px;\ + left: 0;\ + }\ + .ace_search.right {\ + border-radius: 0px 0px 0px 5px;\ + border-right: 0 none;\ + right: 0;\ + }\ + .ace_search_form, .ace_replace_form {\ + border-radius: 3px;\ + border: 1px solid #cbcbcb;\ + float: left;\ + margin-bottom: 4px;\ + overflow: hidden;\ + }\ + .ace_search_form.ace_nomatch {\ + outline: 1px solid red;\ + }\ + .ace_search_field {\ + background-color: white;\ + border-right: 1px solid #cbcbcb;\ + border: 0 none;\ + -webkit-box-sizing: border-box;\ + -moz-box-sizing: border-box;\ + box-sizing: border-box;\ + float: left;\ + height: 22px;\ + outline: 0;\ + padding: 0 7px;\ + width: 214px;\ + margin: 0;\ + }\ + .ace_searchbtn,\ + .ace_replacebtn {\ + background: #fff;\ + border: 0 none;\ + border-left: 1px solid #dcdcdc;\ + cursor: pointer;\ + float: left;\ + height: 22px;\ + margin: 0;\ + position: relative;\ + }\ + .ace_searchbtn:last-child,\ + .ace_replacebtn:last-child {\ + border-top-right-radius: 3px;\ + border-bottom-right-radius: 3px;\ + }\ + .ace_searchbtn:disabled {\ + background: none;\ + cursor: default;\ + }\ + .ace_searchbtn {\ + background-position: 50% 50%;\ + background-repeat: no-repeat;\ + width: 27px;\ + }\ + .ace_searchbtn.prev {\ + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADFJREFUeNpiSU1NZUAC/6E0I0yACYskCpsJiySKIiY0SUZk40FyTEgCjGgKwTRAgAEAQJUIPCE+qfkAAAAASUVORK5CYII=); \ + }\ + .ace_searchbtn.next {\ + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADRJREFUeNpiTE1NZQCC/0DMyIAKwGJMUAYDEo3M/s+EpvM/mkKwCQxYjIeLMaELoLMBAgwAU7UJObTKsvAAAAAASUVORK5CYII=); \ + }\ + .ace_searchbtn_close {\ + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAcCAYAAABRVo5BAAAAZ0lEQVR42u2SUQrAMAhDvazn8OjZBilCkYVVxiis8H4CT0VrAJb4WHT3C5xU2a2IQZXJjiQIRMdkEoJ5Q2yMqpfDIo+XY4k6h+YXOyKqTIj5REaxloNAd0xiKmAtsTHqW8sR2W5f7gCu5nWFUpVjZwAAAABJRU5ErkJggg==) no-repeat 50% 0;\ + border-radius: 50%;\ + border: 0 none;\ + color: #656565;\ + cursor: pointer;\ + float: right;\ + font: 16px/16px Arial;\ + height: 14px;\ + margin: 5px 1px 9px 5px;\ + padding: 0;\ + text-align: center;\ + width: 14px;\ + }\ + .ace_searchbtn_close:hover {\ + background-color: #656565;\ + background-position: 50% 100%;\ + color: white;\ + }\ + .ace_replacebtn.prev {\ + width: 54px\ + }\ + .ace_replacebtn.next {\ + width: 27px\ + }\ + .ace_button {\ + margin-left: 2px;\ + cursor: pointer;\ + -webkit-user-select: none;\ + -moz-user-select: none;\ + -o-user-select: none;\ + -ms-user-select: none;\ + user-select: none;\ + overflow: hidden;\ + opacity: 0.7;\ + border: 1px solid rgba(100,100,100,0.23);\ + padding: 1px;\ + -moz-box-sizing: border-box;\ + box-sizing: border-box;\ + color: black;\ + }\ + .ace_button:hover {\ + background-color: #eee;\ + opacity:1;\ + }\ + .ace_button:active {\ + background-color: #ddd;\ + }\ + .ace_button.checked {\ + border-color: #3399ff;\ + opacity:1;\ + }\ + .ace_search_options{\ + margin-bottom: 3px;\ + text-align: right;\ + -webkit-user-select: none;\ + -moz-user-select: none;\ + -o-user-select: none;\ + -ms-user-select: none;\ + user-select: none;\ + }"; + var HashHandler = acequire("../keyboard/hash_handler").HashHandler; + var keyUtil = acequire("../lib/keys"); + + dom.importCssString(searchboxCss, "ace_searchbox"); + + var html = ''.replace(/>\s+/g, ">"); + + var SearchBox = function(editor, range, showReplaceForm) { + var div = dom.createElement("div"); + div.innerHTML = html; + this.element = div.firstChild; + + this.$init(); + this.setEditor(editor); + }; + + (function() { + this.setEditor = function(editor) { + editor.searchBox = this; + editor.container.appendChild(this.element); + this.editor = editor; + }; + + this.$initElements = function(sb) { + this.searchBox = sb.querySelector(".ace_search_form"); + this.replaceBox = sb.querySelector(".ace_replace_form"); + this.searchOptions = sb.querySelector(".ace_search_options"); + this.regExpOption = sb.querySelector("[action=toggleRegexpMode]"); + this.caseSensitiveOption = sb.querySelector("[action=toggleCaseSensitive]"); + this.wholeWordOption = sb.querySelector("[action=toggleWholeWords]"); + this.searchInput = this.searchBox.querySelector(".ace_search_field"); + this.replaceInput = this.replaceBox.querySelector(".ace_search_field"); + }; + + this.$init = function() { + var sb = this.element; + + this.$initElements(sb); + + var _this = this; + event.addListener(sb, "mousedown", function(e) { + setTimeout(function(){ + _this.activeInput.focus(); + }, 0); + event.stopPropagation(e); + }); + event.addListener(sb, "click", function(e) { + var t = e.target || e.srcElement; + var action = t.getAttribute("action"); + if (action && _this[action]) + _this[action](); + else if (_this.$searchBarKb.commands[action]) + _this.$searchBarKb.commands[action].exec(_this); + event.stopPropagation(e); + }); + + event.addCommandKeyListener(sb, function(e, hashId, keyCode) { + var keyString = keyUtil.keyCodeToString(keyCode); + var command = _this.$searchBarKb.findKeyCommand(hashId, keyString); + if (command && command.exec) { + command.exec(_this); + event.stopEvent(e); + } + }); + + this.$onChange = lang.delayedCall(function() { + _this.find(false, false); + }); + + event.addListener(this.searchInput, "input", function() { + _this.$onChange.schedule(20); + }); + event.addListener(this.searchInput, "focus", function() { + _this.activeInput = _this.searchInput; + _this.searchInput.value && _this.highlight(); + }); + event.addListener(this.replaceInput, "focus", function() { + _this.activeInput = _this.replaceInput; + _this.searchInput.value && _this.highlight(); + }); + }; + this.$closeSearchBarKb = new HashHandler([{ + bindKey: "Esc", + name: "closeSearchBar", + exec: function(editor) { + editor.searchBox.hide(); + } + }]); + this.$searchBarKb = new HashHandler(); + this.$searchBarKb.bindKeys({ + "Ctrl-f|Command-f": function(sb) { + var isReplace = sb.isReplace = !sb.isReplace; + sb.replaceBox.style.display = isReplace ? "" : "none"; + sb.searchInput.focus(); + }, + "Ctrl-H|Command-Option-F": function(sb) { + sb.replaceBox.style.display = ""; + sb.replaceInput.focus(); + }, + "Ctrl-G|Command-G": function(sb) { + sb.findNext(); + }, + "Ctrl-Shift-G|Command-Shift-G": function(sb) { + sb.findPrev(); + }, + "esc": function(sb) { + setTimeout(function() { sb.hide();}); + }, + "Return": function(sb) { + if (sb.activeInput == sb.replaceInput) + sb.replace(); + sb.findNext(); + }, + "Shift-Return": function(sb) { + if (sb.activeInput == sb.replaceInput) + sb.replace(); + sb.findPrev(); + }, + "Alt-Return": function(sb) { + if (sb.activeInput == sb.replaceInput) + sb.replaceAll(); + sb.findAll(); + }, + "Tab": function(sb) { + (sb.activeInput == sb.replaceInput ? sb.searchInput : sb.replaceInput).focus(); + } + }); + + this.$searchBarKb.addCommands([{ + name: "toggleRegexpMode", + bindKey: {win: "Alt-R|Alt-/", mac: "Ctrl-Alt-R|Ctrl-Alt-/"}, + exec: function(sb) { + sb.regExpOption.checked = !sb.regExpOption.checked; + sb.$syncOptions(); + } + }, { + name: "toggleCaseSensitive", + bindKey: {win: "Alt-C|Alt-I", mac: "Ctrl-Alt-R|Ctrl-Alt-I"}, + exec: function(sb) { + sb.caseSensitiveOption.checked = !sb.caseSensitiveOption.checked; + sb.$syncOptions(); + } + }, { + name: "toggleWholeWords", + bindKey: {win: "Alt-B|Alt-W", mac: "Ctrl-Alt-B|Ctrl-Alt-W"}, + exec: function(sb) { + sb.wholeWordOption.checked = !sb.wholeWordOption.checked; + sb.$syncOptions(); + } + }]); + + this.$syncOptions = function() { + dom.setCssClass(this.regExpOption, "checked", this.regExpOption.checked); + dom.setCssClass(this.wholeWordOption, "checked", this.wholeWordOption.checked); + dom.setCssClass(this.caseSensitiveOption, "checked", this.caseSensitiveOption.checked); + this.find(false, false); + }; + + this.highlight = function(re) { + this.editor.session.highlight(re || this.editor.$search.$options.re); + this.editor.renderer.updateBackMarkers() + }; + this.find = function(skipCurrent, backwards, preventScroll) { + var range = this.editor.find(this.searchInput.value, { + skipCurrent: skipCurrent, + backwards: backwards, + wrap: true, + regExp: this.regExpOption.checked, + caseSensitive: this.caseSensitiveOption.checked, + wholeWord: this.wholeWordOption.checked, + preventScroll: preventScroll + }); + var noMatch = !range && this.searchInput.value; + dom.setCssClass(this.searchBox, "ace_nomatch", noMatch); + this.editor._emit("findSearchBox", { match: !noMatch }); + this.highlight(); + }; + this.findNext = function() { + this.find(true, false); + }; + this.findPrev = function() { + this.find(true, true); + }; + this.findAll = function(){ + var range = this.editor.findAll(this.searchInput.value, { + regExp: this.regExpOption.checked, + caseSensitive: this.caseSensitiveOption.checked, + wholeWord: this.wholeWordOption.checked + }); + var noMatch = !range && this.searchInput.value; + dom.setCssClass(this.searchBox, "ace_nomatch", noMatch); + this.editor._emit("findSearchBox", { match: !noMatch }); + this.highlight(); + this.hide(); + }; + this.replace = function() { + if (!this.editor.getReadOnly()) + this.editor.replace(this.replaceInput.value); + }; + this.replaceAndFindNext = function() { + if (!this.editor.getReadOnly()) { + this.editor.replace(this.replaceInput.value); + this.findNext() + } + }; + this.replaceAll = function() { + if (!this.editor.getReadOnly()) + this.editor.replaceAll(this.replaceInput.value); + }; + + this.hide = function() { + this.element.style.display = "none"; + this.editor.keyBinding.removeKeyboardHandler(this.$closeSearchBarKb); + this.editor.focus(); + }; + this.show = function(value, isReplace) { + this.element.style.display = ""; + this.replaceBox.style.display = isReplace ? "" : "none"; + + this.isReplace = isReplace; + + if (value) + this.searchInput.value = value; + + this.find(false, false, true); + + this.searchInput.focus(); + this.searchInput.select(); + + this.editor.keyBinding.addKeyboardHandler(this.$closeSearchBarKb); + }; + + this.isFocused = function() { + var el = document.activeElement; + return el == this.searchInput || el == this.replaceInput; + } + }).call(SearchBox.prototype); + + exports.SearchBox = SearchBox; + + exports.Search = function(editor, isReplace) { + var sb = editor.searchBox || new SearchBox(editor); + sb.show(editor.session.getTextRange(), isReplace); + }; + + }); + (function() { + ace.acequire(["ace/ext/searchbox"], function() {}); + })(); + + +/***/ }, +/* 17 */ +/***/ function(module, exports) { + + /* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + + ace.define('ace/theme/jsoneditor', ['require', 'exports', 'module', 'ace/lib/dom'], function(acequire, exports, module) { + + exports.isDark = false; + exports.cssClass = "ace-jsoneditor"; + exports.cssText = ".ace-jsoneditor .ace_gutter {\ + background: #ebebeb;\ + color: #333\ + }\ + \ + .ace-jsoneditor.ace_editor {\ + font-family: droid sans mono, consolas, monospace, courier new, courier, sans-serif;\ + line-height: 1.3;\ + }\ + .ace-jsoneditor .ace_print-margin {\ + width: 1px;\ + background: #e8e8e8\ + }\ + .ace-jsoneditor .ace_scroller {\ + background-color: #FFFFFF\ + }\ + .ace-jsoneditor .ace_text-layer {\ + color: gray\ + }\ + .ace-jsoneditor .ace_variable {\ + color: #1a1a1a\ + }\ + .ace-jsoneditor .ace_cursor {\ + border-left: 2px solid #000000\ + }\ + .ace-jsoneditor .ace_overwrite-cursors .ace_cursor {\ + border-left: 0px;\ + border-bottom: 1px solid #000000\ + }\ + .ace-jsoneditor .ace_marker-layer .ace_selection {\ + background: lightgray\ + }\ + .ace-jsoneditor.ace_multiselect .ace_selection.ace_start {\ + box-shadow: 0 0 3px 0px #FFFFFF;\ + border-radius: 2px\ + }\ + .ace-jsoneditor .ace_marker-layer .ace_step {\ + background: rgb(255, 255, 0)\ + }\ + .ace-jsoneditor .ace_marker-layer .ace_bracket {\ + margin: -1px 0 0 -1px;\ + border: 1px solid #BFBFBF\ + }\ + .ace-jsoneditor .ace_marker-layer .ace_active-line {\ + background: #FFFBD1\ + }\ + .ace-jsoneditor .ace_gutter-active-line {\ + background-color : #dcdcdc\ + }\ + .ace-jsoneditor .ace_marker-layer .ace_selected-word {\ + border: 1px solid lightgray\ + }\ + .ace-jsoneditor .ace_invisible {\ + color: #BFBFBF\ + }\ + .ace-jsoneditor .ace_keyword,\ + .ace-jsoneditor .ace_meta,\ + .ace-jsoneditor .ace_support.ace_constant.ace_property-value {\ + color: #AF956F\ + }\ + .ace-jsoneditor .ace_keyword.ace_operator {\ + color: #484848\ + }\ + .ace-jsoneditor .ace_keyword.ace_other.ace_unit {\ + color: #96DC5F\ + }\ + .ace-jsoneditor .ace_constant.ace_language {\ + color: darkorange\ + }\ + .ace-jsoneditor .ace_constant.ace_numeric {\ + color: red\ + }\ + .ace-jsoneditor .ace_constant.ace_character.ace_entity {\ + color: #BF78CC\ + }\ + .ace-jsoneditor .ace_invalid {\ + color: #FFFFFF;\ + background-color: #FF002A;\ + }\ + .ace-jsoneditor .ace_fold {\ + background-color: #AF956F;\ + border-color: #000000\ + }\ + .ace-jsoneditor .ace_storage,\ + .ace-jsoneditor .ace_support.ace_class,\ + .ace-jsoneditor .ace_support.ace_function,\ + .ace-jsoneditor .ace_support.ace_other,\ + .ace-jsoneditor .ace_support.ace_type {\ + color: #C52727\ + }\ + .ace-jsoneditor .ace_string {\ + color: green\ + }\ + .ace-jsoneditor .ace_comment {\ + color: #BCC8BA\ + }\ + .ace-jsoneditor .ace_entity.ace_name.ace_tag,\ + .ace-jsoneditor .ace_entity.ace_other.ace_attribute-name {\ + color: #606060\ + }\ + .ace-jsoneditor .ace_markup.ace_underline {\ + text-decoration: underline\ + }\ + .ace-jsoneditor .ace_indent-guide {\ + background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y\ + }"; + + var dom = acequire("../lib/dom"); + dom.importCssString(exports.cssText, exports.cssClass); + }); + + +/***/ } +/******/ ]) +}); +; \ No newline at end of file diff --git a/ui/app/bower_components/jsoneditor/dist/jsoneditor-minimalist.map b/ui/app/bower_components/jsoneditor/dist/jsoneditor-minimalist.map new file mode 100644 index 0000000..968c4ff --- /dev/null +++ b/ui/app/bower_components/jsoneditor/dist/jsoneditor-minimalist.map @@ -0,0 +1 @@ +{"version":3,"sources":["./dist/jsoneditor-minimalist.js"],"names":["root","factory","exports","module","define","amd","this","modules","__webpack_require__","moduleId","installedModules","id","loaded","call","m","c","p","JSONEditor","container","options","json","Error","ieVersion","util","getInternetExplorerVersion","error","console","warn","onError","change","onChange","editable","onEditable","VALID_OPTIONS","Object","keys","forEach","option","indexOf","arguments","length","_create","Ajv","e","code","err","treemode","textmode","modes","prototype","DEBOUNCE_INTERVAL","mode","setMode","destroy","set","get","setText","jsonText","parse","getText","JSON","stringify","setName","name","getName","data","extend","oldMode","config","asText","clear","mixin","create","load","onModeChange","_onError","getMode","setSchema","schema","ajv","allErrors","verbose","validateSchema","compile","validate","refresh","registerMode","i","prop","isArray","reserved","Highlighter","History","SearchBox","ContextMenu","Node","ModeSwitcher","dom","highlighter","selection","undefined","multiselection","nodes","errorNodes","node","focusTarget","_setOptions","history","_createFrame","_createTable","frame","parentNode","removeChild","_debouncedValidate","searchBox","modeSwitcher","search","hasOwnProperty","debounce","bind","Function","content","table","params","field","value","_setRoot","recurse","expand","appendChild","getNodeFromTarget","blur","getValue","updateField","focus","input","querySelector","menu","collapse","tbody","getDom","text","results","expandAll","collapseAll","_onAction","action","add","_onChange","setError","duplicateErrors","schemaErrors","valid","errors","map","improveSchemaError","findNode","dataPath","filter","entry","concat","reduce","all","findParents","parent","child","message","type","updateDom","startAutoScroll","mouseY","me","top","getAbsoluteTop","height","clientHeight","bottom","margin","interval","scrollTop","autoScrollStep","scrollHeight","autoScrollTimer","setInterval","stopAutoScroll","clearTimeout","setSelection","select","range","setSelectionOffset","getSelection","getSelectionOffset","nodeName","slice","scrollTo","callback","editor","animateTimeout","animateCallback","finalScrollTop","Math","min","max","animate","diff","abs","setTimeout","onEvent","event","_onEvent","document","createElement","className","onclick","target","preventDefault","oninput","onchange","onkeydown","onkeyup","oncut","onpaste","onmousedown","onmouseup","onmouseover","onmouseout","addEventListener","onfocusin","onfocusout","title","undo","_onUndo","redo","_onRedo","disabled","canUndo","canRedo","_onKeyDown","_startDragDistance","_updateDragDistance","selected","showContextMenu","hasMoved","deselect","onDragStart","drag","_onMultiSelectStart","dragDistanceEvent","initialTarget","initialPageX","pageX","initialPageY","pageY","dragDistance","diffX","diffY","sqrt","start","end","mousemove","window","_onMultiSelect","mouseup","_onMultiSelectEnd","_findTopLevelNodes","removeEventListener","clearStartAndEnd","setSelected","Array","first","startPath","getNodePath","endPath","startChild","endChild","childs","startIndex","endIndex","firstIndex","lastIndex","keynum","which","keyCode","ctrlKey","shiftKey","handled","selectContentEditable","previous","next","stopPropagation","contentOuter","col","colgroupContent","width","anchor","onClose","items","push","click","onDuplicate","onRemove","close","show","locked","highlight","setHighlight","_cancelUnhighlight","unhighlight","unhighlightTimer","lock","unlock","index","actions","editField","oldValue","newValue","editValue","updateValue","changeType","oldType","newType","appendNodes","insertBeforeNodes","insertBefore","beforeNode","insertAfterNodes","afterNode","insertAfter","removeNodes","append","duplicateNodes","moveNodes","oldBeforeNode","moveBefore","newBeforeNode","sort","hideChilds","oldSort","oldChilds","showChilds","newSort","newChilds","timestamp","Date","splice","obj","oldSelection","newSelection","jsonlint","jsonString","sanitize","jsString","curr","charAt","prev","lastNonWhitespace","chars","pp","skipBlockComment","skipComment","parseString","quote","parseKey","specialValues","key","regexp","test","match","join","escapeUnicodeChars","replace","charCodeAt","toString","a","b","object","Number","String","Boolean","RegExp","isUrlRegex","isUrl","getAbsoluteLeft","elem","rect","getBoundingClientRect","left","pageXOffset","scrollLeft","pageYOffset","addClassName","classes","split","removeClassName","stripFormatting","divElement","childNodes","iMax","style","removeAttribute","attributes","j","attribute","specified","setEndOfContentEditable","contentEditableElement","createRange","selectNodeContents","removeAllRanges","addRange","sel","getRangeAt","rangeCount","startContainer","endContainer","startOffset","endOffset","firstChild","createTextNode","setStart","setEnd","getInnerText","element","buffer","flush","nodeValue","hasChildNodes","innerText","prevChild","prevName","_ieVersion","rv","navigator","appName","ua","userAgent","re","exec","parseFloat","$1","isFirefox","listener","useCapture","attachEvent","f","detachEvent","parsePath","jsonPath","remainder","substr","SyntaxError","substring","keyword","enums","more","additionalProperty","insideRect","_margin","right","func","wait","immediate","timeout","context","args","later","apply","callNow","textDiff","oldText","newText","len","oldEnd","newEnd","parser","trace","yy","symbols_","JSONString","STRING","JSONNumber","NUMBER","JSONNullLiteral","NULL","JSONBooleanLiteral","TRUE","FALSE","JSONText","JSONValue","EOF","JSONObject","JSONArray","{","}","JSONMemberList","JSONMember",":",",","[","]","JSONElementList","$accept","$end","terminals_","2","4","6","8","10","11","14","17","18","21","22","23","24","productions_","performAction","yytext","yyleng","yylineno","yystate","$$","_$","$0","$","3","5","7","9","12","13","15","16","1","19","20","25","defaultActions","parseError","str","hash","popStack","n","stack","vstack","lstack","lex","token","self","lexer","recovering","TERROR","setInput","yylloc","yyloc","symbol","preErrorSymbol","state","r","newState","expected","yyval","errStr","showPosition","line","loc","first_line","last_line","first_column","last_column","_input","_more","_less","done","matched","conditionStack","ch","lines","unput","less","pastInput","past","upcomingInput","pre","tempMatch","rules","_currentRules","flex","begin","condition","popState","pop","conditions","topState","pushState","yy_","$avoiding_name_collisions","YY_START","INITIAL","inclusive","delay","lastText","tr","td","divInput","tableInput","tbodySearch","refreshSearch","_onDelayedSearch","_onSearch","_onKeyUp","searchNext","searchPrevious","resultIndex","_setActiveResult","activeResult","prevNode","prevElem","searchFieldActive","searchValueActive","_clearDelay","forceSearch","resultCount","innerHTML","createMenuItems","list","domItems","item","separator","li","domItem","button","hide","submenu","divIcon","buttonSubmenu","buttonExpand","submenuTitle","divExpand","_onExpandItem","domSubItems","subItems","ul","eventListeners","focusButton","overflow","maxHeight","_getVisibleButtons","buttons","expandedItem","subItem","visibleMenu","contentWindow","showBelow","anchorRect","contentRect","anchorHeight","offsetHeight","mousedown","_isChildOf","keydown","fn","alreadyVisible","padding","display","targetIndex","prevButton","nextButton","expanded","setField","fieldEditable","setValue","_debouncedOnChangeValue","_onChangeValue","_debouncedOnChangeField","_onChangeField","naturalSort","appendNodeFactory","_updateEditability","path","getPath","unshift","shift","parents","tdError","tdValue","popover","onfocus","directions","direction","popoverRect","fit","getIndex","setParent","previousField","getField","_getDomField","childValue","_getType","childField","sortObjectKeys","previousValue","arr","_getDomValue","getLevel","clone","fieldInnerText","valueInnerText","cloneChilds","childClone","getAppend","nextTr","nextSibling","_hasChilds","newTr","appendTr","updateIndexes","trTemp","AppendNode","moveTo","currentIndex","toLowerCase","searchField","searchValue","_updateDomField","childResults","_updateDomValue","offsetTop","focusElement","elementName","editableDiv","containsNode","_move","clearDom","removedNode","_remove","lastTr","_stringCast","silent","_unescapeHTML","undoDiff","redoDiff","domValue","classNames","isEmpty","count","checkbox","tdCheckbox","checked","getUTCMilliseconds","tdSelect","valueFieldHTML","visibility","domField","duplicateKeys","tdDrag","domDrag","tdMenu","tdField","tree","_createDomTree","firstNode","lastNode","draggedNode","_nextSibling","offsetY","onDrag","onDragEnd","oldCursor","body","cursor","mouseX","level","trThis","trPrev","trNext","trFirst","trLast","trRoot","nodePrev","nodeNext","topThis","topPrev","topFirst","heightThis","bottomNext","heightNext","moved","previousSibling","diffLevel","round","levelNext","isDraggedNode","some","_createDomField","isFirst","domTree","marginLeft","contentEditable","spellcheck","fieldText","_escapeHTML","_updateSchema","_updateDomIndexes","_findSchema","_findEnum","composite","oneOf","anyOf","allOf","childSchema","properties","_createDomValue","href","_createDomExpandButton","borderCollapse","tdExpand","tdSeparator","srcElement","expandable","_onExpand","open","offsetX","onKeyDown","nextNode","nextDom","nextDom2","altKey","selectedNodes","_onInsertBefore","_onInsertAfter","endNode","_lastNode","_getElementName","homeNode","_firstNode","prevElement","_previousElement","appendDom","nextNode2","_previousNode","nextElement","_nextElement","prevDom","isVisible","_nextNode","blurNodes","clones","newNode","_onAppend","_onChangeType","order","oldSortOrder","sortOrder","firstDom","lastDom","lastChild","TYPE_TITLES","auto","array","string","titles","lower","num","numFloat","isNaN","htmlEscaped","html","escapeUnicode","escapedText","_escapeJSON","escaped","oFxNcL","oFyNcL","sre","dre","hre","ore","s","insensitive","x","y","xN","yN","xD","parseInt","yD","cLoc","numS","trAppend","tdAppend","domText","paddingLeft","current","onSwitch","availableModes","form","view","currentMode","currentTitle","box","position","ace","MAX_ERRORS","indentation","_ace","theme","aceEditor","textarea","clientWidth","buttonFormat","format","buttonCompact","compact","editorDom","edit","$blockScrolling","Infinity","setTheme","setShowPrintMargin","setFontSize","getSession","setTabSize","setUseSoftTabs","setUseWrapMode","commands","bindKey","defineProperty","poweredBy","on","resize","force","originalOnChange","validationErrors","marginBottom","paddingBottom","doValidate","limit","hidden","acequire","oop","TextHighlightRules","JsonHighlightRules","$rules","regex","inherits","Range","MatchingBraceOutdent","checkOutdent","autoOutdent","doc","row","getLine","column","openBracePos","findMatchingBracket","indent","$getIndent","Behaviour","TokenIterator","lang","SAFE_INSERT_IN_TOKENS","SAFE_INSERT_BEFORE_TOKENS","contextCache","initContext","multiSelect","autoInsertedBrackets","autoInsertedRow","autoInsertedLineEnd","maybeInsertedBrackets","maybeInsertedRow","maybeInsertedLineStart","maybeInsertedLineEnd","getWrapped","opening","closing","rowDiff","CstyleBehaviour","session","getCursorPosition","getSelectionRange","getTextRange","getWrapBehavioursEnabled","isSaneInsertion","inMultiSelectMode","recordAutoInsert","recordMaybeInsert","rightChar","matching","$findOpeningBracket","isAutoInsertedClosing","popAutoInsertedClosing","isMaybeInsertedClosing","stringRepeat","clearMaybeInsertedClosing","next_indent","getTabString","isMultiLine","leftChar","getTokenAt","rightToken","pair","stringBefore","stringAfter","wordRe","$mode","tokenRe","isWordBefore","isWordAfter","iterator","$matchTokenType","getCurrentToken","iterator2","stepForward","getCurrentTokenRow","types","bracket","BaseFoldMode","FoldMode","commentRegex","foldingStartMarker","source","foldingStopMarker","singleLineBlockCommentRe","tripleStarBlockCommentRe","startRegionRe","_getFoldWidgetBase","getFoldWidget","foldStyle","fw","getFoldWidgetRange","forceMultiline","getCommentRegionBlock","openingBracketBlock","getCommentFoldRange","getSectionRange","closingBracketBlock","startIndent","startRow","startColumn","endRow","maxRow","getLength","subRange","depth","TextMode","Mode","HighlightRules","CStyleFoldMode","WorkerClient","$outdent","$behaviour","foldingRules","getNextLineIndent","tab","createWorker","worker","attachToDocument","getDocument","setAnnotations","clearAnnotations","$id","src","searchboxCss","HashHandler","keyUtil","importCssString","showReplaceForm","div","$init","setEditor","$initElements","sb","replaceBox","searchOptions","regExpOption","caseSensitiveOption","wholeWordOption","searchInput","replaceInput","_this","addListener","activeInput","t","getAttribute","$searchBarKb","addCommandKeyListener","hashId","keyString","keyCodeToString","command","findKeyCommand","stopEvent","$onChange","delayedCall","find","schedule","$closeSearchBarKb","bindKeys","Ctrl-f|Command-f","isReplace","Ctrl-H|Command-Option-F","Ctrl-G|Command-G","findNext","Ctrl-Shift-G|Command-Shift-G","findPrev","esc","Return","Shift-Return","Alt-Return","replaceAll","findAll","Tab","addCommands","win","mac","$syncOptions","setCssClass","$search","$options","renderer","updateBackMarkers","skipCurrent","backwards","preventScroll","wrap","regExp","caseSensitive","wholeWord","noMatch","_emit","getReadOnly","replaceAndFindNext","keyBinding","removeKeyboardHandler","addKeyboardHandler","isFocused","el","activeElement","Search","isDark","cssClass","cssText"],"mappings":"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","file":"jsoneditor-minimalist.map"} \ No newline at end of file diff --git a/ui/app/bower_components/jsoneditor/dist/jsoneditor-minimalist.min.js b/ui/app/bower_components/jsoneditor/dist/jsoneditor-minimalist.min.js new file mode 100644 index 0000000..a1c4f9e --- /dev/null +++ b/ui/app/bower_components/jsoneditor/dist/jsoneditor-minimalist.min.js @@ -0,0 +1,35 @@ +/*! + * jsoneditor.js + * + * @brief + * JSONEditor is a web-based tool to view, edit, format, and validate JSON. + * It has various modes such as a tree editor, a code editor, and a plain text + * editor. + * + * Supported browsers: Chrome, Firefox, Safari, Opera, Internet Explorer 8+ + * + * @license + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + * + * Copyright (c) 2011-2016 Jos de Jong, http://jsoneditoronline.org + * + * @author Jos de Jong, + * @version 5.5.10 + * @date 2016-11-02 + */ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.JSONEditor=t():e.JSONEditor=t()}(this,function(){return function(e){function t(i){if(n[i])return n[i].exports;var o=n[i]={exports:{},id:i,loaded:!1};return e[i].call(o.exports,o,o.exports,t),o.loaded=!0,o.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){"use strict";function i(e,t,n){if(!(this instanceof i))throw new Error('JSONEditor constructor called without "new".');var o=l.getInternetExplorerVersion();if(-1!=o&&9>o)throw new Error("Unsupported browser, IE9 or newer required. Please install the newest version of your browser.");if(t&&(t.error&&(console.warn('Option "error" has been renamed to "onError"'),t.onError=t.error,delete t.error),t.change&&(console.warn('Option "change" has been renamed to "onChange"'),t.onChange=t.change,delete t.change),t.editable&&(console.warn('Option "editable" has been renamed to "onEditable"'),t.onEditable=t.editable,delete t.editable),t)){var r=["ace","theme","ajv","schema","onChange","onEditable","onError","onModeChange","escapeUnicode","history","search","mode","modes","name","indentation","sortObjectKeys"];Object.keys(t).forEach(function(e){-1===r.indexOf(e)&&console.warn('Unknown option "'+e+'". This option will be ignored')})}arguments.length&&this._create(e,t,n)}var o;try{o=n(!function(){var e=new Error('Cannot find module "ajv"');throw e.code="MODULE_NOT_FOUND",e}())}catch(r){}var s=n(1),a=n(12),l=n(4);i.modes={},i.prototype.DEBOUNCE_INTERVAL=150,i.prototype._create=function(e,t,n){this.container=e,this.options=t||{},this.json=n||{};var i=this.options.mode||"tree";this.setMode(i)},i.prototype.destroy=function(){},i.prototype.set=function(e){this.json=e},i.prototype.get=function(){return this.json},i.prototype.setText=function(e){this.json=l.parse(e)},i.prototype.getText=function(){return JSON.stringify(this.json)},i.prototype.setName=function(e){this.options||(this.options={}),this.options.name=e},i.prototype.getName=function(){return this.options&&this.options.name},i.prototype.setMode=function(e){var t,n,o=this.container,r=l.extend({},this.options),s=r.mode;r.mode=e;var a=i.modes[e];if(!a)throw new Error('Unknown mode "'+r.mode+'"');try{var c="text"==a.data;if(n=this.getName(),t=this[c?"getText":"get"](),this.destroy(),l.clear(this),l.extend(this,a.mixin),this.create(o,r),this.setName(n),this[c?"setText":"set"](t),"function"==typeof a.load)try{a.load.call(this)}catch(d){console.error(d)}if("function"==typeof r.onModeChange&&e!==s)try{r.onModeChange(e,s)}catch(d){console.error(d)}}catch(d){this._onError(d)}},i.prototype.getMode=function(){return this.options.mode},i.prototype._onError=function(e){if(!this.options||"function"!=typeof this.options.onError)throw e;this.options.onError(e)},i.prototype.setSchema=function(e){if(e){var t;try{t=this.options.ajv||o({allErrors:!0,verbose:!0})}catch(n){console.warn("Failed to create an instance of Ajv, JSON Schema validation is not available. Please use a JSONEditor bundle including Ajv, or pass an instance of Ajv as via the configuration option `ajv`.")}t&&(this.validateSchema=t.compile(e),this.options.schema=e,this.validate()),this.refresh()}else this.validateSchema=null,this.options.schema=null,this.validate(),this.refresh()},i.prototype.validate=function(){},i.prototype.refresh=function(){},i.registerMode=function(e){var t,n;if(l.isArray(e))for(t=0;te&&n.scrollTop>0?this.autoScrollStep=(i+s-e)/3:e>r-s&&o+n.scrollTop3?(n.scrollTop+=o/3,i.animateCallback=t,i.animateTimeout=setTimeout(a,50)):(t&&t(!0),n.scrollTop=s,delete i.animateTimeout,delete i.animateCallback)};a()}else t&&t(!1)},d._createFrame=function(){function e(e){t._onEvent&&t._onEvent(e)}this.frame=document.createElement("div"),this.frame.className="jsoneditor jsoneditor-mode-"+this.options.mode,this.container.appendChild(this.frame);var t=this;this.frame.onclick=function(t){var n=t.target;e(t),"BUTTON"==n.nodeName&&t.preventDefault()},this.frame.oninput=e,this.frame.onchange=e,this.frame.onkeydown=e,this.frame.onkeyup=e,this.frame.oncut=e,this.frame.onpaste=e,this.frame.onmousedown=e,this.frame.onmouseup=e,this.frame.onmouseover=e,this.frame.onmouseout=e,c.addEventListener(this.frame,"focus",e,!0),c.addEventListener(this.frame,"blur",e,!0),this.frame.onfocusin=e,this.frame.onfocusout=e,this.menu=document.createElement("div"),this.menu.className="jsoneditor-menu",this.frame.appendChild(this.menu);var n=document.createElement("button");n.type="button",n.className="jsoneditor-expand-all",n.title="Expand all fields",n.onclick=function(){t.expandAll()},this.menu.appendChild(n);var i=document.createElement("button");if(i.type="button",i.title="Collapse all fields",i.className="jsoneditor-collapse-all",i.onclick=function(){t.collapseAll()},this.menu.appendChild(i),this.history){var o=document.createElement("button");o.type="button",o.className="jsoneditor-undo jsoneditor-separator",o.title="Undo last action (Ctrl+Z)",o.onclick=function(){t._onUndo()},this.menu.appendChild(o),this.dom.undo=o;var s=document.createElement("button");s.type="button",s.className="jsoneditor-redo",s.title="Redo (Ctrl+Shift+Z)",s.onclick=function(){t._onRedo()},this.menu.appendChild(s),this.dom.redo=s,this.history.onChange=function(){o.disabled=!t.history.canUndo(),s.disabled=!t.history.canRedo()},this.history.onChange()}if(this.options&&this.options.modes&&this.options.modes.length){var a=this;this.modeSwitcher=new l(this.menu,this.options.modes,this.options.mode,function(e){a.modeSwitcher.destroy(),a.setMode(e),a.modeSwitcher.focus()})}this.options.search&&(this.searchBox=new r(this,this.menu))},d._onUndo=function(){this.history&&(this.history.undo(),this._onChange())},d._onRedo=function(){this.history&&(this.history.redo(),this._onChange())},d._onEvent=function(e){"keydown"==e.type&&this._onKeyDown(e),"focus"==e.type&&(this.focusTarget=e.target),"mousedown"==e.type&&this._startDragDistance(e),"mousemove"!=e.type&&"mouseup"!=e.type&&"click"!=e.type||this._updateDragDistance(e);var t=a.getNodeFromTarget(e.target);if(t&&t.selected){if("click"==e.type){if(e.target==t.dom.menu)return void this.showContextMenu(e.target);e.hasMoved||this.deselect()}"mousedown"==e.type&&a.onDragStart(this.multiselection.nodes,e)}else"mousedown"==e.type&&(this.deselect(),t&&e.target==t.dom.drag?a.onDragStart(t,e):(!t||e.target!=t.dom.field&&e.target!=t.dom.value&&e.target!=t.dom.select)&&this._onMultiSelectStart(e));t&&t.onEvent(e)},d._startDragDistance=function(e){this.dragDistanceEvent={initialTarget:e.target,initialPageX:e.pageX,initialPageY:e.pageY,dragDistance:0,hasMoved:!1}},d._updateDragDistance=function(e){this.dragDistanceEvent||this._startDragDistance(e);var t=e.pageX-this.dragDistanceEvent.initialPageX,n=e.pageY-this.dragDistanceEvent.initialPageY;return this.dragDistanceEvent.dragDistance=Math.sqrt(t*t+n*n),this.dragDistanceEvent.hasMoved=this.dragDistanceEvent.hasMoved||this.dragDistanceEvent.dragDistance>10,e.dragDistance=this.dragDistanceEvent.dragDistance,e.hasMoved=this.dragDistanceEvent.hasMoved,e.dragDistance},d._onMultiSelectStart=function(e){var t=a.getNodeFromTarget(e.target);if("tree"===this.options.mode&&void 0===this.options.onEditable){this.multiselection={start:t||null,end:null,nodes:[]},this._startDragDistance(e);var n=this;this.mousemove||(this.mousemove=c.addEventListener(window,"mousemove",function(e){n._onMultiSelect(e)})),this.mouseup||(this.mouseup=c.addEventListener(window,"mouseup",function(e){n._onMultiSelectEnd(e)}))}},d._onMultiSelect=function(e){if(e.preventDefault(),this._updateDragDistance(e),e.hasMoved){var t=a.getNodeFromTarget(e.target);t&&(null==this.multiselection.start&&(this.multiselection.start=t),this.multiselection.end=t),this.deselect();var n=this.multiselection.start,i=this.multiselection.end||this.multiselection.start;n&&i&&(this.multiselection.nodes=this._findTopLevelNodes(n,i),this.select(this.multiselection.nodes))}},d._onMultiSelectEnd=function(e){this.multiselection.nodes[0]&&this.multiselection.nodes[0].dom.menu.focus(),this.multiselection.start=null,this.multiselection.end=null,this.mousemove&&(c.removeEventListener(window,"mousemove",this.mousemove),delete this.mousemove),this.mouseup&&(c.removeEventListener(window,"mouseup",this.mouseup),delete this.mouseup)},d.deselect=function(e){this.multiselection.nodes.forEach(function(e){e.setSelected(!1)}),this.multiselection.nodes=[],e&&(this.multiselection.start=null,this.multiselection.end=null)},d.select=function(e){if(!Array.isArray(e))return this.select([e]);if(e){this.deselect(),this.multiselection.nodes=e.slice(0);var t=e[0];e.forEach(function(e){e.setSelected(!0,e===t)})}},d._findTopLevelNodes=function(e,t){for(var n=e.getNodePath(),i=t.getNodePath(),o=0;o=0},i.prototype.canRedo=function(){return this.index=0;){var t=c[e];if(" "!==t&&"\n"!==t&&"\r"!==t&&" "!==t)return t;e--}return""}function r(){for(d+=2;di;i++){var r=n[i];r.style&&r.removeAttribute("style");var s=r.attributes;if(s)for(var a=s.length-1;a>=0;a--){var l=s[a];l.specified===!0&&r.removeAttribute(l.name)}t.stripFormatting(r)}},t.setEndOfContentEditable=function(e){var t,n;document.createRange&&(t=document.createRange(),t.selectNodeContents(e),t.collapse(!1),n=window.getSelection(),n.removeAllRanges(),n.addRange(t))},t.selectContentEditable=function(e){if(e&&"DIV"==e.nodeName){var t,n;window.getSelection&&document.createRange&&(n=document.createRange(),n.selectNodeContents(e),t=window.getSelection(),t.removeAllRanges(),t.addRange(n))}},t.getSelection=function(){if(window.getSelection){var e=window.getSelection();if(e.getRangeAt&&e.rangeCount)return e.getRangeAt(0)}return null},t.setSelection=function(e){if(e&&window.getSelection){var t=window.getSelection();t.removeAllRanges(),t.addRange(e)}},t.getSelectionOffset=function(){var e=t.getSelection();return e&&"startOffset"in e&&"endOffset"in e&&e.startContainer&&e.startContainer==e.endContainer?{startOffset:e.startOffset,endOffset:e.endOffset,container:e.startContainer.parentNode}:null},t.setSelectionOffset=function(e){if(document.createRange&&window.getSelection){var n=window.getSelection();if(n){var i=document.createRange();e.container.firstChild||e.container.appendChild(document.createTextNode("")),i.setStart(e.container.firstChild,e.startOffset),i.setEnd(e.container.firstChild,e.endOffset),t.setSelection(i)}}},t.getInnerText=function(e,n){var i=void 0==n;if(i&&(n={text:"",flush:function(){var e=this.text;return this.text="",e},set:function(e){this.text=e}}),e.nodeValue)return n.flush()+e.nodeValue;if(e.hasChildNodes()){for(var o=e.childNodes,r="",s=0,a=o.length;a>s;s++){var l=o[s];if("DIV"==l.nodeName||"P"==l.nodeName){var c=o[s-1],d=c?c.nodeName:void 0;d&&"DIV"!=d&&"P"!=d&&"BR"!=d&&(r+="\n",n.flush()),r+=t.getInnerText(l,n),n.set("\n")}else"BR"==l.nodeName?(r+=n.flush(),n.set("\n")):r+=t.getInnerText(l,n)}return r}return"P"==e.nodeName&&-1!=t.getInternetExplorerVersion()?n.flush():""},t.getInternetExplorerVersion=function(){if(-1==r){var e=-1;if("Microsoft Internet Explorer"==navigator.appName){var t=navigator.userAgent,n=new RegExp("MSIE ([0-9]{1,}[.0-9]{0,})");null!=n.exec(t)&&(e=parseFloat(RegExp.$1))}r=e}return r},t.isFirefox=function(){return-1!=navigator.userAgent.indexOf("Firefox")};var r=-1;t.addEventListener=function(e,n,i,o){if(e.addEventListener)return void 0===o&&(o=!1),"mousewheel"===n&&t.isFirefox()&&(n="DOMMouseScroll"),e.addEventListener(n,i,o),i;if(e.attachEvent){var r=function(){return i.call(e,window.event)};return e.attachEvent("on"+n,r),r}},t.removeEventListener=function(e,n,i,o){e.removeEventListener?(void 0===o&&(o=!1),"mousewheel"===n&&t.isFirefox()&&(n="DOMMouseScroll"),e.removeEventListener(n,i,o)):e.detachEvent&&e.detachEvent("on"+n,i)},t.parsePath=function s(e){var t,n;if(0===e.length)return[];var i=e.match(/^\.(\w+)/);if(i)t=i[1],n=e.substr(t.length+1);else{if("["!==e[0])throw new SyntaxError("Failed to parse path");var o=e.indexOf("]");if(-1===o)throw new SyntaxError("Character ] expected in path");if(1===o)throw new SyntaxError("Index expected after [");var r=e.substring(1,o);"'"===r[0]&&(r='"'+r.substring(1,r.length-1)+'"'),t="*"===r?r:JSON.parse(r),n=e.substr(o+1)}return[t].concat(s(n))},t.improveSchemaError=function(e){if("enum"===e.keyword&&Array.isArray(e.schema)){var t=e.schema;if(t){if(t=t.map(function(e){return JSON.stringify(e)}),t.length>5){var n=["("+(t.length-5)+" more...)"];t=t.slice(0,5),t.push(n)}e.message="should be equal to one of: "+t.join(", ")}}return"additionalProperties"===e.keyword&&(e.message="should NOT have additional property: "+e.params.additionalProperty),e},t.insideRect=function(e,t,n){var i=void 0!==n?n:0;return t.left-i>=e.left&&t.right+i<=e.right&&t.top-i>=e.top&&t.bottom+i<=e.bottom},t.debounce=function(e,t,n){var i;return function(){var o=this,r=arguments,s=function(){i=null,n||e.apply(o,r)},a=n&&!i;clearTimeout(i),i=setTimeout(s,t),a&&e.apply(o,r)}},t.textDiff=function(e,t){for(var n=t.length,i=0,o=e.length,r=t.length;t.charAt(i)===e.charAt(i)&&n>i;)i++;for(;t.charAt(r-1)===e.charAt(o-1)&&r>i&&o>0;)r--,o--;return{start:i,end:r}}},function(e,t,n){var i=function(){var e={trace:function(){},yy:{},symbols_:{error:2,JSONString:3,STRING:4,JSONNumber:5,NUMBER:6,JSONNullLiteral:7,NULL:8,JSONBooleanLiteral:9,TRUE:10,FALSE:11,JSONText:12,JSONValue:13,EOF:14,JSONObject:15,JSONArray:16,"{":17,"}":18,JSONMemberList:19,JSONMember:20,":":21,",":22,"[":23,"]":24,JSONElementList:25,$accept:0,$end:1},terminals_:{2:"error",4:"STRING",6:"NUMBER",8:"NULL",10:"TRUE",11:"FALSE",14:"EOF",17:"{",18:"}",21:":",22:",",23:"[",24:"]"},productions_:[0,[3,1],[5,1],[7,1],[9,1],[9,1],[12,2],[13,1],[13,1],[13,1],[13,1],[13,1],[13,1],[15,2],[15,3],[20,3],[19,1],[19,3],[16,2],[16,3],[25,1],[25,3]],performAction:function(e,t,n,i,o,r,s){var a=r.length-1;switch(o){case 1:this.$=e.replace(/\\(\\|")/g,"$1").replace(/\\n/g,"\n").replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\v/g,"\x0B").replace(/\\f/g,"\f").replace(/\\b/g,"\b");break;case 2:this.$=Number(e);break;case 3:this.$=null;break;case 4:this.$=!0;break;case 5:this.$=!1;break;case 6:return this.$=r[a-1];case 13:this.$={};break;case 14:this.$=r[a-1];break;case 15:this.$=[r[a-2],r[a]];break;case 16:this.$={},this.$[r[a][0]]=r[a][1];break;case 17:this.$=r[a-2],r[a-2][r[a][0]]=r[a][1];break;case 18:this.$=[];break;case 19:this.$=r[a-1];break;case 20:this.$=[r[a]];break;case 21:this.$=r[a-2],r[a-2].push(r[a])}},table:[{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],12:1,13:2,15:7,16:8,17:[1,14],23:[1,15]},{1:[3]},{14:[1,16]},{14:[2,7],18:[2,7],22:[2,7],24:[2,7]},{14:[2,8],18:[2,8],22:[2,8],24:[2,8]},{14:[2,9],18:[2,9],22:[2,9],24:[2,9]},{14:[2,10],18:[2,10],22:[2,10],24:[2,10]},{14:[2,11],18:[2,11],22:[2,11],24:[2,11]},{14:[2,12],18:[2,12],22:[2,12],24:[2,12]},{14:[2,3],18:[2,3],22:[2,3],24:[2,3]},{14:[2,4],18:[2,4],22:[2,4],24:[2,4]},{14:[2,5],18:[2,5],22:[2,5],24:[2,5]},{14:[2,1],18:[2,1],21:[2,1],22:[2,1],24:[2,1]},{14:[2,2],18:[2,2],22:[2,2],24:[2,2]},{3:20,4:[1,12],18:[1,17],19:18,20:19},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:23,15:7,16:8,17:[1,14],23:[1,15],24:[1,21],25:22},{1:[2,6]},{14:[2,13],18:[2,13],22:[2,13],24:[2,13]},{18:[1,24],22:[1,25]},{18:[2,16],22:[2,16]},{21:[1,26]},{14:[2,18],18:[2,18],22:[2,18],24:[2,18]},{22:[1,28],24:[1,27]},{22:[2,20],24:[2,20]},{14:[2,14],18:[2,14],22:[2,14],24:[2,14]},{3:20,4:[1,12],20:29},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:30,15:7,16:8,17:[1,14],23:[1,15]},{14:[2,19],18:[2,19],22:[2,19],24:[2,19]},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:31,15:7,16:8,17:[1,14],23:[1,15]},{18:[2,17],22:[2,17]},{18:[2,15],22:[2,15]},{22:[2,21],24:[2,21]}],defaultActions:{16:[2,6]},parseError:function(e,t){throw new Error(e)},parse:function(e){function t(e){o.length=o.length-2*e,r.length=r.length-e,s.length=s.length-e}function n(){var e;return e=i.lexer.lex()||1,"number"!=typeof e&&(e=i.symbols_[e]||e),e}var i=this,o=[0],r=[null],s=[],a=this.table,l="",c=0,d=0,h=0,u=2,p=1;this.lexer.setInput(e),this.lexer.yy=this.yy,this.yy.lexer=this.lexer,"undefined"==typeof this.lexer.yylloc&&(this.lexer.yylloc={});var f=this.lexer.yylloc;s.push(f),"function"==typeof this.yy.parseError&&(this.parseError=this.yy.parseError);for(var m,g,v,y,b,w,x,_,E,C={};;){if(v=o[o.length-1],this.defaultActions[v]?y=this.defaultActions[v]:(null==m&&(m=n()),y=a[v]&&a[v][m]),"undefined"==typeof y||!y.length||!y[0]){if(!h){E=[];for(w in a[v])this.terminals_[w]&&w>2&&E.push("'"+this.terminals_[w]+"'");var S="";S=this.lexer.showPosition?"Parse error on line "+(c+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+E.join(", ")+", got '"+this.terminals_[m]+"'":"Parse error on line "+(c+1)+": Unexpected "+(1==m?"end of input":"'"+(this.terminals_[m]||m)+"'"),this.parseError(S,{text:this.lexer.match,token:this.terminals_[m]||m,line:this.lexer.yylineno,loc:f,expected:E})}if(3==h){if(m==p)throw new Error(S||"Parsing halted.");d=this.lexer.yyleng,l=this.lexer.yytext,c=this.lexer.yylineno,f=this.lexer.yylloc,m=n()}for(;;){if(u.toString()in a[v])break;if(0==v)throw new Error(S||"Parsing halted.");t(1),v=o[o.length-1]}g=m,m=u,v=o[o.length-1],y=a[v]&&a[v][u],h=3}if(y[0]instanceof Array&&y.length>1)throw new Error("Parse Error: multiple actions possible at state: "+v+", token: "+m);switch(y[0]){case 1:o.push(m),r.push(this.lexer.yytext),s.push(this.lexer.yylloc),o.push(y[1]),m=null,g?(m=g,g=null):(d=this.lexer.yyleng,l=this.lexer.yytext,c=this.lexer.yylineno,f=this.lexer.yylloc,h>0&&h--);break;case 2:if(x=this.productions_[y[1]][1],C.$=r[r.length-x],C._$={first_line:s[s.length-(x||1)].first_line,last_line:s[s.length-1].last_line,first_column:s[s.length-(x||1)].first_column,last_column:s[s.length-1].last_column},b=this.performAction.call(C,l,d,c,this.yy,y[1],r,s),"undefined"!=typeof b)return b;x&&(o=o.slice(0,-1*x*2),r=r.slice(0,-1*x),s=s.slice(0,-1*x)),o.push(this.productions_[y[1]][0]),r.push(C.$),s.push(C._$),_=a[o[o.length-2]][o[o.length-1]],o.push(_);break; +case 3:return!0}}return!0}},t=function(){var e={EOF:1,parseError:function(e,t){if(!this.yy.parseError)throw new Error(e);this.yy.parseError(e,t)},setInput:function(e){return this._input=e,this._more=this._less=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this},input:function(){var e=this._input[0];this.yytext+=e,this.yyleng++,this.match+=e,this.matched+=e;var t=e.match(/\n/);return t&&this.yylineno++,this._input=this._input.slice(1),e},unput:function(e){return this._input=e+this._input,this},more:function(){return this._more=!0,this},less:function(e){this._input=this.match.slice(e)+this._input},pastInput:function(){var e=this.matched.substr(0,this.matched.length-this.match.length);return(e.length>20?"...":"")+e.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var e=this.match;return e.length<20&&(e+=this._input.substr(0,20-e.length)),(e.substr(0,20)+(e.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var e=this.pastInput(),t=new Array(e.length+1).join("-");return e+this.upcomingInput()+"\n"+t+"^"},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var e,t,n,i,o;this._more||(this.yytext="",this.match="");for(var r=this._currentRules(),s=0;st[0].length)||(t=n,i=s,this.options.flex));s++);return t?(o=t[0].match(/\n.*/g),o&&(this.yylineno+=o.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:o?o[o.length-1].length-1:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.yyleng=this.yytext.length,this._more=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],e=this.performAction.call(this,this.yy,this,r[i],this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),e?e:void 0):""===this._input?this.EOF:void this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var e=this.next();return"undefined"!=typeof e?e:this.lex()},begin:function(e){this.conditionStack.push(e)},popState:function(){return this.conditionStack.pop()},_currentRules:function(){return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules},topState:function(){return this.conditionStack[this.conditionStack.length-2]},pushState:function(e){this.begin(e)}};return e.options={},e.performAction=function(e,t,n,i){switch(n){case 0:break;case 1:return 6;case 2:return t.yytext=t.yytext.substr(1,t.yyleng-2),4;case 3:return 17;case 4:return 18;case 5:return 23;case 6:return 24;case 7:return 22;case 8:return 21;case 9:return 10;case 10:return 11;case 11:return 8;case 12:return 14;case 13:return"INVALID"}},e.rules=[/^(?:\s+)/,/^(?:(-?([0-9]|[1-9][0-9]+))(\.[0-9]+)?([eE][-+]?[0-9]+)?\b)/,/^(?:"(?:\\[\\"bfnrt\/]|\\u[a-fA-F0-9]{4}|[^\\\0-\x09\x0a-\x1f"])*")/,/^(?:\{)/,/^(?:\})/,/^(?:\[)/,/^(?:\])/,/^(?:,)/,/^(?::)/,/^(?:true\b)/,/^(?:false\b)/,/^(?:null\b)/,/^(?:$)/,/^(?:.)/],e.conditions={INITIAL:{rules:[0,1,2,3,4,5,6,7,8,9,10,11,12,13],inclusive:!0}},e}();return e.lexer=t,e}();t.parser=i,t.parse=i.parse.bind(i)},function(e,t){"use strict";function n(e,t){var n=this;this.editor=e,this.timeout=void 0,this.delay=200,this.lastText=void 0,this.dom={},this.dom.container=t;var i=document.createElement("table");this.dom.table=i,i.className="jsoneditor-search",t.appendChild(i);var o=document.createElement("tbody");this.dom.tbody=o,i.appendChild(o);var r=document.createElement("tr");o.appendChild(r);var s=document.createElement("td");r.appendChild(s);var a=document.createElement("div");this.dom.results=a,a.className="jsoneditor-results",s.appendChild(a),s=document.createElement("td"),r.appendChild(s);var l=document.createElement("div");this.dom.input=l,l.className="jsoneditor-frame",l.title="Search fields and values",s.appendChild(l);var c=document.createElement("table");l.appendChild(c);var d=document.createElement("tbody");c.appendChild(d),r=document.createElement("tr"),d.appendChild(r);var h=document.createElement("button");h.type="button",h.className="jsoneditor-refresh",s=document.createElement("td"),s.appendChild(h),r.appendChild(s);var u=document.createElement("input");this.dom.search=u,u.oninput=function(e){n._onDelayedSearch(e)},u.onchange=function(e){n._onSearch()},u.onkeydown=function(e){n._onKeyDown(e)},u.onkeyup=function(e){n._onKeyUp(e)},h.onclick=function(e){u.select()},s=document.createElement("td"),s.appendChild(u),r.appendChild(s);var p=document.createElement("button");p.type="button",p.title="Next result (Enter)",p.className="jsoneditor-next",p.onclick=function(){n.next()},s=document.createElement("td"),s.appendChild(p),r.appendChild(s);var f=document.createElement("button");f.type="button",f.title="Previous result (Shift+Enter)",f.className="jsoneditor-previous",f.onclick=function(){n.previous()},s=document.createElement("td"),s.appendChild(f),r.appendChild(s)}n.prototype.next=function(e){if(void 0!=this.results){var t=void 0!=this.resultIndex?this.resultIndex+1:0;t>this.results.length-1&&(t=0),this._setActiveResult(t,e)}},n.prototype.previous=function(e){if(void 0!=this.results){var t=this.results.length-1,n=void 0!=this.resultIndex?this.resultIndex-1:t;0>n&&(n=t),this._setActiveResult(n,e)}},n.prototype._setActiveResult=function(e,t){if(this.activeResult){var n=this.activeResult.node,i=this.activeResult.elem;"field"==i?delete n.searchFieldActive:delete n.searchValueActive,n.updateDom()}if(!this.results||!this.results[e])return this.resultIndex=void 0,void(this.activeResult=void 0);this.resultIndex=e;var o=this.results[this.resultIndex].node,r=this.results[this.resultIndex].elem;"field"==r?o.searchFieldActive=!0:o.searchValueActive=!0,this.activeResult=this.results[this.resultIndex],o.updateDom(),o.scrollTo(function(){t&&o.focus(r)})},n.prototype._clearDelay=function(){void 0!=this.timeout&&(clearTimeout(this.timeout),delete this.timeout)},n.prototype._onDelayedSearch=function(e){this._clearDelay();var t=this;this.timeout=setTimeout(function(e){t._onSearch()},this.delay)},n.prototype._onSearch=function(e){this._clearDelay();var t=this.dom.search.value,n=t.length>0?t:void 0;if(n!=this.lastText||e)if(this.lastText=n,this.results=this.editor.search(n),this._setActiveResult(void 0),void 0!=n){var i=this.results.length;switch(i){case 0:this.dom.results.innerHTML="no results";break;case 1:this.dom.results.innerHTML="1 result";break;default:this.dom.results.innerHTML=i+" results"}}else this.dom.results.innerHTML=""},n.prototype._onKeyDown=function(e){var t=e.which;27==t?(this.dom.search.value="",this._onSearch(),e.preventDefault(),e.stopPropagation()):13==t&&(e.ctrlKey?this._onSearch(!0):e.shiftKey?this.previous():this.next(),e.preventDefault(),e.stopPropagation())},n.prototype._onKeyUp=function(e){var t=e.keyCode;27!=t&&13!=t&&this._onDelayedSearch(e)},n.prototype.clear=function(){this.dom.search.value="",this._onSearch()},n.prototype.destroy=function(){this.editor=null,this.dom.container.removeChild(this.dom.table),this.dom=null,this.results=null,this.activeResult=null,this._clearDelay()},e.exports=n},function(e,t,n){"use strict";function i(e,t){function n(e,t,o){o.forEach(function(o){if("separator"==o.type){var r=document.createElement("div");r.className="jsoneditor-separator",a=document.createElement("li"),a.appendChild(r),e.appendChild(a)}else{var s={},a=document.createElement("li");e.appendChild(a);var l=document.createElement("button");if(l.type="button",l.className=o.className,s.button=l,o.title&&(l.title=o.title),o.click&&(l.onclick=function(e){e.preventDefault(),i.hide(),o.click()}),a.appendChild(l),o.submenu){var c=document.createElement("div");c.className="jsoneditor-icon",l.appendChild(c),l.appendChild(document.createTextNode(o.text));var d;if(o.click){l.className+=" jsoneditor-default";var h=document.createElement("button");h.type="button",s.buttonExpand=h,h.className="jsoneditor-expand",h.innerHTML='
',a.appendChild(h),o.submenuTitle&&(h.title=o.submenuTitle),d=h}else{var u=document.createElement("div");u.className="jsoneditor-expand",l.appendChild(u),d=l}d.onclick=function(e){e.preventDefault(),i._onExpandItem(s),d.focus()};var p=[];s.subItems=p;var f=document.createElement("ul");s.ul=f,f.className="jsoneditor-menu",f.style.height="0",a.appendChild(f),n(f,p,o.submenu)}else l.innerHTML='
'+o.text;t.push(s)}})}this.dom={};var i=this,o=this.dom;this.anchor=void 0,this.items=e,this.eventListeners={},this.selection=void 0,this.onClose=t?t.close:void 0;var r=document.createElement("div");r.className="jsoneditor-contextmenu-root",o.root=r;var s=document.createElement("div");s.className="jsoneditor-contextmenu",o.menu=s,r.appendChild(s);var a=document.createElement("ul");a.className="jsoneditor-menu",s.appendChild(a),o.list=a,o.items=[];var l=document.createElement("button");l.type="button",o.focusButton=l;var c=document.createElement("li");c.style.overflow="hidden",c.style.height="0",c.appendChild(l),a.appendChild(c),n(a,this.dom.items,e),this.maxHeight=0,e.forEach(function(t){var n=24*(e.length+(t.submenu?t.submenu.length:0));i.maxHeight=Math.max(i.maxHeight,n)})}var o=n(4);i.prototype._getVisibleButtons=function(){var e=[],t=this;return this.dom.items.forEach(function(n){e.push(n.button),n.buttonExpand&&e.push(n.buttonExpand),n.subItems&&n==t.expandedItem&&n.subItems.forEach(function(t){e.push(t.button),t.buttonExpand&&e.push(t.buttonExpand)})}),e},i.visibleMenu=void 0,i.prototype.show=function(e,t){this.hide();var n=!0;if(t){var r=e.getBoundingClientRect(),s=t.getBoundingClientRect();r.bottom+this.maxHeights.top&&(n=!1)}if(n){var a=e.offsetHeight;this.dom.menu.style.left="0px",this.dom.menu.style.top=a+"px",this.dom.menu.style.bottom=""}else this.dom.menu.style.left="0px",this.dom.menu.style.top="",this.dom.menu.style.bottom="0px";var l=e.parentNode;l.insertBefore(this.dom.root,l.firstChild);var c=this,d=this.dom.list;this.eventListeners.mousedown=o.addEventListener(window,"mousedown",function(e){var t=e.target;t==d||c._isChildOf(t,d)||(c.hide(),e.stopPropagation(),e.preventDefault())}),this.eventListeners.keydown=o.addEventListener(window,"keydown",function(e){c._onKeyDown(e)}),this.selection=o.getSelection(),this.anchor=e,setTimeout(function(){c.dom.focusButton.focus()},0),i.visibleMenu&&i.visibleMenu.hide(),i.visibleMenu=this},i.prototype.hide=function(){this.dom.root.parentNode&&(this.dom.root.parentNode.removeChild(this.dom.root),this.onClose&&this.onClose());for(var e in this.eventListeners)if(this.eventListeners.hasOwnProperty(e)){var t=this.eventListeners[e];t&&o.removeEventListener(window,e,t),delete this.eventListeners[e]}i.visibleMenu==this&&(i.visibleMenu=void 0)},i.prototype._onExpandItem=function(e){var t=this,n=e==this.expandedItem,i=this.expandedItem;if(i&&(i.ul.style.height="0",i.ul.style.padding="",setTimeout(function(){t.expandedItem!=i&&(i.ul.style.display="",o.removeClassName(i.ul.parentNode,"jsoneditor-selected"))},300),this.expandedItem=void 0),!n){var r=e.ul;r.style.display="block";r.clientHeight;setTimeout(function(){t.expandedItem==e&&(r.style.height=24*r.childNodes.length+"px",r.style.padding="5px 10px")},0),o.addClassName(r.parentNode,"jsoneditor-selected"),this.expandedItem=e}},i.prototype._onKeyDown=function(e){var t,n,i,r,s=e.target,a=e.which,l=!1;27==a?(this.selection&&o.setSelection(this.selection),this.anchor&&this.anchor.focus(),this.hide(),l=!0):9==a?e.shiftKey?(t=this._getVisibleButtons(),n=t.indexOf(s),0==n&&(t[t.length-1].focus(),l=!0)):(t=this._getVisibleButtons(),n=t.indexOf(s),n==t.length-1&&(t[0].focus(),l=!0)):37==a?("jsoneditor-expand"==s.className&&(t=this._getVisibleButtons(),n=t.indexOf(s),i=t[n-1],i&&i.focus()),l=!0):38==a?(t=this._getVisibleButtons(),n=t.indexOf(s),i=t[n-1],i&&"jsoneditor-expand"==i.className&&(i=t[n-2]),i||(i=t[t.length-1]),i&&i.focus(),l=!0):39==a?(t=this._getVisibleButtons(),n=t.indexOf(s),r=t[n+1],r&&"jsoneditor-expand"==r.className&&r.focus(),l=!0):40==a&&(t=this._getVisibleButtons(),n=t.indexOf(s),r=t[n+1],r&&"jsoneditor-expand"==r.className&&(r=t[n+2]),r||(r=t[0]),r&&(r.focus(),l=!0),l=!0),l&&(e.stopPropagation(),e.preventDefault())},i.prototype._isChildOf=function(e,t){for(var n=e.parentNode;n;){if(n==t)return!0;n=n.parentNode}return!1},e.exports=i},function(e,t,n){"use strict";function i(e,t){this.editor=e,this.dom={},this.expanded=!1,t&&t instanceof Object?(this.setField(t.field,t.fieldEditable),this.setValue(t.value,t.type)):(this.setField(""),this.setValue(null)),this._debouncedOnChangeValue=a.debounce(this._onChangeValue.bind(this),i.prototype.DEBOUNCE_INTERVAL),this._debouncedOnChangeField=a.debounce(this._onChangeField.bind(this),i.prototype.DEBOUNCE_INTERVAL)}var o=n(9),r=n(7),s=n(10),a=n(4);i.prototype.DEBOUNCE_INTERVAL=150,i.prototype._updateEditability=function(){if(this.editable={field:!0,value:!0},this.editor&&(this.editable.field="tree"===this.editor.options.mode,this.editable.value="view"!==this.editor.options.mode,("tree"===this.editor.options.mode||"form"===this.editor.options.mode)&&"function"==typeof this.editor.options.onEditable)){var e=this.editor.options.onEditable({field:this.field,value:this.value,path:this.getPath()});"boolean"==typeof e?(this.editable.field=e,this.editable.value=e):("boolean"==typeof e.field&&(this.editable.field=e.field),"boolean"==typeof e.value&&(this.editable.value=e.value))}},i.prototype.getPath=function(){for(var e=this,t=[];e;){var n=e.parent?"array"!=e.parent.type?e.field:e.index:void 0;void 0!==n&&t.unshift(n),e=e.parent}return t},i.prototype.findNode=function(e){for(var t=a.parsePath(e),n=this;n&&t.length>0;){var i=t.shift();if("number"==typeof i){if("array"!==n.type)throw new Error("Cannot get child node at index "+i+": node is no array");n=n.childs[i]}else{if("object"!==n.type)throw new Error("Cannot get child node "+i+": node is no object");n=n.childs.filter(function(e){return e.field===i})[0]}}return n},i.prototype.findParents=function(){for(var e=[],t=this.parent;t;)e.unshift(t),t=t.parent;return e},i.prototype.setError=function(e,t){this.getDom(),this.error=e;var n=this.dom.tdError;if(e){n||(n=document.createElement("td"),this.dom.tdError=n,this.dom.tdValue.parentNode.appendChild(n));var i=document.createElement("div");i.className="jsoneditor-popover jsoneditor-right",i.appendChild(document.createTextNode(e.message));var o=document.createElement("button");for(o.type="button",o.className="jsoneditor-schema-error",o.appendChild(i),o.onmouseover=o.onfocus=function(){for(var e=["right","above","below","left"],t=0;ts;s++)n=e[s],void 0===n||n instanceof Function||(o=new i(this.editor,{value:n}),this.appendChild(o));this.value=""}else if("object"==this.type){this.childs=[];for(var l in e)e.hasOwnProperty(l)&&(n=e[l],void 0===n||n instanceof Function||(o=new i(this.editor,{field:l,value:n}),this.appendChild(o)));this.value="",this.editor.options.sortObjectKeys===!0&&this.sort("asc")}else this.childs=void 0,this.value=e;this.previousValue=this.value},i.prototype.getValue=function(){if("array"==this.type){var e=[];return this.childs.forEach(function(t){e.push(t.getValue())}),e}if("object"==this.type){var t={};return this.childs.forEach(function(e){t[e.getField()]=e.getValue()}),t}return void 0===this.value&&this._getDomValue(),this.value},i.prototype.getLevel=function(){return this.parent?this.parent.getLevel()+1:0},i.prototype.getNodePath=function(){var e=this.parent?this.parent.getNodePath():[];return e.push(this),e},i.prototype.clone=function(){var e=new i(this.editor);if(e.type=this.type,e.field=this.field,e.fieldInnerText=this.fieldInnerText,e.fieldEditable=this.fieldEditable,e.value=this.value,e.valueInnerText=this.valueInnerText,e.expanded=this.expanded,this.childs){var t=[];this.childs.forEach(function(n){var i=n.clone();i.setParent(e),t.push(i)}),e.childs=t}else e.childs=void 0;return e},i.prototype.expand=function(e){this.childs&&(this.expanded=!0,this.dom.expand&&(this.dom.expand.className="jsoneditor-expanded"),this.showChilds(),e!==!1&&this.childs.forEach(function(t){t.expand(e)}))},i.prototype.collapse=function(e){this.childs&&(this.hideChilds(),e!==!1&&this.childs.forEach(function(t){t.collapse(e)}),this.dom.expand&&(this.dom.expand.className="jsoneditor-collapsed"),this.expanded=!1)},i.prototype.showChilds=function(){var e=this.childs;if(e&&this.expanded){var t=this.dom.tr,n=t?t.parentNode:void 0;if(n){var i=this.getAppend(),o=t.nextSibling;o?n.insertBefore(i,o):n.appendChild(i),this.childs.forEach(function(e){n.insertBefore(e.getDom(),i),e.showChilds()})}}},i.prototype.hide=function(){var e=this.dom.tr,t=e?e.parentNode:void 0;t&&t.removeChild(e),this.hideChilds()},i.prototype.hideChilds=function(){var e=this.childs;if(e&&this.expanded){var t=this.getAppend();t.parentNode&&t.parentNode.removeChild(t),this.childs.forEach(function(e){e.hide()})}},i.prototype.appendChild=function(e){if(this._hasChilds()){if(e.setParent(this),e.fieldEditable="object"==this.type,"array"==this.type&&(e.index=this.childs.length),this.childs.push(e),this.expanded){var t=e.getDom(),n=this.getAppend(),i=n?n.parentNode:void 0;n&&i&&i.insertBefore(t,n),e.showChilds()}this.updateDom({updateIndexes:!0}),e.updateDom({recurse:!0})}},i.prototype.moveBefore=function(e,t){if(this._hasChilds()){var n=this.dom.tr?this.dom.tr.parentNode:void 0;if(n){var i=document.createElement("tr");i.style.height=n.clientHeight+"px",n.appendChild(i)}e.parent&&e.parent.removeChild(e),t instanceof l?this.appendChild(e):this.insertBefore(e,t),n&&n.removeChild(i)}},i.prototype.moveTo=function(e,t){if(e.parent==this){var n=this.childs.indexOf(e);t>n&&t++}var i=this.childs[t]||this.append;this.moveBefore(e,i)},i.prototype.insertBefore=function(e,t){if(this._hasChilds()){if(t==this.append)e.setParent(this),e.fieldEditable="object"==this.type,this.childs.push(e);else{var n=this.childs.indexOf(t);if(-1==n)throw new Error("Node not found");e.setParent(this),e.fieldEditable="object"==this.type,this.childs.splice(n,0,e)}if(this.expanded){var i=e.getDom(),o=t.getDom(),r=o?o.parentNode:void 0;o&&r&&r.insertBefore(i,o),e.showChilds()}this.updateDom({updateIndexes:!0}),e.updateDom({recurse:!0})}},i.prototype.insertAfter=function(e,t){if(this._hasChilds()){var n=this.childs.indexOf(t),i=this.childs[n+1];i?this.insertBefore(e,i):this.appendChild(e)}},i.prototype.search=function(e){var t,n=[],i=e?e.toLowerCase():void 0;if(delete this.searchField,delete this.searchValue,void 0!=this.field){var o=String(this.field).toLowerCase();t=o.indexOf(i),-1!=t&&(this.searchField=!0,n.push({node:this,elem:"field"})),this._updateDomField()}if(this._hasChilds()){if(this.childs){var r=[];this.childs.forEach(function(t){r=r.concat(t.search(e))}),n=n.concat(r)}if(void 0!=i){var s=!1;0==r.length?this.collapse(s):this.expand(s)}}else{if(void 0!=this.value){var a=String(this.value).toLowerCase();t=a.indexOf(i),-1!=t&&(this.searchValue=!0,n.push({node:this,elem:"value"}))}this._updateDomValue()}return n},i.prototype.scrollTo=function(e){if(!this.dom.tr||!this.dom.tr.parentNode)for(var t=this.parent,n=!1;t;)t.expand(n),t=t.parent;this.dom.tr&&this.dom.tr.parentNode&&this.editor.scrollTo(this.dom.tr.offsetTop,e)},i.focusElement=void 0,i.prototype.focus=function(e){if(i.focusElement=e,this.dom.tr&&this.dom.tr.parentNode){var t=this.dom;switch(e){case"drag":t.drag?t.drag.focus():t.menu.focus();break;case"menu":t.menu.focus();break;case"expand":this._hasChilds()?t.expand.focus():t.field&&this.fieldEditable?(t.field.focus(),a.selectContentEditable(t.field)):t.value&&!this._hasChilds()?(t.value.focus(),a.selectContentEditable(t.value)):t.menu.focus();break;case"field":t.field&&this.fieldEditable?(t.field.focus(),a.selectContentEditable(t.field)):t.value&&!this._hasChilds()?(t.value.focus(),a.selectContentEditable(t.value)):this._hasChilds()?t.expand.focus():t.menu.focus();break;case"value":default:t.value&&!this._hasChilds()?(t.value.focus(),a.selectContentEditable(t.value)):t.field&&this.fieldEditable?(t.field.focus(),a.selectContentEditable(t.field)):this._hasChilds()?t.expand.focus():t.menu.focus()}}},i.select=function(e){setTimeout(function(){a.selectContentEditable(e)},0)},i.prototype.blur=function(){this._getDomValue(!1),this._getDomField(!1)},i.prototype.containsNode=function(e){if(this==e)return!0;var t=this.childs;if(t)for(var n=0,i=t.length;i>n;n++)if(t[n].containsNode(e))return!0;return!1},i.prototype._move=function(e,t){if(e!=t){if(e.containsNode(this))throw new Error("Cannot move a field into a child of itself");e.parent&&e.parent.removeChild(e);var n=e.clone();e.clearDom(),t?this.insertBefore(n,t):this.appendChild(n)}},i.prototype.removeChild=function(e){if(this.childs){var t=this.childs.indexOf(e);if(-1!=t){e.hide(),delete e.searchField,delete e.searchValue;var n=this.childs.splice(t,1)[0];return n.parent=null,this.updateDom({updateIndexes:!0}),n}}},i.prototype._remove=function(e){this.removeChild(e)},i.prototype.changeType=function(e){var t=this.type;if(t!=e){if("string"!=e&&"auto"!=e||"string"!=t&&"auto"!=t){var n,i=this.dom.tr?this.dom.tr.parentNode:void 0;n=this.expanded?this.getAppend():this.getDom();var o=n&&n.parentNode?n.nextSibling:void 0;this.hide(),this.clearDom(),this.type=e,"object"==e?(this.childs||(this.childs=[]),this.childs.forEach(function(e,t){e.clearDom(),delete e.index,e.fieldEditable=!0,void 0==e.field&&(e.field="")}),"string"!=t&&"auto"!=t||(this.expanded=!0)):"array"==e?(this.childs||(this.childs=[]),this.childs.forEach(function(e,t){e.clearDom(),e.fieldEditable=!1,e.index=t}),"string"!=t&&"auto"!=t||(this.expanded=!0)):this.expanded=!1,i&&(o?i.insertBefore(this.getDom(),o):i.appendChild(this.getDom())),this.showChilds()}else this.type=e;"auto"!=e&&"string"!=e||("string"==e?this.value=String(this.value):this.value=this._stringCast(String(this.value)),this.focus()),this.updateDom({updateIndexes:!0})}},i.prototype._getDomValue=function(e){if(this.dom.value&&"array"!=this.type&&"object"!=this.type&&(this.valueInnerText=a.getInnerText(this.dom.value)),void 0!=this.valueInnerText)try{var t;if("string"==this.type)t=this._unescapeHTML(this.valueInnerText);else{var n=this._unescapeHTML(this.valueInnerText);t=this._stringCast(n)}t!==this.value&&(this.value=t,this._debouncedOnChangeValue())}catch(i){if(this.value=void 0,e!==!0)throw i}},i.prototype._onChangeValue=function(){var e=this.editor.getSelection();if(e.range){var t=a.textDiff(String(this.value),String(this.previousValue));e.range.startOffset=t.start,e.range.endOffset=t.end}var n=this.editor.getSelection();if(n.range){var i=a.textDiff(String(this.previousValue),String(this.value));n.range.startOffset=i.start,n.range.endOffset=i.end}this.editor._onAction("editValue",{node:this,oldValue:this.previousValue,newValue:this.value,oldSelection:e,newSelection:n}),this.previousValue=this.value},i.prototype._onChangeField=function(){var e=this.editor.getSelection();if(e.range){var t=a.textDiff(this.field,this.previousField);e.range.startOffset=t.start,e.range.endOffset=t.end}var n=this.editor.getSelection();if(n.range){var i=a.textDiff(this.previousField,this.field);n.range.startOffset=i.start,n.range.endOffset=i.end}this.editor._onAction("editField",{node:this,oldValue:this.previousField,newValue:this.field,oldSelection:e,newSelection:n}),this.previousField=this.field},i.prototype._updateDomValue=function(){var e=this.dom.value;if(e){var t=["jsoneditor-value"],n=this.value,i="auto"==this.type?a.type(n):this.type,o="string"==i&&a.isUrl(n);t.push("jsoneditor-"+i),o&&t.push("jsoneditor-url");var r=""==String(this.value)&&"array"!=this.type&&"object"!=this.type;if(r&&t.push("jsoneditor-empty"),this.searchValueActive&&t.push("jsoneditor-highlight-active"),this.searchValue&&t.push("jsoneditor-highlight"),e.className=t.join(" "),"array"==i||"object"==i){var s=this.childs?this.childs.length:0;e.title=this.type+" containing "+s+" items"}else o&&this.editable.value?e.title="Ctrl+Click or Ctrl+Enter to open url in new window":e.title="";if("boolean"===i&&this.editable.value?(this.dom.checkbox||(this.dom.checkbox=document.createElement("input"),this.dom.checkbox.type="checkbox",this.dom.tdCheckbox=document.createElement("td"),this.dom.tdCheckbox.className="jsoneditor-tree",this.dom.tdCheckbox.appendChild(this.dom.checkbox),this.dom.tdValue.parentNode.insertBefore(this.dom.tdCheckbox,this.dom.tdValue)),this.dom.checkbox.checked=this.value):this.dom.tdCheckbox&&(this.dom.tdCheckbox.parentNode.removeChild(this.dom.tdCheckbox),delete this.dom.tdCheckbox,delete this.dom.checkbox),this["enum"]&&this.editable.value){if(!this.dom.select){this.dom.select=document.createElement("select"),this.id=this.field+"_"+(new Date).getUTCMilliseconds(),this.dom.select.id=this.id,this.dom.select.name=this.dom.select.id,this.dom.select.option=document.createElement("option"),this.dom.select.option.value="",this.dom.select.option.innerHTML="--",this.dom.select.appendChild(this.dom.select.option);for(var l=0;l0&&(e=this.childs.filter(function(e){return-1!==n.indexOf(e.field)}).map(function(e){return{node:e,error:{message:'duplicate key "'+e.field+'"'}}}))}if(this.childs)for(var i=0;i0&&(e=e.concat(r))}return e},i.prototype.clearDom=function(){this.dom={}},i.prototype.getDom=function(){var e=this.dom;if(e.tr)return e.tr;if(this._updateEditability(),e.tr=document.createElement("tr"),e.tr.node=this,"tree"===this.editor.options.mode){var t=document.createElement("td");if(this.editable.field&&this.parent){var n=document.createElement("button");n.type="button",e.drag=n,n.className="jsoneditor-dragarea",n.title="Drag to move this field (Alt+Shift+Arrows)",t.appendChild(n)}e.tr.appendChild(t);var i=document.createElement("td"),o=document.createElement("button");o.type="button",e.menu=o,o.className="jsoneditor-contextmenu",o.title="Click to open the actions menu (Ctrl+M)",i.appendChild(e.menu),e.tr.appendChild(i)}var r=document.createElement("td");return e.tr.appendChild(r),e.tree=this._createDomTree(),r.appendChild(e.tree),this.updateDom({updateIndexes:!0}),e.tr},i.onDragStart=function(e,t){if(!Array.isArray(e))return i.onDragStart([e],t);if(0!==e.length){var n=e[0],o=e[e.length-1],r=i.getNodeFromTarget(t.target),s=o._nextSibling(),l=n.editor,c=a.getAbsoluteTop(r.dom.tr)-a.getAbsoluteTop(n.dom.tr);l.mousemove||(l.mousemove=a.addEventListener(window,"mousemove",function(t){i.onDrag(e,t)})),l.mouseup||(l.mouseup=a.addEventListener(window,"mouseup",function(t){i.onDragEnd(e,t)})),l.highlighter.lock(),l.drag={oldCursor:document.body.style.cursor,oldSelection:l.getSelection(),oldBeforeNode:s,mouseX:t.pageX,offsetY:c,level:n.getLevel()},document.body.style.cursor="move",t.preventDefault()}},i.onDrag=function(e,t){if(!Array.isArray(e))return i.onDrag([e],t);if(0!==e.length){var n,o,r,s,c,d,h,u,p,f,m,g,v,y,b=e[0].editor,w=t.pageY-b.drag.offsetY,x=t.pageX,_=!1,E=e[0];if(n=E.dom.tr,p=a.getAbsoluteTop(n),g=n.offsetHeight,p>w){o=n;do o=o.previousSibling,h=i.getNodeFromTarget(o),f=o?a.getAbsoluteTop(o):0;while(o&&f>w);h&&!h.parent&&(h=void 0),h||(d=n.parentNode.firstChild,o=d?d.nextSibling:void 0,h=i.getNodeFromTarget(o),h==E&&(h=void 0)),h&&(o=h.dom.tr,f=o?a.getAbsoluteTop(o):0,w>f+g&&(h=void 0)),h&&(e.forEach(function(e){h.parent.moveBefore(e,h)}),_=!0)}else{var C=e[e.length-1];if(c=C.expanded&&C.append?C.append.getDom():C.dom.tr,s=c?c.nextSibling:void 0){m=a.getAbsoluteTop(s),r=s;do u=i.getNodeFromTarget(r),r&&(v=r.nextSibling?a.getAbsoluteTop(r.nextSibling):0,y=r?v-m:0,u.parent.childs.length==e.length&&u.parent.childs[e.length-1]==C&&(p+=27)),r=r.nextSibling;while(r&&w>p+y);if(u&&u.parent){var S=x-b.drag.mouseX,j=Math.round(S/24/2),N=b.drag.level+j,k=u.getLevel();for(o=u.dom.tr.previousSibling;N>k&&o;){h=i.getNodeFromTarget(o);var A=e.some(function(e){return e===h||h._isChildOf(e)});if(A);else{if(!(h instanceof l))break;var O=h.parent.childs;if(O.length==e.length&&O[e.length-1]==C)break;u=i.getNodeFromTarget(o),k=u.getLevel()}o=o.previousSibling}c.nextSibling!=u.dom.tr&&(e.forEach(function(e){u.parent.moveBefore(e,u)}),_=!0)}}}_&&(b.drag.mouseX=x,b.drag.level=E.getLevel()),b.startAutoScroll(w),t.preventDefault()}},i.onDragEnd=function(e,t){if(!Array.isArray(e))return i.onDrag([e],t);if(0!==e.length){var n=e[0],o=n.editor,r=n.parent,s=r.childs.indexOf(n),l=r.childs[s+e.length]||r.append;e[0]&&e[0].dom.menu.focus();var c={nodes:e,oldSelection:o.drag.oldSelection,newSelection:o.getSelection(),oldBeforeNode:o.drag.oldBeforeNode,newBeforeNode:l};c.oldBeforeNode!=c.newBeforeNode&&o._onAction("moveNodes",c),document.body.style.cursor=o.drag.oldCursor,o.highlighter.unlock(), +e.forEach(function(e){t.target!==e.dom.drag&&t.target!==e.dom.menu&&o.highlighter.unhighlight()}),delete o.drag,o.mousemove&&(a.removeEventListener(window,"mousemove",o.mousemove),delete o.mousemove),o.mouseup&&(a.removeEventListener(window,"mouseup",o.mouseup),delete o.mouseup),o.stopAutoScroll(),t.preventDefault()}},i.prototype._isChildOf=function(e){for(var t=this.parent;t;){if(t==e)return!0;t=t.parent}return!1},i.prototype._createDomField=function(){return document.createElement("div")},i.prototype.setHighlight=function(e){this.dom.tr&&(e?a.addClassName(this.dom.tr,"jsoneditor-highlight"):a.removeClassName(this.dom.tr,"jsoneditor-highlight"),this.append&&this.append.setHighlight(e),this.childs&&this.childs.forEach(function(t){t.setHighlight(e)}))},i.prototype.setSelected=function(e,t){this.selected=e,this.dom.tr&&(e?a.addClassName(this.dom.tr,"jsoneditor-selected"):a.removeClassName(this.dom.tr,"jsoneditor-selected"),t?a.addClassName(this.dom.tr,"jsoneditor-first"):a.removeClassName(this.dom.tr,"jsoneditor-first"),this.append&&this.append.setSelected(e),this.childs&&this.childs.forEach(function(t){t.setSelected(e)}))},i.prototype.updateValue=function(e){this.value=e,this.updateDom()},i.prototype.updateField=function(e){this.field=e,this.updateDom()},i.prototype.updateDom=function(e){var t=this.dom.tree;t&&(t.style.marginLeft=24*this.getLevel()+"px");var n=this.dom.field;if(n){this.fieldEditable?(n.contentEditable=this.editable.field,n.spellcheck=!1,n.className="jsoneditor-field"):n.className="jsoneditor-readonly";var i;i=void 0!=this.index?this.index:void 0!=this.field?this.field:this._hasChilds()?this.type:"",n.innerHTML=this._escapeHTML(i),this._updateSchema()}var o=this.dom.value;if(o){var r=this.childs?this.childs.length:0;"array"==this.type?(o.innerHTML="["+r+"]",a.addClassName(this.dom.tr,"jsoneditor-expandable")):"object"==this.type?(o.innerHTML="{"+r+"}",a.addClassName(this.dom.tr,"jsoneditor-expandable")):(o.innerHTML=this._escapeHTML(this.value),a.removeClassName(this.dom.tr,"jsoneditor-expandable"))}this._updateDomField(),this._updateDomValue(),e&&e.updateIndexes===!0&&this._updateDomIndexes(),e&&e.recurse===!0&&this.childs&&this.childs.forEach(function(t){t.updateDom(e)}),this.append&&this.append.updateDom()},i.prototype._updateSchema=function(){this.editor&&this.editor.options&&(this.schema=i._findSchema(this.editor.options.schema,this.getPath()),this.schema?this["enum"]=i._findEnum(this.schema):delete this["enum"])},i._findEnum=function(e){if(e["enum"])return e["enum"];var t=e.oneOf||e.anyOf||e.allOf;if(t){var n=t.filter(function(e){return e["enum"]});if(n.length>0)return n[0]["enum"]}return null},i._findSchema=function(e,t){for(var n=e,i=0;i0?this.editor.multiselection.nodes:[this],w=b[0],x=b[b.length-1];if(13==u){if(p==this.dom.value)this.editable.value&&!e.ctrlKey||a.isUrl(this.value)&&(window.open(this.value,"_blank"),v=!0);else if(p==this.dom.expand){var _=this._hasChilds();if(_){var E=e.ctrlKey;this._onExpand(E),p.focus(),v=!0}}}else if(68==u)f&&y&&(i.onDuplicate(b),v=!0);else if(69==u)f&&(this._onExpand(m),p.focus(),v=!0);else if(77==u&&y)f&&(this.showContextMenu(p),v=!0);else if(46==u&&y)f&&(i.onRemove(b),v=!0);else if(45==u&&y)f&&!m?(this._onInsertBefore(),v=!0):f&&m&&(this._onInsertAfter(),v=!0);else if(35==u){if(g){var C=this._lastNode();C&&C.focus(i.focusElement||this._getElementName(p)),v=!0}}else if(36==u){if(g){var S=this._firstNode();S&&S.focus(i.focusElement||this._getElementName(p)),v=!0}}else if(37==u){if(g&&!m){var j=this._previousElement(p);j&&this.focus(this._getElementName(j)),v=!0}else if(g&&m&&y){if(x.expanded){var N=x.getAppend();o=N?N.nextSibling:void 0}else{var k=x.getDom();o=k.nextSibling}o&&(n=i.getNodeFromTarget(o),r=o.nextSibling,T=i.getNodeFromTarget(r),n&&n instanceof l&&1!=x.parent.childs.length&&T&&T.parent&&(s=this.editor.getSelection(),c=x._nextSibling(),b.forEach(function(e){T.parent.moveBefore(e,T)}),this.focus(i.focusElement||this._getElementName(p)),this.editor._onAction("moveNodes",{nodes:b,oldBeforeNode:c,newBeforeNode:T,oldSelection:s,newSelection:this.editor.getSelection()})))}}else if(38==u)g&&!m?(t=this._previousNode(),t&&(this.editor.deselect(!0),t.focus(i.focusElement||this._getElementName(p))),v=!0):!g&&f&&m&&y?(t=this._previousNode(),t&&(h=this.editor.multiselection,h.start=h.start||this,h.end=t,d=this.editor._findTopLevelNodes(h.start,h.end),this.editor.select(d),t.focus("field")),v=!0):g&&m&&y&&(t=w._previousNode(),t&&t.parent&&(s=this.editor.getSelection(),c=x._nextSibling(),b.forEach(function(e){t.parent.moveBefore(e,t)}),this.focus(i.focusElement||this._getElementName(p)),this.editor._onAction("moveNodes",{nodes:b,oldBeforeNode:c,newBeforeNode:t,oldSelection:s,newSelection:this.editor.getSelection()})),v=!0);else if(39==u){if(g&&!m){var A=this._nextElement(p);A&&this.focus(this._getElementName(A)),v=!0}else if(g&&m&&y){k=w.getDom();var O=k.previousSibling;O&&(t=i.getNodeFromTarget(O),t&&t.parent&&t instanceof l&&!t.isVisible()&&(s=this.editor.getSelection(),c=x._nextSibling(),b.forEach(function(e){t.parent.moveBefore(e,t)}),this.focus(i.focusElement||this._getElementName(p)),this.editor._onAction("moveNodes",{nodes:b,oldBeforeNode:c,newBeforeNode:t,oldSelection:s,newSelection:this.editor.getSelection()})))}}else if(40==u)if(g&&!m)n=this._nextNode(),n&&(this.editor.deselect(!0),n.focus(i.focusElement||this._getElementName(p))),v=!0;else if(!g&&f&&m&&y)n=this._nextNode(),n&&(h=this.editor.multiselection,h.start=h.start||this,h.end=n,d=this.editor._findTopLevelNodes(h.start,h.end),this.editor.select(d),n.focus("field")),v=!0;else if(g&&m&&y){n=x.expanded?x.append?x.append._nextNode():void 0:x._nextNode();var T=n&&(n._nextNode()||n.parent.append);T&&T.parent&&(s=this.editor.getSelection(),c=x._nextSibling(),b.forEach(function(e){T.parent.moveBefore(e,T)}),this.focus(i.focusElement||this._getElementName(p)),this.editor._onAction("moveNodes",{nodes:b,oldBeforeNode:c,newBeforeNode:T,oldSelection:s,newSelection:this.editor.getSelection()})),v=!0}v&&(e.preventDefault(),e.stopPropagation())},i.prototype._onExpand=function(e){if(e){var t=this.dom.tr.parentNode,n=t.parentNode,i=n.scrollTop;n.removeChild(t)}this.expanded?this.collapse(e):this.expand(e),e&&(n.appendChild(t),n.scrollTop=i)},i.onRemove=function(e){if(!Array.isArray(e))return i.onRemove([e]);if(e&&e.length>0){var t=e[0],n=t.parent,o=t.editor,r=t.getIndex();o.highlighter.unhighlight();var s=o.getSelection();i.blurNodes(e);var a=o.getSelection();e.forEach(function(e){e.parent._remove(e)}),o._onAction("removeNodes",{nodes:e.slice(0),parent:n,index:r,oldSelection:s,newSelection:a})}},i.onDuplicate=function(e){if(!Array.isArray(e))return i.onDuplicate([e]);if(e&&e.length>0){var t=e[e.length-1],n=t.parent,o=t.editor;o.deselect(o.multiselection.nodes);var r=o.getSelection(),s=t,a=e.map(function(e){var t=e.clone();return n.insertAfter(t,s),s=t,t});1===e.length?a[0].focus():o.select(a);var l=o.getSelection();o._onAction("duplicateNodes",{afterNode:t,nodes:a,parent:n,oldSelection:r,newSelection:l})}},i.prototype._onInsertBefore=function(e,t,n){var o=this.editor.getSelection(),r=new i(this.editor,{field:void 0!=e?e:"",value:void 0!=t?t:"",type:n});r.expand(!0),this.parent.insertBefore(r,this),this.editor.highlighter.unhighlight(),r.focus("field");var s=this.editor.getSelection();this.editor._onAction("insertBeforeNodes",{nodes:[r],beforeNode:this,parent:this.parent,oldSelection:o,newSelection:s})},i.prototype._onInsertAfter=function(e,t,n){var o=this.editor.getSelection(),r=new i(this.editor,{field:void 0!=e?e:"",value:void 0!=t?t:"",type:n});r.expand(!0),this.parent.insertAfter(r,this),this.editor.highlighter.unhighlight(),r.focus("field");var s=this.editor.getSelection();this.editor._onAction("insertAfterNodes",{nodes:[r],afterNode:this,parent:this.parent,oldSelection:o,newSelection:s})},i.prototype._onAppend=function(e,t,n){var o=this.editor.getSelection(),r=new i(this.editor,{field:void 0!=e?e:"",value:void 0!=t?t:"",type:n});r.expand(!0),this.parent.appendChild(r),this.editor.highlighter.unhighlight(),r.focus("field");var s=this.editor.getSelection();this.editor._onAction("appendNodes",{nodes:[r],parent:this.parent,oldSelection:o,newSelection:s})},i.prototype._onChangeType=function(e){var t=this.type;if(e!=t){var n=this.editor.getSelection();this.changeType(e);var i=this.editor.getSelection();this.editor._onAction("changeType",{node:this,oldType:t,newType:e,oldSelection:n,newSelection:i})}},i.prototype.sort=function(e){if(this._hasChilds()){var t="desc"==e?-1:1,n="array"==this.type?"value":"field";this.hideChilds();var i=this.childs,r=this.sortOrder;this.childs=this.childs.concat(),this.childs.sort(function(e,i){return t*o(e[n],i[n])}),this.sortOrder=1==t?"asc":"desc",this.editor._onAction("sort",{node:this,oldChilds:i,oldSort:r,newChilds:this.childs,newSort:this.sortOrder}),this.showChilds()}},i.prototype.getAppend=function(){return this.append||(this.append=new l(this.editor),this.append.setParent(this)),this.append.getDom()},i.getNodeFromTarget=function(e){for(;e;){if(e.node)return e.node;e=e.parentNode}},i.blurNodes=function(e){if(!Array.isArray(e))return void i.blurNodes([e]);var t=e[0],n=t.parent,o=t.getIndex();n.childs[o+e.length]?n.childs[o+e.length].focus():n.childs[o-1]?n.childs[o-1].focus():n.focus()},i.prototype._nextSibling=function(){var e=this.parent.childs.indexOf(this);return this.parent.childs[e+1]||this.parent.append},i.prototype._previousNode=function(){var e=null,t=this.getDom();if(t&&t.parentNode){var n=t;do n=n.previousSibling,e=i.getNodeFromTarget(n);while(n&&e instanceof l&&!e.isVisible())}return e},i.prototype._nextNode=function(){var e=null,t=this.getDom();if(t&&t.parentNode){var n=t;do n=n.nextSibling,e=i.getNodeFromTarget(n);while(n&&e instanceof l&&!e.isVisible())}return e},i.prototype._firstNode=function(){var e=null,t=this.getDom();if(t&&t.parentNode){var n=t.parentNode.firstChild;e=i.getNodeFromTarget(n)}return e},i.prototype._lastNode=function(){var e=null,t=this.getDom();if(t&&t.parentNode){var n=t.parentNode.lastChild;for(e=i.getNodeFromTarget(n);n&&e instanceof l&&!e.isVisible();)n=n.previousSibling,e=i.getNodeFromTarget(n)}return e},i.prototype._previousElement=function(e){var t=this.dom;switch(e){case t.value:if(this.fieldEditable)return t.field;case t.field:if(this._hasChilds())return t.expand;case t.expand:return t.menu;case t.menu:if(t.drag)return t.drag;default:return null}},i.prototype._nextElement=function(e){var t=this.dom;switch(e){case t.drag:return t.menu;case t.menu:if(this._hasChilds())return t.expand;case t.expand:if(this.fieldEditable)return t.field;case t.field:if(!this._hasChilds())return t.value;default:return null}},i.prototype._getElementName=function(e){var t=this.dom;for(var n in t)if(t.hasOwnProperty(n)&&t[n]==e)return n;return null},i.prototype._hasChilds=function(){return"array"==this.type||"object"==this.type},i.TYPE_TITLES={auto:'Field type "auto". The field type is automatically determined from the value and can be a string, number, boolean, or null.',object:'Field type "object". An object contains an unordered set of key/value pairs.',array:'Field type "array". An array contains an ordered collection of values.',string:'Field type "string". Field type is not determined from the value, but always returned as string.'},i.prototype.showContextMenu=function(e,t){var n=this,o=i.TYPE_TITLES,s=[];if(this.editable.value&&s.push({text:"Type",title:"Change the type of this field",className:"jsoneditor-type-"+this.type,submenu:[{text:"Auto",className:"jsoneditor-type-auto"+("auto"==this.type?" jsoneditor-selected":""),title:o.auto,click:function(){n._onChangeType("auto")}},{text:"Array",className:"jsoneditor-type-array"+("array"==this.type?" jsoneditor-selected":""),title:o.array,click:function(){n._onChangeType("array")}},{text:"Object",className:"jsoneditor-type-object"+("object"==this.type?" jsoneditor-selected":""),title:o.object,click:function(){n._onChangeType("object")}},{text:"String",className:"jsoneditor-type-string"+("string"==this.type?" jsoneditor-selected":""),title:o.string,click:function(){n._onChangeType("string")}}]}),this._hasChilds()){var a="asc"==this.sortOrder?"desc":"asc";s.push({text:"Sort",title:"Sort the childs of this "+this.type,className:"jsoneditor-sort-"+a,click:function(){n.sort(a)},submenu:[{text:"Ascending",className:"jsoneditor-sort-asc",title:"Sort the childs of this "+this.type+" in ascending order",click:function(){n.sort("asc")}},{text:"Descending",className:"jsoneditor-sort-desc",title:"Sort the childs of this "+this.type+" in descending order",click:function(){n.sort("desc")}}]})}if(this.parent&&this.parent._hasChilds()){s.length&&s.push({type:"separator"});var l=n.parent.childs;n==l[l.length-1]&&s.push({text:"Append",title:"Append a new field with type 'auto' after this field (Ctrl+Shift+Ins)",submenuTitle:"Select the type of the field to be appended",className:"jsoneditor-append",click:function(){n._onAppend("","","auto")},submenu:[{text:"Auto",className:"jsoneditor-type-auto",title:o.auto,click:function(){n._onAppend("","","auto")}},{text:"Array",className:"jsoneditor-type-array",title:o.array,click:function(){n._onAppend("",[])}},{text:"Object",className:"jsoneditor-type-object",title:o.object,click:function(){n._onAppend("",{})}},{text:"String",className:"jsoneditor-type-string",title:o.string,click:function(){n._onAppend("","","string")}}]}),s.push({text:"Insert",title:"Insert a new field with type 'auto' before this field (Ctrl+Ins)",submenuTitle:"Select the type of the field to be inserted",className:"jsoneditor-insert",click:function(){n._onInsertBefore("","","auto")},submenu:[{text:"Auto",className:"jsoneditor-type-auto",title:o.auto,click:function(){n._onInsertBefore("","","auto")}},{text:"Array",className:"jsoneditor-type-array",title:o.array,click:function(){n._onInsertBefore("",[])}},{text:"Object",className:"jsoneditor-type-object",title:o.object,click:function(){n._onInsertBefore("",{})}},{text:"String",className:"jsoneditor-type-string",title:o.string,click:function(){n._onInsertBefore("","","string")}}]}),this.editable.field&&(s.push({text:"Duplicate",title:"Duplicate this field (Ctrl+D)",className:"jsoneditor-duplicate",click:function(){i.onDuplicate(n)}}),s.push({text:"Remove",title:"Remove this field (Ctrl+Del)",className:"jsoneditor-remove",click:function(){i.onRemove(n)}}))}var c=new r(s,{close:t});c.show(e,this.editor.content)},i.prototype._getType=function(e){return e instanceof Array?"array":e instanceof Object?"object":"string"==typeof e&&"string"!=typeof this._stringCast(e)?"string":"auto"},i.prototype._stringCast=function(e){var t=e.toLowerCase(),n=Number(e),i=parseFloat(e);return""==e?"":"null"==t?null:"true"==t?!0:"false"==t?!1:isNaN(n)||isNaN(i)?e:n},i.prototype._escapeHTML=function(e){if("string"!=typeof e)return String(e);var t=String(e).replace(/&/g,"&").replace(//g,">").replace(/ /g,"  ").replace(/^ /," ").replace(/ $/," "),n=JSON.stringify(t),i=n.substring(1,n.length-1);return this.editor.options.escapeUnicode===!0&&(i=a.escapeUnicodeChars(i)),i},i.prototype._unescapeHTML=function(e){var t='"'+this._escapeJSON(e)+'"',n=a.parse(t);return n.replace(/</g,"<").replace(/>/g,">").replace(/ |\u00A0/g," ").replace(/&/g,"&")},i.prototype._escapeJSON=function(e){for(var t="",n=0;nm)return-1;if(m>g)return 1}for(var v=0,y=Math.max(p.length,f.length);y>v;v++){if(i=!(p[v]||"").match(c)&&parseFloat(p[v])||p[v]||0,o=!(f[v]||"").match(c)&&parseFloat(f[v])||f[v]||0,isNaN(i)!==isNaN(o))return isNaN(i)?1:-1;if(typeof i!=typeof o&&(i+="",o+=""),o>i)return-1;if(i>o)return 1}return 0}},function(e,t,n){"use strict";function i(e){function t(e){this.editor=e,this.dom={}}return t.prototype=new e,t.prototype.getDom=function(){var e=this.dom;if(e.tr)return e.tr;this._updateEditability();var t=document.createElement("tr");if(t.node=this,e.tr=t,"tree"===this.editor.options.mode){e.tdDrag=document.createElement("td");var n=document.createElement("td");e.tdMenu=n;var i=document.createElement("button");i.type="button",i.className="jsoneditor-contextmenu",i.title="Click to open the actions menu (Ctrl+M)",e.menu=i,n.appendChild(e.menu)}var o=document.createElement("td"),r=document.createElement("div");return r.innerHTML="(empty)",r.className="jsoneditor-readonly",o.appendChild(r),e.td=o,e.text=r,this.updateDom(),t},t.prototype.updateDom=function(){var e=this.dom,t=e.td;t&&(t.style.paddingLeft=24*this.getLevel()+26+"px");var n=e.text;n&&(n.innerHTML="(empty "+this.parent.type+")");var i=e.tr;this.isVisible()?e.tr.firstChild||(e.tdDrag&&i.appendChild(e.tdDrag),e.tdMenu&&i.appendChild(e.tdMenu),i.appendChild(t)):e.tr.firstChild&&(e.tdDrag&&i.removeChild(e.tdDrag),e.tdMenu&&i.removeChild(e.tdMenu),i.removeChild(t))},t.prototype.isVisible=function(){return 0==this.parent.childs.length},t.prototype.showContextMenu=function(t,n){var i=this,o=e.TYPE_TITLES,s=[{text:"Append",title:"Append a new field with type 'auto' (Ctrl+Shift+Ins)",submenuTitle:"Select the type of the field to be appended",className:"jsoneditor-insert",click:function(){i._onAppend("","","auto")},submenu:[{text:"Auto",className:"jsoneditor-type-auto",title:o.auto,click:function(){i._onAppend("","","auto")}},{text:"Array",className:"jsoneditor-type-array",title:o.array,click:function(){i._onAppend("",[])}},{text:"Object",className:"jsoneditor-type-object",title:o.object,click:function(){i._onAppend("",{})}},{text:"String",className:"jsoneditor-type-string",title:o.string,click:function(){i._onAppend("","","string")}}]}],a=new r(s,{close:n});a.show(t,this.editor.content)},t.prototype.onEvent=function(e){var t=e.type,n=e.target||e.srcElement,i=this.dom,r=i.menu;if(n==r&&("mouseover"==t?this.editor.highlighter.highlight(this.parent):"mouseout"==t&&this.editor.highlighter.unhighlight()),"click"==t&&n==i.menu){var s=this.editor.highlighter;s.highlight(this.parent),s.lock(),o.addClassName(i.menu,"jsoneditor-selected"),this.showContextMenu(i.menu,function(){o.removeClassName(i.menu,"jsoneditor-selected"),s.unlock(),s.unhighlight()})}"keydown"==t&&this.onKeyDown(e)},t}var o=n(4),r=n(7);e.exports=i},function(e,t,n){"use strict";function i(e,t,n,i){for(var r={code:{text:"Code",title:"Switch to code highlighter",click:function(){i("code")}},form:{text:"Form",title:"Switch to form editor",click:function(){i("form")}},text:{text:"Text",title:"Switch to plain text editor",click:function(){i("text")}},tree:{text:"Tree",title:"Switch to tree editor",click:function(){i("tree")}},view:{text:"View",title:"Switch to tree view",click:function(){i("view")}}},s=[],a=0;a0){var r=n.length>l;if(r){n=n.slice(0,l);var a=this.validateSchema.errors.length-l;n.push("("+a+" more errors...)")}var c=document.createElement("div");c.innerHTML=''+n.map(function(e){var t;return t="string"==typeof e?'":"",''+t+""}).join("")+"
'+e+"
"+e.dataPath+""+e.message+"
",this.dom.validationErrors=c,this.frame.appendChild(c);var d=c.clientHeight;this.content.style.marginBottom=-d+"px",this.content.style.paddingBottom=d+"px"}if(this.aceEditor){var h=!1;this.aceEditor.resize(h)}},e.exports=[{mode:"text",mixin:a,data:"text",load:a.format},{mode:"code",mixin:a,data:"text",load:a.format}]},function(e,t,n){var i=n(!function(){var e=new Error('Cannot find module "brace"');throw e.code="MODULE_NOT_FOUND",e}());n(14),n(16),n(17),e.exports=i},function(e,t,n){ace.define("ace/mode/json_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){"use strict";var i=e("../lib/oop"),o=e("./text_highlight_rules").TextHighlightRules,r=function(){this.$rules={start:[{token:"variable",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]\\s*(?=:)'},{token:"string",regex:'"',next:"string"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:"invalid.illegal", +regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"invalid.illegal",regex:"\\/\\/.*$"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],string:[{token:"constant.language.escape",regex:/\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|["\\\/bfnrt])/},{token:"string",regex:'[^"\\\\]+'},{token:"string",regex:'"',next:"start"},{token:"string",regex:"",next:"start"}]}};i.inherits(r,o),t.JsonHighlightRules=r}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){"use strict";var i=e("../range").Range,o=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),o=n.match(/^(\s*\})/);if(!o)return 0;var r=o[1].length,s=e.findMatchingBracket({row:t,column:r});if(!s||s.row==t)return 0;var a=this.$getIndent(e.getLine(s.row));e.replace(new i(t,0,t,r-1),a)},this.$getIndent=function(e){return e.match(/^\s*/)[0]}}).call(o.prototype),t.MatchingBraceOutdent=o}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){"use strict";var i,o=e("../../lib/oop"),r=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,a=e("../../lib/lang"),l=["text","paren.rparen","punctuation.operator"],c=["text","paren.rparen","punctuation.operator","comment"],d={},h=function(e){var t=-1;return e.multiSelect&&(t=e.selection.index,d.rangeCount!=e.multiSelect.rangeCount&&(d={rangeCount:e.multiSelect.rangeCount})),d[t]?i=d[t]:void(i=d[t]={autoInsertedBrackets:0,autoInsertedRow:-1,autoInsertedLineEnd:"",maybeInsertedBrackets:0,maybeInsertedRow:-1,maybeInsertedLineStart:"",maybeInsertedLineEnd:""})},u=function(e,t,n,i){var o=e.end.row-e.start.row;return{text:n+t+i,selection:[0,e.start.column+1,o,e.end.column+(o?0:1)]}},p=function(){this.add("braces","insertion",function(e,t,n,o,r){var s=n.getCursorPosition(),l=o.doc.getLine(s.row);if("{"==r){h(n);var c=n.getSelectionRange(),d=o.doc.getTextRange(c);if(""!==d&&"{"!==d&&n.getWrapBehavioursEnabled())return u(c,d,"{","}");if(p.isSaneInsertion(n,o))return/[\]\}\)]/.test(l[s.column])||n.inMultiSelectMode?(p.recordAutoInsert(n,o,"}"),{text:"{}",selection:[1,1]}):(p.recordMaybeInsert(n,o,"{"),{text:"{",selection:[1,1]})}else if("}"==r){h(n);var f=l.substring(s.column,s.column+1);if("}"==f){var m=o.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(null!==m&&p.isAutoInsertedClosing(s,l,r))return p.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else{if("\n"==r||"\r\n"==r){h(n);var g="";p.isMaybeInsertedClosing(s,l)&&(g=a.stringRepeat("}",i.maybeInsertedBrackets),p.clearMaybeInsertedClosing());var f=l.substring(s.column,s.column+1);if("}"===f){var v=o.findMatchingBracket({row:s.row,column:s.column+1},"}");if(!v)return null;var y=this.$getIndent(o.getLine(v.row))}else{if(!g)return void p.clearMaybeInsertedClosing();var y=this.$getIndent(l)}var b=y+o.getTabString();return{text:"\n"+b+"\n"+y+g,selection:[1,b.length,1,b.length]}}p.clearMaybeInsertedClosing()}}),this.add("braces","deletion",function(e,t,n,o,r){var s=o.doc.getTextRange(r);if(!r.isMultiLine()&&"{"==s){h(n);var a=o.doc.getLine(r.start.row),l=a.substring(r.end.column,r.end.column+1);if("}"==l)return r.end.column++,r;i.maybeInsertedBrackets--}}),this.add("parens","insertion",function(e,t,n,i,o){if("("==o){h(n);var r=n.getSelectionRange(),s=i.doc.getTextRange(r);if(""!==s&&n.getWrapBehavioursEnabled())return u(r,s,"(",")");if(p.isSaneInsertion(n,i))return p.recordAutoInsert(n,i,")"),{text:"()",selection:[1,1]}}else if(")"==o){h(n);var a=n.getCursorPosition(),l=i.doc.getLine(a.row),c=l.substring(a.column,a.column+1);if(")"==c){var d=i.$findOpeningBracket(")",{column:a.column+1,row:a.row});if(null!==d&&p.isAutoInsertedClosing(a,l,o))return p.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,i,o){var r=i.doc.getTextRange(o);if(!o.isMultiLine()&&"("==r){h(n);var s=i.doc.getLine(o.start.row),a=s.substring(o.start.column+1,o.start.column+2);if(")"==a)return o.end.column++,o}}),this.add("brackets","insertion",function(e,t,n,i,o){if("["==o){h(n);var r=n.getSelectionRange(),s=i.doc.getTextRange(r);if(""!==s&&n.getWrapBehavioursEnabled())return u(r,s,"[","]");if(p.isSaneInsertion(n,i))return p.recordAutoInsert(n,i,"]"),{text:"[]",selection:[1,1]}}else if("]"==o){h(n);var a=n.getCursorPosition(),l=i.doc.getLine(a.row),c=l.substring(a.column,a.column+1);if("]"==c){var d=i.$findOpeningBracket("]",{column:a.column+1,row:a.row});if(null!==d&&p.isAutoInsertedClosing(a,l,o))return p.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,i,o){var r=i.doc.getTextRange(o);if(!o.isMultiLine()&&"["==r){h(n);var s=i.doc.getLine(o.start.row),a=s.substring(o.start.column+1,o.start.column+2);if("]"==a)return o.end.column++,o}}),this.add("string_dquotes","insertion",function(e,t,n,i,o){if('"'==o||"'"==o){h(n);var r=o,s=n.getSelectionRange(),a=i.doc.getTextRange(s);if(""!==a&&"'"!==a&&'"'!=a&&n.getWrapBehavioursEnabled())return u(s,a,r,r);if(!a){var l=n.getCursorPosition(),c=i.doc.getLine(l.row),d=c.substring(l.column-1,l.column),p=c.substring(l.column,l.column+1),f=i.getTokenAt(l.row,l.column),m=i.getTokenAt(l.row,l.column+1);if("\\"==d&&f&&/escape/.test(f.type))return null;var g,v=f&&/string|escape/.test(f.type),y=!m||/string|escape/.test(m.type);if(p==r)g=v!==y;else{if(v&&!y)return null;if(v&&y)return null;var b=i.$mode.tokenRe;b.lastIndex=0;var w=b.test(d);b.lastIndex=0;var x=b.test(d);if(w||x)return null;if(p&&!/[\s;,.})\]\\]/.test(p))return null;g=!0}return{text:g?r+r:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,i,o){var r=i.doc.getTextRange(o);if(!o.isMultiLine()&&('"'==r||"'"==r)){h(n);var s=i.doc.getLine(o.start.row),a=s.substring(o.start.column+1,o.start.column+2);if(a==r)return o.end.column++,o}})};p.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),i=new s(t,n.row,n.column);if(!this.$matchTokenType(i.getCurrentToken()||"text",l)){var o=new s(t,n.row,n.column+1);if(!this.$matchTokenType(o.getCurrentToken()||"text",l))return!1}return i.stepForward(),i.getCurrentTokenRow()!==n.row||this.$matchTokenType(i.getCurrentToken()||"text",c)},p.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},p.recordAutoInsert=function(e,t,n){var o=e.getCursorPosition(),r=t.doc.getLine(o.row);this.isAutoInsertedClosing(o,r,i.autoInsertedLineEnd[0])||(i.autoInsertedBrackets=0),i.autoInsertedRow=o.row,i.autoInsertedLineEnd=n+r.substr(o.column),i.autoInsertedBrackets++},p.recordMaybeInsert=function(e,t,n){var o=e.getCursorPosition(),r=t.doc.getLine(o.row);this.isMaybeInsertedClosing(o,r)||(i.maybeInsertedBrackets=0),i.maybeInsertedRow=o.row,i.maybeInsertedLineStart=r.substr(0,o.column)+n,i.maybeInsertedLineEnd=r.substr(o.column),i.maybeInsertedBrackets++},p.isAutoInsertedClosing=function(e,t,n){return i.autoInsertedBrackets>0&&e.row===i.autoInsertedRow&&n===i.autoInsertedLineEnd[0]&&t.substr(e.column)===i.autoInsertedLineEnd},p.isMaybeInsertedClosing=function(e,t){return i.maybeInsertedBrackets>0&&e.row===i.maybeInsertedRow&&t.substr(e.column)===i.maybeInsertedLineEnd&&t.substr(0,e.column)==i.maybeInsertedLineStart},p.popAutoInsertedClosing=function(){i.autoInsertedLineEnd=i.autoInsertedLineEnd.substr(1),i.autoInsertedBrackets--},p.clearMaybeInsertedClosing=function(){i&&(i.maybeInsertedBrackets=0,i.maybeInsertedRow=-1)},o.inherits(p,r),t.CstyleBehaviour=p}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){"use strict";var i=e("../../lib/oop"),o=e("../../range").Range,r=e("./fold_mode").FoldMode,s=t.FoldMode=function(e){e&&(this.foldingStartMarker=new RegExp(this.foldingStartMarker.source.replace(/\|[^|]*?$/,"|"+e.start)),this.foldingStopMarker=new RegExp(this.foldingStopMarker.source.replace(/\|[^|]*?$/,"|"+e.end)))};i.inherits(s,r),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.singleLineBlockCommentRe=/^\s*(\/\*).*\*\/\s*$/,this.tripleStarBlockCommentRe=/^\s*(\/\*\*\*).*\*\/\s*$/,this.startRegionRe=/^\s*(\/\*|\/\/)#?region\b/,this._getFoldWidgetBase=this.getFoldWidget,this.getFoldWidget=function(e,t,n){var i=e.getLine(n);if(this.singleLineBlockCommentRe.test(i)&&!this.startRegionRe.test(i)&&!this.tripleStarBlockCommentRe.test(i))return"";var o=this._getFoldWidgetBase(e,t,n);return!o&&this.startRegionRe.test(i)?"start":o},this.getFoldWidgetRange=function(e,t,n,i){var o=e.getLine(n);if(this.startRegionRe.test(o))return this.getCommentRegionBlock(e,o,n);var r=o.match(this.foldingStartMarker);if(r){var s=r.index;if(r[1])return this.openingBracketBlock(e,r[1],n,s);var a=e.getCommentFoldRange(n,s+r[0].length,1);return a&&!a.isMultiLine()&&(i?a=this.getSectionRange(e,n):"all"!=t&&(a=null)),a}if("markbegin"!==t){var r=o.match(this.foldingStopMarker);if(r){var s=r.index+r[0].length;return r[1]?this.closingBracketBlock(e,r[1],n,s):e.getCommentFoldRange(n,s,-1)}}},this.getSectionRange=function(e,t){var n=e.getLine(t),i=n.search(/\S/),r=t,s=n.length;t+=1;for(var a=t,l=e.getLength();++tc)break;var d=this.getFoldWidgetRange(e,"all",t);if(d){if(d.start.row<=r)break;if(d.isMultiLine())t=d.end.row;else if(i==c)break}a=t}}return new o(r,s,a,e.getLine(a).length)},this.getCommentRegionBlock=function(e,t,n){for(var i=t.search(/\s*$/),r=e.getLength(),s=n,a=/^\s*(?:\/\*|\/\/|--)#?(end)?region\b/,l=1;++ns?new o(s,i,d,t.length):void 0}}.call(s.prototype)}),ace.define("ace/mode/json",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/json_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle","ace/worker/worker_client"],function(e,t,i){"use strict";var o=e("../lib/oop"),r=e("./text").Mode,s=e("./json_highlight_rules").JsonHighlightRules,a=e("./matching_brace_outdent").MatchingBraceOutdent,l=e("./behaviour/cstyle").CstyleBehaviour,c=e("./folding/cstyle").FoldMode,d=e("../worker/worker_client").WorkerClient,h=function(){this.HighlightRules=s,this.$outdent=new a,this.$behaviour=new l,this.foldingRules=new c};o.inherits(h,r),function(){this.getNextLineIndent=function(e,t,n){var i=this.$getIndent(t);if("start"==e){var o=t.match(/^.*[\{\(\[]\s*$/);o&&(i+=n)}return i},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){var t=new d(["ace"],n(15),"JsonWorker");return t.attachToDocument(e.getDocument()),t.on("annotate",function(t){e.setAnnotations(t.data)}),t.on("terminate",function(){e.clearAnnotations()}),t},this.$id="ace/mode/json"}.call(h.prototype),t.Mode=h})},function(e,t){e.exports.id="ace/mode/json_worker",e.exports.src='"no use strict";(function(window){function resolveModuleId(id,paths){for(var testPath=id,tail="";testPath;){var alias=paths[testPath];if("string"==typeof alias)return alias+tail;if(alias)return alias.location.replace(/\\/*$/,"/")+(tail||alias.main||alias.name);if(alias===!1)return"";var i=testPath.lastIndexOf("/");if(-1===i)break;tail=testPath.substr(i)+tail,testPath=testPath.slice(0,i)}return id}if(!(void 0!==window.window&&window.document||window.acequire&&window.define)){window.console||(window.console=function(){var msgs=Array.prototype.slice.call(arguments,0);postMessage({type:"log",data:msgs})},window.console.error=window.console.warn=window.console.log=window.console.trace=window.console),window.window=window,window.ace=window,window.onerror=function(message,file,line,col,err){postMessage({type:"error",data:{message:message,data:err.data,file:file,line:line,col:col,stack:err.stack}})},window.normalizeModule=function(parentId,moduleName){if(-1!==moduleName.indexOf("!")){var chunks=moduleName.split("!");return window.normalizeModule(parentId,chunks[0])+"!"+window.normalizeModule(parentId,chunks[1])}if("."==moduleName.charAt(0)){var base=parentId.split("/").slice(0,-1).join("/");for(moduleName=(base?base+"/":"")+moduleName;-1!==moduleName.indexOf(".")&&previous!=moduleName;){var previous=moduleName;moduleName=moduleName.replace(/^\\.\\//,"").replace(/\\/\\.\\//,"/").replace(/[^\\/]+\\/\\.\\.\\//,"")}}return moduleName},window.acequire=function acequire(parentId,id){if(id||(id=parentId,parentId=null),!id.charAt)throw Error("worker.js acequire() accepts only (parentId, id) as arguments");id=window.normalizeModule(parentId,id);var module=window.acequire.modules[id];if(module)return module.initialized||(module.initialized=!0,module.exports=module.factory().exports),module.exports;if(!window.acequire.tlns)return console.log("unable to load "+id);var path=resolveModuleId(id,window.acequire.tlns);return".js"!=path.slice(-3)&&(path+=".js"),window.acequire.id=id,window.acequire.modules[id]={},importScripts(path),window.acequire(parentId,id)},window.acequire.modules={},window.acequire.tlns={},window.define=function(id,deps,factory){if(2==arguments.length?(factory=deps,"string"!=typeof id&&(deps=id,id=window.acequire.id)):1==arguments.length&&(factory=id,deps=[],id=window.acequire.id),"function"!=typeof factory)return window.acequire.modules[id]={exports:factory,initialized:!0},void 0;deps.length||(deps=["require","exports","module"]);var req=function(childId){return window.acequire(id,childId)};window.acequire.modules[id]={exports:{},factory:function(){var module=this,returnExports=factory.apply(this,deps.map(function(dep){switch(dep){case"require":return req;case"exports":return module.exports;case"module":return module;default:return req(dep)}}));return returnExports&&(module.exports=returnExports),module}}},window.define.amd={},acequire.tlns={},window.initBaseUrls=function(topLevelNamespaces){for(var i in topLevelNamespaces)acequire.tlns[i]=topLevelNamespaces[i]},window.initSender=function(){var EventEmitter=window.acequire("ace/lib/event_emitter").EventEmitter,oop=window.acequire("ace/lib/oop"),Sender=function(){};return function(){oop.implement(this,EventEmitter),this.callback=function(data,callbackId){postMessage({type:"call",id:callbackId,data:data})},this.emit=function(name,data){postMessage({type:"event",name:name,data:data})}}.call(Sender.prototype),new Sender};var main=window.main=null,sender=window.sender=null;window.onmessage=function(e){var msg=e.data;if(msg.event&&sender)sender._signal(msg.event,msg.data);else if(msg.command)if(main[msg.command])main[msg.command].apply(main,msg.args);else{if(!window[msg.command])throw Error("Unknown command:"+msg.command);window[msg.command].apply(window,msg.args)}else if(msg.init){window.initBaseUrls(msg.tlns),acequire("ace/lib/es5-shim"),sender=window.sender=window.initSender();var clazz=acequire(msg.module)[msg.classname];main=window.main=new clazz(sender)}}}})(this),ace.define("ace/lib/oop",["require","exports","module"],function(acequire,exports){"use strict";exports.inherits=function(ctor,superCtor){ctor.super_=superCtor,ctor.prototype=Object.create(superCtor.prototype,{constructor:{value:ctor,enumerable:!1,writable:!0,configurable:!0}})},exports.mixin=function(obj,mixin){for(var key in mixin)obj[key]=mixin[key];return obj},exports.implement=function(proto,mixin){exports.mixin(proto,mixin)}}),ace.define("ace/range",["require","exports","module"],function(acequire,exports){"use strict";var comparePoints=function(p1,p2){return p1.row-p2.row||p1.column-p2.column},Range=function(startRow,startColumn,endRow,endColumn){this.start={row:startRow,column:startColumn},this.end={row:endRow,column:endColumn}};(function(){this.isEqual=function(range){return this.start.row===range.start.row&&this.end.row===range.end.row&&this.start.column===range.start.column&&this.end.column===range.end.column},this.toString=function(){return"Range: ["+this.start.row+"/"+this.start.column+"] -> ["+this.end.row+"/"+this.end.column+"]"},this.contains=function(row,column){return 0==this.compare(row,column)},this.compareRange=function(range){var cmp,end=range.end,start=range.start;return cmp=this.compare(end.row,end.column),1==cmp?(cmp=this.compare(start.row,start.column),1==cmp?2:0==cmp?1:0):-1==cmp?-2:(cmp=this.compare(start.row,start.column),-1==cmp?-1:1==cmp?42:0)},this.comparePoint=function(p){return this.compare(p.row,p.column)},this.containsRange=function(range){return 0==this.comparePoint(range.start)&&0==this.comparePoint(range.end)},this.intersects=function(range){var cmp=this.compareRange(range);return-1==cmp||0==cmp||1==cmp},this.isEnd=function(row,column){return this.end.row==row&&this.end.column==column},this.isStart=function(row,column){return this.start.row==row&&this.start.column==column},this.setStart=function(row,column){"object"==typeof row?(this.start.column=row.column,this.start.row=row.row):(this.start.row=row,this.start.column=column)},this.setEnd=function(row,column){"object"==typeof row?(this.end.column=row.column,this.end.row=row.row):(this.end.row=row,this.end.column=column)},this.inside=function(row,column){return 0==this.compare(row,column)?this.isEnd(row,column)||this.isStart(row,column)?!1:!0:!1},this.insideStart=function(row,column){return 0==this.compare(row,column)?this.isEnd(row,column)?!1:!0:!1},this.insideEnd=function(row,column){return 0==this.compare(row,column)?this.isStart(row,column)?!1:!0:!1},this.compare=function(row,column){return this.isMultiLine()||row!==this.start.row?this.start.row>row?-1:row>this.end.row?1:this.start.row===row?column>=this.start.column?0:-1:this.end.row===row?this.end.column>=column?0:1:0:this.start.column>column?-1:column>this.end.column?1:0},this.compareStart=function(row,column){return this.start.row==row&&this.start.column==column?-1:this.compare(row,column)},this.compareEnd=function(row,column){return this.end.row==row&&this.end.column==column?1:this.compare(row,column)},this.compareInside=function(row,column){return this.end.row==row&&this.end.column==column?1:this.start.row==row&&this.start.column==column?-1:this.compare(row,column)},this.clipRows=function(firstRow,lastRow){if(this.end.row>lastRow)var end={row:lastRow+1,column:0};else if(firstRow>this.end.row)var end={row:firstRow,column:0};if(this.start.row>lastRow)var start={row:lastRow+1,column:0};else if(firstRow>this.start.row)var start={row:firstRow,column:0};return Range.fromPoints(start||this.start,end||this.end)},this.extend=function(row,column){var cmp=this.compare(row,column);if(0==cmp)return this;if(-1==cmp)var start={row:row,column:column};else var end={row:row,column:column};return Range.fromPoints(start||this.start,end||this.end)},this.isEmpty=function(){return this.start.row===this.end.row&&this.start.column===this.end.column},this.isMultiLine=function(){return this.start.row!==this.end.row},this.clone=function(){return Range.fromPoints(this.start,this.end)},this.collapseRows=function(){return 0==this.end.column?new Range(this.start.row,0,Math.max(this.start.row,this.end.row-1),0):new Range(this.start.row,0,this.end.row,0)},this.toScreenRange=function(session){var screenPosStart=session.documentToScreenPosition(this.start),screenPosEnd=session.documentToScreenPosition(this.end);return new Range(screenPosStart.row,screenPosStart.column,screenPosEnd.row,screenPosEnd.column)},this.moveBy=function(row,column){this.start.row+=row,this.start.column+=column,this.end.row+=row,this.end.column+=column}}).call(Range.prototype),Range.fromPoints=function(start,end){return new Range(start.row,start.column,end.row,end.column)},Range.comparePoints=comparePoints,Range.comparePoints=function(p1,p2){return p1.row-p2.row||p1.column-p2.column},exports.Range=Range}),ace.define("ace/apply_delta",["require","exports","module"],function(acequire,exports){"use strict";exports.applyDelta=function(docLines,delta){var row=delta.start.row,startColumn=delta.start.column,line=docLines[row]||"";switch(delta.action){case"insert":var lines=delta.lines;if(1===lines.length)docLines[row]=line.substring(0,startColumn)+delta.lines[0]+line.substring(startColumn);else{var args=[row,1].concat(delta.lines);docLines.splice.apply(docLines,args),docLines[row]=line.substring(0,startColumn)+docLines[row],docLines[row+delta.lines.length-1]+=line.substring(startColumn)}break;case"remove":var endColumn=delta.end.column,endRow=delta.end.row;row===endRow?docLines[row]=line.substring(0,startColumn)+line.substring(endColumn):docLines.splice(row,endRow-row+1,line.substring(0,startColumn)+docLines[endRow].substring(endColumn))}}}),ace.define("ace/lib/event_emitter",["require","exports","module"],function(acequire,exports){"use strict";var EventEmitter={},stopPropagation=function(){this.propagationStopped=!0},preventDefault=function(){this.defaultPrevented=!0};EventEmitter._emit=EventEmitter._dispatchEvent=function(eventName,e){this._eventRegistry||(this._eventRegistry={}),this._defaultHandlers||(this._defaultHandlers={});var listeners=this._eventRegistry[eventName]||[],defaultHandler=this._defaultHandlers[eventName];if(listeners.length||defaultHandler){"object"==typeof e&&e||(e={}),e.type||(e.type=eventName),e.stopPropagation||(e.stopPropagation=stopPropagation),e.preventDefault||(e.preventDefault=preventDefault),listeners=listeners.slice();for(var i=0;listeners.length>i&&(listeners[i](e,this),!e.propagationStopped);i++);return defaultHandler&&!e.defaultPrevented?defaultHandler(e,this):void 0}},EventEmitter._signal=function(eventName,e){var listeners=(this._eventRegistry||{})[eventName];if(listeners){listeners=listeners.slice();for(var i=0;listeners.length>i;i++)listeners[i](e,this)}},EventEmitter.once=function(eventName,callback){var _self=this;callback&&this.addEventListener(eventName,function newCallback(){_self.removeEventListener(eventName,newCallback),callback.apply(null,arguments)})},EventEmitter.setDefaultHandler=function(eventName,callback){var handlers=this._defaultHandlers;if(handlers||(handlers=this._defaultHandlers={_disabled_:{}}),handlers[eventName]){var old=handlers[eventName],disabled=handlers._disabled_[eventName];disabled||(handlers._disabled_[eventName]=disabled=[]),disabled.push(old);var i=disabled.indexOf(callback);-1!=i&&disabled.splice(i,1)}handlers[eventName]=callback},EventEmitter.removeDefaultHandler=function(eventName,callback){var handlers=this._defaultHandlers;if(handlers){var disabled=handlers._disabled_[eventName];if(handlers[eventName]==callback)handlers[eventName],disabled&&this.setDefaultHandler(eventName,disabled.pop());else if(disabled){var i=disabled.indexOf(callback);-1!=i&&disabled.splice(i,1)}}},EventEmitter.on=EventEmitter.addEventListener=function(eventName,callback,capturing){this._eventRegistry=this._eventRegistry||{};var listeners=this._eventRegistry[eventName];return listeners||(listeners=this._eventRegistry[eventName]=[]),-1==listeners.indexOf(callback)&&listeners[capturing?"unshift":"push"](callback),callback},EventEmitter.off=EventEmitter.removeListener=EventEmitter.removeEventListener=function(eventName,callback){this._eventRegistry=this._eventRegistry||{};var listeners=this._eventRegistry[eventName];if(listeners){var index=listeners.indexOf(callback);-1!==index&&listeners.splice(index,1)}},EventEmitter.removeAllListeners=function(eventName){this._eventRegistry&&(this._eventRegistry[eventName]=[])},exports.EventEmitter=EventEmitter}),ace.define("ace/anchor",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"],function(acequire,exports){"use strict";var oop=acequire("./lib/oop"),EventEmitter=acequire("./lib/event_emitter").EventEmitter,Anchor=exports.Anchor=function(doc,row,column){this.$onChange=this.onChange.bind(this),this.attach(doc),column===void 0?this.setPosition(row.row,row.column):this.setPosition(row,column)};(function(){function $pointsInOrder(point1,point2,equalPointsInOrder){var bColIsAfter=equalPointsInOrder?point1.column<=point2.column:point1.columnthis.row)){var point=$getTransformedPoint(delta,{row:this.row,column:this.column},this.$insertRight);this.setPosition(point.row,point.column,!0)}},this.setPosition=function(row,column,noClip){var pos;if(pos=noClip?{row:row,column:column}:this.$clipPositionToDocument(row,column),this.row!=pos.row||this.column!=pos.column){var old={row:this.row,column:this.column};this.row=pos.row,this.column=pos.column,this._signal("change",{old:old,value:pos})}},this.detach=function(){this.document.removeEventListener("change",this.$onChange)},this.attach=function(doc){this.document=doc||this.document,this.document.on("change",this.$onChange)},this.$clipPositionToDocument=function(row,column){var pos={};return row>=this.document.getLength()?(pos.row=Math.max(0,this.document.getLength()-1),pos.column=this.document.getLine(pos.row).length):0>row?(pos.row=0,pos.column=0):(pos.row=row,pos.column=Math.min(this.document.getLine(pos.row).length,Math.max(0,column))),0>column&&(pos.column=0),pos}}).call(Anchor.prototype)}),ace.define("ace/document",["require","exports","module","ace/lib/oop","ace/apply_delta","ace/lib/event_emitter","ace/range","ace/anchor"],function(acequire,exports){"use strict";var oop=acequire("./lib/oop"),applyDelta=acequire("./apply_delta").applyDelta,EventEmitter=acequire("./lib/event_emitter").EventEmitter,Range=acequire("./range").Range,Anchor=acequire("./anchor").Anchor,Document=function(textOrLines){this.$lines=[""],0===textOrLines.length?this.$lines=[""]:Array.isArray(textOrLines)?this.insertMergedLines({row:0,column:0},textOrLines):this.insert({row:0,column:0},textOrLines)};(function(){oop.implement(this,EventEmitter),this.setValue=function(text){var len=this.getLength()-1;this.remove(new Range(0,0,len,this.getLine(len).length)),this.insert({row:0,column:0},text)},this.getValue=function(){return this.getAllLines().join(this.getNewLineCharacter())},this.createAnchor=function(row,column){return new Anchor(this,row,column)},this.$split=0==="aaa".split(/a/).length?function(text){return text.replace(/\\r\\n|\\r/g,"\\n").split("\\n")}:function(text){return text.split(/\\r\\n|\\r|\\n/)},this.$detectNewLine=function(text){var match=text.match(/^.*?(\\r\\n|\\r|\\n)/m);this.$autoNewLine=match?match[1]:"\\n",this._signal("changeNewLineMode")},this.getNewLineCharacter=function(){switch(this.$newLineMode){case"windows":return"\\r\\n";case"unix":return"\\n";default:return this.$autoNewLine||"\\n"}},this.$autoNewLine="",this.$newLineMode="auto",this.setNewLineMode=function(newLineMode){this.$newLineMode!==newLineMode&&(this.$newLineMode=newLineMode,this._signal("changeNewLineMode"))},this.getNewLineMode=function(){return this.$newLineMode},this.isNewLine=function(text){return"\\r\\n"==text||"\\r"==text||"\\n"==text},this.getLine=function(row){return this.$lines[row]||""},this.getLines=function(firstRow,lastRow){return this.$lines.slice(firstRow,lastRow+1)},this.getAllLines=function(){return this.getLines(0,this.getLength())},this.getLength=function(){return this.$lines.length},this.getTextRange=function(range){return this.getLinesForRange(range).join(this.getNewLineCharacter())},this.getLinesForRange=function(range){var lines;if(range.start.row===range.end.row)lines=[this.getLine(range.start.row).substring(range.start.column,range.end.column)];else{lines=this.getLines(range.start.row,range.end.row),lines[0]=(lines[0]||"").substring(range.start.column);var l=lines.length-1;range.end.row-range.start.row==l&&(lines[l]=lines[l].substring(0,range.end.column))}return lines},this.insertLines=function(row,lines){return console.warn("Use of document.insertLines is deprecated. Use the insertFullLines method instead."),this.insertFullLines(row,lines)},this.removeLines=function(firstRow,lastRow){return console.warn("Use of document.removeLines is deprecated. Use the removeFullLines method instead."),this.removeFullLines(firstRow,lastRow)},this.insertNewLine=function(position){return console.warn("Use of document.insertNewLine is deprecated. Use insertMergedLines(position, [\'\', \'\']) instead."),this.insertMergedLines(position,["",""])},this.insert=function(position,text){return 1>=this.getLength()&&this.$detectNewLine(text),this.insertMergedLines(position,this.$split(text))},this.insertInLine=function(position,text){var start=this.clippedPos(position.row,position.column),end=this.pos(position.row,position.column+text.length);return this.applyDelta({start:start,end:end,action:"insert",lines:[text]},!0),this.clonePos(end)},this.clippedPos=function(row,column){var length=this.getLength();void 0===row?row=length:0>row?row=0:row>=length&&(row=length-1,column=void 0);var line=this.getLine(row);return void 0==column&&(column=line.length),column=Math.min(Math.max(column,0),line.length),{row:row,column:column}},this.clonePos=function(pos){return{row:pos.row,column:pos.column}},this.pos=function(row,column){return{row:row,column:column}},this.$clipPosition=function(position){var length=this.getLength();return position.row>=length?(position.row=Math.max(0,length-1),position.column=this.getLine(length-1).length):(position.row=Math.max(0,position.row),position.column=Math.min(Math.max(position.column,0),this.getLine(position.row).length)),position},this.insertFullLines=function(row,lines){row=Math.min(Math.max(row,0),this.getLength());var column=0;this.getLength()>row?(lines=lines.concat([""]),column=0):(lines=[""].concat(lines),row--,column=this.$lines[row].length),this.insertMergedLines({row:row,column:column},lines)},this.insertMergedLines=function(position,lines){var start=this.clippedPos(position.row,position.column),end={row:start.row+lines.length-1,column:(1==lines.length?start.column:0)+lines[lines.length-1].length};return this.applyDelta({start:start,end:end,action:"insert",lines:lines}),this.clonePos(end)},this.remove=function(range){var start=this.clippedPos(range.start.row,range.start.column),end=this.clippedPos(range.end.row,range.end.column);return this.applyDelta({start:start,end:end,action:"remove",lines:this.getLinesForRange({start:start,end:end})}),this.clonePos(start)},this.removeInLine=function(row,startColumn,endColumn){var start=this.clippedPos(row,startColumn),end=this.clippedPos(row,endColumn);return this.applyDelta({start:start,end:end,action:"remove",lines:this.getLinesForRange({start:start,end:end})},!0),this.clonePos(start)},this.removeFullLines=function(firstRow,lastRow){firstRow=Math.min(Math.max(0,firstRow),this.getLength()-1),lastRow=Math.min(Math.max(0,lastRow),this.getLength()-1);var deleteFirstNewLine=lastRow==this.getLength()-1&&firstRow>0,deleteLastNewLine=this.getLength()-1>lastRow,startRow=deleteFirstNewLine?firstRow-1:firstRow,startCol=deleteFirstNewLine?this.getLine(startRow).length:0,endRow=deleteLastNewLine?lastRow+1:lastRow,endCol=deleteLastNewLine?0:this.getLine(endRow).length,range=new Range(startRow,startCol,endRow,endCol),deletedLines=this.$lines.slice(firstRow,lastRow+1);return this.applyDelta({start:range.start,end:range.end,action:"remove",lines:this.getLinesForRange(range)}),deletedLines},this.removeNewLine=function(row){this.getLength()-1>row&&row>=0&&this.applyDelta({start:this.pos(row,this.getLine(row).length),end:this.pos(row+1,0),action:"remove",lines:["",""]})},this.replace=function(range,text){if(range instanceof Range||(range=Range.fromPoints(range.start,range.end)),0===text.length&&range.isEmpty())return range.start;if(text==this.getTextRange(range))return range.end;this.remove(range);var end;return end=text?this.insert(range.start,text):range.start},this.applyDeltas=function(deltas){for(var i=0;deltas.length>i;i++)this.applyDelta(deltas[i])},this.revertDeltas=function(deltas){for(var i=deltas.length-1;i>=0;i--)this.revertDelta(deltas[i])},this.applyDelta=function(delta,doNotValidate){var isInsert="insert"==delta.action;(isInsert?1>=delta.lines.length&&!delta.lines[0]:!Range.comparePoints(delta.start,delta.end))||(isInsert&&delta.lines.length>2e4&&this.$splitAndapplyLargeDelta(delta,2e4),applyDelta(this.$lines,delta,doNotValidate),this._signal("change",delta))},this.$splitAndapplyLargeDelta=function(delta,MAX){for(var lines=delta.lines,l=lines.length,row=delta.start.row,column=delta.start.column,from=0,to=0;;){from=to,to+=MAX-1;var chunk=lines.slice(from,to);if(to>l){delta.lines=chunk,delta.start.row=row+from,delta.start.column=column;break}chunk.push(""),this.applyDelta({start:this.pos(row+from,column),end:this.pos(row+to,column=0),action:delta.action,lines:chunk},!0)}},this.revertDelta=function(delta){this.applyDelta({start:this.clonePos(delta.start),end:this.clonePos(delta.end),action:"insert"==delta.action?"remove":"insert",lines:delta.lines.slice()})},this.indexToPosition=function(index,startRow){for(var lines=this.$lines||this.getAllLines(),newlineLength=this.getNewLineCharacter().length,i=startRow||0,l=lines.length;l>i;i++)if(index-=lines[i].length+newlineLength,0>index)return{row:i,column:index+lines[i].length+newlineLength};return{row:l-1,column:lines[l-1].length}},this.positionToIndex=function(pos,startRow){for(var lines=this.$lines||this.getAllLines(),newlineLength=this.getNewLineCharacter().length,index=0,row=Math.min(pos.row,lines.length),i=startRow||0;row>i;++i)index+=lines[i].length+newlineLength;return index+pos.column}}).call(Document.prototype),exports.Document=Document}),ace.define("ace/lib/lang",["require","exports","module"],function(acequire,exports){"use strict";exports.last=function(a){return a[a.length-1]},exports.stringReverse=function(string){return string.split("").reverse().join("")},exports.stringRepeat=function(string,count){for(var result="";count>0;)1&count&&(result+=string),(count>>=1)&&(string+=string);return result};var trimBeginRegexp=/^\\s\\s*/,trimEndRegexp=/\\s\\s*$/;exports.stringTrimLeft=function(string){return string.replace(trimBeginRegexp,"")},exports.stringTrimRight=function(string){return string.replace(trimEndRegexp,"")},exports.copyObject=function(obj){var copy={};for(var key in obj)copy[key]=obj[key];return copy},exports.copyArray=function(array){for(var copy=[],i=0,l=array.length;l>i;i++)copy[i]=array[i]&&"object"==typeof array[i]?this.copyObject(array[i]):array[i];return copy},exports.deepCopy=function deepCopy(obj){if("object"!=typeof obj||!obj)return obj;var copy;if(Array.isArray(obj)){copy=[];for(var key=0;obj.length>key;key++)copy[key]=deepCopy(obj[key]);return copy}var cons=obj.constructor;if(cons===RegExp)return obj;copy=cons();for(var key in obj)copy[key]=deepCopy(obj[key]);return copy},exports.arrayToMap=function(arr){for(var map={},i=0;arr.length>i;i++)map[arr[i]]=1;return map},exports.createMap=function(props){var map=Object.create(null);for(var i in props)map[i]=props[i];return map},exports.arrayRemove=function(array,value){for(var i=0;array.length>=i;i++)value===array[i]&&array.splice(i,1)},exports.escapeRegExp=function(str){return str.replace(/([.*+?^${}()|[\\]\\/\\\\])/g,"\\\\$1")},exports.escapeHTML=function(str){return str.replace(/&/g,"&").replace(/"/g,""").replace(/\'/g,"'").replace(/i;i+=2){if(Array.isArray(data[i+1]))var d={action:"insert",start:data[i],lines:data[i+1]};else var d={action:"remove",start:data[i],end:data[i+1]};doc.applyDelta(d,!0)}return _self.$timeout?deferredUpdate.schedule(_self.$timeout):(_self.onUpdate(),void 0)})};(function(){this.$timeout=500,this.setTimeout=function(timeout){this.$timeout=timeout},this.setValue=function(value){this.doc.setValue(value),this.deferredUpdate.schedule(this.$timeout)},this.getValue=function(callbackId){this.sender.callback(this.doc.getValue(),callbackId)},this.onUpdate=function(){},this.isPending=function(){return this.deferredUpdate.isPending()}}).call(Mirror.prototype)}),ace.define("ace/mode/json/json_parse",["require","exports","module"],function(){"use strict";var at,ch,text,value,escapee={\'"\':\'"\',"\\\\":"\\\\","/":"/",b:"\\b",f:"\\f",n:"\\n",r:"\\r",t:" "},error=function(m){throw{name:"SyntaxError",message:m,at:at,text:text}},next=function(c){return c&&c!==ch&&error("Expected \'"+c+"\' instead of \'"+ch+"\'"),ch=text.charAt(at),at+=1,ch},number=function(){var number,string="";for("-"===ch&&(string="-",next("-"));ch>="0"&&"9">=ch;)string+=ch,next();if("."===ch)for(string+=".";next()&&ch>="0"&&"9">=ch;)string+=ch;if("e"===ch||"E"===ch)for(string+=ch,next(),("-"===ch||"+"===ch)&&(string+=ch,next());ch>="0"&&"9">=ch;)string+=ch,next();return number=+string,isNaN(number)?(error("Bad number"),void 0):number},string=function(){var hex,i,uffff,string="";if(\'"\'===ch)for(;next();){if(\'"\'===ch)return next(),string;if("\\\\"===ch)if(next(),"u"===ch){for(uffff=0,i=0;4>i&&(hex=parseInt(next(),16),isFinite(hex));i+=1)uffff=16*uffff+hex;string+=String.fromCharCode(uffff)}else{if("string"!=typeof escapee[ch])break;string+=escapee[ch]}else string+=ch}error("Bad string")},white=function(){for(;ch&&" ">=ch;)next()},word=function(){switch(ch){case"t":return next("t"),next("r"),next("u"),next("e"),!0;case"f":return next("f"),next("a"),next("l"),next("s"),next("e"),!1;case"n":return next("n"),next("u"),next("l"),next("l"),null}error("Unexpected \'"+ch+"\'")},array=function(){var array=[];if("["===ch){if(next("["),white(),"]"===ch)return next("]"),array;for(;ch;){if(array.push(value()),white(),"]"===ch)return next("]"),array;next(","),white()}}error("Bad array")},object=function(){var key,object={};if("{"===ch){if(next("{"),white(),"}"===ch)return next("}"),object;for(;ch;){if(key=string(),white(),next(":"),Object.hasOwnProperty.call(object,key)&&error(\'Duplicate key "\'+key+\'"\'),object[key]=value(),white(),"}"===ch)return next("}"),object;next(","),white()}}error("Bad object")};return value=function(){switch(white(),ch){case"{":return object();case"[":return array();case\'"\':return string();case"-":return number();default:return ch>="0"&&"9">=ch?number():word()}},function(source,reviver){var result;return text=source,at=0,ch=" ",result=value(),white(),ch&&error("Syntax error"),"function"==typeof reviver?function walk(holder,key){var k,v,value=holder[key];if(value&&"object"==typeof value)for(k in value)Object.hasOwnProperty.call(value,k)&&(v=walk(value,k),void 0!==v?value[k]=v:delete value[k]);return reviver.call(holder,key,value)}({"":result},""):result}}),ace.define("ace/mode/json_worker",["require","exports","module","ace/lib/oop","ace/worker/mirror","ace/mode/json/json_parse"],function(acequire,exports){"use strict";var oop=acequire("../lib/oop"),Mirror=acequire("../worker/mirror").Mirror,parse=acequire("./json/json_parse"),JsonWorker=exports.JsonWorker=function(sender){Mirror.call(this,sender),this.setTimeout(200)};oop.inherits(JsonWorker,Mirror),function(){this.onUpdate=function(){var value=this.doc.getValue(),errors=[];try{value&&parse(value)}catch(e){var pos=this.doc.indexToPosition(e.at-1);errors.push({row:pos.row,column:pos.column,text:e.message,type:"error"})}this.sender.emit("annotate",errors)}}.call(JsonWorker.prototype)}),ace.define("ace/lib/es5-shim",["require","exports","module"],function(){function Empty(){}function doesDefinePropertyWork(object){try{return Object.defineProperty(object,"sentinel",{}),"sentinel"in object}catch(exception){}}function toInteger(n){return n=+n,n!==n?n=0:0!==n&&n!==1/0&&n!==-(1/0)&&(n=(n>0||-1)*Math.floor(Math.abs(n))),n}Function.prototype.bind||(Function.prototype.bind=function(that){var target=this;if("function"!=typeof target)throw new TypeError("Function.prototype.bind called on incompatible "+target);var args=slice.call(arguments,1),bound=function(){if(this instanceof bound){var result=target.apply(this,args.concat(slice.call(arguments)));return Object(result)===result?result:this}return target.apply(that,args.concat(slice.call(arguments)))};return target.prototype&&(Empty.prototype=target.prototype,bound.prototype=new Empty,Empty.prototype=null),bound});var defineGetter,defineSetter,lookupGetter,lookupSetter,supportsAccessors,call=Function.prototype.call,prototypeOfArray=Array.prototype,prototypeOfObject=Object.prototype,slice=prototypeOfArray.slice,_toString=call.bind(prototypeOfObject.toString),owns=call.bind(prototypeOfObject.hasOwnProperty);if((supportsAccessors=owns(prototypeOfObject,"__defineGetter__"))&&(defineGetter=call.bind(prototypeOfObject.__defineGetter__),defineSetter=call.bind(prototypeOfObject.__defineSetter__),lookupGetter=call.bind(prototypeOfObject.__lookupGetter__),lookupSetter=call.bind(prototypeOfObject.__lookupSetter__)),2!=[1,2].splice(0).length)if(function(){function makeArray(l){var a=Array(l+2);return a[0]=a[1]=0,a}var lengthBefore,array=[];return array.splice.apply(array,makeArray(20)),array.splice.apply(array,makeArray(26)),lengthBefore=array.length,array.splice(5,0,"XXX"),lengthBefore+1==array.length,lengthBefore+1==array.length?!0:void 0\n}()){var array_splice=Array.prototype.splice;Array.prototype.splice=function(start,deleteCount){return arguments.length?array_splice.apply(this,[void 0===start?0:start,void 0===deleteCount?this.length-start:deleteCount].concat(slice.call(arguments,2))):[]}}else Array.prototype.splice=function(pos,removeCount){var length=this.length;pos>0?pos>length&&(pos=length):void 0==pos?pos=0:0>pos&&(pos=Math.max(length+pos,0)),length>pos+removeCount||(removeCount=length-pos);var removed=this.slice(pos,pos+removeCount),insert=slice.call(arguments,2),add=insert.length;if(pos===length)add&&this.push.apply(this,insert);else{var remove=Math.min(removeCount,length-pos),tailOldPos=pos+remove,tailNewPos=tailOldPos+add-remove,tailCount=length-tailOldPos,lengthAfterRemove=length-remove;if(tailOldPos>tailNewPos)for(var i=0;tailCount>i;++i)this[tailNewPos+i]=this[tailOldPos+i];else if(tailNewPos>tailOldPos)for(i=tailCount;i--;)this[tailNewPos+i]=this[tailOldPos+i];if(add&&pos===lengthAfterRemove)this.length=lengthAfterRemove,this.push.apply(this,insert);else for(this.length=lengthAfterRemove+add,i=0;add>i;++i)this[pos+i]=insert[i]}return removed};Array.isArray||(Array.isArray=function(obj){return"[object Array]"==_toString(obj)});var boxedString=Object("a"),splitString="a"!=boxedString[0]||!(0 in boxedString);if(Array.prototype.forEach||(Array.prototype.forEach=function(fun){var object=toObject(this),self=splitString&&"[object String]"==_toString(this)?this.split(""):object,thisp=arguments[1],i=-1,length=self.length>>>0;if("[object Function]"!=_toString(fun))throw new TypeError;for(;length>++i;)i in self&&fun.call(thisp,self[i],i,object)}),Array.prototype.map||(Array.prototype.map=function(fun){var object=toObject(this),self=splitString&&"[object String]"==_toString(this)?this.split(""):object,length=self.length>>>0,result=Array(length),thisp=arguments[1];if("[object Function]"!=_toString(fun))throw new TypeError(fun+" is not a function");for(var i=0;length>i;i++)i in self&&(result[i]=fun.call(thisp,self[i],i,object));return result}),Array.prototype.filter||(Array.prototype.filter=function(fun){var value,object=toObject(this),self=splitString&&"[object String]"==_toString(this)?this.split(""):object,length=self.length>>>0,result=[],thisp=arguments[1];if("[object Function]"!=_toString(fun))throw new TypeError(fun+" is not a function");for(var i=0;length>i;i++)i in self&&(value=self[i],fun.call(thisp,value,i,object)&&result.push(value));return result}),Array.prototype.every||(Array.prototype.every=function(fun){var object=toObject(this),self=splitString&&"[object String]"==_toString(this)?this.split(""):object,length=self.length>>>0,thisp=arguments[1];if("[object Function]"!=_toString(fun))throw new TypeError(fun+" is not a function");for(var i=0;length>i;i++)if(i in self&&!fun.call(thisp,self[i],i,object))return!1;return!0}),Array.prototype.some||(Array.prototype.some=function(fun){var object=toObject(this),self=splitString&&"[object String]"==_toString(this)?this.split(""):object,length=self.length>>>0,thisp=arguments[1];if("[object Function]"!=_toString(fun))throw new TypeError(fun+" is not a function");for(var i=0;length>i;i++)if(i in self&&fun.call(thisp,self[i],i,object))return!0;return!1}),Array.prototype.reduce||(Array.prototype.reduce=function(fun){var object=toObject(this),self=splitString&&"[object String]"==_toString(this)?this.split(""):object,length=self.length>>>0;if("[object Function]"!=_toString(fun))throw new TypeError(fun+" is not a function");if(!length&&1==arguments.length)throw new TypeError("reduce of empty array with no initial value");var result,i=0;if(arguments.length>=2)result=arguments[1];else for(;;){if(i in self){result=self[i++];break}if(++i>=length)throw new TypeError("reduce of empty array with no initial value")}for(;length>i;i++)i in self&&(result=fun.call(void 0,result,self[i],i,object));return result}),Array.prototype.reduceRight||(Array.prototype.reduceRight=function(fun){var object=toObject(this),self=splitString&&"[object String]"==_toString(this)?this.split(""):object,length=self.length>>>0;if("[object Function]"!=_toString(fun))throw new TypeError(fun+" is not a function");if(!length&&1==arguments.length)throw new TypeError("reduceRight of empty array with no initial value");var result,i=length-1;if(arguments.length>=2)result=arguments[1];else for(;;){if(i in self){result=self[i--];break}if(0>--i)throw new TypeError("reduceRight of empty array with no initial value")}do i in this&&(result=fun.call(void 0,result,self[i],i,object));while(i--);return result}),Array.prototype.indexOf&&-1==[0,1].indexOf(1,2)||(Array.prototype.indexOf=function(sought){var self=splitString&&"[object String]"==_toString(this)?this.split(""):toObject(this),length=self.length>>>0;if(!length)return-1;var i=0;for(arguments.length>1&&(i=toInteger(arguments[1])),i=i>=0?i:Math.max(0,length+i);length>i;i++)if(i in self&&self[i]===sought)return i;return-1}),Array.prototype.lastIndexOf&&-1==[0,1].lastIndexOf(0,-3)||(Array.prototype.lastIndexOf=function(sought){var self=splitString&&"[object String]"==_toString(this)?this.split(""):toObject(this),length=self.length>>>0;if(!length)return-1;var i=length-1;for(arguments.length>1&&(i=Math.min(i,toInteger(arguments[1]))),i=i>=0?i:length-Math.abs(i);i>=0;i--)if(i in self&&sought===self[i])return i;return-1}),Object.getPrototypeOf||(Object.getPrototypeOf=function(object){return object.__proto__||(object.constructor?object.constructor.prototype:prototypeOfObject)}),!Object.getOwnPropertyDescriptor){var ERR_NON_OBJECT="Object.getOwnPropertyDescriptor called on a non-object: ";Object.getOwnPropertyDescriptor=function(object,property){if("object"!=typeof object&&"function"!=typeof object||null===object)throw new TypeError(ERR_NON_OBJECT+object);if(owns(object,property)){var descriptor,getter,setter;if(descriptor={enumerable:!0,configurable:!0},supportsAccessors){var prototype=object.__proto__;object.__proto__=prototypeOfObject;var getter=lookupGetter(object,property),setter=lookupSetter(object,property);if(object.__proto__=prototype,getter||setter)return getter&&(descriptor.get=getter),setter&&(descriptor.set=setter),descriptor}return descriptor.value=object[property],descriptor}}}if(Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(object){return Object.keys(object)}),!Object.create){var createEmpty;createEmpty=null===Object.prototype.__proto__?function(){return{__proto__:null}}:function(){var empty={};for(var i in empty)empty[i]=null;return empty.constructor=empty.hasOwnProperty=empty.propertyIsEnumerable=empty.isPrototypeOf=empty.toLocaleString=empty.toString=empty.valueOf=empty.__proto__=null,empty},Object.create=function(prototype,properties){var object;if(null===prototype)object=createEmpty();else{if("object"!=typeof prototype)throw new TypeError("typeof prototype["+typeof prototype+"] != \'object\'");var Type=function(){};Type.prototype=prototype,object=new Type,object.__proto__=prototype}return void 0!==properties&&Object.defineProperties(object,properties),object}}if(Object.defineProperty){var definePropertyWorksOnObject=doesDefinePropertyWork({}),definePropertyWorksOnDom="undefined"==typeof document||doesDefinePropertyWork(document.createElement("div"));if(!definePropertyWorksOnObject||!definePropertyWorksOnDom)var definePropertyFallback=Object.defineProperty}if(!Object.defineProperty||definePropertyFallback){var ERR_NON_OBJECT_DESCRIPTOR="Property description must be an object: ",ERR_NON_OBJECT_TARGET="Object.defineProperty called on non-object: ",ERR_ACCESSORS_NOT_SUPPORTED="getters & setters can not be defined on this javascript engine";Object.defineProperty=function(object,property,descriptor){if("object"!=typeof object&&"function"!=typeof object||null===object)throw new TypeError(ERR_NON_OBJECT_TARGET+object);if("object"!=typeof descriptor&&"function"!=typeof descriptor||null===descriptor)throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR+descriptor);if(definePropertyFallback)try{return definePropertyFallback.call(Object,object,property,descriptor)}catch(exception){}if(owns(descriptor,"value"))if(supportsAccessors&&(lookupGetter(object,property)||lookupSetter(object,property))){var prototype=object.__proto__;object.__proto__=prototypeOfObject,delete object[property],object[property]=descriptor.value,object.__proto__=prototype}else object[property]=descriptor.value;else{if(!supportsAccessors)throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);owns(descriptor,"get")&&defineGetter(object,property,descriptor.get),owns(descriptor,"set")&&defineSetter(object,property,descriptor.set)}return object}}Object.defineProperties||(Object.defineProperties=function(object,properties){for(var property in properties)owns(properties,property)&&Object.defineProperty(object,property,properties[property]);return object}),Object.seal||(Object.seal=function(object){return object}),Object.freeze||(Object.freeze=function(object){return object});try{Object.freeze(function(){})}catch(exception){Object.freeze=function(freezeObject){return function(object){return"function"==typeof object?object:freezeObject(object)}}(Object.freeze)}if(Object.preventExtensions||(Object.preventExtensions=function(object){return object}),Object.isSealed||(Object.isSealed=function(){return!1}),Object.isFrozen||(Object.isFrozen=function(){return!1}),Object.isExtensible||(Object.isExtensible=function(object){if(Object(object)===object)throw new TypeError;for(var name="";owns(object,name);)name+="?";object[name]=!0;var returnValue=owns(object,name);return delete object[name],returnValue}),!Object.keys){var hasDontEnumBug=!0,dontEnums=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],dontEnumsLength=dontEnums.length;for(var key in{toString:null})hasDontEnumBug=!1;Object.keys=function(object){if("object"!=typeof object&&"function"!=typeof object||null===object)throw new TypeError("Object.keys called on a non-object");var keys=[];for(var name in object)owns(object,name)&&keys.push(name);if(hasDontEnumBug)for(var i=0,ii=dontEnumsLength;ii>i;i++){var dontEnum=dontEnums[i];owns(object,dontEnum)&&keys.push(dontEnum)}return keys}}Date.now||(Date.now=function(){return(new Date).getTime()});var ws=" \\n\x0B\\f\\r   ᠎              \\u2028\\u2029\ufeff";if(!String.prototype.trim||ws.trim()){ws="["+ws+"]";var trimBeginRegexp=RegExp("^"+ws+ws+"*"),trimEndRegexp=RegExp(ws+ws+"*$");String.prototype.trim=function(){return(this+"").replace(trimBeginRegexp,"").replace(trimEndRegexp,"")}}var toObject=function(o){if(null==o)throw new TypeError("can\'t convert "+o+" to object");return Object(o)}});'; +},function(e,t){ace.define("ace/ext/searchbox",["require","exports","module","ace/lib/dom","ace/lib/lang","ace/lib/event","ace/keyboard/hash_handler","ace/lib/keys"],function(e,t,n){"use strict";var i=e("../lib/dom"),o=e("../lib/lang"),r=e("../lib/event"),s=" .ace_search { background-color: #ddd; border: 1px solid #cbcbcb; border-top: 0 none; max-width: 325px; overflow: hidden; margin: 0; padding: 4px; padding-right: 6px; padding-bottom: 0; position: absolute; top: 0px; z-index: 99; white-space: normal; } .ace_search.left { border-left: 0 none; border-radius: 0px 0px 5px 0px; left: 0; } .ace_search.right { border-radius: 0px 0px 0px 5px; border-right: 0 none; right: 0; } .ace_search_form, .ace_replace_form { border-radius: 3px; border: 1px solid #cbcbcb; float: left; margin-bottom: 4px; overflow: hidden; } .ace_search_form.ace_nomatch { outline: 1px solid red; } .ace_search_field { background-color: white; border-right: 1px solid #cbcbcb; border: 0 none; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; float: left; height: 22px; outline: 0; padding: 0 7px; width: 214px; margin: 0; } .ace_searchbtn, .ace_replacebtn { background: #fff; border: 0 none; border-left: 1px solid #dcdcdc; cursor: pointer; float: left; height: 22px; margin: 0; position: relative; } .ace_searchbtn:last-child, .ace_replacebtn:last-child { border-top-right-radius: 3px; border-bottom-right-radius: 3px; } .ace_searchbtn:disabled { background: none; cursor: default; } .ace_searchbtn { background-position: 50% 50%; background-repeat: no-repeat; width: 27px; } .ace_searchbtn.prev { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADFJREFUeNpiSU1NZUAC/6E0I0yACYskCpsJiySKIiY0SUZk40FyTEgCjGgKwTRAgAEAQJUIPCE+qfkAAAAASUVORK5CYII=); } .ace_searchbtn.next { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADRJREFUeNpiTE1NZQCC/0DMyIAKwGJMUAYDEo3M/s+EpvM/mkKwCQxYjIeLMaELoLMBAgwAU7UJObTKsvAAAAAASUVORK5CYII=); } .ace_searchbtn_close { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAcCAYAAABRVo5BAAAAZ0lEQVR42u2SUQrAMAhDvazn8OjZBilCkYVVxiis8H4CT0VrAJb4WHT3C5xU2a2IQZXJjiQIRMdkEoJ5Q2yMqpfDIo+XY4k6h+YXOyKqTIj5REaxloNAd0xiKmAtsTHqW8sR2W5f7gCu5nWFUpVjZwAAAABJRU5ErkJggg==) no-repeat 50% 0; border-radius: 50%; border: 0 none; color: #656565; cursor: pointer; float: right; font: 16px/16px Arial; height: 14px; margin: 5px 1px 9px 5px; padding: 0; text-align: center; width: 14px; } .ace_searchbtn_close:hover { background-color: #656565; background-position: 50% 100%; color: white; } .ace_replacebtn.prev { width: 54px } .ace_replacebtn.next { width: 27px } .ace_button { margin-left: 2px; cursor: pointer; -webkit-user-select: none; -moz-user-select: none; -o-user-select: none; -ms-user-select: none; user-select: none; overflow: hidden; opacity: 0.7; border: 1px solid rgba(100,100,100,0.23); padding: 1px; -moz-box-sizing: border-box; box-sizing: border-box; color: black; } .ace_button:hover { background-color: #eee; opacity:1; } .ace_button:active { background-color: #ddd; } .ace_button.checked { border-color: #3399ff; opacity:1; } .ace_search_options{ margin-bottom: 3px; text-align: right; -webkit-user-select: none; -moz-user-select: none; -o-user-select: none; -ms-user-select: none; user-select: none; }",a=e("../keyboard/hash_handler").HashHandler,l=e("../lib/keys");i.importCssString(s,"ace_searchbox");var c=''.replace(/>\s+/g,">"),d=function(e,t,n){var o=i.createElement("div");o.innerHTML=c,this.element=o.firstChild,this.$init(),this.setEditor(e)};(function(){this.setEditor=function(e){e.searchBox=this,e.container.appendChild(this.element),this.editor=e},this.$initElements=function(e){this.searchBox=e.querySelector(".ace_search_form"),this.replaceBox=e.querySelector(".ace_replace_form"),this.searchOptions=e.querySelector(".ace_search_options"),this.regExpOption=e.querySelector("[action=toggleRegexpMode]"),this.caseSensitiveOption=e.querySelector("[action=toggleCaseSensitive]"),this.wholeWordOption=e.querySelector("[action=toggleWholeWords]"),this.searchInput=this.searchBox.querySelector(".ace_search_field"),this.replaceInput=this.replaceBox.querySelector(".ace_search_field")},this.$init=function(){var e=this.element;this.$initElements(e);var t=this;r.addListener(e,"mousedown",function(e){setTimeout(function(){t.activeInput.focus()},0),r.stopPropagation(e)}),r.addListener(e,"click",function(e){var n=e.target||e.srcElement,i=n.getAttribute("action");i&&t[i]?t[i]():t.$searchBarKb.commands[i]&&t.$searchBarKb.commands[i].exec(t),r.stopPropagation(e)}),r.addCommandKeyListener(e,function(e,n,i){var o=l.keyCodeToString(i),s=t.$searchBarKb.findKeyCommand(n,o);s&&s.exec&&(s.exec(t),r.stopEvent(e))}),this.$onChange=o.delayedCall(function(){t.find(!1,!1)}),r.addListener(this.searchInput,"input",function(){t.$onChange.schedule(20)}),r.addListener(this.searchInput,"focus",function(){t.activeInput=t.searchInput,t.searchInput.value&&t.highlight()}),r.addListener(this.replaceInput,"focus",function(){t.activeInput=t.replaceInput,t.searchInput.value&&t.highlight()})},this.$closeSearchBarKb=new a([{bindKey:"Esc",name:"closeSearchBar",exec:function(e){e.searchBox.hide()}}]),this.$searchBarKb=new a,this.$searchBarKb.bindKeys({"Ctrl-f|Command-f":function(e){var t=e.isReplace=!e.isReplace;e.replaceBox.style.display=t?"":"none",e.searchInput.focus()},"Ctrl-H|Command-Option-F":function(e){e.replaceBox.style.display="",e.replaceInput.focus()},"Ctrl-G|Command-G":function(e){e.findNext()},"Ctrl-Shift-G|Command-Shift-G":function(e){e.findPrev()},esc:function(e){setTimeout(function(){e.hide()})},Return:function(e){e.activeInput==e.replaceInput&&e.replace(),e.findNext()},"Shift-Return":function(e){e.activeInput==e.replaceInput&&e.replace(),e.findPrev()},"Alt-Return":function(e){e.activeInput==e.replaceInput&&e.replaceAll(),e.findAll()},Tab:function(e){(e.activeInput==e.replaceInput?e.searchInput:e.replaceInput).focus()}}),this.$searchBarKb.addCommands([{name:"toggleRegexpMode",bindKey:{win:"Alt-R|Alt-/",mac:"Ctrl-Alt-R|Ctrl-Alt-/"},exec:function(e){e.regExpOption.checked=!e.regExpOption.checked,e.$syncOptions()}},{name:"toggleCaseSensitive",bindKey:{win:"Alt-C|Alt-I",mac:"Ctrl-Alt-R|Ctrl-Alt-I"},exec:function(e){e.caseSensitiveOption.checked=!e.caseSensitiveOption.checked,e.$syncOptions()}},{name:"toggleWholeWords",bindKey:{win:"Alt-B|Alt-W",mac:"Ctrl-Alt-B|Ctrl-Alt-W"},exec:function(e){e.wholeWordOption.checked=!e.wholeWordOption.checked,e.$syncOptions()}}]),this.$syncOptions=function(){i.setCssClass(this.regExpOption,"checked",this.regExpOption.checked),i.setCssClass(this.wholeWordOption,"checked",this.wholeWordOption.checked),i.setCssClass(this.caseSensitiveOption,"checked",this.caseSensitiveOption.checked),this.find(!1,!1)},this.highlight=function(e){this.editor.session.highlight(e||this.editor.$search.$options.re),this.editor.renderer.updateBackMarkers()},this.find=function(e,t,n){var o=this.editor.find(this.searchInput.value,{skipCurrent:e,backwards:t,wrap:!0,regExp:this.regExpOption.checked,caseSensitive:this.caseSensitiveOption.checked,wholeWord:this.wholeWordOption.checked,preventScroll:n}),r=!o&&this.searchInput.value;i.setCssClass(this.searchBox,"ace_nomatch",r),this.editor._emit("findSearchBox",{match:!r}),this.highlight()},this.findNext=function(){this.find(!0,!1)},this.findPrev=function(){this.find(!0,!0)},this.findAll=function(){var e=this.editor.findAll(this.searchInput.value,{regExp:this.regExpOption.checked,caseSensitive:this.caseSensitiveOption.checked,wholeWord:this.wholeWordOption.checked}),t=!e&&this.searchInput.value;i.setCssClass(this.searchBox,"ace_nomatch",t),this.editor._emit("findSearchBox",{match:!t}),this.highlight(),this.hide()},this.replace=function(){this.editor.getReadOnly()||this.editor.replace(this.replaceInput.value)},this.replaceAndFindNext=function(){this.editor.getReadOnly()||(this.editor.replace(this.replaceInput.value),this.findNext())},this.replaceAll=function(){this.editor.getReadOnly()||this.editor.replaceAll(this.replaceInput.value)},this.hide=function(){this.element.style.display="none",this.editor.keyBinding.removeKeyboardHandler(this.$closeSearchBarKb),this.editor.focus()},this.show=function(e,t){this.element.style.display="",this.replaceBox.style.display=t?"":"none",this.isReplace=t,e&&(this.searchInput.value=e),this.find(!1,!1,!0),this.searchInput.focus(),this.searchInput.select(),this.editor.keyBinding.addKeyboardHandler(this.$closeSearchBarKb)},this.isFocused=function(){var e=document.activeElement;return e==this.searchInput||e==this.replaceInput}}).call(d.prototype),t.SearchBox=d,t.Search=function(e,t){var n=e.searchBox||new d(e);n.show(e.session.getTextRange(),t)}}),function(){ace.acequire(["ace/ext/searchbox"],function(){})}()},function(e,t){ace.define("ace/theme/jsoneditor",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!1,t.cssClass="ace-jsoneditor",t.cssText='.ace-jsoneditor .ace_gutter { background: #ebebeb; color: #333 } .ace-jsoneditor.ace_editor { font-family: droid sans mono, consolas, monospace, courier new, courier, sans-serif; line-height: 1.3; } .ace-jsoneditor .ace_print-margin { width: 1px; background: #e8e8e8 } .ace-jsoneditor .ace_scroller { background-color: #FFFFFF } .ace-jsoneditor .ace_text-layer { color: gray } .ace-jsoneditor .ace_variable { color: #1a1a1a } .ace-jsoneditor .ace_cursor { border-left: 2px solid #000000 } .ace-jsoneditor .ace_overwrite-cursors .ace_cursor { border-left: 0px; border-bottom: 1px solid #000000 } .ace-jsoneditor .ace_marker-layer .ace_selection { background: lightgray } .ace-jsoneditor.ace_multiselect .ace_selection.ace_start { box-shadow: 0 0 3px 0px #FFFFFF; border-radius: 2px } .ace-jsoneditor .ace_marker-layer .ace_step { background: rgb(255, 255, 0) } .ace-jsoneditor .ace_marker-layer .ace_bracket { margin: -1px 0 0 -1px; border: 1px solid #BFBFBF } .ace-jsoneditor .ace_marker-layer .ace_active-line { background: #FFFBD1 } .ace-jsoneditor .ace_gutter-active-line { background-color : #dcdcdc } .ace-jsoneditor .ace_marker-layer .ace_selected-word { border: 1px solid lightgray } .ace-jsoneditor .ace_invisible { color: #BFBFBF } .ace-jsoneditor .ace_keyword, .ace-jsoneditor .ace_meta, .ace-jsoneditor .ace_support.ace_constant.ace_property-value { color: #AF956F } .ace-jsoneditor .ace_keyword.ace_operator { color: #484848 } .ace-jsoneditor .ace_keyword.ace_other.ace_unit { color: #96DC5F } .ace-jsoneditor .ace_constant.ace_language { color: darkorange } .ace-jsoneditor .ace_constant.ace_numeric { color: red } .ace-jsoneditor .ace_constant.ace_character.ace_entity { color: #BF78CC } .ace-jsoneditor .ace_invalid { color: #FFFFFF; background-color: #FF002A; } .ace-jsoneditor .ace_fold { background-color: #AF956F; border-color: #000000 } .ace-jsoneditor .ace_storage, .ace-jsoneditor .ace_support.ace_class, .ace-jsoneditor .ace_support.ace_function, .ace-jsoneditor .ace_support.ace_other, .ace-jsoneditor .ace_support.ace_type { color: #C52727 } .ace-jsoneditor .ace_string { color: green } .ace-jsoneditor .ace_comment { color: #BCC8BA } .ace-jsoneditor .ace_entity.ace_name.ace_tag, .ace-jsoneditor .ace_entity.ace_other.ace_attribute-name { color: #606060 } .ace-jsoneditor .ace_markup.ace_underline { text-decoration: underline } .ace-jsoneditor .ace_indent-guide { background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==") right repeat-y }';var i=e("../lib/dom");i.importCssString(t.cssText,t.cssClass)})}])}); +//# sourceMappingURL=jsoneditor-minimalist.map \ No newline at end of file diff --git a/ui/app/bower_components/jsoneditor/dist/jsoneditor.css b/ui/app/bower_components/jsoneditor/dist/jsoneditor.css new file mode 100644 index 0000000..f517e8e --- /dev/null +++ b/ui/app/bower_components/jsoneditor/dist/jsoneditor.css @@ -0,0 +1,929 @@ +/* reset styling (prevent conflicts with bootstrap, materialize.css, etc.) */ + +div.jsoneditor input { + height: auto; + border: inherit; +} + +div.jsoneditor input:focus { + border: none !important; + box-shadow: none !important; +} + +div.jsoneditor table { + border-collapse: collapse; + width: auto; +} + +div.jsoneditor td, +div.jsoneditor th { + padding: 0; + display: table-cell; + text-align: left; + vertical-align: inherit; + border-radius: inherit; +} + + +div.jsoneditor-field, +div.jsoneditor-value, +div.jsoneditor-readonly { + border: 1px solid transparent; + min-height: 16px; + min-width: 32px; + padding: 2px; + margin: 1px; + word-wrap: break-word; + float: left; +} + +/* adjust margin of p elements inside editable divs, needed for Opera, IE */ + +div.jsoneditor-field p, +div.jsoneditor-value p { + margin: 0; +} + +div.jsoneditor-value { + word-break: break-word; +} + +div.jsoneditor-readonly { + min-width: 16px; + color: gray; +} + +div.jsoneditor-empty { + border-color: lightgray; + border-style: dashed; + border-radius: 2px; +} + +div.jsoneditor-field.jsoneditor-empty::after, +div.jsoneditor-value.jsoneditor-empty::after { + pointer-events: none; + color: lightgray; + font-size: 8pt; +} + +div.jsoneditor-field.jsoneditor-empty::after { + content: "field"; +} + +div.jsoneditor-value.jsoneditor-empty::after { + content: "value"; +} + +div.jsoneditor-value.jsoneditor-url, +a.jsoneditor-value.jsoneditor-url { + color: green; + text-decoration: underline; +} + +a.jsoneditor-value.jsoneditor-url { + display: inline-block; + padding: 2px; + margin: 2px; +} + +a.jsoneditor-value.jsoneditor-url:hover, +a.jsoneditor-value.jsoneditor-url:focus { + color: #ee422e; +} + +div.jsoneditor td.jsoneditor-separator { + padding: 3px 0; + vertical-align: top; + color: gray; +} + +div.jsoneditor-field[contenteditable=true]:focus, +div.jsoneditor-field[contenteditable=true]:hover, +div.jsoneditor-value[contenteditable=true]:focus, +div.jsoneditor-value[contenteditable=true]:hover, +div.jsoneditor-field.jsoneditor-highlight, +div.jsoneditor-value.jsoneditor-highlight { + background-color: #FFFFAB; + border: 1px solid yellow; + border-radius: 2px; +} + +div.jsoneditor-field.jsoneditor-highlight-active, +div.jsoneditor-field.jsoneditor-highlight-active:focus, +div.jsoneditor-field.jsoneditor-highlight-active:hover, +div.jsoneditor-value.jsoneditor-highlight-active, +div.jsoneditor-value.jsoneditor-highlight-active:focus, +div.jsoneditor-value.jsoneditor-highlight-active:hover { + background-color: #ffee00; + border: 1px solid #ffc700; + border-radius: 2px; +} + +div.jsoneditor-value.jsoneditor-string { + color: #008000; +} + +div.jsoneditor-value.jsoneditor-object, +div.jsoneditor-value.jsoneditor-array { + min-width: 16px; + color: #808080; +} + +div.jsoneditor-value.jsoneditor-number { + color: #ee422e; +} + +div.jsoneditor-value.jsoneditor-boolean { + color: #ff8c00; +} + +div.jsoneditor-value.jsoneditor-null { + color: #004ED0; +} + +div.jsoneditor-value.jsoneditor-invalid { + color: #000000; +} + +div.jsoneditor-tree button { + width: 24px; + height: 24px; + padding: 0; + margin: 0; + border: none; + cursor: pointer; + background: transparent url("img/jsoneditor-icons.svg"); +} + +div.jsoneditor-mode-view tr.jsoneditor-expandable td.jsoneditor-tree, +div.jsoneditor-mode-form tr.jsoneditor-expandable td.jsoneditor-tree { + cursor: pointer; +} + +div.jsoneditor-tree button.jsoneditor-collapsed { + background-position: 0 -48px; +} + +div.jsoneditor-tree button.jsoneditor-expanded { + background-position: 0 -72px; +} + +div.jsoneditor-tree button.jsoneditor-contextmenu { + background-position: -48px -72px; +} + +div.jsoneditor-tree button.jsoneditor-contextmenu:hover, +div.jsoneditor-tree button.jsoneditor-contextmenu:focus, +div.jsoneditor-tree button.jsoneditor-contextmenu.jsoneditor-selected, +tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-contextmenu { + background-position: -48px -48px; +} + +div.jsoneditor-tree *:focus { + outline: none; +} + +div.jsoneditor-tree button:focus { + /* TODO: nice outline for buttons with focus + outline: #97B0F8 solid 2px; + box-shadow: 0 0 8px #97B0F8; + */ + background-color: #f5f5f5; + outline: #e5e5e5 solid 1px; +} + +div.jsoneditor-tree button.jsoneditor-invisible { + visibility: hidden; + background: none; +} + +div.jsoneditor { + color: #1A1A1A; + border: 1px solid #3883fa; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + width: 100%; + height: 100%; + overflow: hidden; + position: relative; + padding: 0; + line-height: 100%; +} + +div.jsoneditor-tree table.jsoneditor-tree { + border-collapse: collapse; + border-spacing: 0; + width: 100%; + margin: 0; +} + +div.jsoneditor-outer { + width: 100%; + height: 100%; + margin: -35px 0 0 0; + padding: 35px 0 0 0; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +textarea.jsoneditor-text, +.ace-jsoneditor { + min-height: 150px; +} + +div.jsoneditor-tree { + width: 100%; + height: 100%; + position: relative; + overflow: auto; +} + +textarea.jsoneditor-text { + width: 100%; + height: 100%; + margin: 0; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + outline-width: 0; + border: none; + background-color: white; + resize: none; +} + +tr.jsoneditor-highlight, +tr.jsoneditor-selected { + background-color: #e6e6e6; +} + +tr.jsoneditor-selected button.jsoneditor-dragarea, +tr.jsoneditor-selected button.jsoneditor-contextmenu { + visibility: hidden; +} + +tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-dragarea, +tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-contextmenu { + visibility: visible; +} + +div.jsoneditor-tree button.jsoneditor-dragarea { + background: url("img/jsoneditor-icons.svg") -72px -72px; + cursor: move; +} + +div.jsoneditor-tree button.jsoneditor-dragarea:hover, +div.jsoneditor-tree button.jsoneditor-dragarea:focus, +tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-dragarea { + background-position: -72px -48px; +} + +div.jsoneditor tr, +div.jsoneditor th, +div.jsoneditor td { + padding: 0; + margin: 0; +} + +div.jsoneditor td { + vertical-align: top; +} + +div.jsoneditor td.jsoneditor-tree { + vertical-align: top; +} + +div.jsoneditor-field, +div.jsoneditor-value, +div.jsoneditor td, +div.jsoneditor th, +div.jsoneditor textarea, +.jsoneditor-schema-error { + font-family: droid sans mono, consolas, monospace, courier new, courier, sans-serif; + font-size: 10pt; + color: #1A1A1A; +} + +/* popover */ + +.jsoneditor-schema-error { + cursor: default; + display: inline-block; + /*font-family: arial, sans-serif;*/ + height: 24px; + line-height: 24px; + position: relative; + text-align: center; + width: 24px; +} + +div.jsoneditor-tree .jsoneditor-schema-error { + width: 24px; + height: 24px; + padding: 0; + margin: 0 4px 0 0; + background: url("img/jsoneditor-icons.svg") -168px -48px; +} + +.jsoneditor-schema-error .jsoneditor-popover { + background-color: #4c4c4c; + border-radius: 3px; + box-shadow: 0 0 5px rgba(0,0,0,0.4); + color: #fff; + display: none; + padding: 7px 10px; + position: absolute; + width: 200px; + z-index: 4; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-above { + bottom: 32px; + left: -98px; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-below { + top: 32px; + left: -98px; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-left { + top: -7px; + right: 32px; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-right { + top: -7px; + left: 32px; +} + +.jsoneditor-schema-error .jsoneditor-popover:before { + border-right: 7px solid transparent; + border-left: 7px solid transparent; + content: ''; + display: block; + left: 50%; + margin-left: -7px; + position: absolute; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-above:before { + border-top: 7px solid #4c4c4c; + bottom: -7px; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-below:before { + border-bottom: 7px solid #4c4c4c; + top: -7px; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-left:before { + border-left: 7px solid #4c4c4c; + border-top: 7px solid transparent; + border-bottom: 7px solid transparent; + content: ''; + top: 19px; + right: -14px; + left: inherit; + margin-left: inherit; + margin-top: -7px; + position: absolute; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-right:before { + border-right: 7px solid #4c4c4c; + border-top: 7px solid transparent; + border-bottom: 7px solid transparent; + content: ''; + top: 19px; + left: -14px; + margin-left: inherit; + margin-top: -7px; + position: absolute; +} + +.jsoneditor-schema-error:hover .jsoneditor-popover, +.jsoneditor-schema-error:focus .jsoneditor-popover { + display: block; + -webkit-animation: fade-in .3s linear 1, move-up .3s linear 1; + -moz-animation: fade-in .3s linear 1, move-up .3s linear 1; + -ms-animation: fade-in .3s linear 1, move-up .3s linear 1; +} + +@-webkit-keyframes fade-in { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +@-moz-keyframes fade-in { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +@-ms-keyframes fade-in { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +/*@-webkit-keyframes move-up {*/ + +/*from { bottom: 24px; }*/ + +/*to { bottom: 32px; }*/ + +/*}*/ + +/*@-moz-keyframes move-up {*/ + +/*from { bottom: 24px; }*/ + +/*to { bottom: 32px; }*/ + +/*}*/ + +/*@-ms-keyframes move-up {*/ + +/*from { bottom: 24px; }*/ + +/*to { bottom: 32px; }*/ + +/*}*/ + +/* JSON schema errors displayed at the bottom of the editor in mode text and code */ + +.jsoneditor .jsoneditor-text-errors { + width: 100%; + border-collapse: collapse; + background-color: #ffef8b; + border-top: 1px solid #ffd700; +} + +.jsoneditor .jsoneditor-text-errors td { + padding: 3px 6px; + vertical-align: middle; +} + +.jsoneditor-text-errors .jsoneditor-schema-error { + border: none; + width: 24px; + height: 24px; + padding: 0; + margin: 0 4px 0 0; + background: url("img/jsoneditor-icons.svg") -168px -48px; +} +/* ContextMenu - main menu */ + +div.jsoneditor-contextmenu-root { + position: relative; + width: 0; + height: 0; +} + +div.jsoneditor-contextmenu { + position: absolute; + box-sizing: content-box; + z-index: 99999; +} + +div.jsoneditor-contextmenu ul, +div.jsoneditor-contextmenu li { + box-sizing: content-box; +} + +div.jsoneditor-contextmenu ul { + position: relative; + left: 0; + top: 0; + width: 124px; + background: white; + border: 1px solid #d3d3d3; + box-shadow: 2px 2px 12px rgba(128, 128, 128, 0.3); + list-style: none; + margin: 0; + padding: 0; +} + +div.jsoneditor-contextmenu ul li button { + padding: 0; + margin: 0; + width: 124px; + height: 24px; + border: none; + cursor: pointer; + color: #4d4d4d; + background: transparent; + font-size: 10pt; + font-family: arial, sans-serif; + box-sizing: border-box; + line-height: 26px; + text-align: left; +} + +/* Fix button padding in firefox */ + +div.jsoneditor-contextmenu ul li button::-moz-focus-inner { + padding: 0; + border: 0; +} + +div.jsoneditor-contextmenu ul li button:hover, +div.jsoneditor-contextmenu ul li button:focus { + color: #1a1a1a; + background-color: #f5f5f5; + outline: none; +} + +div.jsoneditor-contextmenu ul li button.jsoneditor-default { + width: 92px; +} + +div.jsoneditor-contextmenu ul li button.jsoneditor-expand { + float: right; + width: 32px; + height: 24px; + border-left: 1px solid #e5e5e5; +} + +div.jsoneditor-contextmenu div.jsoneditor-icon { + float: left; + width: 24px; + height: 24px; + border: none; + padding: 0; + margin: 0; + background-image: url("img/jsoneditor-icons.svg"); +} + +div.jsoneditor-contextmenu ul li button div.jsoneditor-expand { + float: right; + width: 24px; + height: 24px; + padding: 0; + margin: 0 4px 0 0; + background: url("img/jsoneditor-icons.svg") 0 -72px; + opacity: 0.4; +} + +div.jsoneditor-contextmenu ul li button:hover div.jsoneditor-expand, +div.jsoneditor-contextmenu ul li button:focus div.jsoneditor-expand, +div.jsoneditor-contextmenu ul li.jsoneditor-selected div.jsoneditor-expand, +div.jsoneditor-contextmenu ul li button.jsoneditor-expand:hover div.jsoneditor-expand, +div.jsoneditor-contextmenu ul li button.jsoneditor-expand:focus div.jsoneditor-expand { + opacity: 1; +} + +div.jsoneditor-contextmenu div.jsoneditor-separator { + height: 0; + border-top: 1px solid #e5e5e5; + padding-top: 5px; + margin-top: 5px; +} + +div.jsoneditor-contextmenu button.jsoneditor-remove > div.jsoneditor-icon { + background-position: -24px -24px; +} + +div.jsoneditor-contextmenu button.jsoneditor-remove:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-remove:focus > div.jsoneditor-icon { + background-position: -24px 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-append > div.jsoneditor-icon { + background-position: 0 -24px; +} + +div.jsoneditor-contextmenu button.jsoneditor-append:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-append:focus > div.jsoneditor-icon { + background-position: 0 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-insert > div.jsoneditor-icon { + background-position: 0 -24px; +} + +div.jsoneditor-contextmenu button.jsoneditor-insert:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-insert:focus > div.jsoneditor-icon { + background-position: 0 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-duplicate > div.jsoneditor-icon { + background-position: -48px -24px; +} + +div.jsoneditor-contextmenu button.jsoneditor-duplicate:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-duplicate:focus > div.jsoneditor-icon { + background-position: -48px 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-sort-asc > div.jsoneditor-icon { + background-position: -168px -24px; +} + +div.jsoneditor-contextmenu button.jsoneditor-sort-asc:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-sort-asc:focus > div.jsoneditor-icon { + background-position: -168px 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-sort-desc > div.jsoneditor-icon { + background-position: -192px -24px; +} + +div.jsoneditor-contextmenu button.jsoneditor-sort-desc:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-sort-desc:focus > div.jsoneditor-icon { + background-position: -192px 0; +} + +/* ContextMenu - sub menu */ + +div.jsoneditor-contextmenu ul li button.jsoneditor-selected, +div.jsoneditor-contextmenu ul li button.jsoneditor-selected:hover, +div.jsoneditor-contextmenu ul li button.jsoneditor-selected:focus { + color: white; + background-color: #ee422e; +} + +div.jsoneditor-contextmenu ul li { + overflow: hidden; +} + +div.jsoneditor-contextmenu ul li ul { + display: none; + position: relative; + left: -10px; + top: 0; + border: none; + box-shadow: inset 0 0 10px rgba(128, 128, 128, 0.5); + padding: 0 10px; + /* TODO: transition is not supported on IE8-9 */ + -webkit-transition: all 0.3s ease-out; + -moz-transition: all 0.3s ease-out; + -o-transition: all 0.3s ease-out; + transition: all 0.3s ease-out; +} + + + +div.jsoneditor-contextmenu ul li ul li button { + padding-left: 24px; + animation: all ease-in-out 1s; +} + +div.jsoneditor-contextmenu ul li ul li button:hover, +div.jsoneditor-contextmenu ul li ul li button:focus { + background-color: #f5f5f5; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-string > div.jsoneditor-icon { + background-position: -144px -24px; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-string:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-string:focus > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-string.jsoneditor-selected > div.jsoneditor-icon { + background-position: -144px 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-auto > div.jsoneditor-icon { + background-position: -120px -24px; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-auto:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-auto:focus > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-auto.jsoneditor-selected > div.jsoneditor-icon { + background-position: -120px 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-object > div.jsoneditor-icon { + background-position: -72px -24px; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-object:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-object:focus > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-object.jsoneditor-selected > div.jsoneditor-icon { + background-position: -72px 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-array > div.jsoneditor-icon { + background-position: -96px -24px; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-array:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-array:focus > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-array.jsoneditor-selected > div.jsoneditor-icon { + background-position: -96px 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-modes > div.jsoneditor-icon { + background-image: none; + width: 6px; +} +div.jsoneditor-menu { + width: 100%; + height: 35px; + padding: 2px; + margin: 0; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + color: white; + background-color: #3883fa; + border-bottom: 1px solid #3883fa; +} + +div.jsoneditor-menu > button, +div.jsoneditor-menu > div.jsoneditor-modes > button { + width: 26px; + height: 26px; + margin: 2px; + padding: 0; + border-radius: 2px; + border: 1px solid transparent; + background: transparent url("img/jsoneditor-icons.svg"); + color: white; + opacity: 0.8; + font-family: arial, sans-serif; + font-size: 10pt; + float: left; +} + +div.jsoneditor-menu > button:hover, +div.jsoneditor-menu > div.jsoneditor-modes > button:hover { + background-color: rgba(255,255,255,0.2); + border: 1px solid rgba(255,255,255,0.4); +} + +div.jsoneditor-menu > button:focus, +div.jsoneditor-menu > button:active, +div.jsoneditor-menu > div.jsoneditor-modes > button:focus, +div.jsoneditor-menu > div.jsoneditor-modes > button:active { + background-color: rgba(255,255,255,0.3); +} + +div.jsoneditor-menu > button:disabled, +div.jsoneditor-menu > div.jsoneditor-modes > button:disabled { + opacity: 0.5; +} + +div.jsoneditor-menu > button.jsoneditor-collapse-all { + background-position: 0 -96px; +} + +div.jsoneditor-menu > button.jsoneditor-expand-all { + background-position: 0 -120px; +} + +div.jsoneditor-menu > button.jsoneditor-undo { + background-position: -24px -96px; +} + +div.jsoneditor-menu > button.jsoneditor-undo:disabled { + background-position: -24px -120px; +} + +div.jsoneditor-menu > button.jsoneditor-redo { + background-position: -48px -96px; +} + +div.jsoneditor-menu > button.jsoneditor-redo:disabled { + background-position: -48px -120px; +} + +div.jsoneditor-menu > button.jsoneditor-compact { + background-position: -72px -96px; +} + +div.jsoneditor-menu > button.jsoneditor-format { + background-position: -72px -120px; +} + +div.jsoneditor-menu > div.jsoneditor-modes { + display: inline-block; + float: left; +} + +div.jsoneditor-menu > div.jsoneditor-modes > button { + background-image: none; + width: auto; + padding-left: 6px; + padding-right: 6px; +} + +div.jsoneditor-menu > button.jsoneditor-separator, +div.jsoneditor-menu > div.jsoneditor-modes > button.jsoneditor-separator { + margin-left: 10px; +} + +div.jsoneditor-menu a { + font-family: arial, sans-serif; + font-size: 10pt; + color: white; + opacity: 0.8; + vertical-align: middle; +} + +div.jsoneditor-menu a:hover { + opacity: 1; +} + +div.jsoneditor-menu a.jsoneditor-poweredBy { + font-size: 8pt; + position: absolute; + right: 0; + top: 0; + padding: 10px; +} +table.jsoneditor-search input, +table.jsoneditor-search div.jsoneditor-results { + font-family: arial, sans-serif; + font-size: 10pt; + color: #1A1A1A; + background: transparent; + /* For Firefox */ +} + +table.jsoneditor-search div.jsoneditor-results { + color: white; + padding-right: 5px; + line-height: 24px; +} + +table.jsoneditor-search { + position: absolute; + right: 4px; + top: 4px; + border-collapse: collapse; + border-spacing: 0; +} + +table.jsoneditor-search div.jsoneditor-frame { + border: 1px solid transparent; + background-color: white; + padding: 0 2px; + margin: 0; +} + +table.jsoneditor-search div.jsoneditor-frame table { + border-collapse: collapse; +} + +table.jsoneditor-search input { + width: 120px; + border: none; + outline: none; + margin: 1px; + line-height: 20px; +} + +table.jsoneditor-search button { + width: 16px; + height: 24px; + padding: 0; + margin: 0; + border: none; + background: url("img/jsoneditor-icons.svg"); + vertical-align: top; +} + +table.jsoneditor-search button:hover { + background-color: transparent; +} + +table.jsoneditor-search button.jsoneditor-refresh { + width: 18px; + background-position: -99px -73px; +} + +table.jsoneditor-search button.jsoneditor-next { + cursor: pointer; + background-position: -124px -73px; +} + +table.jsoneditor-search button.jsoneditor-next:hover { + background-position: -124px -49px; +} + +table.jsoneditor-search button.jsoneditor-previous { + cursor: pointer; + background-position: -148px -73px; + margin-right: 2px; +} + +table.jsoneditor-search button.jsoneditor-previous:hover { + background-position: -148px -49px; +} \ No newline at end of file diff --git a/ui/app/bower_components/jsoneditor/dist/jsoneditor.js b/ui/app/bower_components/jsoneditor/dist/jsoneditor.js new file mode 100644 index 0000000..d7b5af8 --- /dev/null +++ b/ui/app/bower_components/jsoneditor/dist/jsoneditor.js @@ -0,0 +1,36373 @@ +/*! + * jsoneditor.js + * + * @brief + * JSONEditor is a web-based tool to view, edit, format, and validate JSON. + * It has various modes such as a tree editor, a code editor, and a plain text + * editor. + * + * Supported browsers: Chrome, Firefox, Safari, Opera, Internet Explorer 8+ + * + * @license + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + * + * Copyright (c) 2011-2016 Jos de Jong, http://jsoneditoronline.org + * + * @author Jos de Jong, + * @version 5.5.10 + * @date 2016-11-02 + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports["JSONEditor"] = factory(); + else + root["JSONEditor"] = factory(); +})(this, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; + +/******/ // The require function +/******/ function __webpack_require__(moduleId) { + +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; + +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; + +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + +/******/ // Flag the module as loaded +/******/ module.loaded = true; + +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } + + +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; + +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; + +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; + +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var Ajv; + try { + Ajv = __webpack_require__(1); + } + catch (err) { + // no problem... when we need Ajv we will throw a neat exception + } + + var treemode = __webpack_require__(51); + var textmode = __webpack_require__(62); + var util = __webpack_require__(54); + + /** + * @constructor JSONEditor + * @param {Element} container Container element + * @param {Object} [options] Object with options. available options: + * {String} mode Editor mode. Available values: + * 'tree' (default), 'view', + * 'form', 'text', and 'code'. + * {function} onChange Callback method, triggered + * on change of contents + * {function} onError Callback method, triggered + * when an error occurs + * {Boolean} search Enable search box. + * True by default + * Only applicable for modes + * 'tree', 'view', and 'form' + * {Boolean} history Enable history (undo/redo). + * True by default + * Only applicable for modes + * 'tree', 'view', and 'form' + * {String} name Field name for the root node. + * Only applicable for modes + * 'tree', 'view', and 'form' + * {Number} indentation Number of indentation + * spaces. 4 by default. + * Only applicable for + * modes 'text' and 'code' + * {boolean} escapeUnicode If true, unicode + * characters are escaped. + * false by default. + * {boolean} sortObjectKeys If true, object keys are + * sorted before display. + * false by default. + * @param {Object | undefined} json JSON object + */ + function JSONEditor (container, options, json) { + if (!(this instanceof JSONEditor)) { + throw new Error('JSONEditor constructor called without "new".'); + } + + // check for unsupported browser (IE8 and older) + var ieVersion = util.getInternetExplorerVersion(); + if (ieVersion != -1 && ieVersion < 9) { + throw new Error('Unsupported browser, IE9 or newer required. ' + + 'Please install the newest version of your browser.'); + } + + if (options) { + // check for deprecated options + if (options.error) { + console.warn('Option "error" has been renamed to "onError"'); + options.onError = options.error; + delete options.error; + } + if (options.change) { + console.warn('Option "change" has been renamed to "onChange"'); + options.onChange = options.change; + delete options.change; + } + if (options.editable) { + console.warn('Option "editable" has been renamed to "onEditable"'); + options.onEditable = options.editable; + delete options.editable; + } + + // validate options + if (options) { + var VALID_OPTIONS = [ + 'ace', 'theme', + 'ajv', 'schema', + 'onChange', 'onEditable', 'onError', 'onModeChange', + 'escapeUnicode', 'history', 'search', 'mode', 'modes', 'name', 'indentation', 'sortObjectKeys' + ]; + + Object.keys(options).forEach(function (option) { + if (VALID_OPTIONS.indexOf(option) === -1) { + console.warn('Unknown option "' + option + '". This option will be ignored'); + } + }); + } + } + + if (arguments.length) { + this._create(container, options, json); + } + } + + /** + * Configuration for all registered modes. Example: + * { + * tree: { + * mixin: TreeEditor, + * data: 'json' + * }, + * text: { + * mixin: TextEditor, + * data: 'text' + * } + * } + * + * @type { Object. } + */ + JSONEditor.modes = {}; + + // debounce interval for JSON schema vaidation in milliseconds + JSONEditor.prototype.DEBOUNCE_INTERVAL = 150; + + /** + * Create the JSONEditor + * @param {Element} container Container element + * @param {Object} [options] See description in constructor + * @param {Object | undefined} json JSON object + * @private + */ + JSONEditor.prototype._create = function (container, options, json) { + this.container = container; + this.options = options || {}; + this.json = json || {}; + + var mode = this.options.mode || 'tree'; + this.setMode(mode); + }; + + /** + * Destroy the editor. Clean up DOM, event listeners, and web workers. + */ + JSONEditor.prototype.destroy = function () {}; + + /** + * Set JSON object in editor + * @param {Object | undefined} json JSON data + */ + JSONEditor.prototype.set = function (json) { + this.json = json; + }; + + /** + * Get JSON from the editor + * @returns {Object} json + */ + JSONEditor.prototype.get = function () { + return this.json; + }; + + /** + * Set string containing JSON for the editor + * @param {String | undefined} jsonText + */ + JSONEditor.prototype.setText = function (jsonText) { + this.json = util.parse(jsonText); + }; + + /** + * Get stringified JSON contents from the editor + * @returns {String} jsonText + */ + JSONEditor.prototype.getText = function () { + return JSON.stringify(this.json); + }; + + /** + * Set a field name for the root node. + * @param {String | undefined} name + */ + JSONEditor.prototype.setName = function (name) { + if (!this.options) { + this.options = {}; + } + this.options.name = name; + }; + + /** + * Get the field name for the root node. + * @return {String | undefined} name + */ + JSONEditor.prototype.getName = function () { + return this.options && this.options.name; + }; + + /** + * Change the mode of the editor. + * JSONEditor will be extended with all methods needed for the chosen mode. + * @param {String} mode Available modes: 'tree' (default), 'view', 'form', + * 'text', and 'code'. + */ + JSONEditor.prototype.setMode = function (mode) { + var container = this.container; + var options = util.extend({}, this.options); + var oldMode = options.mode; + var data; + var name; + + options.mode = mode; + var config = JSONEditor.modes[mode]; + if (config) { + try { + var asText = (config.data == 'text'); + name = this.getName(); + data = this[asText ? 'getText' : 'get'](); // get text or json + + this.destroy(); + util.clear(this); + util.extend(this, config.mixin); + this.create(container, options); + + this.setName(name); + this[asText ? 'setText' : 'set'](data); // set text or json + + if (typeof config.load === 'function') { + try { + config.load.call(this); + } + catch (err) { + console.error(err); + } + } + + if (typeof options.onModeChange === 'function' && mode !== oldMode) { + try { + options.onModeChange(mode, oldMode); + } + catch (err) { + console.error(err); + } + } + } + catch (err) { + this._onError(err); + } + } + else { + throw new Error('Unknown mode "' + options.mode + '"'); + } + }; + + /** + * Get the current mode + * @return {string} + */ + JSONEditor.prototype.getMode = function () { + return this.options.mode; + }; + + /** + * Throw an error. If an error callback is configured in options.error, this + * callback will be invoked. Else, a regular error is thrown. + * @param {Error} err + * @private + */ + JSONEditor.prototype._onError = function(err) { + if (this.options && typeof this.options.onError === 'function') { + this.options.onError(err); + } + else { + throw err; + } + }; + + /** + * Set a JSON schema for validation of the JSON object. + * To remove the schema, call JSONEditor.setSchema(null) + * @param {Object | null} schema + */ + JSONEditor.prototype.setSchema = function (schema) { + // compile a JSON schema validator if a JSON schema is provided + if (schema) { + var ajv; + try { + // grab ajv from options if provided, else create a new instance + ajv = this.options.ajv || Ajv({ allErrors: true, verbose: true }); + + } + catch (err) { + console.warn('Failed to create an instance of Ajv, JSON Schema validation is not available. Please use a JSONEditor bundle including Ajv, or pass an instance of Ajv as via the configuration option `ajv`.'); + } + + if (ajv) { + this.validateSchema = ajv.compile(schema); + + // add schema to the options, so that when switching to an other mode, + // the set schema is not lost + this.options.schema = schema; + + // validate now + this.validate(); + } + + this.refresh(); // update DOM + } + else { + // remove current schema + this.validateSchema = null; + this.options.schema = null; + this.validate(); // to clear current error messages + this.refresh(); // update DOM + } + }; + + /** + * Validate current JSON object against the configured JSON schema + * Throws an exception when no JSON schema is configured + */ + JSONEditor.prototype.validate = function () { + // must be implemented by treemode and textmode + }; + + /** + * Refresh the rendered contents + */ + JSONEditor.prototype.refresh = function () { + // can be implemented by treemode and textmode + }; + + /** + * Register a plugin with one ore multiple modes for the JSON Editor. + * + * A mode is described as an object with properties: + * + * - `mode: String` The name of the mode. + * - `mixin: Object` An object containing the mixin functions which + * will be added to the JSONEditor. Must contain functions + * create, get, getText, set, and setText. May have + * additional functions. + * When the JSONEditor switches to a mixin, all mixin + * functions are added to the JSONEditor, and then + * the function `create(container, options)` is executed. + * - `data: 'text' | 'json'` The type of data that will be used to load the mixin. + * - `[load: function]` An optional function called after the mixin + * has been loaded. + * + * @param {Object | Array} mode A mode object or an array with multiple mode objects. + */ + JSONEditor.registerMode = function (mode) { + var i, prop; + + if (util.isArray(mode)) { + // multiple modes + for (i = 0; i < mode.length; i++) { + JSONEditor.registerMode(mode[i]); + } + } + else { + // validate the new mode + if (!('mode' in mode)) throw new Error('Property "mode" missing'); + if (!('mixin' in mode)) throw new Error('Property "mixin" missing'); + if (!('data' in mode)) throw new Error('Property "data" missing'); + var name = mode.mode; + if (name in JSONEditor.modes) { + throw new Error('Mode "' + name + '" already registered'); + } + + // validate the mixin + if (typeof mode.mixin.create !== 'function') { + throw new Error('Required function "create" missing on mixin'); + } + var reserved = ['setMode', 'registerMode', 'modes']; + for (i = 0; i < reserved.length; i++) { + prop = reserved[i]; + if (prop in mode.mixin) { + throw new Error('Reserved property "' + prop + '" not allowed in mixin'); + } + } + + JSONEditor.modes[name] = mode; + } + }; + + // register tree and text modes + JSONEditor.registerMode(treemode); + JSONEditor.registerMode(textmode); + + module.exports = JSONEditor; + + +/***/ }, +/* 1 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var compileSchema = __webpack_require__(2) + , resolve = __webpack_require__(3) + , Cache = __webpack_require__(21) + , SchemaObject = __webpack_require__(16) + , stableStringify = __webpack_require__(12) + , formats = __webpack_require__(22) + , rules = __webpack_require__(23) + , v5 = __webpack_require__(43) + , util = __webpack_require__(11) + , async = __webpack_require__(17) + , co = __webpack_require__(19); + + module.exports = Ajv; + + Ajv.prototype.compileAsync = async.compile; + Ajv.prototype.addKeyword = __webpack_require__(49); + Ajv.ValidationError = __webpack_require__(20); + + var META_SCHEMA_ID = 'http://json-schema.org/draft-04/schema'; + var SCHEMA_URI_FORMAT = /^(?:(?:[a-z][a-z0-9+-.]*:)?\/\/)?[^\s]*$/i; + function SCHEMA_URI_FORMAT_FUNC(str) { + return SCHEMA_URI_FORMAT.test(str); + } + + var META_IGNORE_OPTIONS = [ 'removeAdditional', 'useDefaults', 'coerceTypes' ]; + + /** + * Creates validator instance. + * Usage: `Ajv(opts)` + * @param {Object} opts optional options + * @return {Object} ajv instance + */ + function Ajv(opts) { + if (!(this instanceof Ajv)) return new Ajv(opts); + var self = this; + + opts = this._opts = util.copy(opts) || {}; + this._schemas = {}; + this._refs = {}; + this._formats = formats(opts.format); + this._cache = opts.cache || new Cache; + this._loadingSchemas = {}; + this.RULES = rules(); + + // this is done on purpose, so that methods are bound to the instance + // (without using bind) so that they can be used without the instance + this.validate = validate; + this.compile = compile; + this.addSchema = addSchema; + this.addMetaSchema = addMetaSchema; + this.validateSchema = validateSchema; + this.getSchema = getSchema; + this.removeSchema = removeSchema; + this.addFormat = addFormat; + this.errorsText = errorsText; + + this._addSchema = _addSchema; + this._compile = _compile; + + opts.loopRequired = opts.loopRequired || Infinity; + if (opts.async || opts.transpile) async.setup(opts); + if (opts.beautify === true) opts.beautify = { indent_size: 2 }; + if (opts.errorDataPath == 'property') opts._errorDataPathProperty = true; + this._metaOpts = getMetaSchemaOptions(); + + addInitialSchemas(); + if (opts.formats) addInitialFormats(); + if (opts.v5) v5.enable(this); + if (typeof opts.meta == 'object') addMetaSchema(opts.meta); + + + /** + * Validate data using schema + * Schema will be compiled and cached (using serialized JSON as key. [json-stable-stringify](https://github.com/substack/json-stable-stringify) is used to serialize. + * @param {String|Object} schemaKeyRef key, ref or schema object + * @param {Any} data to be validated + * @return {Boolean} validation result. Errors from the last validation will be available in `ajv.errors` (and also in compiled schema: `schema.errors`). + */ + function validate(schemaKeyRef, data) { + var v; + if (typeof schemaKeyRef == 'string') { + v = getSchema(schemaKeyRef); + if (!v) throw new Error('no schema with key or ref "' + schemaKeyRef + '"'); + } else { + var schemaObj = _addSchema(schemaKeyRef); + v = schemaObj.validate || _compile(schemaObj); + } + + var valid = v(data); + if (v.async) return self._opts.async == '*' ? co(valid) : valid; + self.errors = v.errors; + return valid; + } + + + /** + * Create validating function for passed schema. + * @param {Object} schema schema object + * @return {Function} validating function + */ + function compile(schema) { + var schemaObj = _addSchema(schema); + return schemaObj.validate || _compile(schemaObj); + } + + + /** + * Adds schema to the instance. + * @param {Object|Array} schema schema or array of schemas. If array is passed, `key` and other parameters will be ignored. + * @param {String} key Optional schema key. Can be passed to `validate` method instead of schema object or id/ref. One schema per instance can have empty `id` and `key`. + * @param {Boolean} _skipValidation true to skip schema validation. Used internally, option validateSchema should be used instead. + * @param {Boolean} _meta true if schema is a meta-schema. Used internally, addMetaSchema should be used instead. + */ + function addSchema(schema, key, _skipValidation, _meta) { + if (Array.isArray(schema)){ + for (var i=0; i} errors optional array of validation errors, if not passed errors from the instance are used. + * @param {Object} options optional options with properties `separator` and `dataVar`. + * @return {String} human readable string with all errors descriptions + */ + function errorsText(errors, options) { + errors = errors || self.errors; + if (!errors) return 'No errors'; + options = options || {}; + var separator = options.separator === undefined ? ', ' : options.separator; + var dataVar = options.dataVar === undefined ? 'data' : options.dataVar; + + var text = ''; + for (var i=0; i', '"', '`', ' ', '\r', '\n', '\t'], + + // RFC 2396: characters not allowed for various reasons. + unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims), + + // Allowed by RFCs, but cause of XSS attacks. Always escape these. + autoEscape = ['\''].concat(unwise), + // Characters that are never ever allowed in a hostname. + // Note that any invalid chars are also handled, but these + // are the ones that are *expected* to be seen, so we fast-path + // them. + nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape), + hostEndingChars = ['/', '?', '#'], + hostnameMaxLen = 255, + hostnamePartPattern = /^[a-z0-9A-Z_-]{0,63}$/, + hostnamePartStart = /^([a-z0-9A-Z_-]{0,63})(.*)$/, + // protocols that can allow "unsafe" and "unwise" chars. + unsafeProtocol = { + 'javascript': true, + 'javascript:': true + }, + // protocols that never have a hostname. + hostlessProtocol = { + 'javascript': true, + 'javascript:': true + }, + // protocols that always contain a // bit. + slashedProtocol = { + 'http': true, + 'https': true, + 'ftp': true, + 'gopher': true, + 'file': true, + 'http:': true, + 'https:': true, + 'ftp:': true, + 'gopher:': true, + 'file:': true + }, + querystring = __webpack_require__(7); + + function urlParse(url, parseQueryString, slashesDenoteHost) { + if (url && isObject(url) && url instanceof Url) return url; + + var u = new Url; + u.parse(url, parseQueryString, slashesDenoteHost); + return u; + } + + Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { + if (!isString(url)) { + throw new TypeError("Parameter 'url' must be a string, not " + typeof url); + } + + var rest = url; + + // trim before proceeding. + // This is to support parse stuff like " http://foo.com \n" + rest = rest.trim(); + + var proto = protocolPattern.exec(rest); + if (proto) { + proto = proto[0]; + var lowerProto = proto.toLowerCase(); + this.protocol = lowerProto; + rest = rest.substr(proto.length); + } + + // figure out if it's got a host + // user@server is *always* interpreted as a hostname, and url + // resolution will treat //foo/bar as host=foo,path=bar because that's + // how the browser resolves relative URLs. + if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) { + var slashes = rest.substr(0, 2) === '//'; + if (slashes && !(proto && hostlessProtocol[proto])) { + rest = rest.substr(2); + this.slashes = true; + } + } + + if (!hostlessProtocol[proto] && + (slashes || (proto && !slashedProtocol[proto]))) { + + // there's a hostname. + // the first instance of /, ?, ;, or # ends the host. + // + // If there is an @ in the hostname, then non-host chars *are* allowed + // to the left of the last @ sign, unless some host-ending character + // comes *before* the @-sign. + // URLs are obnoxious. + // + // ex: + // http://a@b@c/ => user:a@b host:c + // http://a@b?@c => user:a host:c path:/?@c + + // v0.12 TODO(isaacs): This is not quite how Chrome does things. + // Review our test case against browsers more comprehensively. + + // find the first instance of any hostEndingChars + var hostEnd = -1; + for (var i = 0; i < hostEndingChars.length; i++) { + var hec = rest.indexOf(hostEndingChars[i]); + if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) + hostEnd = hec; + } + + // at this point, either we have an explicit point where the + // auth portion cannot go past, or the last @ char is the decider. + var auth, atSign; + if (hostEnd === -1) { + // atSign can be anywhere. + atSign = rest.lastIndexOf('@'); + } else { + // atSign must be in auth portion. + // http://a@b/c@d => host:b auth:a path:/c@d + atSign = rest.lastIndexOf('@', hostEnd); + } + + // Now we have a portion which is definitely the auth. + // Pull that off. + if (atSign !== -1) { + auth = rest.slice(0, atSign); + rest = rest.slice(atSign + 1); + this.auth = decodeURIComponent(auth); + } + + // the host is the remaining to the left of the first non-host char + hostEnd = -1; + for (var i = 0; i < nonHostChars.length; i++) { + var hec = rest.indexOf(nonHostChars[i]); + if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) + hostEnd = hec; + } + // if we still have not hit it, then the entire thing is a host. + if (hostEnd === -1) + hostEnd = rest.length; + + this.host = rest.slice(0, hostEnd); + rest = rest.slice(hostEnd); + + // pull out port. + this.parseHost(); + + // we've indicated that there is a hostname, + // so even if it's empty, it has to be present. + this.hostname = this.hostname || ''; + + // if hostname begins with [ and ends with ] + // assume that it's an IPv6 address. + var ipv6Hostname = this.hostname[0] === '[' && + this.hostname[this.hostname.length - 1] === ']'; + + // validate a little. + if (!ipv6Hostname) { + var hostparts = this.hostname.split(/\./); + for (var i = 0, l = hostparts.length; i < l; i++) { + var part = hostparts[i]; + if (!part) continue; + if (!part.match(hostnamePartPattern)) { + var newpart = ''; + for (var j = 0, k = part.length; j < k; j++) { + if (part.charCodeAt(j) > 127) { + // we replace non-ASCII char with a temporary placeholder + // we need this to make sure size of hostname is not + // broken by replacing non-ASCII by nothing + newpart += 'x'; + } else { + newpart += part[j]; + } + } + // we test again with ASCII char only + if (!newpart.match(hostnamePartPattern)) { + var validParts = hostparts.slice(0, i); + var notHost = hostparts.slice(i + 1); + var bit = part.match(hostnamePartStart); + if (bit) { + validParts.push(bit[1]); + notHost.unshift(bit[2]); + } + if (notHost.length) { + rest = '/' + notHost.join('.') + rest; + } + this.hostname = validParts.join('.'); + break; + } + } + } + } + + if (this.hostname.length > hostnameMaxLen) { + this.hostname = ''; + } else { + // hostnames are always lower case. + this.hostname = this.hostname.toLowerCase(); + } + + if (!ipv6Hostname) { + // IDNA Support: Returns a puny coded representation of "domain". + // It only converts the part of the domain name that + // has non ASCII characters. I.e. it dosent matter if + // you call it with a domain that already is in ASCII. + var domainArray = this.hostname.split('.'); + var newOut = []; + for (var i = 0; i < domainArray.length; ++i) { + var s = domainArray[i]; + newOut.push(s.match(/[^A-Za-z0-9_-]/) ? + 'xn--' + punycode.encode(s) : s); + } + this.hostname = newOut.join('.'); + } + + var p = this.port ? ':' + this.port : ''; + var h = this.hostname || ''; + this.host = h + p; + this.href += this.host; + + // strip [ and ] from the hostname + // the host field still retains them, though + if (ipv6Hostname) { + this.hostname = this.hostname.substr(1, this.hostname.length - 2); + if (rest[0] !== '/') { + rest = '/' + rest; + } + } + } + + // now rest is set to the post-host stuff. + // chop off any delim chars. + if (!unsafeProtocol[lowerProto]) { + + // First, make 100% sure that any "autoEscape" chars get + // escaped, even if encodeURIComponent doesn't think they + // need to be. + for (var i = 0, l = autoEscape.length; i < l; i++) { + var ae = autoEscape[i]; + var esc = encodeURIComponent(ae); + if (esc === ae) { + esc = escape(ae); + } + rest = rest.split(ae).join(esc); + } + } + + + // chop off from the tail first. + var hash = rest.indexOf('#'); + if (hash !== -1) { + // got a fragment string. + this.hash = rest.substr(hash); + rest = rest.slice(0, hash); + } + var qm = rest.indexOf('?'); + if (qm !== -1) { + this.search = rest.substr(qm); + this.query = rest.substr(qm + 1); + if (parseQueryString) { + this.query = querystring.parse(this.query); + } + rest = rest.slice(0, qm); + } else if (parseQueryString) { + // no query string, but parseQueryString still requested + this.search = ''; + this.query = {}; + } + if (rest) this.pathname = rest; + if (slashedProtocol[lowerProto] && + this.hostname && !this.pathname) { + this.pathname = '/'; + } + + //to support http.request + if (this.pathname || this.search) { + var p = this.pathname || ''; + var s = this.search || ''; + this.path = p + s; + } + + // finally, reconstruct the href based on what has been validated. + this.href = this.format(); + return this; + }; + + // format a parsed object into a url string + function urlFormat(obj) { + // ensure it's an object, and not a string url. + // If it's an obj, this is a no-op. + // this way, you can call url_format() on strings + // to clean up potentially wonky urls. + if (isString(obj)) obj = urlParse(obj); + if (!(obj instanceof Url)) return Url.prototype.format.call(obj); + return obj.format(); + } + + Url.prototype.format = function() { + var auth = this.auth || ''; + if (auth) { + auth = encodeURIComponent(auth); + auth = auth.replace(/%3A/i, ':'); + auth += '@'; + } + + var protocol = this.protocol || '', + pathname = this.pathname || '', + hash = this.hash || '', + host = false, + query = ''; + + if (this.host) { + host = auth + this.host; + } else if (this.hostname) { + host = auth + (this.hostname.indexOf(':') === -1 ? + this.hostname : + '[' + this.hostname + ']'); + if (this.port) { + host += ':' + this.port; + } + } + + if (this.query && + isObject(this.query) && + Object.keys(this.query).length) { + query = querystring.stringify(this.query); + } + + var search = this.search || (query && ('?' + query)) || ''; + + if (protocol && protocol.substr(-1) !== ':') protocol += ':'; + + // only the slashedProtocols get the //. Not mailto:, xmpp:, etc. + // unless they had them to begin with. + if (this.slashes || + (!protocol || slashedProtocol[protocol]) && host !== false) { + host = '//' + (host || ''); + if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname; + } else if (!host) { + host = ''; + } + + if (hash && hash.charAt(0) !== '#') hash = '#' + hash; + if (search && search.charAt(0) !== '?') search = '?' + search; + + pathname = pathname.replace(/[?#]/g, function(match) { + return encodeURIComponent(match); + }); + search = search.replace('#', '%23'); + + return protocol + host + pathname + search + hash; + }; + + function urlResolve(source, relative) { + return urlParse(source, false, true).resolve(relative); + } + + Url.prototype.resolve = function(relative) { + return this.resolveObject(urlParse(relative, false, true)).format(); + }; + + function urlResolveObject(source, relative) { + if (!source) return relative; + return urlParse(source, false, true).resolveObject(relative); + } + + Url.prototype.resolveObject = function(relative) { + if (isString(relative)) { + var rel = new Url(); + rel.parse(relative, false, true); + relative = rel; + } + + var result = new Url(); + Object.keys(this).forEach(function(k) { + result[k] = this[k]; + }, this); + + // hash is always overridden, no matter what. + // even href="" will remove it. + result.hash = relative.hash; + + // if the relative url is empty, then there's nothing left to do here. + if (relative.href === '') { + result.href = result.format(); + return result; + } + + // hrefs like //foo/bar always cut to the protocol. + if (relative.slashes && !relative.protocol) { + // take everything except the protocol from relative + Object.keys(relative).forEach(function(k) { + if (k !== 'protocol') + result[k] = relative[k]; + }); + + //urlParse appends trailing / to urls like http://www.example.com + if (slashedProtocol[result.protocol] && + result.hostname && !result.pathname) { + result.path = result.pathname = '/'; + } + + result.href = result.format(); + return result; + } + + if (relative.protocol && relative.protocol !== result.protocol) { + // if it's a known url protocol, then changing + // the protocol does weird things + // first, if it's not file:, then we MUST have a host, + // and if there was a path + // to begin with, then we MUST have a path. + // if it is file:, then the host is dropped, + // because that's known to be hostless. + // anything else is assumed to be absolute. + if (!slashedProtocol[relative.protocol]) { + Object.keys(relative).forEach(function(k) { + result[k] = relative[k]; + }); + result.href = result.format(); + return result; + } + + result.protocol = relative.protocol; + if (!relative.host && !hostlessProtocol[relative.protocol]) { + var relPath = (relative.pathname || '').split('/'); + while (relPath.length && !(relative.host = relPath.shift())); + if (!relative.host) relative.host = ''; + if (!relative.hostname) relative.hostname = ''; + if (relPath[0] !== '') relPath.unshift(''); + if (relPath.length < 2) relPath.unshift(''); + result.pathname = relPath.join('/'); + } else { + result.pathname = relative.pathname; + } + result.search = relative.search; + result.query = relative.query; + result.host = relative.host || ''; + result.auth = relative.auth; + result.hostname = relative.hostname || relative.host; + result.port = relative.port; + // to support http.request + if (result.pathname || result.search) { + var p = result.pathname || ''; + var s = result.search || ''; + result.path = p + s; + } + result.slashes = result.slashes || relative.slashes; + result.href = result.format(); + return result; + } + + var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'), + isRelAbs = ( + relative.host || + relative.pathname && relative.pathname.charAt(0) === '/' + ), + mustEndAbs = (isRelAbs || isSourceAbs || + (result.host && relative.pathname)), + removeAllDots = mustEndAbs, + srcPath = result.pathname && result.pathname.split('/') || [], + relPath = relative.pathname && relative.pathname.split('/') || [], + psychotic = result.protocol && !slashedProtocol[result.protocol]; + + // if the url is a non-slashed url, then relative + // links like ../.. should be able + // to crawl up to the hostname, as well. This is strange. + // result.protocol has already been set by now. + // Later on, put the first path part into the host field. + if (psychotic) { + result.hostname = ''; + result.port = null; + if (result.host) { + if (srcPath[0] === '') srcPath[0] = result.host; + else srcPath.unshift(result.host); + } + result.host = ''; + if (relative.protocol) { + relative.hostname = null; + relative.port = null; + if (relative.host) { + if (relPath[0] === '') relPath[0] = relative.host; + else relPath.unshift(relative.host); + } + relative.host = null; + } + mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === ''); + } + + if (isRelAbs) { + // it's absolute. + result.host = (relative.host || relative.host === '') ? + relative.host : result.host; + result.hostname = (relative.hostname || relative.hostname === '') ? + relative.hostname : result.hostname; + result.search = relative.search; + result.query = relative.query; + srcPath = relPath; + // fall through to the dot-handling below. + } else if (relPath.length) { + // it's relative + // throw away the existing file, and take the new path instead. + if (!srcPath) srcPath = []; + srcPath.pop(); + srcPath = srcPath.concat(relPath); + result.search = relative.search; + result.query = relative.query; + } else if (!isNullOrUndefined(relative.search)) { + // just pull out the search. + // like href='?foo'. + // Put this after the other two cases because it simplifies the booleans + if (psychotic) { + result.hostname = result.host = srcPath.shift(); + //occationaly the auth can get stuck only in host + //this especialy happens in cases like + //url.resolveObject('mailto:local1@domain1', 'local2@domain2') + var authInHost = result.host && result.host.indexOf('@') > 0 ? + result.host.split('@') : false; + if (authInHost) { + result.auth = authInHost.shift(); + result.host = result.hostname = authInHost.shift(); + } + } + result.search = relative.search; + result.query = relative.query; + //to support http.request + if (!isNull(result.pathname) || !isNull(result.search)) { + result.path = (result.pathname ? result.pathname : '') + + (result.search ? result.search : ''); + } + result.href = result.format(); + return result; + } + + if (!srcPath.length) { + // no path at all. easy. + // we've already handled the other stuff above. + result.pathname = null; + //to support http.request + if (result.search) { + result.path = '/' + result.search; + } else { + result.path = null; + } + result.href = result.format(); + return result; + } + + // if a url ENDs in . or .., then it must get a trailing slash. + // however, if it ends in anything else non-slashy, + // then it must NOT get a trailing slash. + var last = srcPath.slice(-1)[0]; + var hasTrailingSlash = ( + (result.host || relative.host) && (last === '.' || last === '..') || + last === ''); + + // strip single dots, resolve double dots to parent dir + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = srcPath.length; i >= 0; i--) { + last = srcPath[i]; + if (last == '.') { + srcPath.splice(i, 1); + } else if (last === '..') { + srcPath.splice(i, 1); + up++; + } else if (up) { + srcPath.splice(i, 1); + up--; + } + } + + // if the path is allowed to go above the root, restore leading ..s + if (!mustEndAbs && !removeAllDots) { + for (; up--; up) { + srcPath.unshift('..'); + } + } + + if (mustEndAbs && srcPath[0] !== '' && + (!srcPath[0] || srcPath[0].charAt(0) !== '/')) { + srcPath.unshift(''); + } + + if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) { + srcPath.push(''); + } + + var isAbsolute = srcPath[0] === '' || + (srcPath[0] && srcPath[0].charAt(0) === '/'); + + // put the host back + if (psychotic) { + result.hostname = result.host = isAbsolute ? '' : + srcPath.length ? srcPath.shift() : ''; + //occationaly the auth can get stuck only in host + //this especialy happens in cases like + //url.resolveObject('mailto:local1@domain1', 'local2@domain2') + var authInHost = result.host && result.host.indexOf('@') > 0 ? + result.host.split('@') : false; + if (authInHost) { + result.auth = authInHost.shift(); + result.host = result.hostname = authInHost.shift(); + } + } + + mustEndAbs = mustEndAbs || (result.host && srcPath.length); + + if (mustEndAbs && !isAbsolute) { + srcPath.unshift(''); + } + + if (!srcPath.length) { + result.pathname = null; + result.path = null; + } else { + result.pathname = srcPath.join('/'); + } + + //to support request.http + if (!isNull(result.pathname) || !isNull(result.search)) { + result.path = (result.pathname ? result.pathname : '') + + (result.search ? result.search : ''); + } + result.auth = relative.auth || result.auth; + result.slashes = result.slashes || relative.slashes; + result.href = result.format(); + return result; + }; + + Url.prototype.parseHost = function() { + var host = this.host; + var port = portPattern.exec(host); + if (port) { + port = port[0]; + if (port !== ':') { + this.port = port.substr(1); + } + host = host.substr(0, host.length - port.length); + } + if (host) this.hostname = host; + }; + + function isString(arg) { + return typeof arg === "string"; + } + + function isObject(arg) { + return typeof arg === 'object' && arg !== null; + } + + function isNull(arg) { + return arg === null; + } + function isNullOrUndefined(arg) { + return arg == null; + } + + +/***/ }, +/* 5 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/punycode v1.3.2 by @mathias */ + ;(function(root) { + + /** Detect free variables */ + var freeExports = typeof exports == 'object' && exports && + !exports.nodeType && exports; + var freeModule = typeof module == 'object' && module && + !module.nodeType && module; + var freeGlobal = typeof global == 'object' && global; + if ( + freeGlobal.global === freeGlobal || + freeGlobal.window === freeGlobal || + freeGlobal.self === freeGlobal + ) { + root = freeGlobal; + } + + /** + * The `punycode` object. + * @name punycode + * @type Object + */ + var punycode, + + /** Highest positive signed 32-bit float value */ + maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1 + + /** Bootstring parameters */ + base = 36, + tMin = 1, + tMax = 26, + skew = 38, + damp = 700, + initialBias = 72, + initialN = 128, // 0x80 + delimiter = '-', // '\x2D' + + /** Regular expressions */ + regexPunycode = /^xn--/, + regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars + regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators + + /** Error messages */ + errors = { + 'overflow': 'Overflow: input needs wider integers to process', + 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', + 'invalid-input': 'Invalid input' + }, + + /** Convenience shortcuts */ + baseMinusTMin = base - tMin, + floor = Math.floor, + stringFromCharCode = String.fromCharCode, + + /** Temporary variable */ + key; + + /*--------------------------------------------------------------------------*/ + + /** + * A generic error utility function. + * @private + * @param {String} type The error type. + * @returns {Error} Throws a `RangeError` with the applicable error message. + */ + function error(type) { + throw RangeError(errors[type]); + } + + /** + * A generic `Array#map` utility function. + * @private + * @param {Array} array The array to iterate over. + * @param {Function} callback The function that gets called for every array + * item. + * @returns {Array} A new array of values returned by the callback function. + */ + function map(array, fn) { + var length = array.length; + var result = []; + while (length--) { + result[length] = fn(array[length]); + } + return result; + } + + /** + * A simple `Array#map`-like wrapper to work with domain name strings or email + * addresses. + * @private + * @param {String} domain The domain name or email address. + * @param {Function} callback The function that gets called for every + * character. + * @returns {Array} A new string of characters returned by the callback + * function. + */ + function mapDomain(string, fn) { + var parts = string.split('@'); + var result = ''; + if (parts.length > 1) { + // In email addresses, only the domain name should be punycoded. Leave + // the local part (i.e. everything up to `@`) intact. + result = parts[0] + '@'; + string = parts[1]; + } + // Avoid `split(regex)` for IE8 compatibility. See #17. + string = string.replace(regexSeparators, '\x2E'); + var labels = string.split('.'); + var encoded = map(labels, fn).join('.'); + return result + encoded; + } + + /** + * Creates an array containing the numeric code points of each Unicode + * character in the string. While JavaScript uses UCS-2 internally, + * this function will convert a pair of surrogate halves (each of which + * UCS-2 exposes as separate characters) into a single code point, + * matching UTF-16. + * @see `punycode.ucs2.encode` + * @see + * @memberOf punycode.ucs2 + * @name decode + * @param {String} string The Unicode input string (UCS-2). + * @returns {Array} The new array of code points. + */ + function ucs2decode(string) { + var output = [], + counter = 0, + length = string.length, + value, + extra; + while (counter < length) { + value = string.charCodeAt(counter++); + if (value >= 0xD800 && value <= 0xDBFF && counter < length) { + // high surrogate, and there is a next character + extra = string.charCodeAt(counter++); + if ((extra & 0xFC00) == 0xDC00) { // low surrogate + output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); + } else { + // unmatched surrogate; only append this code unit, in case the next + // code unit is the high surrogate of a surrogate pair + output.push(value); + counter--; + } + } else { + output.push(value); + } + } + return output; + } + + /** + * Creates a string based on an array of numeric code points. + * @see `punycode.ucs2.decode` + * @memberOf punycode.ucs2 + * @name encode + * @param {Array} codePoints The array of numeric code points. + * @returns {String} The new Unicode string (UCS-2). + */ + function ucs2encode(array) { + return map(array, function(value) { + var output = ''; + if (value > 0xFFFF) { + value -= 0x10000; + output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); + value = 0xDC00 | value & 0x3FF; + } + output += stringFromCharCode(value); + return output; + }).join(''); + } + + /** + * Converts a basic code point into a digit/integer. + * @see `digitToBasic()` + * @private + * @param {Number} codePoint The basic numeric code point value. + * @returns {Number} The numeric value of a basic code point (for use in + * representing integers) in the range `0` to `base - 1`, or `base` if + * the code point does not represent a value. + */ + function basicToDigit(codePoint) { + if (codePoint - 48 < 10) { + return codePoint - 22; + } + if (codePoint - 65 < 26) { + return codePoint - 65; + } + if (codePoint - 97 < 26) { + return codePoint - 97; + } + return base; + } + + /** + * Converts a digit/integer into a basic code point. + * @see `basicToDigit()` + * @private + * @param {Number} digit The numeric value of a basic code point. + * @returns {Number} The basic code point whose value (when used for + * representing integers) is `digit`, which needs to be in the range + * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is + * used; else, the lowercase form is used. The behavior is undefined + * if `flag` is non-zero and `digit` has no uppercase form. + */ + function digitToBasic(digit, flag) { + // 0..25 map to ASCII a..z or A..Z + // 26..35 map to ASCII 0..9 + return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); + } + + /** + * Bias adaptation function as per section 3.4 of RFC 3492. + * http://tools.ietf.org/html/rfc3492#section-3.4 + * @private + */ + function adapt(delta, numPoints, firstTime) { + var k = 0; + delta = firstTime ? floor(delta / damp) : delta >> 1; + delta += floor(delta / numPoints); + for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) { + delta = floor(delta / baseMinusTMin); + } + return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); + } + + /** + * Converts a Punycode string of ASCII-only symbols to a string of Unicode + * symbols. + * @memberOf punycode + * @param {String} input The Punycode string of ASCII-only symbols. + * @returns {String} The resulting string of Unicode symbols. + */ + function decode(input) { + // Don't use UCS-2 + var output = [], + inputLength = input.length, + out, + i = 0, + n = initialN, + bias = initialBias, + basic, + j, + index, + oldi, + w, + k, + digit, + t, + /** Cached calculation results */ + baseMinusT; + + // Handle the basic code points: let `basic` be the number of input code + // points before the last delimiter, or `0` if there is none, then copy + // the first basic code points to the output. + + basic = input.lastIndexOf(delimiter); + if (basic < 0) { + basic = 0; + } + + for (j = 0; j < basic; ++j) { + // if it's not a basic code point + if (input.charCodeAt(j) >= 0x80) { + error('not-basic'); + } + output.push(input.charCodeAt(j)); + } + + // Main decoding loop: start just after the last delimiter if any basic code + // points were copied; start at the beginning otherwise. + + for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { + + // `index` is the index of the next character to be consumed. + // Decode a generalized variable-length integer into `delta`, + // which gets added to `i`. The overflow checking is easier + // if we increase `i` as we go, then subtract off its starting + // value at the end to obtain `delta`. + for (oldi = i, w = 1, k = base; /* no condition */; k += base) { + + if (index >= inputLength) { + error('invalid-input'); + } + + digit = basicToDigit(input.charCodeAt(index++)); + + if (digit >= base || digit > floor((maxInt - i) / w)) { + error('overflow'); + } + + i += digit * w; + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + + if (digit < t) { + break; + } + + baseMinusT = base - t; + if (w > floor(maxInt / baseMinusT)) { + error('overflow'); + } + + w *= baseMinusT; + + } + + out = output.length + 1; + bias = adapt(i - oldi, out, oldi == 0); + + // `i` was supposed to wrap around from `out` to `0`, + // incrementing `n` each time, so we'll fix that now: + if (floor(i / out) > maxInt - n) { + error('overflow'); + } + + n += floor(i / out); + i %= out; + + // Insert `n` at position `i` of the output + output.splice(i++, 0, n); + + } + + return ucs2encode(output); + } + + /** + * Converts a string of Unicode symbols (e.g. a domain name label) to a + * Punycode string of ASCII-only symbols. + * @memberOf punycode + * @param {String} input The string of Unicode symbols. + * @returns {String} The resulting Punycode string of ASCII-only symbols. + */ + function encode(input) { + var n, + delta, + handledCPCount, + basicLength, + bias, + j, + m, + q, + k, + t, + currentValue, + output = [], + /** `inputLength` will hold the number of code points in `input`. */ + inputLength, + /** Cached calculation results */ + handledCPCountPlusOne, + baseMinusT, + qMinusT; + + // Convert the input in UCS-2 to Unicode + input = ucs2decode(input); + + // Cache the length + inputLength = input.length; + + // Initialize the state + n = initialN; + delta = 0; + bias = initialBias; + + // Handle the basic code points + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue < 0x80) { + output.push(stringFromCharCode(currentValue)); + } + } + + handledCPCount = basicLength = output.length; + + // `handledCPCount` is the number of code points that have been handled; + // `basicLength` is the number of basic code points. + + // Finish the basic string - if it is not empty - with a delimiter + if (basicLength) { + output.push(delimiter); + } + + // Main encoding loop: + while (handledCPCount < inputLength) { + + // All non-basic code points < n have been handled already. Find the next + // larger one: + for (m = maxInt, j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue >= n && currentValue < m) { + m = currentValue; + } + } + + // Increase `delta` enough to advance the decoder's state to , + // but guard against overflow + handledCPCountPlusOne = handledCPCount + 1; + if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { + error('overflow'); + } + + delta += (m - n) * handledCPCountPlusOne; + n = m; + + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + + if (currentValue < n && ++delta > maxInt) { + error('overflow'); + } + + if (currentValue == n) { + // Represent delta as a generalized variable-length integer + for (q = delta, k = base; /* no condition */; k += base) { + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + if (q < t) { + break; + } + qMinusT = q - t; + baseMinusT = base - t; + output.push( + stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) + ); + q = floor(qMinusT / baseMinusT); + } + + output.push(stringFromCharCode(digitToBasic(q, 0))); + bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); + delta = 0; + ++handledCPCount; + } + } + + ++delta; + ++n; + + } + return output.join(''); + } + + /** + * Converts a Punycode string representing a domain name or an email address + * to Unicode. Only the Punycoded parts of the input will be converted, i.e. + * it doesn't matter if you call it on a string that has already been + * converted to Unicode. + * @memberOf punycode + * @param {String} input The Punycoded domain name or email address to + * convert to Unicode. + * @returns {String} The Unicode representation of the given Punycode + * string. + */ + function toUnicode(input) { + return mapDomain(input, function(string) { + return regexPunycode.test(string) + ? decode(string.slice(4).toLowerCase()) + : string; + }); + } + + /** + * Converts a Unicode string representing a domain name or an email address to + * Punycode. Only the non-ASCII parts of the domain name will be converted, + * i.e. it doesn't matter if you call it with a domain that's already in + * ASCII. + * @memberOf punycode + * @param {String} input The domain name or email address to convert, as a + * Unicode string. + * @returns {String} The Punycode representation of the given domain name or + * email address. + */ + function toASCII(input) { + return mapDomain(input, function(string) { + return regexNonASCII.test(string) + ? 'xn--' + encode(string) + : string; + }); + } + + /*--------------------------------------------------------------------------*/ + + /** Define the public API */ + punycode = { + /** + * A string representing the current Punycode.js version number. + * @memberOf punycode + * @type String + */ + 'version': '1.3.2', + /** + * An object of methods to convert from JavaScript's internal character + * representation (UCS-2) to Unicode code points, and back. + * @see + * @memberOf punycode + * @type Object + */ + 'ucs2': { + 'decode': ucs2decode, + 'encode': ucs2encode + }, + 'decode': decode, + 'encode': encode, + 'toASCII': toASCII, + 'toUnicode': toUnicode + }; + + /** Expose `punycode` */ + // Some AMD build optimizers, like r.js, check for specific condition patterns + // like the following: + if ( + true + ) { + !(__WEBPACK_AMD_DEFINE_RESULT__ = function() { + return punycode; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + } else if (freeExports && freeModule) { + if (module.exports == freeExports) { // in Node.js or RingoJS v0.8.0+ + freeModule.exports = punycode; + } else { // in Narwhal or RingoJS v0.7.0- + for (key in punycode) { + punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]); + } + } + } else { // in Rhino or a web browser + root.punycode = punycode; + } + + }(this)); + + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(6)(module), (function() { return this; }()))) + +/***/ }, +/* 6 */ +/***/ function(module, exports) { + + module.exports = function(module) { + if(!module.webpackPolyfill) { + module.deprecate = function() {}; + module.paths = []; + // module.parent = undefined by default + module.children = []; + module.webpackPolyfill = 1; + } + return module; + } + + +/***/ }, +/* 7 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + exports.decode = exports.parse = __webpack_require__(8); + exports.encode = exports.stringify = __webpack_require__(9); + + +/***/ }, +/* 8 */ +/***/ function(module, exports) { + + // Copyright Joyent, Inc. and other Node contributors. + // + // Permission is hereby granted, free of charge, to any person obtaining a + // copy of this software and associated documentation files (the + // "Software"), to deal in the Software without restriction, including + // without limitation the rights to use, copy, modify, merge, publish, + // distribute, sublicense, and/or sell copies of the Software, and to permit + // persons to whom the Software is furnished to do so, subject to the + // following conditions: + // + // The above copyright notice and this permission notice shall be included + // in all copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + // USE OR OTHER DEALINGS IN THE SOFTWARE. + + 'use strict'; + + // If obj.hasOwnProperty has been overridden, then calling + // obj.hasOwnProperty(prop) will break. + // See: https://github.com/joyent/node/issues/1707 + function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); + } + + module.exports = function(qs, sep, eq, options) { + sep = sep || '&'; + eq = eq || '='; + var obj = {}; + + if (typeof qs !== 'string' || qs.length === 0) { + return obj; + } + + var regexp = /\+/g; + qs = qs.split(sep); + + var maxKeys = 1000; + if (options && typeof options.maxKeys === 'number') { + maxKeys = options.maxKeys; + } + + var len = qs.length; + // maxKeys <= 0 means that we should not limit keys count + if (maxKeys > 0 && len > maxKeys) { + len = maxKeys; + } + + for (var i = 0; i < len; ++i) { + var x = qs[i].replace(regexp, '%20'), + idx = x.indexOf(eq), + kstr, vstr, k, v; + + if (idx >= 0) { + kstr = x.substr(0, idx); + vstr = x.substr(idx + 1); + } else { + kstr = x; + vstr = ''; + } + + k = decodeURIComponent(kstr); + v = decodeURIComponent(vstr); + + if (!hasOwnProperty(obj, k)) { + obj[k] = v; + } else if (Array.isArray(obj[k])) { + obj[k].push(v); + } else { + obj[k] = [obj[k], v]; + } + } + + return obj; + }; + + +/***/ }, +/* 9 */ +/***/ function(module, exports) { + + // Copyright Joyent, Inc. and other Node contributors. + // + // Permission is hereby granted, free of charge, to any person obtaining a + // copy of this software and associated documentation files (the + // "Software"), to deal in the Software without restriction, including + // without limitation the rights to use, copy, modify, merge, publish, + // distribute, sublicense, and/or sell copies of the Software, and to permit + // persons to whom the Software is furnished to do so, subject to the + // following conditions: + // + // The above copyright notice and this permission notice shall be included + // in all copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + // USE OR OTHER DEALINGS IN THE SOFTWARE. + + 'use strict'; + + var stringifyPrimitive = function(v) { + switch (typeof v) { + case 'string': + return v; + + case 'boolean': + return v ? 'true' : 'false'; + + case 'number': + return isFinite(v) ? v : ''; + + default: + return ''; + } + }; + + module.exports = function(obj, sep, eq, name) { + sep = sep || '&'; + eq = eq || '='; + if (obj === null) { + obj = undefined; + } + + if (typeof obj === 'object') { + return Object.keys(obj).map(function(k) { + var ks = encodeURIComponent(stringifyPrimitive(k)) + eq; + if (Array.isArray(obj[k])) { + return obj[k].map(function(v) { + return ks + encodeURIComponent(stringifyPrimitive(v)); + }).join(sep); + } else { + return ks + encodeURIComponent(stringifyPrimitive(obj[k])); + } + }).join(sep); + + } + + if (!name) return ''; + return encodeURIComponent(stringifyPrimitive(name)) + eq + + encodeURIComponent(stringifyPrimitive(obj)); + }; + + +/***/ }, +/* 10 */ +/***/ function(module, exports) { + + 'use strict'; + + module.exports = function equal(a, b) { + if (a === b) return true; + + var arrA = Array.isArray(a) + , arrB = Array.isArray(b) + , i; + + if (arrA && arrB) { + if (a.length != b.length) return false; + for (i = 0; i < a.length; i++) + if (!equal(a[i], b[i])) return false; + return true; + } + + if (arrA != arrB) return false; + + if (a && b && typeof a === 'object' && typeof b === 'object') { + var keys = Object.keys(a); + + if (keys.length !== Object.keys(b).length) return false; + + for (i = 0; i < keys.length; i++) + if (b[keys[i]] === undefined) return false; + + for (i = 0; i < keys.length; i++) + if(!equal(a[keys[i]], b[keys[i]])) return false; + + return true; + } + + return false; + }; + + +/***/ }, +/* 11 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + module.exports = { + copy: copy, + checkDataType: checkDataType, + checkDataTypes: checkDataTypes, + coerceToTypes: coerceToTypes, + toHash: toHash, + getProperty: getProperty, + escapeQuotes: escapeQuotes, + ucs2length: ucs2length, + varOccurences: varOccurences, + varReplace: varReplace, + cleanUpCode: cleanUpCode, + cleanUpVarErrors: cleanUpVarErrors, + schemaHasRules: schemaHasRules, + stableStringify: __webpack_require__(12), + toQuotedString: toQuotedString, + getPathExpr: getPathExpr, + getPath: getPath, + getData: getData, + unescapeFragment: unescapeFragment, + escapeFragment: escapeFragment, + escapeJsonPointer: escapeJsonPointer + }; + + + function copy(o, to) { + to = to || {}; + for (var key in o) to[key] = o[key]; + return to; + } + + + function checkDataType(dataType, data, negate) { + var EQUAL = negate ? ' !== ' : ' === ' + , AND = negate ? ' || ' : ' && ' + , OK = negate ? '!' : '' + , NOT = negate ? '' : '!'; + switch (dataType) { + case 'null': return data + EQUAL + 'null'; + case 'array': return OK + 'Array.isArray(' + data + ')'; + case 'object': return '(' + OK + data + AND + + 'typeof ' + data + EQUAL + '"object"' + AND + + NOT + 'Array.isArray(' + data + '))'; + case 'integer': return '(typeof ' + data + EQUAL + '"number"' + AND + + NOT + '(' + data + ' % 1))'; + default: return 'typeof ' + data + EQUAL + '"' + dataType + '"'; + } + } + + + function checkDataTypes(dataTypes, data) { + switch (dataTypes.length) { + case 1: return checkDataType(dataTypes[0], data, true); + default: + var code = ''; + var types = toHash(dataTypes); + if (types.array && types.object) { + code = types.null ? '(': '(!' + data + ' || '; + code += 'typeof ' + data + ' !== "object")'; + delete types.null; + delete types.array; + delete types.object; + } + if (types.number) delete types.integer; + for (var t in types) + code += (code ? ' && ' : '' ) + checkDataType(t, data, true); + + return code; + } + } + + + var COERCE_TO_TYPES = toHash([ 'string', 'number', 'integer', 'boolean', 'null' ]); + function coerceToTypes(dataTypes) { + if (Array.isArray(dataTypes)) { + var types = []; + for (var i=0; i= 0xD800 && value <= 0xDBFF && pos < len) { + // high surrogate, and there is a next character + value = str.charCodeAt(pos); + if ((value & 0xFC00) == 0xDC00) pos++; // low surrogate + } + } + return length; + } + + + function varOccurences(str, dataVar) { + dataVar += '[^0-9]'; + var matches = str.match(new RegExp(dataVar, 'g')); + return matches ? matches.length : 0; + } + + + function varReplace(str, dataVar, expr) { + dataVar += '([^0-9])'; + expr = expr.replace(/\$/g, '$$$$'); + return str.replace(new RegExp(dataVar, 'g'), expr + '$1'); + } + + + var EMPTY_ELSE = /else\s*{\s*}/g + , EMPTY_IF_NO_ELSE = /if\s*\([^)]+\)\s*\{\s*\}(?!\s*else)/g + , EMPTY_IF_WITH_ELSE = /if\s*\(([^)]+)\)\s*\{\s*\}\s*else(?!\s*if)/g; + function cleanUpCode(out) { + return out.replace(EMPTY_ELSE, '') + .replace(EMPTY_IF_NO_ELSE, '') + .replace(EMPTY_IF_WITH_ELSE, 'if (!($1))'); + } + + + var ERRORS_REGEXP = /[^v\.]errors/g + , REMOVE_ERRORS = /var errors = 0;|var vErrors = null;|validate.errors = vErrors;/g + , REMOVE_ERRORS_ASYNC = /var errors = 0;|var vErrors = null;/g + , RETURN_VALID = 'return errors === 0;' + , RETURN_TRUE = 'validate.errors = null; return true;' + , RETURN_ASYNC = /if \(errors === 0\) return true;\s*else throw new ValidationError\(vErrors\);/ + , RETURN_TRUE_ASYNC = 'return true;'; + + function cleanUpVarErrors(out, async) { + var matches = out.match(ERRORS_REGEXP); + if (!matches || matches.length !== 2) return out; + return async + ? out.replace(REMOVE_ERRORS_ASYNC, '') + .replace(RETURN_ASYNC, RETURN_TRUE_ASYNC) + : out.replace(REMOVE_ERRORS, '') + .replace(RETURN_VALID, RETURN_TRUE); + } + + + function schemaHasRules(schema, rules) { + for (var key in schema) if (rules[key]) return true; + } + + + function toQuotedString(str) { + return '\'' + escapeQuotes(str) + '\''; + } + + + function getPathExpr(currentPath, expr, jsonPointers, isNumber) { + var path = jsonPointers // false by default + ? '\'/\' + ' + expr + (isNumber ? '' : '.replace(/~/g, \'~0\').replace(/\\//g, \'~1\')') + : (isNumber ? '\'[\' + ' + expr + ' + \']\'' : '\'[\\\'\' + ' + expr + ' + \'\\\']\''); + return joinPaths(currentPath, path); + } + + + function getPath(currentPath, prop, jsonPointers) { + var path = jsonPointers // false by default + ? toQuotedString('/' + escapeJsonPointer(prop)) + : toQuotedString(getProperty(prop)); + return joinPaths(currentPath, path); + } + + + var RELATIVE_JSON_POINTER = /^([0-9]+)(#|\/(?:[^~]|~0|~1)*)?$/; + function getData($data, lvl, paths) { + var matches = $data.match(RELATIVE_JSON_POINTER); + if (!matches) throw new Error('Invalid relative JSON-pointer: ' + $data); + var up = +matches[1]; + var jsonPointer = matches[2]; + if (jsonPointer == '#') { + if (up >= lvl) throw new Error('Cannot access property/index ' + up + ' levels up, current level is ' + lvl); + return paths[lvl - up]; + } + + if (up > lvl) throw new Error('Cannot access data ' + up + ' levels up, current level is ' + lvl); + var data = 'data' + ((lvl - up) || ''); + if (!jsonPointer) return data; + + var expr = data; + var segments = jsonPointer.split('/'); + for (var i=0; i= '0' && ch <= '9') { + string += ch; + next(); + } + if (ch === '.') { + string += '.'; + while (next() && ch >= '0' && ch <= '9') { + string += ch; + } + } + if (ch === 'e' || ch === 'E') { + string += ch; + next(); + if (ch === '-' || ch === '+') { + string += ch; + next(); + } + while (ch >= '0' && ch <= '9') { + string += ch; + next(); + } + } + number = +string; + if (!isFinite(number)) { + error("Bad number"); + } else { + return number; + } + }, + + string = function () { + // Parse a string value. + var hex, + i, + string = '', + uffff; + + // When parsing for string values, we must look for " and \ characters. + if (ch === '"') { + while (next()) { + if (ch === '"') { + next(); + return string; + } else if (ch === '\\') { + next(); + if (ch === 'u') { + uffff = 0; + for (i = 0; i < 4; i += 1) { + hex = parseInt(next(), 16); + if (!isFinite(hex)) { + break; + } + uffff = uffff * 16 + hex; + } + string += String.fromCharCode(uffff); + } else if (typeof escapee[ch] === 'string') { + string += escapee[ch]; + } else { + break; + } + } else { + string += ch; + } + } + } + error("Bad string"); + }, + + white = function () { + + // Skip whitespace. + + while (ch && ch <= ' ') { + next(); + } + }, + + word = function () { + + // true, false, or null. + + switch (ch) { + case 't': + next('t'); + next('r'); + next('u'); + next('e'); + return true; + case 'f': + next('f'); + next('a'); + next('l'); + next('s'); + next('e'); + return false; + case 'n': + next('n'); + next('u'); + next('l'); + next('l'); + return null; + } + error("Unexpected '" + ch + "'"); + }, + + value, // Place holder for the value function. + + array = function () { + + // Parse an array value. + + var array = []; + + if (ch === '[') { + next('['); + white(); + if (ch === ']') { + next(']'); + return array; // empty array + } + while (ch) { + array.push(value()); + white(); + if (ch === ']') { + next(']'); + return array; + } + next(','); + white(); + } + } + error("Bad array"); + }, + + object = function () { + + // Parse an object value. + + var key, + object = {}; + + if (ch === '{') { + next('{'); + white(); + if (ch === '}') { + next('}'); + return object; // empty object + } + while (ch) { + key = string(); + white(); + next(':'); + if (Object.hasOwnProperty.call(object, key)) { + error('Duplicate key "' + key + '"'); + } + object[key] = value(); + white(); + if (ch === '}') { + next('}'); + return object; + } + next(','); + white(); + } + } + error("Bad object"); + }; + + value = function () { + + // Parse a JSON value. It could be an object, an array, a string, a number, + // or a word. + + white(); + switch (ch) { + case '{': + return object(); + case '[': + return array(); + case '"': + return string(); + case '-': + return number(); + default: + return ch >= '0' && ch <= '9' ? number() : word(); + } + }; + + // Return the json_parse function. It will have access to all of the above + // functions and variables. + + module.exports = function (source, reviver) { + var result; + + text = source; + at = 0; + ch = ' '; + result = value(); + white(); + if (ch) { + error("Syntax error"); + } + + // If there is a reviver function, we recursively walk the new structure, + // passing each name/value pair to the reviver function for possible + // transformation, starting with a temporary root object that holds the result + // in an empty key. If there is not a reviver function, we simply return the + // result. + + return typeof reviver === 'function' ? (function walk(holder, key) { + var k, v, value = holder[key]; + if (value && typeof value === 'object') { + for (k in value) { + if (Object.prototype.hasOwnProperty.call(value, k)) { + v = walk(value, k); + if (v !== undefined) { + value[k] = v; + } else { + delete value[k]; + } + } + } + } + return reviver.call(holder, key, value); + }({'': result}, '')) : result; + }; + + +/***/ }, +/* 15 */ +/***/ function(module, exports) { + + var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + gap, + indent, + meta = { // table of character substitutions + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '\\': '\\\\' + }, + rep; + + function quote(string) { + // If the string contains no control characters, no quote characters, and no + // backslash characters, then we can safely slap some quotes around it. + // Otherwise we must also replace the offending characters with safe escape + // sequences. + + escapable.lastIndex = 0; + return escapable.test(string) ? '"' + string.replace(escapable, function (a) { + var c = meta[a]; + return typeof c === 'string' ? c : + '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }) + '"' : '"' + string + '"'; + } + + function str(key, holder) { + // Produce a string from holder[key]. + var i, // The loop counter. + k, // The member key. + v, // The member value. + length, + mind = gap, + partial, + value = holder[key]; + + // If the value has a toJSON method, call it to obtain a replacement value. + if (value && typeof value === 'object' && + typeof value.toJSON === 'function') { + value = value.toJSON(key); + } + + // If we were called with a replacer function, then call the replacer to + // obtain a replacement value. + if (typeof rep === 'function') { + value = rep.call(holder, key, value); + } + + // What happens next depends on the value's type. + switch (typeof value) { + case 'string': + return quote(value); + + case 'number': + // JSON numbers must be finite. Encode non-finite numbers as null. + return isFinite(value) ? String(value) : 'null'; + + case 'boolean': + case 'null': + // If the value is a boolean or null, convert it to a string. Note: + // typeof null does not produce 'null'. The case is included here in + // the remote chance that this gets fixed someday. + return String(value); + + case 'object': + if (!value) return 'null'; + gap += indent; + partial = []; + + // Array.isArray + if (Object.prototype.toString.apply(value) === '[object Array]') { + length = value.length; + for (i = 0; i < length; i += 1) { + partial[i] = str(i, value) || 'null'; + } + + // Join all of the elements together, separated with commas, and + // wrap them in brackets. + v = partial.length === 0 ? '[]' : gap ? + '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : + '[' + partial.join(',') + ']'; + gap = mind; + return v; + } + + // If the replacer is an array, use it to select the members to be + // stringified. + if (rep && typeof rep === 'object') { + length = rep.length; + for (i = 0; i < length; i += 1) { + k = rep[i]; + if (typeof k === 'string') { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } + else { + // Otherwise, iterate through all of the keys in the object. + for (k in value) { + if (Object.prototype.hasOwnProperty.call(value, k)) { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } + + // Join all of the member texts together, separated with commas, + // and wrap them in braces. + + v = partial.length === 0 ? '{}' : gap ? + '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : + '{' + partial.join(',') + '}'; + gap = mind; + return v; + } + } + + module.exports = function (value, replacer, space) { + var i; + gap = ''; + indent = ''; + + // If the space parameter is a number, make an indent string containing that + // many spaces. + if (typeof space === 'number') { + for (i = 0; i < space; i += 1) { + indent += ' '; + } + } + // If the space parameter is a string, it will be used as the indent string. + else if (typeof space === 'string') { + indent = space; + } + + // If there is a replacer, it must be a function or an array. + // Otherwise, throw an error. + rep = replacer; + if (replacer && typeof replacer !== 'function' + && (typeof replacer !== 'object' || typeof replacer.length !== 'number')) { + throw new Error('JSON.stringify'); + } + + // Make a fake root object containing our value under the key of ''. + // Return the result of stringifying the value. + return str('', {'': value}); + }; + + +/***/ }, +/* 16 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var util = __webpack_require__(11); + + module.exports = SchemaObject; + + function SchemaObject(obj) { + util.copy(obj, this); + } + + +/***/ }, +/* 17 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + module.exports = { + setup: setupAsync, + compile: compileAsync + }; + + + var util = __webpack_require__(11); + + var ASYNC = { + '*': checkGenerators, + 'co*': checkGenerators, + 'es7': checkAsyncFunction + }; + + var TRANSPILE = { + 'nodent': getNodent, + 'regenerator': getRegenerator + }; + + var MODES = [ + { async: 'co*' }, + { async: 'es7', transpile: 'nodent' }, + { async: 'co*', transpile: 'regenerator' } + ]; + + + var regenerator, nodent; + + + function setupAsync(opts, required) { + if (required !== false) required = true; + var async = opts.async + , transpile = opts.transpile + , check; + + switch (typeof transpile) { + case 'string': + var get = TRANSPILE[transpile]; + if (!get) throw new Error('bad transpiler: ' + transpile); + return (opts._transpileFunc = get(opts, required)); + case 'undefined': + case 'boolean': + if (typeof async == 'string') { + check = ASYNC[async]; + if (!check) throw new Error('bad async mode: ' + async); + return (opts.transpile = check(opts, required)); + } + + for (var i=0; i 2) res = slice.call(arguments, 1); + resolve(res); + }); + }); + } + + /** + * Convert an array of "yieldables" to a promise. + * Uses `Promise.all()` internally. + * + * @param {Array} obj + * @return {Promise} + * @api private + */ + + function arrayToPromise(obj) { + return Promise.all(obj.map(toPromise, this)); + } + + /** + * Convert an object of "yieldables" to a promise. + * Uses `Promise.all()` internally. + * + * @param {Object} obj + * @return {Promise} + * @api private + */ + + function objectToPromise(obj){ + var results = new obj.constructor(); + var keys = Object.keys(obj); + var promises = []; + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + var promise = toPromise.call(this, obj[key]); + if (promise && isPromise(promise)) defer(promise, key); + else results[key] = obj[key]; + } + return Promise.all(promises).then(function () { + return results; + }); + + function defer(promise, key) { + // predefine the key in the result + results[key] = undefined; + promises.push(promise.then(function (res) { + results[key] = res; + })); + } + } + + /** + * Check if `obj` is a promise. + * + * @param {Object} obj + * @return {Boolean} + * @api private + */ + + function isPromise(obj) { + return 'function' == typeof obj.then; + } + + /** + * Check if `obj` is a generator. + * + * @param {Mixed} obj + * @return {Boolean} + * @api private + */ + + function isGenerator(obj) { + return 'function' == typeof obj.next && 'function' == typeof obj.throw; + } + + /** + * Check if `obj` is a generator function. + * + * @param {Mixed} obj + * @return {Boolean} + * @api private + */ + function isGeneratorFunction(obj) { + var constructor = obj.constructor; + if (!constructor) return false; + if ('GeneratorFunction' === constructor.name || 'GeneratorFunction' === constructor.displayName) return true; + return isGenerator(constructor.prototype); + } + + /** + * Check for plain object. + * + * @param {Mixed} val + * @return {Boolean} + * @api private + */ + + function isObject(val) { + return Object == val.constructor; + } + + +/***/ }, +/* 20 */ +/***/ function(module, exports) { + + 'use strict'; + + module.exports = ValidationError; + + + function ValidationError(errors) { + this.message = 'validation failed'; + this.errors = errors; + this.ajv = this.validation = true; + } + + + ValidationError.prototype = Object.create(Error.prototype); + ValidationError.prototype.constructor = ValidationError; + + +/***/ }, +/* 21 */ +/***/ function(module, exports) { + + 'use strict'; + + + var Cache = module.exports = function Cache() { + this._cache = {}; + }; + + + Cache.prototype.put = function Cache_put(key, value) { + this._cache[key] = value; + }; + + + Cache.prototype.get = function Cache_get(key) { + return this._cache[key]; + }; + + + Cache.prototype.del = function Cache_del(key) { + delete this._cache[key]; + }; + + + Cache.prototype.clear = function Cache_clear() { + this._cache = {}; + }; + + +/***/ }, +/* 22 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var util = __webpack_require__(11); + + var DATE = /^\d\d\d\d-(\d\d)-(\d\d)$/; + var DAYS = [0,31,29,31,30,31,30,31,31,30,31,30,31]; + var TIME = /^(\d\d):(\d\d):(\d\d)(\.\d+)?(z|[+-]\d\d:\d\d)?$/i; + var HOSTNAME = /^[a-z](?:(?:[-0-9a-z]{0,61})?[0-9a-z])?(\.[a-z](?:(?:[-0-9a-z]{0,61})?[0-9a-z])?)*$/i; + var URI = /^(?:[a-z][a-z0-9+\-.]*:)?(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)(?:\?(?:[a-z0-9\-._~!$&'()*+,;=:@\/?]|%[0-9a-f]{2})*)?(?:\#(?:[a-z0-9\-._~!$&'()*+,;=:@\/?]|%[0-9a-f]{2})*)?$/i; + var UUID = /^(?:urn\:uuid\:)?[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i; + var JSON_POINTER = /^(?:\/(?:[^~\/]|~0|~1)+)*(?:\/)?$|^\#(?:\/(?:[a-z0-9_\-\.!$&'()*+,;:=@]|%[0-9a-f]{2}|~0|~1)+)*(?:\/)?$/i; + var RELATIVE_JSON_POINTER = /^(?:0|[1-9][0-9]*)(?:\#|(?:\/(?:[^~\/]|~0|~1)+)*(?:\/)?)$/; + + + module.exports = formats; + + function formats(mode) { + mode = mode == 'full' ? 'full' : 'fast'; + var formatDefs = util.copy(formats[mode]); + for (var fName in formats.compare) { + formatDefs[fName] = { + validate: formatDefs[fName], + compare: formats.compare[fName] + }; + } + return formatDefs; + } + + + formats.fast = { + // date: http://tools.ietf.org/html/rfc3339#section-5.6 + date: /^\d\d\d\d-[0-1]\d-[0-3]\d$/, + // date-time: http://tools.ietf.org/html/rfc3339#section-5.6 + time: /^[0-2]\d:[0-5]\d:[0-5]\d(?:\.\d+)?(?:z|[+-]\d\d:\d\d)?$/i, + 'date-time': /^\d\d\d\d-[0-1]\d-[0-3]\d[t\s][0-2]\d:[0-5]\d:[0-5]\d(?:\.\d+)?(?:z|[+-]\d\d:\d\d)$/i, + // uri: https://github.com/mafintosh/is-my-json-valid/blob/master/formats.js + uri: /^(?:[a-z][a-z0-9+-.]*)?(?:\:|\/)\/?[^\s]*$/i, + // email (sources from jsen validator): + // http://stackoverflow.com/questions/201323/using-a-regular-expression-to-validate-an-email-address#answer-8829363 + // http://www.w3.org/TR/html5/forms.html#valid-e-mail-address (search for 'willful violation') + email: /^[a-z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/i, + hostname: HOSTNAME, + // optimized https://www.safaribooksonline.com/library/view/regular-expressions-cookbook/9780596802837/ch07s16.html + ipv4: /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/, + // optimized http://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses + ipv6: /^\s*(?:(?:(?:[0-9a-f]{1,4}:){7}(?:[0-9a-f]{1,4}|:))|(?:(?:[0-9a-f]{1,4}:){6}(?::[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){5}(?:(?:(?::[0-9a-f]{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){4}(?:(?:(?::[0-9a-f]{1,4}){1,3})|(?:(?::[0-9a-f]{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){3}(?:(?:(?::[0-9a-f]{1,4}){1,4})|(?:(?::[0-9a-f]{1,4}){0,2}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){2}(?:(?:(?::[0-9a-f]{1,4}){1,5})|(?:(?::[0-9a-f]{1,4}){0,3}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){1}(?:(?:(?::[0-9a-f]{1,4}){1,6})|(?:(?::[0-9a-f]{1,4}){0,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?::(?:(?:(?::[0-9a-f]{1,4}){1,7})|(?:(?::[0-9a-f]{1,4}){0,5}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(?:%.+)?\s*$/i, + regex: regex, + // uuid: http://tools.ietf.org/html/rfc4122 + uuid: UUID, + // JSON-pointer: https://tools.ietf.org/html/rfc6901 + // uri fragment: https://tools.ietf.org/html/rfc3986#appendix-A + 'json-pointer': JSON_POINTER, + // relative JSON-pointer: http://tools.ietf.org/html/draft-luff-relative-json-pointer-00 + 'relative-json-pointer': RELATIVE_JSON_POINTER + }; + + + formats.full = { + date: date, + time: time, + 'date-time': date_time, + uri: uri, + email: /^[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&''*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i, + hostname: hostname, + ipv4: /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/, + ipv6: /^\s*(?:(?:(?:[0-9a-f]{1,4}:){7}(?:[0-9a-f]{1,4}|:))|(?:(?:[0-9a-f]{1,4}:){6}(?::[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){5}(?:(?:(?::[0-9a-f]{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){4}(?:(?:(?::[0-9a-f]{1,4}){1,3})|(?:(?::[0-9a-f]{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){3}(?:(?:(?::[0-9a-f]{1,4}){1,4})|(?:(?::[0-9a-f]{1,4}){0,2}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){2}(?:(?:(?::[0-9a-f]{1,4}){1,5})|(?:(?::[0-9a-f]{1,4}){0,3}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){1}(?:(?:(?::[0-9a-f]{1,4}){1,6})|(?:(?::[0-9a-f]{1,4}){0,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?::(?:(?:(?::[0-9a-f]{1,4}){1,7})|(?:(?::[0-9a-f]{1,4}){0,5}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(?:%.+)?\s*$/i, + regex: regex, + uuid: UUID, + 'json-pointer': JSON_POINTER, + 'relative-json-pointer': RELATIVE_JSON_POINTER + }; + + + formats.compare = { + date: compareDate, + time: compareTime, + 'date-time': compareDateTime + }; + + + function date(str) { + // full-date from http://tools.ietf.org/html/rfc3339#section-5.6 + var matches = str.match(DATE); + if (!matches) return false; + + var month = +matches[1]; + var day = +matches[2]; + return month >= 1 && month <= 12 && day >= 1 && day <= DAYS[month]; + } + + + function time(str, full) { + var matches = str.match(TIME); + if (!matches) return false; + + var hour = matches[1]; + var minute = matches[2]; + var second = matches[3]; + var timeZone = matches[5]; + return hour <= 23 && minute <= 59 && second <= 59 && (!full || timeZone); + } + + + var DATE_TIME_SEPARATOR = /t|\s/i; + function date_time(str) { + // http://tools.ietf.org/html/rfc3339#section-5.6 + var dateTime = str.split(DATE_TIME_SEPARATOR); + return date(dateTime[0]) && time(dateTime[1], true); + } + + + function hostname(str) { + // http://tools.ietf.org/html/rfc1034#section-3.5 + return str.length <= 255 && HOSTNAME.test(str); + } + + + var NOT_URI_FRAGMENT = /\/|\:/; + function uri(str) { + // http://jmrware.com/articles/2009/uri_regexp/URI_regex.html + optional protocol + required "." + return NOT_URI_FRAGMENT.test(str) && URI.test(str); + } + + + function regex(str) { + try { + new RegExp(str); + return true; + } catch(e) { + return false; + } + } + + + function compareDate(d1, d2) { + if (!(d1 && d2)) return; + if (d1 > d2) return 1; + if (d1 < d2) return -1; + if (d1 === d2) return 0; + } + + + function compareTime(t1, t2) { + if (!(t1 && t2)) return; + t1 = t1.match(TIME); + t2 = t2.match(TIME); + if (!(t1 && t2)) return; + t1 = t1[1] + t1[2] + t1[3] + (t1[4]||''); + t2 = t2[1] + t2[2] + t2[3] + (t2[4]||''); + if (t1 > t2) return 1; + if (t1 < t2) return -1; + if (t1 === t2) return 0; + } + + + function compareDateTime(dt1, dt2) { + if (!(dt1 && dt2)) return; + dt1 = dt1.split(DATE_TIME_SEPARATOR); + dt2 = dt2.split(DATE_TIME_SEPARATOR); + var res = compareDate(dt1[0], dt2[0]); + if (res === undefined) return; + return res || compareTime(dt1[1], dt2[1]); + } + + +/***/ }, +/* 23 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var ruleModules = __webpack_require__(24) + , util = __webpack_require__(11); + + module.exports = function rules() { + var RULES = [ + { type: 'number', + rules: [ 'maximum', 'minimum', 'multipleOf'] }, + { type: 'string', + rules: [ 'maxLength', 'minLength', 'pattern', 'format' ] }, + { type: 'array', + rules: [ 'maxItems', 'minItems', 'uniqueItems', 'items' ] }, + { type: 'object', + rules: [ 'maxProperties', 'minProperties', 'required', 'dependencies', 'properties' ] }, + { rules: [ '$ref', 'enum', 'not', 'anyOf', 'oneOf', 'allOf' ] } + ]; + + RULES.all = [ 'type', 'additionalProperties', 'patternProperties' ]; + RULES.keywords = [ 'additionalItems', '$schema', 'id', 'title', 'description', 'default' ]; + RULES.types = [ 'number', 'integer', 'string', 'array', 'object', 'boolean', 'null' ]; + + RULES.forEach(function (group) { + group.rules = group.rules.map(function (keyword) { + RULES.all.push(keyword); + return { + keyword: keyword, + code: ruleModules[keyword] + }; + }); + }); + + RULES.keywords = util.toHash(RULES.all.concat(RULES.keywords)); + RULES.all = util.toHash(RULES.all); + RULES.types = util.toHash(RULES.types); + + return RULES; + }; + + +/***/ }, +/* 24 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + //all requires must be explicit because browserify won't work with dynamic requires + module.exports = { + '$ref': __webpack_require__(25), + allOf: __webpack_require__(26), + anyOf: __webpack_require__(27), + dependencies: __webpack_require__(28), + enum: __webpack_require__(29), + format: __webpack_require__(30), + items: __webpack_require__(31), + maximum: __webpack_require__(32), + minimum: __webpack_require__(32), + maxItems: __webpack_require__(33), + minItems: __webpack_require__(33), + maxLength: __webpack_require__(34), + minLength: __webpack_require__(34), + maxProperties: __webpack_require__(35), + minProperties: __webpack_require__(35), + multipleOf: __webpack_require__(36), + not: __webpack_require__(37), + oneOf: __webpack_require__(38), + pattern: __webpack_require__(39), + properties: __webpack_require__(40), + required: __webpack_require__(41), + uniqueItems: __webpack_require__(42), + validate: __webpack_require__(18) + }; + + +/***/ }, +/* 25 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate_ref(it, $keyword) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $errorKeyword; + var $data = 'data' + ($dataLvl || ''); + var $valid = 'valid' + $lvl; + var $async, $refCode; + if ($schema == '#' || $schema == '#/') { + if (it.isRoot) { + $async = it.async; + $refCode = 'validate'; + } else { + $async = it.root.schema.$async === true; + $refCode = 'root.refVal[0]'; + } + } else { + var $refVal = it.resolveRef(it.baseId, $schema, it.isRoot); + if ($refVal === undefined) { + var $message = 'can\'t resolve reference ' + $schema + ' from id ' + it.baseId; + if (it.opts.missingRefs == 'fail') { + console.log($message); + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || '$ref') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: "' + ($errSchemaPath) + '" , params: { ref: \'' + (it.util.escapeQuotes($schema)) + '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \'can\\\'t resolve reference ' + (it.util.escapeQuotes($schema)) + '\' '; + } + if (it.opts.verbose) { + out += ' , schema: ' + (it.util.toQuotedString($schema)) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + if ($breakOnError) { + out += ' if (false) { '; + } + } else if (it.opts.missingRefs == 'ignore') { + console.log($message); + if ($breakOnError) { + out += ' if (true) { '; + } + } else { + var $error = new Error($message); + $error.missingRef = it.resolve.url(it.baseId, $schema); + $error.missingSchema = it.resolve.normalizeId(it.resolve.fullPath($error.missingRef)); + throw $error; + } + } else if ($refVal.inline) { + var $it = it.util.copy(it); + $it.level++; + $it.schema = $refVal.schema; + $it.schemaPath = ''; + $it.errSchemaPath = $schema; + var $code = it.validate($it).replace(/validate\.schema/g, $refVal.code); + out += ' ' + ($code) + ' '; + if ($breakOnError) { + out += ' if (valid' + ($it.level) + ') { '; + } + } else { + $async = $refVal.async; + $refCode = $refVal.code; + } + } + if ($refCode) { + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; + if (it.opts.passContext) { + out += ' ' + ($refCode) + '.call(this, '; + } else { + out += ' ' + ($refCode) + '( '; + } + out += ' ' + ($data) + ', (dataPath || \'\')'; + if (it.errorPath != '""') { + out += ' + ' + (it.errorPath); + } + if ($dataLvl) { + out += ' , data' + (($dataLvl - 1) || '') + ' , ' + (it.dataPathArr[$dataLvl]) + ' '; + } else { + out += ' , parentData , parentDataProperty '; + } + out += ') '; + var __callValidate = out; + out = $$outStack.pop(); + if ($async) { + if (!it.async) throw new Error('async schema referenced by sync schema'); + out += ' try { '; + if ($breakOnError) { + out += 'var ' + ($valid) + ' ='; + } + out += ' ' + (it.yieldAwait) + ' ' + (__callValidate) + '; } catch (e) { if (!(e instanceof ValidationError)) throw e; if (vErrors === null) vErrors = e.errors; else vErrors = vErrors.concat(e.errors); errors = vErrors.length; } '; + if ($breakOnError) { + out += ' if (' + ($valid) + ') { '; + } + } else { + out += ' if (!' + (__callValidate) + ') { if (vErrors === null) vErrors = ' + ($refCode) + '.errors; else vErrors = vErrors.concat(' + ($refCode) + '.errors); errors = vErrors.length; } '; + if ($breakOnError) { + out += ' else { '; + } + } + } + return out; + } + + +/***/ }, +/* 26 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate_allOf(it, $keyword) { + var out = ' '; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + '.' + $keyword; + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $it = it.util.copy(it); + var $closingBraces = ''; + $it.level++; + var arr1 = $schema; + if (arr1) { + var $sch, $i = -1, + l1 = arr1.length - 1; + while ($i < l1) { + $sch = arr1[$i += 1]; + if (it.util.schemaHasRules($sch, it.RULES.all)) { + $it.schema = $sch; + $it.schemaPath = $schemaPath + '[' + $i + ']'; + $it.errSchemaPath = $errSchemaPath + '/' + $i; + out += ' ' + (it.validate($it)) + ' '; + if ($breakOnError) { + out += ' if (valid' + ($it.level) + ') { '; + $closingBraces += '}'; + } + } + } + } + if ($breakOnError) { + out += ' ' + ($closingBraces.slice(0, -1)); + } + out = it.util.cleanUpCode(out); + return out; + } + + +/***/ }, +/* 27 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate_anyOf(it, $keyword) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + '.' + $keyword; + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $errorKeyword; + var $data = 'data' + ($dataLvl || ''); + var $valid = 'valid' + $lvl; + var $errs = 'errs__' + $lvl; + var $it = it.util.copy(it); + var $closingBraces = ''; + $it.level++; + var $noEmptySchema = $schema.every(function($sch) { + return it.util.schemaHasRules($sch, it.RULES.all); + }); + if ($noEmptySchema) { + out += ' var ' + ($errs) + ' = errors; var ' + ($valid) + ' = false; '; + var $wasComposite = it.compositeRule; + it.compositeRule = $it.compositeRule = true; + var arr1 = $schema; + if (arr1) { + var $sch, $i = -1, + l1 = arr1.length - 1; + while ($i < l1) { + $sch = arr1[$i += 1]; + $it.schema = $sch; + $it.schemaPath = $schemaPath + '[' + $i + ']'; + $it.errSchemaPath = $errSchemaPath + '/' + $i; + out += ' ' + (it.validate($it)) + ' ' + ($valid) + ' = ' + ($valid) + ' || valid' + ($it.level) + '; if (!' + ($valid) + ') { '; + $closingBraces += '}'; + } + } + it.compositeRule = $it.compositeRule = $wasComposite; + out += ' ' + ($closingBraces) + ' if (!' + ($valid) + ') { var err = '; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || 'anyOf') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: "' + ($errSchemaPath) + '" , params: {} '; + if (it.opts.messages !== false) { + out += ' , message: \'should match some schema in anyOf\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; } else { errors = ' + ($errs) + '; if (vErrors !== null) { if (' + ($errs) + ') vErrors.length = ' + ($errs) + '; else vErrors = null; } '; + if (it.opts.allErrors) { + out += ' } '; + } + out = it.util.cleanUpCode(out); + } else { + if ($breakOnError) { + out += ' if (true) { '; + } + } + return out; + } + + +/***/ }, +/* 28 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate_dependencies(it, $keyword) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + '.' + $keyword; + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $errorKeyword; + var $data = 'data' + ($dataLvl || ''); + var $errs = 'errs__' + $lvl; + var $it = it.util.copy(it); + var $closingBraces = ''; + $it.level++; + var $schemaDeps = {}, + $propertyDeps = {}; + for ($property in $schema) { + var $sch = $schema[$property]; + var $deps = Array.isArray($sch) ? $propertyDeps : $schemaDeps; + $deps[$property] = $sch; + } + out += 'var ' + ($errs) + ' = errors;'; + var $currentErrorPath = it.errorPath; + out += 'var missing' + ($lvl) + ';'; + for (var $property in $propertyDeps) { + $deps = $propertyDeps[$property]; + out += ' if (' + ($data) + (it.util.getProperty($property)) + ' !== undefined && ( '; + var arr1 = $deps; + if (arr1) { + var _$property, $i = -1, + l1 = arr1.length - 1; + while ($i < l1) { + _$property = arr1[$i += 1]; + if ($i) { + out += ' || '; + } + var $prop = it.util.getProperty(_$property); + out += ' ( ' + ($data) + ($prop) + ' === undefined && (missing' + ($lvl) + ' = ' + (it.util.toQuotedString(it.opts.jsonPointers ? _$property : $prop)) + ') ) '; + } + } + out += ')) { '; + var $propertyPath = 'missing' + $lvl, + $missingProperty = '\' + ' + $propertyPath + ' + \''; + if (it.opts._errorDataPathProperty) { + it.errorPath = it.opts.jsonPointers ? it.util.getPathExpr($currentErrorPath, $propertyPath, true) : $currentErrorPath + ' + ' + $propertyPath; + } + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || 'dependencies') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: "' + ($errSchemaPath) + '" , params: { property: \'' + (it.util.escapeQuotes($property)) + '\', missingProperty: \'' + ($missingProperty) + '\', depsCount: ' + ($deps.length) + ', deps: \'' + (it.util.escapeQuotes($deps.length == 1 ? $deps[0] : $deps.join(", "))) + '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should have '; + if ($deps.length == 1) { + out += 'property ' + (it.util.escapeQuotes($deps[0])); + } else { + out += 'properties ' + (it.util.escapeQuotes($deps.join(", "))); + } + out += ' when property ' + (it.util.escapeQuotes($property)) + ' is present\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' } '; + if ($breakOnError) { + $closingBraces += '}'; + out += ' else { '; + } + } + it.errorPath = $currentErrorPath; + for (var $property in $schemaDeps) { + var $sch = $schemaDeps[$property]; + if (it.util.schemaHasRules($sch, it.RULES.all)) { + out += ' valid' + ($it.level) + ' = true; if (' + ($data) + '[\'' + ($property) + '\'] !== undefined) { '; + $it.schema = $sch; + $it.schemaPath = $schemaPath + it.util.getProperty($property); + $it.errSchemaPath = $errSchemaPath + '/' + it.util.escapeFragment($property); + out += ' ' + (it.validate($it)) + ' } '; + if ($breakOnError) { + out += ' if (valid' + ($it.level) + ') { '; + $closingBraces += '}'; + } + } + } + if ($breakOnError) { + out += ' ' + ($closingBraces) + ' if (' + ($errs) + ' == errors) {'; + } + out = it.util.cleanUpCode(out); + return out; + } + + +/***/ }, +/* 29 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate_enum(it, $keyword) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + '.' + $keyword; + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $errorKeyword; + var $data = 'data' + ($dataLvl || ''); + var $valid = 'valid' + $lvl; + var $isData = it.opts.v5 && $schema.$data; + var $schemaValue = $isData ? it.util.getData($schema.$data, $dataLvl, it.dataPathArr) : $schema; + if ($isData) { + out += ' var schema' + ($lvl) + ' = ' + ($schemaValue) + '; '; + $schemaValue = 'schema' + $lvl; + } + var $i = 'i' + $lvl; + if (!$isData) { + out += ' var schema' + ($lvl) + ' = validate.schema' + ($schemaPath) + ';'; + } + out += 'var ' + ($valid) + ';'; + if ($isData) { + out += ' if (schema' + ($lvl) + ' === undefined) ' + ($valid) + ' = true; else if (!Array.isArray(schema' + ($lvl) + ')) ' + ($valid) + ' = false; else {'; + } + out += '' + ($valid) + ' = false;for (var ' + ($i) + '=0; ' + ($i) + ' ' + ($i) + ') { '; + var $passData = $data + '[' + $i + ']'; + $it.schema = $sch; + $it.schemaPath = $schemaPath + '[' + $i + ']'; + $it.errSchemaPath = $errSchemaPath + '/' + $i; + $it.errorPath = it.util.getPathExpr(it.errorPath, $i, it.opts.jsonPointers, true); + $it.dataPathArr[$dataNxt] = $i; + var $code = it.validate($it); + if (it.util.varOccurences($code, $nextData) < 2) { + out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; + } else { + out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; + } + out += ' } '; + if ($breakOnError) { + out += ' if (valid' + ($it.level) + ') { '; + $closingBraces += '}'; + } + } + } + } + if (typeof $additionalItems == 'object' && it.util.schemaHasRules($additionalItems, it.RULES.all)) { + $it.schema = $additionalItems; + $it.schemaPath = it.schemaPath + '.additionalItems'; + $it.errSchemaPath = it.errSchemaPath + '/additionalItems'; + out += ' valid' + ($it.level) + ' = true; if (' + ($data) + '.length > ' + ($schema.length) + ') { for (var i' + ($lvl) + ' = ' + ($schema.length) + '; i' + ($lvl) + ' < ' + ($data) + '.length; i' + ($lvl) + '++) { '; + $it.errorPath = it.util.getPathExpr(it.errorPath, 'i' + $lvl, it.opts.jsonPointers, true); + var $passData = $data + '[i' + $lvl + ']'; + $it.dataPathArr[$dataNxt] = 'i' + $lvl; + var $code = it.validate($it); + if (it.util.varOccurences($code, $nextData) < 2) { + out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; + } else { + out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; + } + if ($breakOnError) { + out += ' if (!valid' + ($it.level) + ') break; '; + } + out += ' } } '; + if ($breakOnError) { + out += ' if (valid' + ($it.level) + ') { '; + $closingBraces += '}'; + } + } + } else if (it.util.schemaHasRules($schema, it.RULES.all)) { + $it.schema = $schema; + $it.schemaPath = $schemaPath; + $it.errSchemaPath = $errSchemaPath; + out += ' for (var i' + ($lvl) + ' = ' + (0) + '; i' + ($lvl) + ' < ' + ($data) + '.length; i' + ($lvl) + '++) { '; + $it.errorPath = it.util.getPathExpr(it.errorPath, 'i' + $lvl, it.opts.jsonPointers, true); + var $passData = $data + '[i' + $lvl + ']'; + $it.dataPathArr[$dataNxt] = 'i' + $lvl; + var $code = it.validate($it); + if (it.util.varOccurences($code, $nextData) < 2) { + out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; + } else { + out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; + } + if ($breakOnError) { + out += ' if (!valid' + ($it.level) + ') break; '; + } + out += ' } '; + if ($breakOnError) { + out += ' if (valid' + ($it.level) + ') { '; + $closingBraces += '}'; + } + } + if ($breakOnError) { + out += ' ' + ($closingBraces) + ' if (' + ($errs) + ' == errors) {'; + } + out = it.util.cleanUpCode(out); + return out; + } + + +/***/ }, +/* 32 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate__limit(it, $keyword) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + '.' + $keyword; + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $errorKeyword; + var $data = 'data' + ($dataLvl || ''); + var $isData = it.opts.v5 && $schema.$data; + var $schemaValue = $isData ? it.util.getData($schema.$data, $dataLvl, it.dataPathArr) : $schema; + if ($isData) { + out += ' var schema' + ($lvl) + ' = ' + ($schemaValue) + '; '; + $schemaValue = 'schema' + $lvl; + } + var $isMax = $keyword == 'maximum', + $exclusiveKeyword = $isMax ? 'exclusiveMaximum' : 'exclusiveMinimum', + $schemaExcl = it.schema[$exclusiveKeyword], + $isDataExcl = it.opts.v5 && $schemaExcl && $schemaExcl.$data, + $op = $isMax ? '<' : '>', + $notOp = $isMax ? '>' : '<'; + if ($isDataExcl) { + var $schemaValueExcl = it.util.getData($schemaExcl.$data, $dataLvl, it.dataPathArr), + $exclusive = 'exclusive' + $lvl, + $opExpr = 'op' + $lvl, + $opStr = '\' + ' + $opExpr + ' + \''; + out += ' var schemaExcl' + ($lvl) + ' = ' + ($schemaValueExcl) + '; '; + $schemaValueExcl = 'schemaExcl' + $lvl; + out += ' var exclusive' + ($lvl) + '; if (typeof ' + ($schemaValueExcl) + ' != \'boolean\' && typeof ' + ($schemaValueExcl) + ' != \'undefined\') { '; + var $errorKeyword = $exclusiveKeyword; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || '_exclusiveLimit') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: "' + ($errSchemaPath) + '" , params: {} '; + if (it.opts.messages !== false) { + out += ' , message: \'' + ($exclusiveKeyword) + ' should be boolean\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' } else if( '; + if ($isData) { + out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || '; + } + out += ' ((exclusive' + ($lvl) + ' = ' + ($schemaValueExcl) + ' === true) ? ' + ($data) + ' ' + ($notOp) + '= ' + ($schemaValue) + ' : ' + ($data) + ' ' + ($notOp) + ' ' + ($schemaValue) + ')) { var op' + ($lvl) + ' = exclusive' + ($lvl) + ' ? \'' + ($op) + '\' : \'' + ($op) + '=\';'; + } else { + var $exclusive = $schemaExcl === true, + $opStr = $op; + if (!$exclusive) $opStr += '='; + var $opExpr = '\'' + $opStr + '\''; + out += ' if ( '; + if ($isData) { + out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || '; + } + out += ' ' + ($data) + ' ' + ($notOp); + if ($exclusive) { + out += '='; + } + out += ' ' + ($schemaValue) + ') {'; + } + var $errorKeyword = $keyword; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || '_limit') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: "' + ($errSchemaPath) + '" , params: { comparison: ' + ($opExpr) + ', limit: ' + ($schemaValue) + ', exclusive: ' + ($exclusive) + ' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should be ' + ($opStr) + ' '; + if ($isData) { + out += '\' + ' + ($schemaValue); + } else { + out += '' + ($schema) + '\''; + } + } + if (it.opts.verbose) { + out += ' , schema: '; + if ($isData) { + out += 'validate.schema' + ($schemaPath); + } else { + out += '' + ($schema); + } + out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' } '; + if ($breakOnError) { + out += ' else { '; + } + return out; + } + + +/***/ }, +/* 33 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate__limitItems(it, $keyword) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + '.' + $keyword; + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $errorKeyword; + var $data = 'data' + ($dataLvl || ''); + var $isData = it.opts.v5 && $schema.$data; + var $schemaValue = $isData ? it.util.getData($schema.$data, $dataLvl, it.dataPathArr) : $schema; + if ($isData) { + out += ' var schema' + ($lvl) + ' = ' + ($schemaValue) + '; '; + $schemaValue = 'schema' + $lvl; + } + var $op = $keyword == 'maxItems' ? '>' : '<'; + out += 'if ( '; + if ($isData) { + out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || '; + } + out += ' ' + ($data) + '.length ' + ($op) + ' ' + ($schemaValue) + ') { '; + var $errorKeyword = $keyword; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || '_limitItems') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: "' + ($errSchemaPath) + '" , params: { limit: ' + ($schemaValue) + ' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should NOT have '; + if ($keyword == 'maxItems') { + out += 'more'; + } else { + out += 'less'; + } + out += ' than '; + if ($isData) { + out += '\' + ' + ($schemaValue) + ' + \''; + } else { + out += '' + ($schema); + } + out += ' items\' '; + } + if (it.opts.verbose) { + out += ' , schema: '; + if ($isData) { + out += 'validate.schema' + ($schemaPath); + } else { + out += '' + ($schema); + } + out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += '} '; + if ($breakOnError) { + out += ' else { '; + } + return out; + } + + +/***/ }, +/* 34 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate__limitLength(it, $keyword) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + '.' + $keyword; + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $errorKeyword; + var $data = 'data' + ($dataLvl || ''); + var $isData = it.opts.v5 && $schema.$data; + var $schemaValue = $isData ? it.util.getData($schema.$data, $dataLvl, it.dataPathArr) : $schema; + if ($isData) { + out += ' var schema' + ($lvl) + ' = ' + ($schemaValue) + '; '; + $schemaValue = 'schema' + $lvl; + } + var $op = $keyword == 'maxLength' ? '>' : '<'; + out += 'if ( '; + if ($isData) { + out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || '; + } + if (it.opts.unicode === false) { + out += ' ' + ($data) + '.length '; + } else { + out += ' ucs2length(' + ($data) + ') '; + } + out += ' ' + ($op) + ' ' + ($schemaValue) + ') { '; + var $errorKeyword = $keyword; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || '_limitLength') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: "' + ($errSchemaPath) + '" , params: { limit: ' + ($schemaValue) + ' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should NOT be '; + if ($keyword == 'maxLength') { + out += 'longer'; + } else { + out += 'shorter'; + } + out += ' than '; + if ($isData) { + out += '\' + ' + ($schemaValue) + ' + \''; + } else { + out += '' + ($schema); + } + out += ' characters\' '; + } + if (it.opts.verbose) { + out += ' , schema: '; + if ($isData) { + out += 'validate.schema' + ($schemaPath); + } else { + out += '' + ($schema); + } + out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += '} '; + if ($breakOnError) { + out += ' else { '; + } + return out; + } + + +/***/ }, +/* 35 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate__limitProperties(it, $keyword) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + '.' + $keyword; + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $errorKeyword; + var $data = 'data' + ($dataLvl || ''); + var $isData = it.opts.v5 && $schema.$data; + var $schemaValue = $isData ? it.util.getData($schema.$data, $dataLvl, it.dataPathArr) : $schema; + if ($isData) { + out += ' var schema' + ($lvl) + ' = ' + ($schemaValue) + '; '; + $schemaValue = 'schema' + $lvl; + } + var $op = $keyword == 'maxProperties' ? '>' : '<'; + out += 'if ( '; + if ($isData) { + out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || '; + } + out += ' Object.keys(' + ($data) + ').length ' + ($op) + ' ' + ($schemaValue) + ') { '; + var $errorKeyword = $keyword; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || '_limitProperties') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: "' + ($errSchemaPath) + '" , params: { limit: ' + ($schemaValue) + ' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should NOT have '; + if ($keyword == 'maxProperties') { + out += 'more'; + } else { + out += 'less'; + } + out += ' than '; + if ($isData) { + out += '\' + ' + ($schemaValue) + ' + \''; + } else { + out += '' + ($schema); + } + out += ' properties\' '; + } + if (it.opts.verbose) { + out += ' , schema: '; + if ($isData) { + out += 'validate.schema' + ($schemaPath); + } else { + out += '' + ($schema); + } + out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += '} '; + if ($breakOnError) { + out += ' else { '; + } + return out; + } + + +/***/ }, +/* 36 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate_multipleOf(it, $keyword) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + '.' + $keyword; + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $errorKeyword; + var $data = 'data' + ($dataLvl || ''); + var $isData = it.opts.v5 && $schema.$data; + var $schemaValue = $isData ? it.util.getData($schema.$data, $dataLvl, it.dataPathArr) : $schema; + if ($isData) { + out += ' var schema' + ($lvl) + ' = ' + ($schemaValue) + '; '; + $schemaValue = 'schema' + $lvl; + } + out += 'var division' + ($lvl) + ';if ('; + if ($isData) { + out += ' ' + ($schemaValue) + ' !== undefined && ( typeof ' + ($schemaValue) + ' != \'number\' || '; + } + out += ' (division' + ($lvl) + ' = ' + ($data) + ' / ' + ($schemaValue) + ', '; + if (it.opts.multipleOfPrecision) { + out += ' Math.abs(Math.round(division' + ($lvl) + ') - division' + ($lvl) + ') > 1e-' + (it.opts.multipleOfPrecision) + ' '; + } else { + out += ' division' + ($lvl) + ' !== parseInt(division' + ($lvl) + ') '; + } + out += ' ) '; + if ($isData) { + out += ' ) '; + } + out += ' ) { '; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || 'multipleOf') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: "' + ($errSchemaPath) + '" , params: { multipleOf: ' + ($schemaValue) + ' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should be multiple of '; + if ($isData) { + out += '\' + ' + ($schemaValue); + } else { + out += '' + ($schema) + '\''; + } + } + if (it.opts.verbose) { + out += ' , schema: '; + if ($isData) { + out += 'validate.schema' + ($schemaPath); + } else { + out += '' + ($schema); + } + out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += '} '; + if ($breakOnError) { + out += ' else { '; + } + return out; + } + + +/***/ }, +/* 37 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate_not(it, $keyword) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + '.' + $keyword; + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $errorKeyword; + var $data = 'data' + ($dataLvl || ''); + var $errs = 'errs__' + $lvl; + var $it = it.util.copy(it); + $it.level++; + if (it.util.schemaHasRules($schema, it.RULES.all)) { + $it.schema = $schema; + $it.schemaPath = $schemaPath; + $it.errSchemaPath = $errSchemaPath; + out += ' var ' + ($errs) + ' = errors; '; + var $wasComposite = it.compositeRule; + it.compositeRule = $it.compositeRule = true; + $it.createErrors = false; + var $allErrorsOption; + if ($it.opts.allErrors) { + $allErrorsOption = $it.opts.allErrors; + $it.opts.allErrors = false; + } + out += ' ' + (it.validate($it)) + ' '; + $it.createErrors = true; + if ($allErrorsOption) $it.opts.allErrors = $allErrorsOption; + it.compositeRule = $it.compositeRule = $wasComposite; + out += ' if (valid' + ($it.level) + ') { '; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || 'not') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: "' + ($errSchemaPath) + '" , params: {} '; + if (it.opts.messages !== false) { + out += ' , message: \'should NOT be valid\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' } else { errors = ' + ($errs) + '; if (vErrors !== null) { if (' + ($errs) + ') vErrors.length = ' + ($errs) + '; else vErrors = null; } '; + if (it.opts.allErrors) { + out += ' } '; + } + } else { + out += ' var err = '; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || 'not') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: "' + ($errSchemaPath) + '" , params: {} '; + if (it.opts.messages !== false) { + out += ' , message: \'should NOT be valid\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + if ($breakOnError) { + out += ' if (false) { '; + } + } + return out; + } + + +/***/ }, +/* 38 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate_oneOf(it, $keyword) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + '.' + $keyword; + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $errorKeyword; + var $data = 'data' + ($dataLvl || ''); + var $valid = 'valid' + $lvl; + var $errs = 'errs__' + $lvl; + var $it = it.util.copy(it); + var $closingBraces = ''; + $it.level++; + out += 'var ' + ($errs) + ' = errors;var prevValid' + ($lvl) + ' = false;var ' + ($valid) + ' = false; '; + var $wasComposite = it.compositeRule; + it.compositeRule = $it.compositeRule = true; + var arr1 = $schema; + if (arr1) { + var $sch, $i = -1, + l1 = arr1.length - 1; + while ($i < l1) { + $sch = arr1[$i += 1]; + if (it.util.schemaHasRules($sch, it.RULES.all)) { + $it.schema = $sch; + $it.schemaPath = $schemaPath + '[' + $i + ']'; + $it.errSchemaPath = $errSchemaPath + '/' + $i; + out += ' ' + (it.validate($it)) + ' '; + } else { + out += ' var valid' + ($it.level) + ' = true; '; + } + if ($i) { + out += ' if (valid' + ($it.level) + ' && prevValid' + ($lvl) + ') ' + ($valid) + ' = false; else { '; + $closingBraces += '}'; + } + out += ' if (valid' + ($it.level) + ') ' + ($valid) + ' = prevValid' + ($lvl) + ' = true;'; + } + } + it.compositeRule = $it.compositeRule = $wasComposite; + out += '' + ($closingBraces) + 'if (!' + ($valid) + ') { '; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || 'oneOf') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: "' + ($errSchemaPath) + '" , params: {} '; + if (it.opts.messages !== false) { + out += ' , message: \'should match exactly one schema in oneOf\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += '} else { errors = ' + ($errs) + '; if (vErrors !== null) { if (' + ($errs) + ') vErrors.length = ' + ($errs) + '; else vErrors = null; }'; + if (it.opts.allErrors) { + out += ' } '; + } + return out; + } + + +/***/ }, +/* 39 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate_pattern(it, $keyword) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + '.' + $keyword; + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $errorKeyword; + var $data = 'data' + ($dataLvl || ''); + var $isData = it.opts.v5 && $schema.$data; + var $schemaValue = $isData ? it.util.getData($schema.$data, $dataLvl, it.dataPathArr) : $schema; + if ($isData) { + out += ' var schema' + ($lvl) + ' = ' + ($schemaValue) + '; '; + $schemaValue = 'schema' + $lvl; + } + var $regexp = $isData ? '(new RegExp(' + $schemaValue + '))' : it.usePattern($schema); + out += 'if ( '; + if ($isData) { + out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'string\') || '; + } + out += ' !' + ($regexp) + '.test(' + ($data) + ') ) { '; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || 'pattern') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: "' + ($errSchemaPath) + '" , params: { pattern: '; + if ($isData) { + out += '' + ($schemaValue); + } else { + out += '' + (it.util.toQuotedString($schema)); + } + out += ' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should match pattern "'; + if ($isData) { + out += '\' + ' + ($schemaValue) + ' + \''; + } else { + out += '' + (it.util.escapeQuotes($schema)); + } + out += '"\' '; + } + if (it.opts.verbose) { + out += ' , schema: '; + if ($isData) { + out += 'validate.schema' + ($schemaPath); + } else { + out += '' + (it.util.toQuotedString($schema)); + } + out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += '} '; + if ($breakOnError) { + out += ' else { '; + } + return out; + } + + +/***/ }, +/* 40 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate_properties(it, $keyword) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + '.' + $keyword; + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $errorKeyword; + var $data = 'data' + ($dataLvl || ''); + var $valid = 'valid' + $lvl; + var $errs = 'errs__' + $lvl; + var $it = it.util.copy(it); + var $closingBraces = ''; + $it.level++; + var $dataNxt = $it.dataLevel = it.dataLevel + 1, + $nextData = 'data' + $dataNxt; + var $schemaKeys = Object.keys($schema || {}), + $pProperties = it.schema.patternProperties || {}, + $pPropertyKeys = Object.keys($pProperties), + $aProperties = it.schema.additionalProperties, + $someProperties = $schemaKeys.length || $pPropertyKeys.length, + $noAdditional = $aProperties === false, + $additionalIsSchema = typeof $aProperties == 'object' && Object.keys($aProperties).length, + $removeAdditional = it.opts.removeAdditional, + $checkAdditional = $noAdditional || $additionalIsSchema || $removeAdditional; + var $required = it.schema.required; + if ($required && !(it.opts.v5 && $required.$data) && $required.length < it.opts.loopRequired) var $requiredHash = it.util.toHash($required); + if (it.opts.v5) { + var $pgProperties = it.schema.patternGroups || {}, + $pgPropertyKeys = Object.keys($pgProperties); + } + out += 'var ' + ($errs) + ' = errors;var valid' + ($it.level) + ' = true;'; + if ($checkAdditional) { + out += ' for (var key' + ($lvl) + ' in ' + ($data) + ') { '; + if ($someProperties) { + out += ' var isAdditional' + ($lvl) + ' = !(false '; + if ($schemaKeys.length) { + if ($schemaKeys.length > 5) { + out += ' || validate.schema' + ($schemaPath) + '[key' + ($lvl) + '] '; + } else { + var arr1 = $schemaKeys; + if (arr1) { + var $propertyKey, i1 = -1, + l1 = arr1.length - 1; + while (i1 < l1) { + $propertyKey = arr1[i1 += 1]; + out += ' || key' + ($lvl) + ' == ' + (it.util.toQuotedString($propertyKey)) + ' '; + } + } + } + } + if ($pPropertyKeys.length) { + var arr2 = $pPropertyKeys; + if (arr2) { + var $pProperty, $i = -1, + l2 = arr2.length - 1; + while ($i < l2) { + $pProperty = arr2[$i += 1]; + out += ' || ' + (it.usePattern($pProperty)) + '.test(key' + ($lvl) + ') '; + } + } + } + if (it.opts.v5 && $pgPropertyKeys && $pgPropertyKeys.length) { + var arr3 = $pgPropertyKeys; + if (arr3) { + var $pgProperty, $i = -1, + l3 = arr3.length - 1; + while ($i < l3) { + $pgProperty = arr3[$i += 1]; + out += ' || ' + (it.usePattern($pgProperty)) + '.test(key' + ($lvl) + ') '; + } + } + } + out += ' ); if (isAdditional' + ($lvl) + ') { '; + } + if ($removeAdditional == 'all') { + out += ' delete ' + ($data) + '[key' + ($lvl) + ']; '; + } else { + var $currentErrorPath = it.errorPath; + var $additionalProperty = '\' + key' + $lvl + ' + \''; + if (it.opts._errorDataPathProperty) { + it.errorPath = it.util.getPathExpr(it.errorPath, 'key' + $lvl, it.opts.jsonPointers); + } + if ($noAdditional) { + if ($removeAdditional) { + out += ' delete ' + ($data) + '[key' + ($lvl) + ']; '; + } else { + out += ' valid' + ($it.level) + ' = false; '; + var $currErrSchemaPath = $errSchemaPath; + $errSchemaPath = it.errSchemaPath + '/additionalProperties'; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || 'additionalProperties') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: "' + ($errSchemaPath) + '" , params: { additionalProperty: \'' + ($additionalProperty) + '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should NOT have additional properties\' '; + } + if (it.opts.verbose) { + out += ' , schema: false , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + $errSchemaPath = $currErrSchemaPath; + if ($breakOnError) { + out += ' break; '; + } + } + } else if ($additionalIsSchema) { + if ($removeAdditional == 'failing') { + out += ' var ' + ($errs) + ' = errors; '; + var $wasComposite = it.compositeRule; + it.compositeRule = $it.compositeRule = true; + $it.schema = $aProperties; + $it.schemaPath = it.schemaPath + '.additionalProperties'; + $it.errSchemaPath = it.errSchemaPath + '/additionalProperties'; + $it.errorPath = it.opts._errorDataPathProperty ? it.errorPath : it.util.getPathExpr(it.errorPath, 'key' + $lvl, it.opts.jsonPointers); + var $passData = $data + '[key' + $lvl + ']'; + $it.dataPathArr[$dataNxt] = 'key' + $lvl; + var $code = it.validate($it); + if (it.util.varOccurences($code, $nextData) < 2) { + out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; + } else { + out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; + } + out += ' if (!valid' + ($it.level) + ') { errors = ' + ($errs) + '; if (validate.errors !== null) { if (errors) validate.errors.length = errors; else validate.errors = null; } delete ' + ($data) + '[key' + ($lvl) + ']; } '; + it.compositeRule = $it.compositeRule = $wasComposite; + } else { + $it.schema = $aProperties; + $it.schemaPath = it.schemaPath + '.additionalProperties'; + $it.errSchemaPath = it.errSchemaPath + '/additionalProperties'; + $it.errorPath = it.opts._errorDataPathProperty ? it.errorPath : it.util.getPathExpr(it.errorPath, 'key' + $lvl, it.opts.jsonPointers); + var $passData = $data + '[key' + $lvl + ']'; + $it.dataPathArr[$dataNxt] = 'key' + $lvl; + var $code = it.validate($it); + if (it.util.varOccurences($code, $nextData) < 2) { + out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; + } else { + out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; + } + if ($breakOnError) { + out += ' if (!valid' + ($it.level) + ') break; '; + } + } + } + it.errorPath = $currentErrorPath; + } + if ($someProperties) { + out += ' } '; + } + out += ' } '; + if ($breakOnError) { + out += ' if (valid' + ($it.level) + ') { '; + $closingBraces += '}'; + } + } + var $useDefaults = it.opts.useDefaults && !it.compositeRule; + if ($schemaKeys.length) { + var arr4 = $schemaKeys; + if (arr4) { + var $propertyKey, i4 = -1, + l4 = arr4.length - 1; + while (i4 < l4) { + $propertyKey = arr4[i4 += 1]; + var $sch = $schema[$propertyKey]; + if (it.util.schemaHasRules($sch, it.RULES.all)) { + var $prop = it.util.getProperty($propertyKey), + $passData = $data + $prop, + $hasDefault = $useDefaults && $sch.default !== undefined; + $it.schema = $sch; + $it.schemaPath = $schemaPath + $prop; + $it.errSchemaPath = $errSchemaPath + '/' + it.util.escapeFragment($propertyKey); + $it.errorPath = it.util.getPath(it.errorPath, $propertyKey, it.opts.jsonPointers); + $it.dataPathArr[$dataNxt] = it.util.toQuotedString($propertyKey); + var $code = it.validate($it); + if (it.util.varOccurences($code, $nextData) < 2) { + $code = it.util.varReplace($code, $nextData, $passData); + var $useData = $passData; + } else { + var $useData = $nextData; + out += ' var ' + ($nextData) + ' = ' + ($passData) + '; '; + } + if ($hasDefault) { + out += ' ' + ($code) + ' '; + } else { + if ($requiredHash && $requiredHash[$propertyKey]) { + out += ' if (' + ($useData) + ' === undefined) { valid' + ($it.level) + ' = false; '; + var $currentErrorPath = it.errorPath, + $currErrSchemaPath = $errSchemaPath, + $missingProperty = it.util.escapeQuotes($propertyKey); + if (it.opts._errorDataPathProperty) { + it.errorPath = it.util.getPath($currentErrorPath, $propertyKey, it.opts.jsonPointers); + } + $errSchemaPath = it.errSchemaPath + '/required'; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || 'required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: "' + ($errSchemaPath) + '" , params: { missingProperty: \'' + ($missingProperty) + '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \''; + if (it.opts._errorDataPathProperty) { + out += 'is a required property'; + } else { + out += 'should have required property \\\'' + ($missingProperty) + '\\\''; + } + out += '\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + $errSchemaPath = $currErrSchemaPath; + it.errorPath = $currentErrorPath; + out += ' } else { '; + } else { + if ($breakOnError) { + out += ' if (' + ($useData) + ' === undefined) { valid' + ($it.level) + ' = true; } else { '; + } else { + out += ' if (' + ($useData) + ' !== undefined) { '; + } + } + out += ' ' + ($code) + ' } '; + } + } + if ($breakOnError) { + out += ' if (valid' + ($it.level) + ') { '; + $closingBraces += '}'; + } + } + } + } + var arr5 = $pPropertyKeys; + if (arr5) { + var $pProperty, i5 = -1, + l5 = arr5.length - 1; + while (i5 < l5) { + $pProperty = arr5[i5 += 1]; + var $sch = $pProperties[$pProperty]; + if (it.util.schemaHasRules($sch, it.RULES.all)) { + $it.schema = $sch; + $it.schemaPath = it.schemaPath + '.patternProperties' + it.util.getProperty($pProperty); + $it.errSchemaPath = it.errSchemaPath + '/patternProperties/' + it.util.escapeFragment($pProperty); + out += ' for (var key' + ($lvl) + ' in ' + ($data) + ') { if (' + (it.usePattern($pProperty)) + '.test(key' + ($lvl) + ')) { '; + $it.errorPath = it.util.getPathExpr(it.errorPath, 'key' + $lvl, it.opts.jsonPointers); + var $passData = $data + '[key' + $lvl + ']'; + $it.dataPathArr[$dataNxt] = 'key' + $lvl; + var $code = it.validate($it); + if (it.util.varOccurences($code, $nextData) < 2) { + out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; + } else { + out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; + } + if ($breakOnError) { + out += ' if (!valid' + ($it.level) + ') break; '; + } + out += ' } '; + if ($breakOnError) { + out += ' else valid' + ($it.level) + ' = true; '; + } + out += ' } '; + if ($breakOnError) { + out += ' if (valid' + ($it.level) + ') { '; + $closingBraces += '}'; + } + } + } + } + if (it.opts.v5) { + var arr6 = $pgPropertyKeys; + if (arr6) { + var $pgProperty, i6 = -1, + l6 = arr6.length - 1; + while (i6 < l6) { + $pgProperty = arr6[i6 += 1]; + var $pgSchema = $pgProperties[$pgProperty], + $sch = $pgSchema.schema; + if (it.util.schemaHasRules($sch, it.RULES.all)) { + $it.schema = $sch; + $it.schemaPath = it.schemaPath + '.patternGroups' + it.util.getProperty($pgProperty) + '.schema'; + $it.errSchemaPath = it.errSchemaPath + '/patternGroups/' + it.util.escapeFragment($pgProperty) + '/schema'; + out += ' var pgPropCount' + ($lvl) + ' = 0; for (var key' + ($lvl) + ' in ' + ($data) + ') { if (' + (it.usePattern($pgProperty)) + '.test(key' + ($lvl) + ')) { pgPropCount' + ($lvl) + '++; '; + $it.errorPath = it.util.getPathExpr(it.errorPath, 'key' + $lvl, it.opts.jsonPointers); + var $passData = $data + '[key' + $lvl + ']'; + $it.dataPathArr[$dataNxt] = 'key' + $lvl; + var $code = it.validate($it); + if (it.util.varOccurences($code, $nextData) < 2) { + out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; + } else { + out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; + } + if ($breakOnError) { + out += ' if (!valid' + ($it.level) + ') break; '; + } + out += ' } '; + if ($breakOnError) { + out += ' else valid' + ($it.level) + ' = true; '; + } + out += ' } '; + if ($breakOnError) { + out += ' if (valid' + ($it.level) + ') { '; + $closingBraces += '}'; + } + var $pgMin = $pgSchema.minimum, + $pgMax = $pgSchema.maximum; + if ($pgMin !== undefined || $pgMax !== undefined) { + out += ' var ' + ($valid) + ' = true; '; + var $currErrSchemaPath = $errSchemaPath; + if ($pgMin !== undefined) { + var $limit = $pgMin, + $reason = 'minimum', + $moreOrLess = 'less'; + out += ' ' + ($valid) + ' = pgPropCount' + ($lvl) + ' >= ' + ($pgMin) + '; '; + $errSchemaPath = it.errSchemaPath + '/patternGroups/minimum'; + out += ' if (!' + ($valid) + ') { '; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || 'patternGroups') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: "' + ($errSchemaPath) + '" , params: { reason: \'' + ($reason) + '\', limit: ' + ($limit) + ', pattern: \'' + (it.util.escapeQuotes($pgProperty)) + '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should NOT have ' + ($moreOrLess) + ' than ' + ($limit) + ' properties matching pattern "' + (it.util.escapeQuotes($pgProperty)) + '"\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' } '; + if ($pgMax !== undefined) { + out += ' else '; + } + } + if ($pgMax !== undefined) { + var $limit = $pgMax, + $reason = 'maximum', + $moreOrLess = 'more'; + out += ' ' + ($valid) + ' = pgPropCount' + ($lvl) + ' <= ' + ($pgMax) + '; '; + $errSchemaPath = it.errSchemaPath + '/patternGroups/maximum'; + out += ' if (!' + ($valid) + ') { '; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || 'patternGroups') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: "' + ($errSchemaPath) + '" , params: { reason: \'' + ($reason) + '\', limit: ' + ($limit) + ', pattern: \'' + (it.util.escapeQuotes($pgProperty)) + '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should NOT have ' + ($moreOrLess) + ' than ' + ($limit) + ' properties matching pattern "' + (it.util.escapeQuotes($pgProperty)) + '"\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' } '; + } + $errSchemaPath = $currErrSchemaPath; + if ($breakOnError) { + out += ' if (' + ($valid) + ') { '; + $closingBraces += '}'; + } + } + } + } + } + } + if ($breakOnError) { + out += ' ' + ($closingBraces) + ' if (' + ($errs) + ' == errors) {'; + } + out = it.util.cleanUpCode(out); + return out; + } + + +/***/ }, +/* 41 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate_required(it, $keyword) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + '.' + $keyword; + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $errorKeyword; + var $data = 'data' + ($dataLvl || ''); + var $valid = 'valid' + $lvl; + var $isData = it.opts.v5 && $schema.$data; + var $schemaValue = $isData ? it.util.getData($schema.$data, $dataLvl, it.dataPathArr) : $schema; + if ($isData) { + out += ' var schema' + ($lvl) + ' = ' + ($schemaValue) + '; '; + $schemaValue = 'schema' + $lvl; + } + if (!$isData) { + if ($schema.length < it.opts.loopRequired && it.schema.properties && Object.keys(it.schema.properties).length) { + var $required = []; + var arr1 = $schema; + if (arr1) { + var $property, i1 = -1, + l1 = arr1.length - 1; + while (i1 < l1) { + $property = arr1[i1 += 1]; + var $propertySch = it.schema.properties[$property]; + if (!($propertySch && it.util.schemaHasRules($propertySch, it.RULES.all))) { + $required[$required.length] = $property; + } + } + } + } else { + var $required = $schema; + } + } + if ($isData || $required.length) { + var $currentErrorPath = it.errorPath, + $loopRequired = $isData || $required.length >= it.opts.loopRequired; + if ($breakOnError) { + out += ' var missing' + ($lvl) + '; '; + if ($loopRequired) { + if (!$isData) { + out += ' var schema' + ($lvl) + ' = validate.schema' + ($schemaPath) + '; '; + } + var $i = 'i' + $lvl, + $propertyPath = 'schema' + $lvl + '[' + $i + ']', + $missingProperty = '\' + ' + $propertyPath + ' + \''; + if (it.opts._errorDataPathProperty) { + it.errorPath = it.util.getPathExpr($currentErrorPath, $propertyPath, it.opts.jsonPointers); + } + out += ' var ' + ($valid) + ' = true; '; + if ($isData) { + out += ' if (schema' + ($lvl) + ' === undefined) ' + ($valid) + ' = true; else if (!Array.isArray(schema' + ($lvl) + ')) ' + ($valid) + ' = false; else {'; + } + out += ' for (var ' + ($i) + ' = 0; ' + ($i) + ' < schema' + ($lvl) + '.length; ' + ($i) + '++) { ' + ($valid) + ' = ' + ($data) + '[schema' + ($lvl) + '[' + ($i) + ']] !== undefined; if (!' + ($valid) + ') break; } '; + if ($isData) { + out += ' } '; + } + out += ' if (!' + ($valid) + ') { '; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || 'required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: "' + ($errSchemaPath) + '" , params: { missingProperty: \'' + ($missingProperty) + '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \''; + if (it.opts._errorDataPathProperty) { + out += 'is a required property'; + } else { + out += 'should have required property \\\'' + ($missingProperty) + '\\\''; + } + out += '\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' } else { '; + } else { + out += ' if ( '; + var arr2 = $required; + if (arr2) { + var _$property, $i = -1, + l2 = arr2.length - 1; + while ($i < l2) { + _$property = arr2[$i += 1]; + if ($i) { + out += ' || '; + } + var $prop = it.util.getProperty(_$property); + out += ' ( ' + ($data) + ($prop) + ' === undefined && (missing' + ($lvl) + ' = ' + (it.util.toQuotedString(it.opts.jsonPointers ? _$property : $prop)) + ') ) '; + } + } + out += ') { '; + var $propertyPath = 'missing' + $lvl, + $missingProperty = '\' + ' + $propertyPath + ' + \''; + if (it.opts._errorDataPathProperty) { + it.errorPath = it.opts.jsonPointers ? it.util.getPathExpr($currentErrorPath, $propertyPath, true) : $currentErrorPath + ' + ' + $propertyPath; + } + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || 'required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: "' + ($errSchemaPath) + '" , params: { missingProperty: \'' + ($missingProperty) + '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \''; + if (it.opts._errorDataPathProperty) { + out += 'is a required property'; + } else { + out += 'should have required property \\\'' + ($missingProperty) + '\\\''; + } + out += '\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' } else { '; + } + } else { + if ($loopRequired) { + if (!$isData) { + out += ' var schema' + ($lvl) + ' = validate.schema' + ($schemaPath) + '; '; + } + var $i = 'i' + $lvl, + $propertyPath = 'schema' + $lvl + '[' + $i + ']', + $missingProperty = '\' + ' + $propertyPath + ' + \''; + if (it.opts._errorDataPathProperty) { + it.errorPath = it.util.getPathExpr($currentErrorPath, $propertyPath, it.opts.jsonPointers); + } + if ($isData) { + out += ' if (schema' + ($lvl) + ' && !Array.isArray(schema' + ($lvl) + ')) { var err = '; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || 'required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: "' + ($errSchemaPath) + '" , params: { missingProperty: \'' + ($missingProperty) + '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \''; + if (it.opts._errorDataPathProperty) { + out += 'is a required property'; + } else { + out += 'should have required property \\\'' + ($missingProperty) + '\\\''; + } + out += '\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; } else if (schema' + ($lvl) + ' !== undefined) { '; + } + out += ' for (var ' + ($i) + ' = 0; ' + ($i) + ' < schema' + ($lvl) + '.length; ' + ($i) + '++) { if (' + ($data) + '[schema' + ($lvl) + '[' + ($i) + ']] === undefined) { var err = '; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || 'required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: "' + ($errSchemaPath) + '" , params: { missingProperty: \'' + ($missingProperty) + '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \''; + if (it.opts._errorDataPathProperty) { + out += 'is a required property'; + } else { + out += 'should have required property \\\'' + ($missingProperty) + '\\\''; + } + out += '\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; } } '; + if ($isData) { + out += ' } '; + } + } else { + var arr3 = $required; + if (arr3) { + var $property, $i = -1, + l3 = arr3.length - 1; + while ($i < l3) { + $property = arr3[$i += 1]; + var $prop = it.util.getProperty($property), + $missingProperty = it.util.escapeQuotes($property); + if (it.opts._errorDataPathProperty) { + it.errorPath = it.util.getPath($currentErrorPath, $property, it.opts.jsonPointers); + } + out += ' if (' + ($data) + ($prop) + ' === undefined) { var err = '; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || 'required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: "' + ($errSchemaPath) + '" , params: { missingProperty: \'' + ($missingProperty) + '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \''; + if (it.opts._errorDataPathProperty) { + out += 'is a required property'; + } else { + out += 'should have required property \\\'' + ($missingProperty) + '\\\''; + } + out += '\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; } '; + } + } + } + } + it.errorPath = $currentErrorPath; + } else if ($breakOnError) { + out += ' if (true) {'; + } + return out; + } + + +/***/ }, +/* 42 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate_uniqueItems(it, $keyword) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + '.' + $keyword; + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $errorKeyword; + var $data = 'data' + ($dataLvl || ''); + var $valid = 'valid' + $lvl; + var $isData = it.opts.v5 && $schema.$data; + var $schemaValue = $isData ? it.util.getData($schema.$data, $dataLvl, it.dataPathArr) : $schema; + if ($isData) { + out += ' var schema' + ($lvl) + ' = ' + ($schemaValue) + '; '; + $schemaValue = 'schema' + $lvl; + } + if (($schema || $isData) && it.opts.uniqueItems !== false) { + if ($isData) { + out += ' var ' + ($valid) + '; if (' + ($schemaValue) + ' === false || ' + ($schemaValue) + ' === undefined) ' + ($valid) + ' = true; else if (typeof ' + ($schemaValue) + ' != \'boolean\') ' + ($valid) + ' = false; else { '; + } + out += ' var ' + ($valid) + ' = true; if (' + ($data) + '.length > 1) { var i = ' + ($data) + '.length, j; outer: for (;i--;) { for (j = i; j--;) { if (equal(' + ($data) + '[i], ' + ($data) + '[j])) { ' + ($valid) + ' = false; break outer; } } } } '; + if ($isData) { + out += ' } '; + } + out += ' if (!' + ($valid) + ') { '; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || 'uniqueItems') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: "' + ($errSchemaPath) + '" , params: { i: i, j: j } '; + if (it.opts.messages !== false) { + out += ' , message: \'should NOT have duplicate items (items ## \' + j + \' and \' + i + \' are identical)\' '; + } + if (it.opts.verbose) { + out += ' , schema: '; + if ($isData) { + out += 'validate.schema' + ($schemaPath); + } else { + out += '' + ($schema); + } + out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' } '; + if ($breakOnError) { + out += ' else { '; + } + } else { + if ($breakOnError) { + out += ' if (true) { '; + } + } + return out; + } + + +/***/ }, +/* 43 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var META_SCHEMA_ID = 'https://raw.githubusercontent.com/epoberezkin/ajv/master/lib/refs/json-schema-v5.json'; + + module.exports = { + enable: enableV5, + META_SCHEMA_ID: META_SCHEMA_ID + }; + + + function enableV5(ajv) { + var inlineFunctions = { + 'switch': __webpack_require__(44), + 'constant': __webpack_require__(45), + '_formatLimit': __webpack_require__(46), + 'patternRequired': __webpack_require__(47) + }; + + if (ajv._opts.meta !== false) { + var metaSchema = __webpack_require__(48); + ajv.addMetaSchema(metaSchema, META_SCHEMA_ID); + } + _addKeyword('constant'); + ajv.addKeyword('contains', { type: 'array', macro: containsMacro }); + + _addKeyword('formatMaximum', 'string', inlineFunctions._formatLimit); + _addKeyword('formatMinimum', 'string', inlineFunctions._formatLimit); + ajv.addKeyword('exclusiveFormatMaximum'); + ajv.addKeyword('exclusiveFormatMinimum'); + + ajv.addKeyword('patternGroups'); // implemented in properties.jst + _addKeyword('patternRequired', 'object'); + _addKeyword('switch'); + + + function _addKeyword(keyword, types, inlineFunc) { + var definition = { + inline: inlineFunc || inlineFunctions[keyword], + statements: true, + errors: 'full' + }; + if (types) definition.type = types; + ajv.addKeyword(keyword, definition); + } + } + + + function containsMacro(schema) { + return { + not: { items: { not: schema } } + }; + } + + +/***/ }, +/* 44 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate_switch(it, $keyword) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + '.' + $keyword; + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $errorKeyword; + var $data = 'data' + ($dataLvl || ''); + var $valid = 'valid' + $lvl; + var $errs = 'errs__' + $lvl; + var $it = it.util.copy(it); + var $closingBraces = ''; + $it.level++; + var $ifPassed = 'ifPassed' + it.level, + $shouldContinue; + out += 'var ' + ($ifPassed) + ';'; + var arr1 = $schema; + if (arr1) { + var $sch, $caseIndex = -1, + l1 = arr1.length - 1; + while ($caseIndex < l1) { + $sch = arr1[$caseIndex += 1]; + if ($caseIndex && !$shouldContinue) { + out += ' if (!' + ($ifPassed) + ') { '; + $closingBraces += '}'; + } + if ($sch.if && it.util.schemaHasRules($sch.if, it.RULES.all)) { + out += ' var ' + ($errs) + ' = errors; '; + var $wasComposite = it.compositeRule; + it.compositeRule = $it.compositeRule = true; + $it.createErrors = false; + $it.schema = $sch.if; + $it.schemaPath = $schemaPath + '[' + $caseIndex + '].if'; + $it.errSchemaPath = $errSchemaPath + '/' + $caseIndex + '/if'; + out += ' ' + (it.validate($it)) + ' '; + $it.createErrors = true; + it.compositeRule = $it.compositeRule = $wasComposite; + out += ' ' + ($ifPassed) + ' = valid' + ($it.level) + '; if (' + ($ifPassed) + ') { '; + if (typeof $sch.then == 'boolean') { + if ($sch.then === false) { + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || 'switch') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: "' + ($errSchemaPath) + '" , params: { caseIndex: ' + ($caseIndex) + ' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should pass "switch" keyword validation\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + } + out += ' var valid' + ($it.level) + ' = ' + ($sch.then) + '; '; + } else { + $it.schema = $sch.then; + $it.schemaPath = $schemaPath + '[' + $caseIndex + '].then'; + $it.errSchemaPath = $errSchemaPath + '/' + $caseIndex + '/then'; + out += ' ' + (it.validate($it)) + ' '; + } + out += ' } else { errors = ' + ($errs) + '; if (vErrors !== null) { if (' + ($errs) + ') vErrors.length = ' + ($errs) + '; else vErrors = null; } } '; + } else { + out += ' ' + ($ifPassed) + ' = true; '; + if (typeof $sch.then == 'boolean') { + if ($sch.then === false) { + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || 'switch') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: "' + ($errSchemaPath) + '" , params: { caseIndex: ' + ($caseIndex) + ' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should pass "switch" keyword validation\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + } + out += ' var valid' + ($it.level) + ' = ' + ($sch.then) + '; '; + } else { + $it.schema = $sch.then; + $it.schemaPath = $schemaPath + '[' + $caseIndex + '].then'; + $it.errSchemaPath = $errSchemaPath + '/' + $caseIndex + '/then'; + out += ' ' + (it.validate($it)) + ' '; + } + } + $shouldContinue = $sch.continue + } + } + out += '' + ($closingBraces) + 'var ' + ($valid) + ' = valid' + ($it.level) + '; '; + out = it.util.cleanUpCode(out); + return out; + } + + +/***/ }, +/* 45 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate_constant(it, $keyword) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + '.' + $keyword; + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $errorKeyword; + var $data = 'data' + ($dataLvl || ''); + var $valid = 'valid' + $lvl; + var $isData = it.opts.v5 && $schema.$data; + var $schemaValue = $isData ? it.util.getData($schema.$data, $dataLvl, it.dataPathArr) : $schema; + if ($isData) { + out += ' var schema' + ($lvl) + ' = ' + ($schemaValue) + '; '; + $schemaValue = 'schema' + $lvl; + } + if (!$isData) { + out += ' var schema' + ($lvl) + ' = validate.schema' + ($schemaPath) + ';'; + } + out += 'var ' + ($valid) + ' = equal(' + ($data) + ', schema' + ($lvl) + '); if (!' + ($valid) + ') { '; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || 'constant') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: "' + ($errSchemaPath) + '" , params: {} '; + if (it.opts.messages !== false) { + out += ' , message: \'should be equal to constant\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' }'; + return out; + } + + +/***/ }, +/* 46 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate__formatLimit(it, $keyword) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + '.' + $keyword; + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $errorKeyword; + var $data = 'data' + ($dataLvl || ''); + var $valid = 'valid' + $lvl; + out += 'var ' + ($valid) + ' = undefined;'; + if (it.opts.format === false) { + out += ' ' + ($valid) + ' = true; '; + return out; + } + var $schemaFormat = it.schema.format, + $isDataFormat = it.opts.v5 && $schemaFormat.$data, + $closingBraces = ''; + if ($isDataFormat) { + var $schemaValueFormat = it.util.getData($schemaFormat.$data, $dataLvl, it.dataPathArr), + $format = 'format' + $lvl, + $compare = 'compare' + $lvl; + out += ' var ' + ($format) + ' = formats[' + ($schemaValueFormat) + '] , ' + ($compare) + ' = ' + ($format) + ' && ' + ($format) + '.compare;'; + } else { + var $format = it.formats[$schemaFormat]; + if (!($format && $format.compare)) { + out += ' ' + ($valid) + ' = true; '; + return out; + } + var $compare = 'formats' + it.util.getProperty($schemaFormat) + '.compare'; + } + var $isMax = $keyword == 'formatMaximum', + $exclusiveKeyword = 'exclusiveFormat' + ($isMax ? 'Maximum' : 'Minimum'), + $schemaExcl = it.schema[$exclusiveKeyword], + $isDataExcl = it.opts.v5 && $schemaExcl && $schemaExcl.$data, + $op = $isMax ? '<' : '>', + $result = 'result' + $lvl; + var $isData = it.opts.v5 && $schema.$data; + var $schemaValue = $isData ? it.util.getData($schema.$data, $dataLvl, it.dataPathArr) : $schema; + if ($isData) { + out += ' var schema' + ($lvl) + ' = ' + ($schemaValue) + '; '; + $schemaValue = 'schema' + $lvl; + } + if ($isDataExcl) { + var $schemaValueExcl = it.util.getData($schemaExcl.$data, $dataLvl, it.dataPathArr), + $exclusive = 'exclusive' + $lvl, + $opExpr = 'op' + $lvl, + $opStr = '\' + ' + $opExpr + ' + \''; + out += ' var schemaExcl' + ($lvl) + ' = ' + ($schemaValueExcl) + '; '; + $schemaValueExcl = 'schemaExcl' + $lvl; + out += ' if (typeof ' + ($schemaValueExcl) + ' != \'boolean\' && ' + ($schemaValueExcl) + ' !== undefined) { ' + ($valid) + ' = false; '; + var $errorKeyword = $exclusiveKeyword; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || '_exclusiveFormatLimit') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: "' + ($errSchemaPath) + '" , params: {} '; + if (it.opts.messages !== false) { + out += ' , message: \'' + ($exclusiveKeyword) + ' should be boolean\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' } '; + if ($breakOnError) { + $closingBraces += '}'; + out += ' else { '; + } + if ($isData) { + out += ' if (' + ($schemaValue) + ' === undefined) ' + ($valid) + ' = true; else if (typeof ' + ($schemaValue) + ' != \'string\') ' + ($valid) + ' = false; else { '; + $closingBraces += '}'; + } + if ($isDataFormat) { + out += ' if (!' + ($compare) + ') ' + ($valid) + ' = true; else { '; + $closingBraces += '}'; + } + out += ' var ' + ($result) + ' = ' + ($compare) + '(' + ($data) + ', '; + if ($isData) { + out += '' + ($schemaValue); + } else { + out += '' + (it.util.toQuotedString($schema)); + } + out += ' ); if (' + ($result) + ' === undefined) ' + ($valid) + ' = false; var exclusive' + ($lvl) + ' = ' + ($schemaValueExcl) + ' === true; if (' + ($valid) + ' === undefined) { ' + ($valid) + ' = exclusive' + ($lvl) + ' ? ' + ($result) + ' ' + ($op) + ' 0 : ' + ($result) + ' ' + ($op) + '= 0; } if (!' + ($valid) + ') var op' + ($lvl) + ' = exclusive' + ($lvl) + ' ? \'' + ($op) + '\' : \'' + ($op) + '=\';'; + } else { + var $exclusive = $schemaExcl === true, + $opStr = $op; + if (!$exclusive) $opStr += '='; + var $opExpr = '\'' + $opStr + '\''; + if ($isData) { + out += ' if (' + ($schemaValue) + ' === undefined) ' + ($valid) + ' = true; else if (typeof ' + ($schemaValue) + ' != \'string\') ' + ($valid) + ' = false; else { '; + $closingBraces += '}'; + } + if ($isDataFormat) { + out += ' if (!' + ($compare) + ') ' + ($valid) + ' = true; else { '; + $closingBraces += '}'; + } + out += ' var ' + ($result) + ' = ' + ($compare) + '(' + ($data) + ', '; + if ($isData) { + out += '' + ($schemaValue); + } else { + out += '' + (it.util.toQuotedString($schema)); + } + out += ' ); if (' + ($result) + ' === undefined) ' + ($valid) + ' = false; if (' + ($valid) + ' === undefined) ' + ($valid) + ' = ' + ($result) + ' ' + ($op); + if (!$exclusive) { + out += '='; + } + out += ' 0;'; + } + out += '' + ($closingBraces) + 'if (!' + ($valid) + ') { '; + var $errorKeyword = $keyword; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || '_formatLimit') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: "' + ($errSchemaPath) + '" , params: { limit: '; + if ($isData) { + out += '' + ($schemaValue); + } else { + out += '' + (it.util.toQuotedString($schema)); + } + out += ' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should be ' + ($opStr) + ' "'; + if ($isData) { + out += '\' + ' + ($schemaValue) + ' + \''; + } else { + out += '' + (it.util.escapeQuotes($schema)); + } + out += '"\' '; + } + if (it.opts.verbose) { + out += ' , schema: '; + if ($isData) { + out += 'validate.schema' + ($schemaPath); + } else { + out += '' + (it.util.toQuotedString($schema)); + } + out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += '}'; + return out; + } + + +/***/ }, +/* 47 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate_patternRequired(it, $keyword) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + '.' + $keyword; + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $errorKeyword; + var $data = 'data' + ($dataLvl || ''); + var $valid = 'valid' + $lvl; + var $key = 'key' + $lvl, + $matched = 'patternMatched' + $lvl, + $closingBraces = ''; + out += 'var ' + ($valid) + ' = true;'; + var arr1 = $schema; + if (arr1) { + var $pProperty, i1 = -1, + l1 = arr1.length - 1; + while (i1 < l1) { + $pProperty = arr1[i1 += 1]; + out += ' var ' + ($matched) + ' = false; for (var ' + ($key) + ' in ' + ($data) + ') { ' + ($matched) + ' = ' + (it.usePattern($pProperty)) + '.test(' + ($key) + '); if (' + ($matched) + ') break; } '; + var $missingPattern = it.util.escapeQuotes($pProperty); + out += ' if (!' + ($matched) + ') { ' + ($valid) + ' = false; var err = '; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || 'patternRequired') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: "' + ($errSchemaPath) + '" , params: { missingPattern: \'' + ($missingPattern) + '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should have property matching pattern \\\'' + ($missingPattern) + '\\\'\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; } '; + if ($breakOnError) { + $closingBraces += '}'; + out += ' else { '; + } + } + } + out += '' + ($closingBraces); + return out; + } + + +/***/ }, +/* 48 */ +/***/ function(module, exports) { + + module.exports = { + "id": "https://raw.githubusercontent.com/epoberezkin/ajv/master/lib/refs/json-schema-v5.json#", + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "Core schema meta-schema (v5 proposals)", + "definitions": { + "schemaArray": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#" + } + }, + "positiveInteger": { + "type": "integer", + "minimum": 0 + }, + "positiveIntegerDefault0": { + "allOf": [ + { + "$ref": "#/definitions/positiveInteger" + }, + { + "default": 0 + } + ] + }, + "simpleTypes": { + "enum": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ] + }, + "stringArray": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1, + "uniqueItems": true + }, + "$data": { + "type": "object", + "required": [ + "$data" + ], + "properties": { + "$data": { + "type": "string", + "format": "relative-json-pointer" + } + }, + "additionalProperties": false + } + }, + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uri" + }, + "$schema": { + "type": "string", + "format": "uri" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "default": {}, + "multipleOf": { + "anyOf": [ + { + "type": "number", + "minimum": 0, + "exclusiveMinimum": true + }, + { + "$ref": "#/definitions/$data" + } + ] + }, + "maximum": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/$data" + } + ] + }, + "exclusiveMaximum": { + "anyOf": [ + { + "type": "boolean", + "default": false + }, + { + "$ref": "#/definitions/$data" + } + ] + }, + "minimum": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/$data" + } + ] + }, + "exclusiveMinimum": { + "anyOf": [ + { + "type": "boolean", + "default": false + }, + { + "$ref": "#/definitions/$data" + } + ] + }, + "maxLength": { + "anyOf": [ + { + "$ref": "#/definitions/positiveInteger" + }, + { + "$ref": "#/definitions/$data" + } + ] + }, + "minLength": { + "anyOf": [ + { + "$ref": "#/definitions/positiveIntegerDefault0" + }, + { + "$ref": "#/definitions/$data" + } + ] + }, + "pattern": { + "anyOf": [ + { + "type": "string", + "format": "regex" + }, + { + "$ref": "#/definitions/$data" + } + ] + }, + "additionalItems": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#" + }, + { + "$ref": "#/definitions/$data" + } + ], + "default": {} + }, + "items": { + "anyOf": [ + { + "$ref": "#" + }, + { + "$ref": "#/definitions/schemaArray" + } + ], + "default": {} + }, + "maxItems": { + "anyOf": [ + { + "$ref": "#/definitions/positiveInteger" + }, + { + "$ref": "#/definitions/$data" + } + ] + }, + "minItems": { + "anyOf": [ + { + "$ref": "#/definitions/positiveIntegerDefault0" + }, + { + "$ref": "#/definitions/$data" + } + ] + }, + "uniqueItems": { + "anyOf": [ + { + "type": "boolean", + "default": false + }, + { + "$ref": "#/definitions/$data" + } + ] + }, + "maxProperties": { + "anyOf": [ + { + "$ref": "#/definitions/positiveInteger" + }, + { + "$ref": "#/definitions/$data" + } + ] + }, + "minProperties": { + "anyOf": [ + { + "$ref": "#/definitions/positiveIntegerDefault0" + }, + { + "$ref": "#/definitions/$data" + } + ] + }, + "required": { + "anyOf": [ + { + "$ref": "#/definitions/stringArray" + }, + { + "$ref": "#/definitions/$data" + } + ] + }, + "additionalProperties": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#" + }, + { + "$ref": "#/definitions/$data" + } + ], + "default": {} + }, + "definitions": { + "type": "object", + "additionalProperties": { + "$ref": "#" + }, + "default": {} + }, + "properties": { + "type": "object", + "additionalProperties": { + "$ref": "#" + }, + "default": {} + }, + "patternProperties": { + "type": "object", + "additionalProperties": { + "$ref": "#" + }, + "default": {} + }, + "dependencies": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "$ref": "#" + }, + { + "$ref": "#/definitions/stringArray" + } + ] + } + }, + "enum": { + "anyOf": [ + { + "type": "array", + "minItems": 1, + "uniqueItems": true + }, + { + "$ref": "#/definitions/$data" + } + ] + }, + "type": { + "anyOf": [ + { + "$ref": "#/definitions/simpleTypes" + }, + { + "type": "array", + "items": { + "$ref": "#/definitions/simpleTypes" + }, + "minItems": 1, + "uniqueItems": true + } + ] + }, + "allOf": { + "$ref": "#/definitions/schemaArray" + }, + "anyOf": { + "$ref": "#/definitions/schemaArray" + }, + "oneOf": { + "$ref": "#/definitions/schemaArray" + }, + "not": { + "$ref": "#" + }, + "format": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/$data" + } + ] + }, + "formatMaximum": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/$data" + } + ] + }, + "formatMinimum": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/$data" + } + ] + }, + "exclusiveFormatMaximum": { + "anyOf": [ + { + "type": "boolean", + "default": false + }, + { + "$ref": "#/definitions/$data" + } + ] + }, + "exclusiveFormatMinimum": { + "anyOf": [ + { + "type": "boolean", + "default": false + }, + { + "$ref": "#/definitions/$data" + } + ] + }, + "constant": { + "anyOf": [ + {}, + { + "$ref": "#/definitions/$data" + } + ] + }, + "contains": { + "$ref": "#" + }, + "patternGroups": { + "type": "object", + "additionalProperties": { + "type": "object", + "required": [ + "schema" + ], + "properties": { + "maximum": { + "anyOf": [ + { + "$ref": "#/definitions/positiveInteger" + }, + { + "$ref": "#/definitions/$data" + } + ] + }, + "minimum": { + "anyOf": [ + { + "$ref": "#/definitions/positiveIntegerDefault0" + }, + { + "$ref": "#/definitions/$data" + } + ] + }, + "schema": { + "$ref": "#" + } + }, + "additionalProperties": false + }, + "default": {} + }, + "switch": { + "type": "array", + "items": { + "required": [ + "then" + ], + "properties": { + "if": { + "$ref": "#" + }, + "then": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#" + } + ] + }, + "continue": { + "type": "boolean" + } + }, + "additionalProperties": false, + "dependencies": { + "continue": [ + "if" + ] + } + } + } + }, + "dependencies": { + "exclusiveMaximum": [ + "maximum" + ], + "exclusiveMinimum": [ + "minimum" + ], + "formatMaximum": [ + "format" + ], + "formatMinimum": [ + "format" + ], + "exclusiveFormatMaximum": [ + "formatMaximum" + ], + "exclusiveFormatMinimum": [ + "formatMinimum" + ] + }, + "default": {} + }; + +/***/ }, +/* 49 */ +/***/ function(module, exports) { + + 'use strict'; + + var IDENTIFIER = /^[a-z_$][a-z0-9_$]*$/i; + + /** + * Define custom keyword + * @this Ajv + * @param {String} keyword custom keyword, should be a valid identifier, should be different from all standard, custom and macro keywords. + * @param {Object} definition keyword definition object with properties `type` (type(s) which the keyword applies to), `validate` or `compile`. + */ + module.exports = function addKeyword(keyword, definition) { + /* eslint no-shadow: 0 */ + var self = this; + if (this.RULES.keywords[keyword]) + throw new Error('Keyword ' + keyword + ' is already defined'); + + if (!IDENTIFIER.test(keyword)) + throw new Error('Keyword ' + keyword + ' is not a valid identifier'); + + if (definition) { + var dataType = definition.type; + if (Array.isArray(dataType)) { + var i, len = dataType.length; + for (i=0; i 0) { + this.autoScrollStep = ((top + margin) - mouseY) / 3; + } + else if (mouseY > bottom - margin && + height + content.scrollTop < content.scrollHeight) { + this.autoScrollStep = ((bottom - margin) - mouseY) / 3; + } + else { + this.autoScrollStep = undefined; + } + + if (this.autoScrollStep) { + if (!this.autoScrollTimer) { + this.autoScrollTimer = setInterval(function () { + if (me.autoScrollStep) { + content.scrollTop -= me.autoScrollStep; + } + else { + me.stopAutoScroll(); + } + }, interval); + } + } + else { + this.stopAutoScroll(); + } + }; + + /** + * Stop auto scrolling. Only applicable when scrolling + */ + treemode.stopAutoScroll = function () { + if (this.autoScrollTimer) { + clearTimeout(this.autoScrollTimer); + delete this.autoScrollTimer; + } + if (this.autoScrollStep) { + delete this.autoScrollStep; + } + }; + + + /** + * Set the focus to an element in the editor, set text selection, and + * set scroll position. + * @param {Object} selection An object containing fields: + * {Element | undefined} dom The dom element + * which has focus + * {Range | TextRange} range A text selection + * {Node[]} nodes Nodes in case of multi selection + * {Number} scrollTop Scroll position + */ + treemode.setSelection = function (selection) { + if (!selection) { + return; + } + + if ('scrollTop' in selection && this.content) { + // TODO: animated scroll + this.content.scrollTop = selection.scrollTop; + } + if (selection.nodes) { + // multi-select + this.select(selection.nodes); + } + if (selection.range) { + util.setSelectionOffset(selection.range); + } + if (selection.dom) { + selection.dom.focus(); + } + }; + + /** + * Get the current focus + * @return {Object} selection An object containing fields: + * {Element | undefined} dom The dom element + * which has focus + * {Range | TextRange} range A text selection + * {Node[]} nodes Nodes in case of multi selection + * {Number} scrollTop Scroll position + */ + treemode.getSelection = function () { + var range = util.getSelectionOffset(); + if (range && range.container.nodeName !== 'DIV') { // filter on (editable) divs) + range = null; + } + + return { + dom: this.focusTarget, + range: range, + nodes: this.multiselection.nodes.slice(0), + scrollTop: this.content ? this.content.scrollTop : 0 + }; + }; + + /** + * Adjust the scroll position such that given top position is shown at 1/4 + * of the window height. + * @param {Number} top + * @param {function(boolean)} [callback] Callback, executed when animation is + * finished. The callback returns true + * when animation is finished, or false + * when not. + */ + treemode.scrollTo = function (top, callback) { + var content = this.content; + if (content) { + var editor = this; + // cancel any running animation + if (editor.animateTimeout) { + clearTimeout(editor.animateTimeout); + delete editor.animateTimeout; + } + if (editor.animateCallback) { + editor.animateCallback(false); + delete editor.animateCallback; + } + + // calculate final scroll position + var height = content.clientHeight; + var bottom = content.scrollHeight - height; + var finalScrollTop = Math.min(Math.max(top - height / 4, 0), bottom); + + // animate towards the new scroll position + var animate = function () { + var scrollTop = content.scrollTop; + var diff = (finalScrollTop - scrollTop); + if (Math.abs(diff) > 3) { + content.scrollTop += diff / 3; + editor.animateCallback = callback; + editor.animateTimeout = setTimeout(animate, 50); + } + else { + // finished + if (callback) { + callback(true); + } + content.scrollTop = finalScrollTop; + delete editor.animateTimeout; + delete editor.animateCallback; + } + }; + animate(); + } + else { + if (callback) { + callback(false); + } + } + }; + + /** + * Create main frame + * @private + */ + treemode._createFrame = function () { + // create the frame + this.frame = document.createElement('div'); + this.frame.className = 'jsoneditor jsoneditor-mode-' + this.options.mode; + this.container.appendChild(this.frame); + + // create one global event listener to handle all events from all nodes + var editor = this; + function onEvent(event) { + // when switching to mode "code" or "text" via the menu, some events + // are still fired whilst the _onEvent methods is already removed. + if (editor._onEvent) { + editor._onEvent(event); + } + } + this.frame.onclick = function (event) { + var target = event.target;// || event.srcElement; + + onEvent(event); + + // prevent default submit action of buttons when editor is located + // inside a form + if (target.nodeName == 'BUTTON') { + event.preventDefault(); + } + }; + this.frame.oninput = onEvent; + this.frame.onchange = onEvent; + this.frame.onkeydown = onEvent; + this.frame.onkeyup = onEvent; + this.frame.oncut = onEvent; + this.frame.onpaste = onEvent; + this.frame.onmousedown = onEvent; + this.frame.onmouseup = onEvent; + this.frame.onmouseover = onEvent; + this.frame.onmouseout = onEvent; + // Note: focus and blur events do not propagate, therefore they defined + // using an eventListener with useCapture=true + // see http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html + util.addEventListener(this.frame, 'focus', onEvent, true); + util.addEventListener(this.frame, 'blur', onEvent, true); + this.frame.onfocusin = onEvent; // for IE + this.frame.onfocusout = onEvent; // for IE + + // create menu + this.menu = document.createElement('div'); + this.menu.className = 'jsoneditor-menu'; + this.frame.appendChild(this.menu); + + // create expand all button + var expandAll = document.createElement('button'); + expandAll.type = 'button'; + expandAll.className = 'jsoneditor-expand-all'; + expandAll.title = 'Expand all fields'; + expandAll.onclick = function () { + editor.expandAll(); + }; + this.menu.appendChild(expandAll); + + // create expand all button + var collapseAll = document.createElement('button'); + collapseAll.type = 'button'; + collapseAll.title = 'Collapse all fields'; + collapseAll.className = 'jsoneditor-collapse-all'; + collapseAll.onclick = function () { + editor.collapseAll(); + }; + this.menu.appendChild(collapseAll); + + // create undo/redo buttons + if (this.history) { + // create undo button + var undo = document.createElement('button'); + undo.type = 'button'; + undo.className = 'jsoneditor-undo jsoneditor-separator'; + undo.title = 'Undo last action (Ctrl+Z)'; + undo.onclick = function () { + editor._onUndo(); + }; + this.menu.appendChild(undo); + this.dom.undo = undo; + + // create redo button + var redo = document.createElement('button'); + redo.type = 'button'; + redo.className = 'jsoneditor-redo'; + redo.title = 'Redo (Ctrl+Shift+Z)'; + redo.onclick = function () { + editor._onRedo(); + }; + this.menu.appendChild(redo); + this.dom.redo = redo; + + // register handler for onchange of history + this.history.onChange = function () { + undo.disabled = !editor.history.canUndo(); + redo.disabled = !editor.history.canRedo(); + }; + this.history.onChange(); + } + + // create mode box + if (this.options && this.options.modes && this.options.modes.length) { + var me = this; + this.modeSwitcher = new ModeSwitcher(this.menu, this.options.modes, this.options.mode, function onSwitch(mode) { + me.modeSwitcher.destroy(); + + // switch mode and restore focus + me.setMode(mode); + me.modeSwitcher.focus(); + }); + } + + // create search box + if (this.options.search) { + this.searchBox = new SearchBox(this, this.menu); + } + }; + + /** + * Perform an undo action + * @private + */ + treemode._onUndo = function () { + if (this.history) { + // undo last action + this.history.undo(); + + // fire change event + this._onChange(); + } + }; + + /** + * Perform a redo action + * @private + */ + treemode._onRedo = function () { + if (this.history) { + // redo last action + this.history.redo(); + + // fire change event + this._onChange(); + } + }; + + /** + * Event handler + * @param event + * @private + */ + treemode._onEvent = function (event) { + if (event.type == 'keydown') { + this._onKeyDown(event); + } + + if (event.type == 'focus') { + this.focusTarget = event.target; + } + + if (event.type == 'mousedown') { + this._startDragDistance(event); + } + if (event.type == 'mousemove' || event.type == 'mouseup' || event.type == 'click') { + this._updateDragDistance(event); + } + + var node = Node.getNodeFromTarget(event.target); + + if (node && node.selected) { + if (event.type == 'click') { + if (event.target == node.dom.menu) { + this.showContextMenu(event.target); + + // stop propagation (else we will open the context menu of a single node) + return; + } + + // deselect a multi selection + if (!event.hasMoved) { + this.deselect(); + } + } + + if (event.type == 'mousedown') { + // drag multiple nodes + Node.onDragStart(this.multiselection.nodes, event); + } + } + else { + if (event.type == 'mousedown') { + this.deselect(); + + if (node && event.target == node.dom.drag) { + // drag a singe node + Node.onDragStart(node, event); + } + else if (!node || (event.target != node.dom.field && event.target != node.dom.value && event.target != node.dom.select)) { + // select multiple nodes + this._onMultiSelectStart(event); + } + } + } + + if (node) { + node.onEvent(event); + } + }; + + treemode._startDragDistance = function (event) { + this.dragDistanceEvent = { + initialTarget: event.target, + initialPageX: event.pageX, + initialPageY: event.pageY, + dragDistance: 0, + hasMoved: false + }; + }; + + treemode._updateDragDistance = function (event) { + if (!this.dragDistanceEvent) { + this._startDragDistance(event); + } + + var diffX = event.pageX - this.dragDistanceEvent.initialPageX; + var diffY = event.pageY - this.dragDistanceEvent.initialPageY; + + this.dragDistanceEvent.dragDistance = Math.sqrt(diffX * diffX + diffY * diffY); + this.dragDistanceEvent.hasMoved = + this.dragDistanceEvent.hasMoved || this.dragDistanceEvent.dragDistance > 10; + + event.dragDistance = this.dragDistanceEvent.dragDistance; + event.hasMoved = this.dragDistanceEvent.hasMoved; + + return event.dragDistance; + }; + + /** + * Start multi selection of nodes by dragging the mouse + * @param event + * @private + */ + treemode._onMultiSelectStart = function (event) { + var node = Node.getNodeFromTarget(event.target); + + if (this.options.mode !== 'tree' || this.options.onEditable !== undefined) { + // dragging not allowed in modes 'view' and 'form' + // TODO: allow multiselection of items when option onEditable is specified + return; + } + + this.multiselection = { + start: node || null, + end: null, + nodes: [] + }; + + this._startDragDistance(event); + + var editor = this; + if (!this.mousemove) { + this.mousemove = util.addEventListener(window, 'mousemove', function (event) { + editor._onMultiSelect(event); + }); + } + if (!this.mouseup) { + this.mouseup = util.addEventListener(window, 'mouseup', function (event ) { + editor._onMultiSelectEnd(event); + }); + } + + }; + + /** + * Multiselect nodes by dragging + * @param event + * @private + */ + treemode._onMultiSelect = function (event) { + event.preventDefault(); + + this._updateDragDistance(event); + if (!event.hasMoved) { + return; + } + + var node = Node.getNodeFromTarget(event.target); + + if (node) { + if (this.multiselection.start == null) { + this.multiselection.start = node; + } + this.multiselection.end = node; + } + + // deselect previous selection + this.deselect(); + + // find the selected nodes in the range from first to last + var start = this.multiselection.start; + var end = this.multiselection.end || this.multiselection.start; + if (start && end) { + // find the top level childs, all having the same parent + this.multiselection.nodes = this._findTopLevelNodes(start, end); + this.select(this.multiselection.nodes); + } + }; + + /** + * End of multiselect nodes by dragging + * @param event + * @private + */ + treemode._onMultiSelectEnd = function (event) { + // set focus to the context menu button of the first node + if (this.multiselection.nodes[0]) { + this.multiselection.nodes[0].dom.menu.focus(); + } + + this.multiselection.start = null; + this.multiselection.end = null; + + // cleanup global event listeners + if (this.mousemove) { + util.removeEventListener(window, 'mousemove', this.mousemove); + delete this.mousemove; + } + if (this.mouseup) { + util.removeEventListener(window, 'mouseup', this.mouseup); + delete this.mouseup; + } + }; + + /** + * deselect currently selected nodes + * @param {boolean} [clearStartAndEnd=false] If true, the `start` and `end` + * state is cleared too. + */ + treemode.deselect = function (clearStartAndEnd) { + this.multiselection.nodes.forEach(function (node) { + node.setSelected(false); + }); + this.multiselection.nodes = []; + + if (clearStartAndEnd) { + this.multiselection.start = null; + this.multiselection.end = null; + } + }; + + /** + * select nodes + * @param {Node[] | Node} nodes + */ + treemode.select = function (nodes) { + if (!Array.isArray(nodes)) { + return this.select([nodes]); + } + + if (nodes) { + this.deselect(); + + this.multiselection.nodes = nodes.slice(0); + + var first = nodes[0]; + nodes.forEach(function (node) { + node.setSelected(true, node === first); + }); + } + }; + + /** + * From two arbitrary selected nodes, find their shared parent node. + * From that parent node, select the two child nodes in the brances going to + * nodes `start` and `end`, and select all childs in between. + * @param {Node} start + * @param {Node} end + * @return {Array.} Returns an ordered list with child nodes + * @private + */ + treemode._findTopLevelNodes = function (start, end) { + var startPath = start.getNodePath(); + var endPath = end.getNodePath(); + var i = 0; + while (i < startPath.length && startPath[i] === endPath[i]) { + i++; + } + var root = startPath[i - 1]; + var startChild = startPath[i]; + var endChild = endPath[i]; + + if (!startChild || !endChild) { + if (root.parent) { + // startChild is a parent of endChild or vice versa + startChild = root; + endChild = root; + root = root.parent + } + else { + // we have selected the root node (which doesn't have a parent) + startChild = root.childs[0]; + endChild = root.childs[root.childs.length - 1]; + } + } + + if (root && startChild && endChild) { + var startIndex = root.childs.indexOf(startChild); + var endIndex = root.childs.indexOf(endChild); + var firstIndex = Math.min(startIndex, endIndex); + var lastIndex = Math.max(startIndex, endIndex); + + return root.childs.slice(firstIndex, lastIndex + 1); + } + else { + return []; + } + }; + + /** + * Event handler for keydown. Handles shortcut keys + * @param {Event} event + * @private + */ + treemode._onKeyDown = function (event) { + var keynum = event.which || event.keyCode; + var ctrlKey = event.ctrlKey; + var shiftKey = event.shiftKey; + var handled = false; + + if (keynum == 9) { // Tab or Shift+Tab + var me = this; + setTimeout(function () { + // select all text when moving focus to an editable div + util.selectContentEditable(me.focusTarget); + }, 0); + } + + if (this.searchBox) { + if (ctrlKey && keynum == 70) { // Ctrl+F + this.searchBox.dom.search.focus(); + this.searchBox.dom.search.select(); + handled = true; + } + else if (keynum == 114 || (ctrlKey && keynum == 71)) { // F3 or Ctrl+G + var focus = true; + if (!shiftKey) { + // select next search result (F3 or Ctrl+G) + this.searchBox.next(focus); + } + else { + // select previous search result (Shift+F3 or Ctrl+Shift+G) + this.searchBox.previous(focus); + } + + handled = true; + } + } + + if (this.history) { + if (ctrlKey && !shiftKey && keynum == 90) { // Ctrl+Z + // undo + this._onUndo(); + handled = true; + } + else if (ctrlKey && shiftKey && keynum == 90) { // Ctrl+Shift+Z + // redo + this._onRedo(); + handled = true; + } + } + + if (handled) { + event.preventDefault(); + event.stopPropagation(); + } + }; + + /** + * Create main table + * @private + */ + treemode._createTable = function () { + var contentOuter = document.createElement('div'); + contentOuter.className = 'jsoneditor-outer'; + this.contentOuter = contentOuter; + + this.content = document.createElement('div'); + this.content.className = 'jsoneditor-tree'; + contentOuter.appendChild(this.content); + + this.table = document.createElement('table'); + this.table.className = 'jsoneditor-tree'; + this.content.appendChild(this.table); + + // create colgroup where the first two columns don't have a fixed + // width, and the edit columns do have a fixed width + var col; + this.colgroupContent = document.createElement('colgroup'); + if (this.options.mode === 'tree') { + col = document.createElement('col'); + col.width = "24px"; + this.colgroupContent.appendChild(col); + } + col = document.createElement('col'); + col.width = "24px"; + this.colgroupContent.appendChild(col); + col = document.createElement('col'); + this.colgroupContent.appendChild(col); + this.table.appendChild(this.colgroupContent); + + this.tbody = document.createElement('tbody'); + this.table.appendChild(this.tbody); + + this.frame.appendChild(contentOuter); + }; + + /** + * Show a contextmenu for this node. + * Used for multiselection + * @param {HTMLElement} anchor Anchor element to attache the context menu to. + * @param {function} [onClose] Callback method called when the context menu + * is being closed. + */ + treemode.showContextMenu = function (anchor, onClose) { + var items = []; + var editor = this; + + // create duplicate button + items.push({ + text: 'Duplicate', + title: 'Duplicate selected fields (Ctrl+D)', + className: 'jsoneditor-duplicate', + click: function () { + Node.onDuplicate(editor.multiselection.nodes); + } + }); + + // create remove button + items.push({ + text: 'Remove', + title: 'Remove selected fields (Ctrl+Del)', + className: 'jsoneditor-remove', + click: function () { + Node.onRemove(editor.multiselection.nodes); + } + }); + + var menu = new ContextMenu(items, {close: onClose}); + menu.show(anchor, this.content); + }; + + + // define modes + module.exports = [ + { + mode: 'tree', + mixin: treemode, + data: 'json' + }, + { + mode: 'view', + mixin: treemode, + data: 'json' + }, + { + mode: 'form', + mixin: treemode, + data: 'json' + } + ]; + + +/***/ }, +/* 52 */ +/***/ function(module, exports) { + + 'use strict'; + + /** + * The highlighter can highlight/unhighlight a node, and + * animate the visibility of a context menu. + * @constructor Highlighter + */ + function Highlighter () { + this.locked = false; + } + + /** + * Hightlight given node and its childs + * @param {Node} node + */ + Highlighter.prototype.highlight = function (node) { + if (this.locked) { + return; + } + + if (this.node != node) { + // unhighlight current node + if (this.node) { + this.node.setHighlight(false); + } + + // highlight new node + this.node = node; + this.node.setHighlight(true); + } + + // cancel any current timeout + this._cancelUnhighlight(); + }; + + /** + * Unhighlight currently highlighted node. + * Will be done after a delay + */ + Highlighter.prototype.unhighlight = function () { + if (this.locked) { + return; + } + + var me = this; + if (this.node) { + this._cancelUnhighlight(); + + // do the unhighlighting after a small delay, to prevent re-highlighting + // the same node when moving from the drag-icon to the contextmenu-icon + // or vice versa. + this.unhighlightTimer = setTimeout(function () { + me.node.setHighlight(false); + me.node = undefined; + me.unhighlightTimer = undefined; + }, 0); + } + }; + + /** + * Cancel an unhighlight action (if before the timeout of the unhighlight action) + * @private + */ + Highlighter.prototype._cancelUnhighlight = function () { + if (this.unhighlightTimer) { + clearTimeout(this.unhighlightTimer); + this.unhighlightTimer = undefined; + } + }; + + /** + * Lock highlighting or unhighlighting nodes. + * methods highlight and unhighlight do not work while locked. + */ + Highlighter.prototype.lock = function () { + this.locked = true; + }; + + /** + * Unlock highlighting or unhighlighting nodes + */ + Highlighter.prototype.unlock = function () { + this.locked = false; + }; + + module.exports = Highlighter; + + +/***/ }, +/* 53 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var util = __webpack_require__(54); + + /** + * @constructor History + * Store action history, enables undo and redo + * @param {JSONEditor} editor + */ + function History (editor) { + this.editor = editor; + this.history = []; + this.index = -1; + + this.clear(); + + // map with all supported actions + this.actions = { + 'editField': { + 'undo': function (params) { + params.node.updateField(params.oldValue); + }, + 'redo': function (params) { + params.node.updateField(params.newValue); + } + }, + 'editValue': { + 'undo': function (params) { + params.node.updateValue(params.oldValue); + }, + 'redo': function (params) { + params.node.updateValue(params.newValue); + } + }, + 'changeType': { + 'undo': function (params) { + params.node.changeType(params.oldType); + }, + 'redo': function (params) { + params.node.changeType(params.newType); + } + }, + + 'appendNodes': { + 'undo': function (params) { + params.nodes.forEach(function (node) { + params.parent.removeChild(node); + }); + }, + 'redo': function (params) { + params.nodes.forEach(function (node) { + params.parent.appendChild(node); + }); + } + }, + 'insertBeforeNodes': { + 'undo': function (params) { + params.nodes.forEach(function (node) { + params.parent.removeChild(node); + }); + }, + 'redo': function (params) { + params.nodes.forEach(function (node) { + params.parent.insertBefore(node, params.beforeNode); + }); + } + }, + 'insertAfterNodes': { + 'undo': function (params) { + params.nodes.forEach(function (node) { + params.parent.removeChild(node); + }); + }, + 'redo': function (params) { + var afterNode = params.afterNode; + params.nodes.forEach(function (node) { + params.parent.insertAfter(params.node, afterNode); + afterNode = node; + }); + } + }, + 'removeNodes': { + 'undo': function (params) { + var parent = params.parent; + var beforeNode = parent.childs[params.index] || parent.append; + params.nodes.forEach(function (node) { + parent.insertBefore(node, beforeNode); + }); + }, + 'redo': function (params) { + params.nodes.forEach(function (node) { + params.parent.removeChild(node); + }); + } + }, + 'duplicateNodes': { + 'undo': function (params) { + params.nodes.forEach(function (node) { + params.parent.removeChild(node); + }); + }, + 'redo': function (params) { + var afterNode = params.afterNode; + params.nodes.forEach(function (node) { + params.parent.insertAfter(node, afterNode); + afterNode = node; + }); + } + }, + 'moveNodes': { + 'undo': function (params) { + params.nodes.forEach(function (node) { + params.oldBeforeNode.parent.moveBefore(node, params.oldBeforeNode); + }); + }, + 'redo': function (params) { + params.nodes.forEach(function (node) { + params.newBeforeNode.parent.moveBefore(node, params.newBeforeNode); + }); + } + }, + + 'sort': { + 'undo': function (params) { + var node = params.node; + node.hideChilds(); + node.sort = params.oldSort; + node.childs = params.oldChilds; + node.showChilds(); + }, + 'redo': function (params) { + var node = params.node; + node.hideChilds(); + node.sort = params.newSort; + node.childs = params.newChilds; + node.showChilds(); + } + } + + // TODO: restore the original caret position and selection with each undo + // TODO: implement history for actions "expand", "collapse", "scroll", "setDocument" + }; + } + + /** + * The method onChange is executed when the History is changed, and can + * be overloaded. + */ + History.prototype.onChange = function () {}; + + /** + * Add a new action to the history + * @param {String} action The executed action. Available actions: "editField", + * "editValue", "changeType", "appendNode", + * "removeNode", "duplicateNode", "moveNode" + * @param {Object} params Object containing parameters describing the change. + * The parameters in params depend on the action (for + * example for "editValue" the Node, old value, and new + * value are provided). params contains all information + * needed to undo or redo the action. + */ + History.prototype.add = function (action, params) { + this.index++; + this.history[this.index] = { + 'action': action, + 'params': params, + 'timestamp': new Date() + }; + + // remove redo actions which are invalid now + if (this.index < this.history.length - 1) { + this.history.splice(this.index + 1, this.history.length - this.index - 1); + } + + // fire onchange event + this.onChange(); + }; + + /** + * Clear history + */ + History.prototype.clear = function () { + this.history = []; + this.index = -1; + + // fire onchange event + this.onChange(); + }; + + /** + * Check if there is an action available for undo + * @return {Boolean} canUndo + */ + History.prototype.canUndo = function () { + return (this.index >= 0); + }; + + /** + * Check if there is an action available for redo + * @return {Boolean} canRedo + */ + History.prototype.canRedo = function () { + return (this.index < this.history.length - 1); + }; + + /** + * Undo the last action + */ + History.prototype.undo = function () { + if (this.canUndo()) { + var obj = this.history[this.index]; + if (obj) { + var action = this.actions[obj.action]; + if (action && action.undo) { + action.undo(obj.params); + if (obj.params.oldSelection) { + this.editor.setSelection(obj.params.oldSelection); + } + } + else { + console.error(new Error('unknown action "' + obj.action + '"')); + } + } + this.index--; + + // fire onchange event + this.onChange(); + } + }; + + /** + * Redo the last action + */ + History.prototype.redo = function () { + if (this.canRedo()) { + this.index++; + + var obj = this.history[this.index]; + if (obj) { + var action = this.actions[obj.action]; + if (action && action.redo) { + action.redo(obj.params); + if (obj.params.newSelection) { + this.editor.setSelection(obj.params.newSelection); + } + } + else { + console.error(new Error('unknown action "' + obj.action + '"')); + } + } + + // fire onchange event + this.onChange(); + } + }; + + /** + * Destroy history + */ + History.prototype.destroy = function () { + this.editor = null; + + this.history = []; + this.index = -1; + }; + + module.exports = History; + + +/***/ }, +/* 54 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var jsonlint = __webpack_require__(55); + + /** + * Parse JSON using the parser built-in in the browser. + * On exception, the jsonString is validated and a detailed error is thrown. + * @param {String} jsonString + * @return {JSON} json + */ + exports.parse = function parse(jsonString) { + try { + return JSON.parse(jsonString); + } + catch (err) { + // try to throw a more detailed error message using validate + exports.validate(jsonString); + + // rethrow the original error + throw err; + } + }; + + /** + * Sanitize a JSON-like string containing. For example changes JavaScript + * notation into JSON notation. + * This function for example changes a string like "{a: 2, 'b': {c: 'd'}" + * into '{"a": 2, "b": {"c": "d"}' + * @param {string} jsString + * @returns {string} json + */ + exports.sanitize = function (jsString) { + // escape all single and double quotes inside strings + var chars = []; + var i = 0; + + //If JSON starts with a function (characters/digits/"_-"), remove this function. + //This is useful for "stripping" JSONP objects to become JSON + //For example: /* some comment */ function_12321321 ( [{"a":"b"}] ); => [{"a":"b"}] + var match = jsString.match(/^\s*(\/\*(.|[\r\n])*?\*\/)?\s*[\da-zA-Z_$]+\s*\(([\s\S]*)\)\s*;?\s*$/); + if (match) { + jsString = match[3]; + } + + // helper functions to get the current/prev/next character + function curr () { return jsString.charAt(i); } + function next() { return jsString.charAt(i + 1); } + function prev() { return jsString.charAt(i - 1); } + + // get the last parsed non-whitespace character + function lastNonWhitespace () { + var p = chars.length - 1; + + while (p >= 0) { + var pp = chars[p]; + if (pp !== ' ' && pp !== '\n' && pp !== '\r' && pp !== '\t') { // non whitespace + return pp; + } + p--; + } + + return ''; + } + + // skip a block comment '/* ... */' + function skipBlockComment () { + i += 2; + while (i < jsString.length && (curr() !== '*' || next() !== '/')) { + i++; + } + i += 2; + } + + // skip a comment '// ...' + function skipComment () { + i += 2; + while (i < jsString.length && (curr() !== '\n')) { + i++; + } + } + + // parse single or double quoted string + function parseString(quote) { + chars.push('"'); + i++; + var c = curr(); + while (i < jsString.length && c !== quote) { + if (c === '"' && prev() !== '\\') { + // unescaped double quote, escape it + chars.push('\\'); + } + + // handle escape character + if (c === '\\') { + i++; + c = curr(); + + // remove the escape character when followed by a single quote ', not needed + if (c !== '\'') { + chars.push('\\'); + } + } + chars.push(c); + + i++; + c = curr(); + } + if (c === quote) { + chars.push('"'); + i++; + } + } + + // parse an unquoted key + function parseKey() { + var specialValues = ['null', 'true', 'false']; + var key = ''; + var c = curr(); + + var regexp = /[a-zA-Z_$\d]/; // letter, number, underscore, dollar character + while (regexp.test(c)) { + key += c; + i++; + c = curr(); + } + + if (specialValues.indexOf(key) === -1) { + chars.push('"' + key + '"'); + } + else { + chars.push(key); + } + } + + while(i < jsString.length) { + var c = curr(); + + if (c === '/' && next() === '*') { + skipBlockComment(); + } + else if (c === '/' && next() === '/') { + skipComment(); + } + else if (c === '\'' || c === '"') { + parseString(c); + } + else if (/[a-zA-Z_$]/.test(c) && ['{', ','].indexOf(lastNonWhitespace()) !== -1) { + // an unquoted object key (like a in '{a:2}') + parseKey(); + } + else { + chars.push(c); + i++; + } + } + + return chars.join(''); + }; + + /** + * Escape unicode characters. + * For example input '\u2661' (length 1) will output '\\u2661' (length 5). + * @param {string} text + * @return {string} + */ + exports.escapeUnicodeChars = function (text) { + // see https://www.wikiwand.com/en/UTF-16 + // note: we leave surrogate pairs as two individual chars, + // as JSON doesn't interpret them as a single unicode char. + return text.replace(/[\u007F-\uFFFF]/g, function(c) { + return '\\u'+('0000' + c.charCodeAt(0).toString(16)).slice(-4); + }) + }; + + /** + * Validate a string containing a JSON object + * This method uses JSONLint to validate the String. If JSONLint is not + * available, the built-in JSON parser of the browser is used. + * @param {String} jsonString String with an (invalid) JSON object + * @throws Error + */ + exports.validate = function validate(jsonString) { + if (typeof(jsonlint) != 'undefined') { + jsonlint.parse(jsonString); + } + else { + JSON.parse(jsonString); + } + }; + + /** + * Extend object a with the properties of object b + * @param {Object} a + * @param {Object} b + * @return {Object} a + */ + exports.extend = function extend(a, b) { + for (var prop in b) { + if (b.hasOwnProperty(prop)) { + a[prop] = b[prop]; + } + } + return a; + }; + + /** + * Remove all properties from object a + * @param {Object} a + * @return {Object} a + */ + exports.clear = function clear (a) { + for (var prop in a) { + if (a.hasOwnProperty(prop)) { + delete a[prop]; + } + } + return a; + }; + + /** + * Get the type of an object + * @param {*} object + * @return {String} type + */ + exports.type = function type (object) { + if (object === null) { + return 'null'; + } + if (object === undefined) { + return 'undefined'; + } + if ((object instanceof Number) || (typeof object === 'number')) { + return 'number'; + } + if ((object instanceof String) || (typeof object === 'string')) { + return 'string'; + } + if ((object instanceof Boolean) || (typeof object === 'boolean')) { + return 'boolean'; + } + if ((object instanceof RegExp) || (typeof object === 'regexp')) { + return 'regexp'; + } + if (exports.isArray(object)) { + return 'array'; + } + + return 'object'; + }; + + /** + * Test whether a text contains a url (matches when a string starts + * with 'http://*' or 'https://*' and has no whitespace characters) + * @param {String} text + */ + var isUrlRegex = /^https?:\/\/\S+$/; + exports.isUrl = function isUrl (text) { + return (typeof text == 'string' || text instanceof String) && + isUrlRegex.test(text); + }; + + /** + * Tes whether given object is an Array + * @param {*} obj + * @returns {boolean} returns true when obj is an array + */ + exports.isArray = function (obj) { + return Object.prototype.toString.call(obj) === '[object Array]'; + }; + + /** + * Retrieve the absolute left value of a DOM element + * @param {Element} elem A dom element, for example a div + * @return {Number} left The absolute left position of this element + * in the browser page. + */ + exports.getAbsoluteLeft = function getAbsoluteLeft(elem) { + var rect = elem.getBoundingClientRect(); + return rect.left + window.pageXOffset || document.scrollLeft || 0; + }; + + /** + * Retrieve the absolute top value of a DOM element + * @param {Element} elem A dom element, for example a div + * @return {Number} top The absolute top position of this element + * in the browser page. + */ + exports.getAbsoluteTop = function getAbsoluteTop(elem) { + var rect = elem.getBoundingClientRect(); + return rect.top + window.pageYOffset || document.scrollTop || 0; + }; + + /** + * add a className to the given elements style + * @param {Element} elem + * @param {String} className + */ + exports.addClassName = function addClassName(elem, className) { + var classes = elem.className.split(' '); + if (classes.indexOf(className) == -1) { + classes.push(className); // add the class to the array + elem.className = classes.join(' '); + } + }; + + /** + * add a className to the given elements style + * @param {Element} elem + * @param {String} className + */ + exports.removeClassName = function removeClassName(elem, className) { + var classes = elem.className.split(' '); + var index = classes.indexOf(className); + if (index != -1) { + classes.splice(index, 1); // remove the class from the array + elem.className = classes.join(' '); + } + }; + + /** + * Strip the formatting from the contents of a div + * the formatting from the div itself is not stripped, only from its childs. + * @param {Element} divElement + */ + exports.stripFormatting = function stripFormatting(divElement) { + var childs = divElement.childNodes; + for (var i = 0, iMax = childs.length; i < iMax; i++) { + var child = childs[i]; + + // remove the style + if (child.style) { + // TODO: test if child.attributes does contain style + child.removeAttribute('style'); + } + + // remove all attributes + var attributes = child.attributes; + if (attributes) { + for (var j = attributes.length - 1; j >= 0; j--) { + var attribute = attributes[j]; + if (attribute.specified === true) { + child.removeAttribute(attribute.name); + } + } + } + + // recursively strip childs + exports.stripFormatting(child); + } + }; + + /** + * Set focus to the end of an editable div + * code from Nico Burns + * http://stackoverflow.com/users/140293/nico-burns + * http://stackoverflow.com/questions/1125292/how-to-move-cursor-to-end-of-contenteditable-entity + * @param {Element} contentEditableElement A content editable div + */ + exports.setEndOfContentEditable = function setEndOfContentEditable(contentEditableElement) { + var range, selection; + if(document.createRange) { + range = document.createRange();//Create a range (a range is a like the selection but invisible) + range.selectNodeContents(contentEditableElement);//Select the entire contents of the element with the range + range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start + selection = window.getSelection();//get the selection object (allows you to change selection) + selection.removeAllRanges();//remove any selections already made + selection.addRange(range);//make the range you have just created the visible selection + } + }; + + /** + * Select all text of a content editable div. + * http://stackoverflow.com/a/3806004/1262753 + * @param {Element} contentEditableElement A content editable div + */ + exports.selectContentEditable = function selectContentEditable(contentEditableElement) { + if (!contentEditableElement || contentEditableElement.nodeName != 'DIV') { + return; + } + + var sel, range; + if (window.getSelection && document.createRange) { + range = document.createRange(); + range.selectNodeContents(contentEditableElement); + sel = window.getSelection(); + sel.removeAllRanges(); + sel.addRange(range); + } + }; + + /** + * Get text selection + * http://stackoverflow.com/questions/4687808/contenteditable-selected-text-save-and-restore + * @return {Range | TextRange | null} range + */ + exports.getSelection = function getSelection() { + if (window.getSelection) { + var sel = window.getSelection(); + if (sel.getRangeAt && sel.rangeCount) { + return sel.getRangeAt(0); + } + } + return null; + }; + + /** + * Set text selection + * http://stackoverflow.com/questions/4687808/contenteditable-selected-text-save-and-restore + * @param {Range | TextRange | null} range + */ + exports.setSelection = function setSelection(range) { + if (range) { + if (window.getSelection) { + var sel = window.getSelection(); + sel.removeAllRanges(); + sel.addRange(range); + } + } + }; + + /** + * Get selected text range + * @return {Object} params object containing parameters: + * {Number} startOffset + * {Number} endOffset + * {Element} container HTML element holding the + * selected text element + * Returns null if no text selection is found + */ + exports.getSelectionOffset = function getSelectionOffset() { + var range = exports.getSelection(); + + if (range && 'startOffset' in range && 'endOffset' in range && + range.startContainer && (range.startContainer == range.endContainer)) { + return { + startOffset: range.startOffset, + endOffset: range.endOffset, + container: range.startContainer.parentNode + }; + } + + return null; + }; + + /** + * Set selected text range in given element + * @param {Object} params An object containing: + * {Element} container + * {Number} startOffset + * {Number} endOffset + */ + exports.setSelectionOffset = function setSelectionOffset(params) { + if (document.createRange && window.getSelection) { + var selection = window.getSelection(); + if(selection) { + var range = document.createRange(); + + if (!params.container.firstChild) { + params.container.appendChild(document.createTextNode('')); + } + + // TODO: do not suppose that the first child of the container is a textnode, + // but recursively find the textnodes + range.setStart(params.container.firstChild, params.startOffset); + range.setEnd(params.container.firstChild, params.endOffset); + + exports.setSelection(range); + } + } + }; + + /** + * Get the inner text of an HTML element (for example a div element) + * @param {Element} element + * @param {Object} [buffer] + * @return {String} innerText + */ + exports.getInnerText = function getInnerText(element, buffer) { + var first = (buffer == undefined); + if (first) { + buffer = { + 'text': '', + 'flush': function () { + var text = this.text; + this.text = ''; + return text; + }, + 'set': function (text) { + this.text = text; + } + }; + } + + // text node + if (element.nodeValue) { + return buffer.flush() + element.nodeValue; + } + + // divs or other HTML elements + if (element.hasChildNodes()) { + var childNodes = element.childNodes; + var innerText = ''; + + for (var i = 0, iMax = childNodes.length; i < iMax; i++) { + var child = childNodes[i]; + + if (child.nodeName == 'DIV' || child.nodeName == 'P') { + var prevChild = childNodes[i - 1]; + var prevName = prevChild ? prevChild.nodeName : undefined; + if (prevName && prevName != 'DIV' && prevName != 'P' && prevName != 'BR') { + innerText += '\n'; + buffer.flush(); + } + innerText += exports.getInnerText(child, buffer); + buffer.set('\n'); + } + else if (child.nodeName == 'BR') { + innerText += buffer.flush(); + buffer.set('\n'); + } + else { + innerText += exports.getInnerText(child, buffer); + } + } + + return innerText; + } + else { + if (element.nodeName == 'P' && exports.getInternetExplorerVersion() != -1) { + // On Internet Explorer, a

with hasChildNodes()==false is + // rendered with a new line. Note that a

with + // hasChildNodes()==true is rendered without a new line + // Other browsers always ensure there is a
inside the

, + // and if not, the

does not render a new line + return buffer.flush(); + } + } + + // br or unknown + return ''; + }; + + /** + * Returns the version of Internet Explorer or a -1 + * (indicating the use of another browser). + * Source: http://msdn.microsoft.com/en-us/library/ms537509(v=vs.85).aspx + * @return {Number} Internet Explorer version, or -1 in case of an other browser + */ + exports.getInternetExplorerVersion = function getInternetExplorerVersion() { + if (_ieVersion == -1) { + var rv = -1; // Return value assumes failure. + if (navigator.appName == 'Microsoft Internet Explorer') + { + var ua = navigator.userAgent; + var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})"); + if (re.exec(ua) != null) { + rv = parseFloat( RegExp.$1 ); + } + } + + _ieVersion = rv; + } + + return _ieVersion; + }; + + /** + * Test whether the current browser is Firefox + * @returns {boolean} isFirefox + */ + exports.isFirefox = function isFirefox () { + return (navigator.userAgent.indexOf("Firefox") != -1); + }; + + /** + * cached internet explorer version + * @type {Number} + * @private + */ + var _ieVersion = -1; + + /** + * Add and event listener. Works for all browsers + * @param {Element} element An html element + * @param {string} action The action, for example "click", + * without the prefix "on" + * @param {function} listener The callback function to be executed + * @param {boolean} [useCapture] false by default + * @return {function} the created event listener + */ + exports.addEventListener = function addEventListener(element, action, listener, useCapture) { + if (element.addEventListener) { + if (useCapture === undefined) + useCapture = false; + + if (action === "mousewheel" && exports.isFirefox()) { + action = "DOMMouseScroll"; // For Firefox + } + + element.addEventListener(action, listener, useCapture); + return listener; + } else if (element.attachEvent) { + // Old IE browsers + var f = function () { + return listener.call(element, window.event); + }; + element.attachEvent("on" + action, f); + return f; + } + }; + + /** + * Remove an event listener from an element + * @param {Element} element An html dom element + * @param {string} action The name of the event, for example "mousedown" + * @param {function} listener The listener function + * @param {boolean} [useCapture] false by default + */ + exports.removeEventListener = function removeEventListener(element, action, listener, useCapture) { + if (element.removeEventListener) { + if (useCapture === undefined) + useCapture = false; + + if (action === "mousewheel" && exports.isFirefox()) { + action = "DOMMouseScroll"; // For Firefox + } + + element.removeEventListener(action, listener, useCapture); + } else if (element.detachEvent) { + // Old IE browsers + element.detachEvent("on" + action, listener); + } + }; + + /** + * Parse a JSON path like '.items[3].name' into an array + * @param {string} jsonPath + * @return {Array} + */ + exports.parsePath = function parsePath(jsonPath) { + var prop, remainder; + + if (jsonPath.length === 0) { + return []; + } + + // find a match like '.prop' + var match = jsonPath.match(/^\.(\w+)/); + if (match) { + prop = match[1]; + remainder = jsonPath.substr(prop.length + 1); + } + else if (jsonPath[0] === '[') { + // find a match like + var end = jsonPath.indexOf(']'); + if (end === -1) { + throw new SyntaxError('Character ] expected in path'); + } + if (end === 1) { + throw new SyntaxError('Index expected after ['); + } + + var value = jsonPath.substring(1, end); + if (value[0] === '\'') { + // ajv produces string prop names with single quotes, so we need + // to reformat them into valid double-quoted JSON strings + value = '\"' + value.substring(1, value.length - 1) + '\"'; + } + + prop = value === '*' ? value : JSON.parse(value); // parse string and number + remainder = jsonPath.substr(end + 1); + } + else { + throw new SyntaxError('Failed to parse path'); + } + + return [prop].concat(parsePath(remainder)) + }; + + /** + * Improve the error message of a JSON schema error + * @param {Object} error + * @return {Object} The error + */ + exports.improveSchemaError = function (error) { + if (error.keyword === 'enum' && Array.isArray(error.schema)) { + var enums = error.schema; + if (enums) { + enums = enums.map(function (value) { + return JSON.stringify(value); + }); + + if (enums.length > 5) { + var more = ['(' + (enums.length - 5) + ' more...)']; + enums = enums.slice(0, 5); + enums.push(more); + } + error.message = 'should be equal to one of: ' + enums.join(', '); + } + } + + if (error.keyword === 'additionalProperties') { + error.message = 'should NOT have additional property: ' + error.params.additionalProperty; + } + + return error; + }; + + /** + * Test whether the child rect fits completely inside the parent rect. + * @param {ClientRect} parent + * @param {ClientRect} child + * @param {number} margin + */ + exports.insideRect = function (parent, child, margin) { + var _margin = margin !== undefined ? margin : 0; + return child.left - _margin >= parent.left + && child.right + _margin <= parent.right + && child.top - _margin >= parent.top + && child.bottom + _margin <= parent.bottom; + }; + + /** + * Returns a function, that, as long as it continues to be invoked, will not + * be triggered. The function will be called after it stops being called for + * N milliseconds. + * + * Source: https://davidwalsh.name/javascript-debounce-function + * + * @param {function} func + * @param {number} wait Number in milliseconds + * @param {boolean} [immediate=false] If `immediate` is passed, trigger the + * function on the leading edge, instead + * of the trailing. + * @return {function} Return the debounced function + */ + exports.debounce = function debounce(func, wait, immediate) { + var timeout; + return function() { + var context = this, args = arguments; + var later = function() { + timeout = null; + if (!immediate) func.apply(context, args); + }; + var callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) func.apply(context, args); + }; + }; + + /** + * Determines the difference between two texts. + * Can only detect one removed or inserted block of characters. + * @param {string} oldText + * @param {string} newText + * @return {{start: number, end: number}} Returns the start and end + * of the changed part in newText. + */ + exports.textDiff = function textDiff(oldText, newText) { + var len = newText.length; + var start = 0; + var oldEnd = oldText.length; + var newEnd = newText.length; + + while (newText.charAt(start) === oldText.charAt(start) + && start < len) { + start++; + } + + while (newText.charAt(newEnd - 1) === oldText.charAt(oldEnd - 1) + && newEnd > start && oldEnd > 0) { + newEnd--; + oldEnd--; + } + + return {start: start, end: newEnd}; + }; + + +/***/ }, +/* 55 */ +/***/ function(module, exports, __webpack_require__) { + + /* Jison generated parser */ + var jsonlint = (function(){ + var parser = {trace: function trace() { }, + yy: {}, + symbols_: {"error":2,"JSONString":3,"STRING":4,"JSONNumber":5,"NUMBER":6,"JSONNullLiteral":7,"NULL":8,"JSONBooleanLiteral":9,"TRUE":10,"FALSE":11,"JSONText":12,"JSONValue":13,"EOF":14,"JSONObject":15,"JSONArray":16,"{":17,"}":18,"JSONMemberList":19,"JSONMember":20,":":21,",":22,"[":23,"]":24,"JSONElementList":25,"$accept":0,"$end":1}, + terminals_: {2:"error",4:"STRING",6:"NUMBER",8:"NULL",10:"TRUE",11:"FALSE",14:"EOF",17:"{",18:"}",21:":",22:",",23:"[",24:"]"}, + productions_: [0,[3,1],[5,1],[7,1],[9,1],[9,1],[12,2],[13,1],[13,1],[13,1],[13,1],[13,1],[13,1],[15,2],[15,3],[20,3],[19,1],[19,3],[16,2],[16,3],[25,1],[25,3]], + performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) { + + var $0 = $$.length - 1; + switch (yystate) { + case 1: // replace escaped characters with actual character + this.$ = yytext.replace(/\\(\\|")/g, "$"+"1") + .replace(/\\n/g,'\n') + .replace(/\\r/g,'\r') + .replace(/\\t/g,'\t') + .replace(/\\v/g,'\v') + .replace(/\\f/g,'\f') + .replace(/\\b/g,'\b'); + + break; + case 2:this.$ = Number(yytext); + break; + case 3:this.$ = null; + break; + case 4:this.$ = true; + break; + case 5:this.$ = false; + break; + case 6:return this.$ = $$[$0-1]; + break; + case 13:this.$ = {}; + break; + case 14:this.$ = $$[$0-1]; + break; + case 15:this.$ = [$$[$0-2], $$[$0]]; + break; + case 16:this.$ = {}; this.$[$$[$0][0]] = $$[$0][1]; + break; + case 17:this.$ = $$[$0-2]; $$[$0-2][$$[$0][0]] = $$[$0][1]; + break; + case 18:this.$ = []; + break; + case 19:this.$ = $$[$0-1]; + break; + case 20:this.$ = [$$[$0]]; + break; + case 21:this.$ = $$[$0-2]; $$[$0-2].push($$[$0]); + break; + } + }, + table: [{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],12:1,13:2,15:7,16:8,17:[1,14],23:[1,15]},{1:[3]},{14:[1,16]},{14:[2,7],18:[2,7],22:[2,7],24:[2,7]},{14:[2,8],18:[2,8],22:[2,8],24:[2,8]},{14:[2,9],18:[2,9],22:[2,9],24:[2,9]},{14:[2,10],18:[2,10],22:[2,10],24:[2,10]},{14:[2,11],18:[2,11],22:[2,11],24:[2,11]},{14:[2,12],18:[2,12],22:[2,12],24:[2,12]},{14:[2,3],18:[2,3],22:[2,3],24:[2,3]},{14:[2,4],18:[2,4],22:[2,4],24:[2,4]},{14:[2,5],18:[2,5],22:[2,5],24:[2,5]},{14:[2,1],18:[2,1],21:[2,1],22:[2,1],24:[2,1]},{14:[2,2],18:[2,2],22:[2,2],24:[2,2]},{3:20,4:[1,12],18:[1,17],19:18,20:19},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:23,15:7,16:8,17:[1,14],23:[1,15],24:[1,21],25:22},{1:[2,6]},{14:[2,13],18:[2,13],22:[2,13],24:[2,13]},{18:[1,24],22:[1,25]},{18:[2,16],22:[2,16]},{21:[1,26]},{14:[2,18],18:[2,18],22:[2,18],24:[2,18]},{22:[1,28],24:[1,27]},{22:[2,20],24:[2,20]},{14:[2,14],18:[2,14],22:[2,14],24:[2,14]},{3:20,4:[1,12],20:29},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:30,15:7,16:8,17:[1,14],23:[1,15]},{14:[2,19],18:[2,19],22:[2,19],24:[2,19]},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:31,15:7,16:8,17:[1,14],23:[1,15]},{18:[2,17],22:[2,17]},{18:[2,15],22:[2,15]},{22:[2,21],24:[2,21]}], + defaultActions: {16:[2,6]}, + parseError: function parseError(str, hash) { + throw new Error(str); + }, + parse: function parse(input) { + var self = this, + stack = [0], + vstack = [null], // semantic value stack + lstack = [], // location stack + table = this.table, + yytext = '', + yylineno = 0, + yyleng = 0, + recovering = 0, + TERROR = 2, + EOF = 1; + + //this.reductionCount = this.shiftCount = 0; + + this.lexer.setInput(input); + this.lexer.yy = this.yy; + this.yy.lexer = this.lexer; + if (typeof this.lexer.yylloc == 'undefined') + this.lexer.yylloc = {}; + var yyloc = this.lexer.yylloc; + lstack.push(yyloc); + + if (typeof this.yy.parseError === 'function') + this.parseError = this.yy.parseError; + + function popStack (n) { + stack.length = stack.length - 2*n; + vstack.length = vstack.length - n; + lstack.length = lstack.length - n; + } + + function lex() { + var token; + token = self.lexer.lex() || 1; // $end = 1 + // if token isn't its numeric value, convert + if (typeof token !== 'number') { + token = self.symbols_[token] || token; + } + return token; + } + + var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected; + while (true) { + // retreive state number from top of stack + state = stack[stack.length-1]; + + // use default actions if available + if (this.defaultActions[state]) { + action = this.defaultActions[state]; + } else { + if (symbol == null) + symbol = lex(); + // read action for current state and first input + action = table[state] && table[state][symbol]; + } + + // handle parse error + _handle_error: + if (typeof action === 'undefined' || !action.length || !action[0]) { + + if (!recovering) { + // Report error + expected = []; + for (p in table[state]) if (this.terminals_[p] && p > 2) { + expected.push("'"+this.terminals_[p]+"'"); + } + var errStr = ''; + if (this.lexer.showPosition) { + errStr = 'Parse error on line '+(yylineno+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+expected.join(', ') + ", got '" + this.terminals_[symbol]+ "'"; + } else { + errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " + + (symbol == 1 /*EOF*/ ? "end of input" : + ("'"+(this.terminals_[symbol] || symbol)+"'")); + } + this.parseError(errStr, + {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected}); + } + + // just recovered from another error + if (recovering == 3) { + if (symbol == EOF) { + throw new Error(errStr || 'Parsing halted.'); + } + + // discard current lookahead and grab another + yyleng = this.lexer.yyleng; + yytext = this.lexer.yytext; + yylineno = this.lexer.yylineno; + yyloc = this.lexer.yylloc; + symbol = lex(); + } + + // try to recover from error + while (1) { + // check for error recovery rule in this state + if ((TERROR.toString()) in table[state]) { + break; + } + if (state == 0) { + throw new Error(errStr || 'Parsing halted.'); + } + popStack(1); + state = stack[stack.length-1]; + } + + preErrorSymbol = symbol; // save the lookahead token + symbol = TERROR; // insert generic error symbol as new lookahead + state = stack[stack.length-1]; + action = table[state] && table[state][TERROR]; + recovering = 3; // allow 3 real symbols to be shifted before reporting a new error + } + + // this shouldn't happen, unless resolve defaults are off + if (action[0] instanceof Array && action.length > 1) { + throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol); + } + + switch (action[0]) { + + case 1: // shift + //this.shiftCount++; + + stack.push(symbol); + vstack.push(this.lexer.yytext); + lstack.push(this.lexer.yylloc); + stack.push(action[1]); // push state + symbol = null; + if (!preErrorSymbol) { // normal execution/no error + yyleng = this.lexer.yyleng; + yytext = this.lexer.yytext; + yylineno = this.lexer.yylineno; + yyloc = this.lexer.yylloc; + if (recovering > 0) + recovering--; + } else { // error just occurred, resume old lookahead f/ before error + symbol = preErrorSymbol; + preErrorSymbol = null; + } + break; + + case 2: // reduce + //this.reductionCount++; + + len = this.productions_[action[1]][1]; + + // perform semantic action + yyval.$ = vstack[vstack.length-len]; // default to $$ = $1 + // default location, uses first token for firsts, last for lasts + yyval._$ = { + first_line: lstack[lstack.length-(len||1)].first_line, + last_line: lstack[lstack.length-1].last_line, + first_column: lstack[lstack.length-(len||1)].first_column, + last_column: lstack[lstack.length-1].last_column + }; + r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); + + if (typeof r !== 'undefined') { + return r; + } + + // pop off stack + if (len) { + stack = stack.slice(0,-1*len*2); + vstack = vstack.slice(0, -1*len); + lstack = lstack.slice(0, -1*len); + } + + stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce) + vstack.push(yyval.$); + lstack.push(yyval._$); + // goto new state = table[STATE][NONTERMINAL] + newState = table[stack[stack.length-2]][stack[stack.length-1]]; + stack.push(newState); + break; + + case 3: // accept + return true; + } + + } + + return true; + }}; + /* Jison generated lexer */ + var lexer = (function(){ + var lexer = ({EOF:1, + parseError:function parseError(str, hash) { + if (this.yy.parseError) { + this.yy.parseError(str, hash); + } else { + throw new Error(str); + } + }, + setInput:function (input) { + this._input = input; + this._more = this._less = this.done = false; + this.yylineno = this.yyleng = 0; + this.yytext = this.matched = this.match = ''; + this.conditionStack = ['INITIAL']; + this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0}; + return this; + }, + input:function () { + var ch = this._input[0]; + this.yytext+=ch; + this.yyleng++; + this.match+=ch; + this.matched+=ch; + var lines = ch.match(/\n/); + if (lines) this.yylineno++; + this._input = this._input.slice(1); + return ch; + }, + unput:function (ch) { + this._input = ch + this._input; + return this; + }, + more:function () { + this._more = true; + return this; + }, + less:function (n) { + this._input = this.match.slice(n) + this._input; + }, + pastInput:function () { + var past = this.matched.substr(0, this.matched.length - this.match.length); + return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, ""); + }, + upcomingInput:function () { + var next = this.match; + if (next.length < 20) { + next += this._input.substr(0, 20-next.length); + } + return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, ""); + }, + showPosition:function () { + var pre = this.pastInput(); + var c = new Array(pre.length + 1).join("-"); + return pre + this.upcomingInput() + "\n" + c+"^"; + }, + next:function () { + if (this.done) { + return this.EOF; + } + if (!this._input) this.done = true; + + var token, + match, + tempMatch, + index, + col, + lines; + if (!this._more) { + this.yytext = ''; + this.match = ''; + } + var rules = this._currentRules(); + for (var i=0;i < rules.length; i++) { + tempMatch = this._input.match(this.rules[rules[i]]); + if (tempMatch && (!match || tempMatch[0].length > match[0].length)) { + match = tempMatch; + index = i; + if (!this.options.flex) break; + } + } + if (match) { + lines = match[0].match(/\n.*/g); + if (lines) this.yylineno += lines.length; + this.yylloc = {first_line: this.yylloc.last_line, + last_line: this.yylineno+1, + first_column: this.yylloc.last_column, + last_column: lines ? lines[lines.length-1].length-1 : this.yylloc.last_column + match[0].length} + this.yytext += match[0]; + this.match += match[0]; + this.yyleng = this.yytext.length; + this._more = false; + this._input = this._input.slice(match[0].length); + this.matched += match[0]; + token = this.performAction.call(this, this.yy, this, rules[index],this.conditionStack[this.conditionStack.length-1]); + if (this.done && this._input) this.done = false; + if (token) return token; + else return; + } + if (this._input === "") { + return this.EOF; + } else { + this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(), + {text: "", token: null, line: this.yylineno}); + } + }, + lex:function lex() { + var r = this.next(); + if (typeof r !== 'undefined') { + return r; + } else { + return this.lex(); + } + }, + begin:function begin(condition) { + this.conditionStack.push(condition); + }, + popState:function popState() { + return this.conditionStack.pop(); + }, + _currentRules:function _currentRules() { + return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules; + }, + topState:function () { + return this.conditionStack[this.conditionStack.length-2]; + }, + pushState:function begin(condition) { + this.begin(condition); + }}); + lexer.options = {}; + lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) { + + var YYSTATE=YY_START + switch($avoiding_name_collisions) { + case 0:/* skip whitespace */ + break; + case 1:return 6 + break; + case 2:yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2); return 4 + break; + case 3:return 17 + break; + case 4:return 18 + break; + case 5:return 23 + break; + case 6:return 24 + break; + case 7:return 22 + break; + case 8:return 21 + break; + case 9:return 10 + break; + case 10:return 11 + break; + case 11:return 8 + break; + case 12:return 14 + break; + case 13:return 'INVALID' + break; + } + }; + lexer.rules = [/^(?:\s+)/,/^(?:(-?([0-9]|[1-9][0-9]+))(\.[0-9]+)?([eE][-+]?[0-9]+)?\b)/,/^(?:"(?:\\[\\"bfnrt/]|\\u[a-fA-F0-9]{4}|[^\\\0-\x09\x0a-\x1f"])*")/,/^(?:\{)/,/^(?:\})/,/^(?:\[)/,/^(?:\])/,/^(?:,)/,/^(?::)/,/^(?:true\b)/,/^(?:false\b)/,/^(?:null\b)/,/^(?:$)/,/^(?:.)/]; + lexer.conditions = {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13],"inclusive":true}}; + + + ; + return lexer;})() + parser.lexer = lexer; + return parser; + })(); + if (true) { + exports.parser = jsonlint; + exports.parse = jsonlint.parse.bind(jsonlint); + } + +/***/ }, +/* 56 */ +/***/ function(module, exports) { + + 'use strict'; + + /** + * @constructor SearchBox + * Create a search box in given HTML container + * @param {JSONEditor} editor The JSON Editor to attach to + * @param {Element} container HTML container element of where to + * create the search box + */ + function SearchBox (editor, container) { + var searchBox = this; + + this.editor = editor; + this.timeout = undefined; + this.delay = 200; // ms + this.lastText = undefined; + + this.dom = {}; + this.dom.container = container; + + var table = document.createElement('table'); + this.dom.table = table; + table.className = 'jsoneditor-search'; + container.appendChild(table); + var tbody = document.createElement('tbody'); + this.dom.tbody = tbody; + table.appendChild(tbody); + var tr = document.createElement('tr'); + tbody.appendChild(tr); + + var td = document.createElement('td'); + tr.appendChild(td); + var results = document.createElement('div'); + this.dom.results = results; + results.className = 'jsoneditor-results'; + td.appendChild(results); + + td = document.createElement('td'); + tr.appendChild(td); + var divInput = document.createElement('div'); + this.dom.input = divInput; + divInput.className = 'jsoneditor-frame'; + divInput.title = 'Search fields and values'; + td.appendChild(divInput); + + // table to contain the text input and search button + var tableInput = document.createElement('table'); + divInput.appendChild(tableInput); + var tbodySearch = document.createElement('tbody'); + tableInput.appendChild(tbodySearch); + tr = document.createElement('tr'); + tbodySearch.appendChild(tr); + + var refreshSearch = document.createElement('button'); + refreshSearch.type = 'button'; + refreshSearch.className = 'jsoneditor-refresh'; + td = document.createElement('td'); + td.appendChild(refreshSearch); + tr.appendChild(td); + + var search = document.createElement('input'); + // search.type = 'button'; + this.dom.search = search; + search.oninput = function (event) { + searchBox._onDelayedSearch(event); + }; + search.onchange = function (event) { // For IE 9 + searchBox._onSearch(); + }; + search.onkeydown = function (event) { + searchBox._onKeyDown(event); + }; + search.onkeyup = function (event) { + searchBox._onKeyUp(event); + }; + refreshSearch.onclick = function (event) { + search.select(); + }; + + // TODO: ESC in FF restores the last input, is a FF bug, https://bugzilla.mozilla.org/show_bug.cgi?id=598819 + td = document.createElement('td'); + td.appendChild(search); + tr.appendChild(td); + + var searchNext = document.createElement('button'); + searchNext.type = 'button'; + searchNext.title = 'Next result (Enter)'; + searchNext.className = 'jsoneditor-next'; + searchNext.onclick = function () { + searchBox.next(); + }; + td = document.createElement('td'); + td.appendChild(searchNext); + tr.appendChild(td); + + var searchPrevious = document.createElement('button'); + searchPrevious.type = 'button'; + searchPrevious.title = 'Previous result (Shift+Enter)'; + searchPrevious.className = 'jsoneditor-previous'; + searchPrevious.onclick = function () { + searchBox.previous(); + }; + td = document.createElement('td'); + td.appendChild(searchPrevious); + tr.appendChild(td); + } + + /** + * Go to the next search result + * @param {boolean} [focus] If true, focus will be set to the next result + * focus is false by default. + */ + SearchBox.prototype.next = function(focus) { + if (this.results != undefined) { + var index = (this.resultIndex != undefined) ? this.resultIndex + 1 : 0; + if (index > this.results.length - 1) { + index = 0; + } + this._setActiveResult(index, focus); + } + }; + + /** + * Go to the prevous search result + * @param {boolean} [focus] If true, focus will be set to the next result + * focus is false by default. + */ + SearchBox.prototype.previous = function(focus) { + if (this.results != undefined) { + var max = this.results.length - 1; + var index = (this.resultIndex != undefined) ? this.resultIndex - 1 : max; + if (index < 0) { + index = max; + } + this._setActiveResult(index, focus); + } + }; + + /** + * Set new value for the current active result + * @param {Number} index + * @param {boolean} [focus] If true, focus will be set to the next result. + * focus is false by default. + * @private + */ + SearchBox.prototype._setActiveResult = function(index, focus) { + // de-activate current active result + if (this.activeResult) { + var prevNode = this.activeResult.node; + var prevElem = this.activeResult.elem; + if (prevElem == 'field') { + delete prevNode.searchFieldActive; + } + else { + delete prevNode.searchValueActive; + } + prevNode.updateDom(); + } + + if (!this.results || !this.results[index]) { + // out of range, set to undefined + this.resultIndex = undefined; + this.activeResult = undefined; + return; + } + + this.resultIndex = index; + + // set new node active + var node = this.results[this.resultIndex].node; + var elem = this.results[this.resultIndex].elem; + if (elem == 'field') { + node.searchFieldActive = true; + } + else { + node.searchValueActive = true; + } + this.activeResult = this.results[this.resultIndex]; + node.updateDom(); + + // TODO: not so nice that the focus is only set after the animation is finished + node.scrollTo(function () { + if (focus) { + node.focus(elem); + } + }); + }; + + /** + * Cancel any running onDelayedSearch. + * @private + */ + SearchBox.prototype._clearDelay = function() { + if (this.timeout != undefined) { + clearTimeout(this.timeout); + delete this.timeout; + } + }; + + /** + * Start a timer to execute a search after a short delay. + * Used for reducing the number of searches while typing. + * @param {Event} event + * @private + */ + SearchBox.prototype._onDelayedSearch = function (event) { + // execute the search after a short delay (reduces the number of + // search actions while typing in the search text box) + this._clearDelay(); + var searchBox = this; + this.timeout = setTimeout(function (event) { + searchBox._onSearch(); + }, + this.delay); + }; + + /** + * Handle onSearch event + * @param {boolean} [forceSearch] If true, search will be executed again even + * when the search text is not changed. + * Default is false. + * @private + */ + SearchBox.prototype._onSearch = function (forceSearch) { + this._clearDelay(); + + var value = this.dom.search.value; + var text = (value.length > 0) ? value : undefined; + if (text != this.lastText || forceSearch) { + // only search again when changed + this.lastText = text; + this.results = this.editor.search(text); + this._setActiveResult(undefined); + + // display search results + if (text != undefined) { + var resultCount = this.results.length; + switch (resultCount) { + case 0: this.dom.results.innerHTML = 'no results'; break; + case 1: this.dom.results.innerHTML = '1 result'; break; + default: this.dom.results.innerHTML = resultCount + ' results'; break; + } + } + else { + this.dom.results.innerHTML = ''; + } + } + }; + + /** + * Handle onKeyDown event in the input box + * @param {Event} event + * @private + */ + SearchBox.prototype._onKeyDown = function (event) { + var keynum = event.which; + if (keynum == 27) { // ESC + this.dom.search.value = ''; // clear search + this._onSearch(); + event.preventDefault(); + event.stopPropagation(); + } + else if (keynum == 13) { // Enter + if (event.ctrlKey) { + // force to search again + this._onSearch(true); + } + else if (event.shiftKey) { + // move to the previous search result + this.previous(); + } + else { + // move to the next search result + this.next(); + } + event.preventDefault(); + event.stopPropagation(); + } + }; + + /** + * Handle onKeyUp event in the input box + * @param {Event} event + * @private + */ + SearchBox.prototype._onKeyUp = function (event) { + var keynum = event.keyCode; + if (keynum != 27 && keynum != 13) { // !show and !Enter + this._onDelayedSearch(event); // For IE 9 + } + }; + + /** + * Clear the search results + */ + SearchBox.prototype.clear = function () { + this.dom.search.value = ''; + this._onSearch(); + }; + + /** + * Destroy the search box + */ + SearchBox.prototype.destroy = function () { + this.editor = null; + this.dom.container.removeChild(this.dom.table); + this.dom = null; + + this.results = null; + this.activeResult = null; + + this._clearDelay(); + + }; + + module.exports = SearchBox; + + +/***/ }, +/* 57 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var util = __webpack_require__(54); + + /** + * A context menu + * @param {Object[]} items Array containing the menu structure + * TODO: describe structure + * @param {Object} [options] Object with options. Available options: + * {function} close Callback called when the + * context menu is being closed. + * @constructor + */ + function ContextMenu (items, options) { + this.dom = {}; + + var me = this; + var dom = this.dom; + this.anchor = undefined; + this.items = items; + this.eventListeners = {}; + this.selection = undefined; // holds the selection before the menu was opened + this.onClose = options ? options.close : undefined; + + // create root element + var root = document.createElement('div'); + root.className = 'jsoneditor-contextmenu-root'; + dom.root = root; + + // create a container element + var menu = document.createElement('div'); + menu.className = 'jsoneditor-contextmenu'; + dom.menu = menu; + root.appendChild(menu); + + // create a list to hold the menu items + var list = document.createElement('ul'); + list.className = 'jsoneditor-menu'; + menu.appendChild(list); + dom.list = list; + dom.items = []; // list with all buttons + + // create a (non-visible) button to set the focus to the menu + var focusButton = document.createElement('button'); + focusButton.type = 'button'; + dom.focusButton = focusButton; + var li = document.createElement('li'); + li.style.overflow = 'hidden'; + li.style.height = '0'; + li.appendChild(focusButton); + list.appendChild(li); + + function createMenuItems (list, domItems, items) { + items.forEach(function (item) { + if (item.type == 'separator') { + // create a separator + var separator = document.createElement('div'); + separator.className = 'jsoneditor-separator'; + li = document.createElement('li'); + li.appendChild(separator); + list.appendChild(li); + } + else { + var domItem = {}; + + // create a menu item + var li = document.createElement('li'); + list.appendChild(li); + + // create a button in the menu item + var button = document.createElement('button'); + button.type = 'button'; + button.className = item.className; + domItem.button = button; + if (item.title) { + button.title = item.title; + } + if (item.click) { + button.onclick = function (event) { + event.preventDefault(); + me.hide(); + item.click(); + }; + } + li.appendChild(button); + + // create the contents of the button + if (item.submenu) { + // add the icon to the button + var divIcon = document.createElement('div'); + divIcon.className = 'jsoneditor-icon'; + button.appendChild(divIcon); + button.appendChild(document.createTextNode(item.text)); + + var buttonSubmenu; + if (item.click) { + // submenu and a button with a click handler + button.className += ' jsoneditor-default'; + + var buttonExpand = document.createElement('button'); + buttonExpand.type = 'button'; + domItem.buttonExpand = buttonExpand; + buttonExpand.className = 'jsoneditor-expand'; + buttonExpand.innerHTML = '

'; + li.appendChild(buttonExpand); + if (item.submenuTitle) { + buttonExpand.title = item.submenuTitle; + } + + buttonSubmenu = buttonExpand; + } + else { + // submenu and a button without a click handler + var divExpand = document.createElement('div'); + divExpand.className = 'jsoneditor-expand'; + button.appendChild(divExpand); + + buttonSubmenu = button; + } + + // attach a handler to expand/collapse the submenu + buttonSubmenu.onclick = function (event) { + event.preventDefault(); + me._onExpandItem(domItem); + buttonSubmenu.focus(); + }; + + // create the submenu + var domSubItems = []; + domItem.subItems = domSubItems; + var ul = document.createElement('ul'); + domItem.ul = ul; + ul.className = 'jsoneditor-menu'; + ul.style.height = '0'; + li.appendChild(ul); + createMenuItems(ul, domSubItems, item.submenu); + } + else { + // no submenu, just a button with clickhandler + button.innerHTML = '
' + item.text; + } + + domItems.push(domItem); + } + }); + } + createMenuItems(list, this.dom.items, items); + + // TODO: when the editor is small, show the submenu on the right instead of inline? + + // calculate the max height of the menu with one submenu expanded + this.maxHeight = 0; // height in pixels + items.forEach(function (item) { + var height = (items.length + (item.submenu ? item.submenu.length : 0)) * 24; + me.maxHeight = Math.max(me.maxHeight, height); + }); + } + + /** + * Get the currently visible buttons + * @return {Array.} buttons + * @private + */ + ContextMenu.prototype._getVisibleButtons = function () { + var buttons = []; + var me = this; + this.dom.items.forEach(function (item) { + buttons.push(item.button); + if (item.buttonExpand) { + buttons.push(item.buttonExpand); + } + if (item.subItems && item == me.expandedItem) { + item.subItems.forEach(function (subItem) { + buttons.push(subItem.button); + if (subItem.buttonExpand) { + buttons.push(subItem.buttonExpand); + } + // TODO: change to fully recursive method + }); + } + }); + + return buttons; + }; + + // currently displayed context menu, a singleton. We may only have one visible context menu + ContextMenu.visibleMenu = undefined; + + /** + * Attach the menu to an anchor + * @param {HTMLElement} anchor Anchor where the menu will be attached + * as sibling. + * @param {HTMLElement} [contentWindow] The DIV with with the (scrollable) contents + */ + ContextMenu.prototype.show = function (anchor, contentWindow) { + this.hide(); + + // determine whether to display the menu below or above the anchor + var showBelow = true; + if (contentWindow) { + var anchorRect = anchor.getBoundingClientRect(); + var contentRect = contentWindow.getBoundingClientRect(); + + if (anchorRect.bottom + this.maxHeight < contentRect.bottom) { + // fits below -> show below + } + else if (anchorRect.top - this.maxHeight > contentRect.top) { + // fits above -> show above + showBelow = false; + } + else { + // doesn't fit above nor below -> show below + } + } + + // position the menu + if (showBelow) { + // display the menu below the anchor + var anchorHeight = anchor.offsetHeight; + this.dom.menu.style.left = '0px'; + this.dom.menu.style.top = anchorHeight + 'px'; + this.dom.menu.style.bottom = ''; + } + else { + // display the menu above the anchor + this.dom.menu.style.left = '0px'; + this.dom.menu.style.top = ''; + this.dom.menu.style.bottom = '0px'; + } + + // attach the menu to the parent of the anchor + var parent = anchor.parentNode; + parent.insertBefore(this.dom.root, parent.firstChild); + + // create and attach event listeners + var me = this; + var list = this.dom.list; + this.eventListeners.mousedown = util.addEventListener(window, 'mousedown', function (event) { + // hide menu on click outside of the menu + var target = event.target; + if ((target != list) && !me._isChildOf(target, list)) { + me.hide(); + event.stopPropagation(); + event.preventDefault(); + } + }); + this.eventListeners.keydown = util.addEventListener(window, 'keydown', function (event) { + me._onKeyDown(event); + }); + + // move focus to the first button in the context menu + this.selection = util.getSelection(); + this.anchor = anchor; + setTimeout(function () { + me.dom.focusButton.focus(); + }, 0); + + if (ContextMenu.visibleMenu) { + ContextMenu.visibleMenu.hide(); + } + ContextMenu.visibleMenu = this; + }; + + /** + * Hide the context menu if visible + */ + ContextMenu.prototype.hide = function () { + // remove the menu from the DOM + if (this.dom.root.parentNode) { + this.dom.root.parentNode.removeChild(this.dom.root); + if (this.onClose) { + this.onClose(); + } + } + + // remove all event listeners + // all event listeners are supposed to be attached to document. + for (var name in this.eventListeners) { + if (this.eventListeners.hasOwnProperty(name)) { + var fn = this.eventListeners[name]; + if (fn) { + util.removeEventListener(window, name, fn); + } + delete this.eventListeners[name]; + } + } + + if (ContextMenu.visibleMenu == this) { + ContextMenu.visibleMenu = undefined; + } + }; + + /** + * Expand a submenu + * Any currently expanded submenu will be hided. + * @param {Object} domItem + * @private + */ + ContextMenu.prototype._onExpandItem = function (domItem) { + var me = this; + var alreadyVisible = (domItem == this.expandedItem); + + // hide the currently visible submenu + var expandedItem = this.expandedItem; + if (expandedItem) { + //var ul = expandedItem.ul; + expandedItem.ul.style.height = '0'; + expandedItem.ul.style.padding = ''; + setTimeout(function () { + if (me.expandedItem != expandedItem) { + expandedItem.ul.style.display = ''; + util.removeClassName(expandedItem.ul.parentNode, 'jsoneditor-selected'); + } + }, 300); // timeout duration must match the css transition duration + this.expandedItem = undefined; + } + + if (!alreadyVisible) { + var ul = domItem.ul; + ul.style.display = 'block'; + var height = ul.clientHeight; // force a reflow in Firefox + setTimeout(function () { + if (me.expandedItem == domItem) { + ul.style.height = (ul.childNodes.length * 24) + 'px'; + ul.style.padding = '5px 10px'; + } + }, 0); + util.addClassName(ul.parentNode, 'jsoneditor-selected'); + this.expandedItem = domItem; + } + }; + + /** + * Handle onkeydown event + * @param {Event} event + * @private + */ + ContextMenu.prototype._onKeyDown = function (event) { + var target = event.target; + var keynum = event.which; + var handled = false; + var buttons, targetIndex, prevButton, nextButton; + + if (keynum == 27) { // ESC + // hide the menu on ESC key + + // restore previous selection and focus + if (this.selection) { + util.setSelection(this.selection); + } + if (this.anchor) { + this.anchor.focus(); + } + + this.hide(); + + handled = true; + } + else if (keynum == 9) { // Tab + if (!event.shiftKey) { // Tab + buttons = this._getVisibleButtons(); + targetIndex = buttons.indexOf(target); + if (targetIndex == buttons.length - 1) { + // move to first button + buttons[0].focus(); + handled = true; + } + } + else { // Shift+Tab + buttons = this._getVisibleButtons(); + targetIndex = buttons.indexOf(target); + if (targetIndex == 0) { + // move to last button + buttons[buttons.length - 1].focus(); + handled = true; + } + } + } + else if (keynum == 37) { // Arrow Left + if (target.className == 'jsoneditor-expand') { + buttons = this._getVisibleButtons(); + targetIndex = buttons.indexOf(target); + prevButton = buttons[targetIndex - 1]; + if (prevButton) { + prevButton.focus(); + } + } + handled = true; + } + else if (keynum == 38) { // Arrow Up + buttons = this._getVisibleButtons(); + targetIndex = buttons.indexOf(target); + prevButton = buttons[targetIndex - 1]; + if (prevButton && prevButton.className == 'jsoneditor-expand') { + // skip expand button + prevButton = buttons[targetIndex - 2]; + } + if (!prevButton) { + // move to last button + prevButton = buttons[buttons.length - 1]; + } + if (prevButton) { + prevButton.focus(); + } + handled = true; + } + else if (keynum == 39) { // Arrow Right + buttons = this._getVisibleButtons(); + targetIndex = buttons.indexOf(target); + nextButton = buttons[targetIndex + 1]; + if (nextButton && nextButton.className == 'jsoneditor-expand') { + nextButton.focus(); + } + handled = true; + } + else if (keynum == 40) { // Arrow Down + buttons = this._getVisibleButtons(); + targetIndex = buttons.indexOf(target); + nextButton = buttons[targetIndex + 1]; + if (nextButton && nextButton.className == 'jsoneditor-expand') { + // skip expand button + nextButton = buttons[targetIndex + 2]; + } + if (!nextButton) { + // move to first button + nextButton = buttons[0]; + } + if (nextButton) { + nextButton.focus(); + handled = true; + } + handled = true; + } + // TODO: arrow left and right + + if (handled) { + event.stopPropagation(); + event.preventDefault(); + } + }; + + /** + * Test if an element is a child of a parent element. + * @param {Element} child + * @param {Element} parent + * @return {boolean} isChild + */ + ContextMenu.prototype._isChildOf = function (child, parent) { + var e = child.parentNode; + while (e) { + if (e == parent) { + return true; + } + e = e.parentNode; + } + + return false; + }; + + module.exports = ContextMenu; + + +/***/ }, +/* 58 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var naturalSort = __webpack_require__(59); + var ContextMenu = __webpack_require__(57); + var appendNodeFactory = __webpack_require__(60); + var util = __webpack_require__(54); + + /** + * @constructor Node + * Create a new Node + * @param {./treemode} editor + * @param {Object} [params] Can contain parameters: + * {string} field + * {boolean} fieldEditable + * {*} value + * {String} type Can have values 'auto', 'array', + * 'object', or 'string'. + */ + function Node (editor, params) { + /** @type {./treemode} */ + this.editor = editor; + this.dom = {}; + this.expanded = false; + + if(params && (params instanceof Object)) { + this.setField(params.field, params.fieldEditable); + this.setValue(params.value, params.type); + } + else { + this.setField(''); + this.setValue(null); + } + + this._debouncedOnChangeValue = util.debounce(this._onChangeValue.bind(this), Node.prototype.DEBOUNCE_INTERVAL); + this._debouncedOnChangeField = util.debounce(this._onChangeField.bind(this), Node.prototype.DEBOUNCE_INTERVAL); + } + + // debounce interval for keyboard input in milliseconds + Node.prototype.DEBOUNCE_INTERVAL = 150; + + /** + * Determine whether the field and/or value of this node are editable + * @private + */ + Node.prototype._updateEditability = function () { + this.editable = { + field: true, + value: true + }; + + if (this.editor) { + this.editable.field = this.editor.options.mode === 'tree'; + this.editable.value = this.editor.options.mode !== 'view'; + + if ((this.editor.options.mode === 'tree' || this.editor.options.mode === 'form') && + (typeof this.editor.options.onEditable === 'function')) { + var editable = this.editor.options.onEditable({ + field: this.field, + value: this.value, + path: this.getPath() + }); + + if (typeof editable === 'boolean') { + this.editable.field = editable; + this.editable.value = editable; + } + else { + if (typeof editable.field === 'boolean') this.editable.field = editable.field; + if (typeof editable.value === 'boolean') this.editable.value = editable.value; + } + } + } + }; + + /** + * Get the path of this node + * @return {String[]} Array containing the path to this node + */ + Node.prototype.getPath = function () { + var node = this; + var path = []; + while (node) { + var field = !node.parent + ? undefined // do not add an (optional) field name of the root node + : (node.parent.type != 'array') + ? node.field + : node.index; + + if (field !== undefined) { + path.unshift(field); + } + node = node.parent; + } + return path; + }; + + /** + * Find a Node from a JSON path like '.items[3].name' + * @param {string} jsonPath + * @return {Node | null} Returns the Node when found, returns null if not found + */ + Node.prototype.findNode = function (jsonPath) { + var path = util.parsePath(jsonPath); + var node = this; + while (node && path.length > 0) { + var prop = path.shift(); + if (typeof prop === 'number') { + if (node.type !== 'array') { + throw new Error('Cannot get child node at index ' + prop + ': node is no array'); + } + node = node.childs[prop]; + } + else { // string + if (node.type !== 'object') { + throw new Error('Cannot get child node ' + prop + ': node is no object'); + } + node = node.childs.filter(function (child) { + return child.field === prop; + })[0]; + } + } + + return node; + }; + + /** + * Find all parents of this node. The parents are ordered from root node towards + * the original node. + * @return {Array.} + */ + Node.prototype.findParents = function () { + var parents = []; + var parent = this.parent; + while (parent) { + parents.unshift(parent); + parent = parent.parent; + } + return parents; + }; + + /** + * + * @param {{dataPath: string, keyword: string, message: string, params: Object, schemaPath: string} | null} error + * @param {Node} [child] When this is the error of a parent node, pointing + * to an invalid child node, the child node itself + * can be provided. If provided, clicking the error + * icon will set focus to the invalid child node. + */ + Node.prototype.setError = function (error, child) { + // ensure the dom exists + this.getDom(); + + this.error = error; + var tdError = this.dom.tdError; + if (error) { + if (!tdError) { + tdError = document.createElement('td'); + this.dom.tdError = tdError; + this.dom.tdValue.parentNode.appendChild(tdError); + } + + var popover = document.createElement('div'); + popover.className = 'jsoneditor-popover jsoneditor-right'; + popover.appendChild(document.createTextNode(error.message)); + + var button = document.createElement('button'); + button.type = 'button'; + button.className = 'jsoneditor-schema-error'; + button.appendChild(popover); + + // update the direction of the popover + button.onmouseover = button.onfocus = function updateDirection() { + var directions = ['right', 'above', 'below', 'left']; + for (var i = 0; i < directions.length; i++) { + var direction = directions[i]; + popover.className = 'jsoneditor-popover jsoneditor-' + direction; + + var contentRect = this.editor.content.getBoundingClientRect(); + var popoverRect = popover.getBoundingClientRect(); + var margin = 20; // account for a scroll bar + var fit = util.insideRect(contentRect, popoverRect, margin); + + if (fit) { + break; + } + } + }.bind(this); + + // when clicking the error icon, expand all nodes towards the invalid + // child node, and set focus to the child node + if (child) { + button.onclick = function showInvalidNode() { + child.findParents().forEach(function (parent) { + parent.expand(false); + }); + + child.scrollTo(function () { + child.focus(); + }); + }; + } + + // apply the error message to the node + while (tdError.firstChild) { + tdError.removeChild(tdError.firstChild); + } + tdError.appendChild(button); + } + else { + if (tdError) { + this.dom.tdError.parentNode.removeChild(this.dom.tdError); + delete this.dom.tdError; + } + } + }; + + /** + * Get the index of this node: the index in the list of childs where this + * node is part of + * @return {number} Returns the index, or -1 if this is the root node + */ + Node.prototype.getIndex = function () { + return this.parent ? this.parent.childs.indexOf(this) : -1; + }; + + /** + * Set parent node + * @param {Node} parent + */ + Node.prototype.setParent = function(parent) { + this.parent = parent; + }; + + /** + * Set field + * @param {String} field + * @param {boolean} [fieldEditable] + */ + Node.prototype.setField = function(field, fieldEditable) { + this.field = field; + this.previousField = field; + this.fieldEditable = (fieldEditable === true); + }; + + /** + * Get field + * @return {String} + */ + Node.prototype.getField = function() { + if (this.field === undefined) { + this._getDomField(); + } + + return this.field; + }; + + /** + * Set value. Value is a JSON structure or an element String, Boolean, etc. + * @param {*} value + * @param {String} [type] Specify the type of the value. Can be 'auto', + * 'array', 'object', or 'string' + */ + Node.prototype.setValue = function(value, type) { + var childValue, child; + + // first clear all current childs (if any) + var childs = this.childs; + if (childs) { + while (childs.length) { + this.removeChild(childs[0]); + } + } + + // TODO: remove the DOM of this Node + + this.type = this._getType(value); + + // check if type corresponds with the provided type + if (type && type != this.type) { + if (type == 'string' && this.type == 'auto') { + this.type = type; + } + else { + throw new Error('Type mismatch: ' + + 'cannot cast value of type "' + this.type + + ' to the specified type "' + type + '"'); + } + } + + if (this.type == 'array') { + // array + this.childs = []; + for (var i = 0, iMax = value.length; i < iMax; i++) { + childValue = value[i]; + if (childValue !== undefined && !(childValue instanceof Function)) { + // ignore undefined and functions + child = new Node(this.editor, { + value: childValue + }); + this.appendChild(child); + } + } + this.value = ''; + } + else if (this.type == 'object') { + // object + this.childs = []; + for (var childField in value) { + if (value.hasOwnProperty(childField)) { + childValue = value[childField]; + if (childValue !== undefined && !(childValue instanceof Function)) { + // ignore undefined and functions + child = new Node(this.editor, { + field: childField, + value: childValue + }); + this.appendChild(child); + } + } + } + this.value = ''; + + // sort object keys + if (this.editor.options.sortObjectKeys === true) { + this.sort('asc'); + } + } + else { + // value + this.childs = undefined; + this.value = value; + } + + this.previousValue = this.value; + }; + + /** + * Get value. Value is a JSON structure + * @return {*} value + */ + Node.prototype.getValue = function() { + //var childs, i, iMax; + + if (this.type == 'array') { + var arr = []; + this.childs.forEach (function (child) { + arr.push(child.getValue()); + }); + return arr; + } + else if (this.type == 'object') { + var obj = {}; + this.childs.forEach (function (child) { + obj[child.getField()] = child.getValue(); + }); + return obj; + } + else { + if (this.value === undefined) { + this._getDomValue(); + } + + return this.value; + } + }; + + /** + * Get the nesting level of this node + * @return {Number} level + */ + Node.prototype.getLevel = function() { + return (this.parent ? this.parent.getLevel() + 1 : 0); + }; + + /** + * Get path of the root node till the current node + * @return {Node[]} Returns an array with nodes + */ + Node.prototype.getNodePath = function() { + var path = this.parent ? this.parent.getNodePath() : []; + path.push(this); + return path; + }; + + /** + * Create a clone of a node + * The complete state of a clone is copied, including whether it is expanded or + * not. The DOM elements are not cloned. + * @return {Node} clone + */ + Node.prototype.clone = function() { + var clone = new Node(this.editor); + clone.type = this.type; + clone.field = this.field; + clone.fieldInnerText = this.fieldInnerText; + clone.fieldEditable = this.fieldEditable; + clone.value = this.value; + clone.valueInnerText = this.valueInnerText; + clone.expanded = this.expanded; + + if (this.childs) { + // an object or array + var cloneChilds = []; + this.childs.forEach(function (child) { + var childClone = child.clone(); + childClone.setParent(clone); + cloneChilds.push(childClone); + }); + clone.childs = cloneChilds; + } + else { + // a value + clone.childs = undefined; + } + + return clone; + }; + + /** + * Expand this node and optionally its childs. + * @param {boolean} [recurse] Optional recursion, true by default. When + * true, all childs will be expanded recursively + */ + Node.prototype.expand = function(recurse) { + if (!this.childs) { + return; + } + + // set this node expanded + this.expanded = true; + if (this.dom.expand) { + this.dom.expand.className = 'jsoneditor-expanded'; + } + + this.showChilds(); + + if (recurse !== false) { + this.childs.forEach(function (child) { + child.expand(recurse); + }); + } + }; + + /** + * Collapse this node and optionally its childs. + * @param {boolean} [recurse] Optional recursion, true by default. When + * true, all childs will be collapsed recursively + */ + Node.prototype.collapse = function(recurse) { + if (!this.childs) { + return; + } + + this.hideChilds(); + + // collapse childs in case of recurse + if (recurse !== false) { + this.childs.forEach(function (child) { + child.collapse(recurse); + }); + + } + + // make this node collapsed + if (this.dom.expand) { + this.dom.expand.className = 'jsoneditor-collapsed'; + } + this.expanded = false; + }; + + /** + * Recursively show all childs when they are expanded + */ + Node.prototype.showChilds = function() { + var childs = this.childs; + if (!childs) { + return; + } + if (!this.expanded) { + return; + } + + var tr = this.dom.tr; + var table = tr ? tr.parentNode : undefined; + if (table) { + // show row with append button + var append = this.getAppend(); + var nextTr = tr.nextSibling; + if (nextTr) { + table.insertBefore(append, nextTr); + } + else { + table.appendChild(append); + } + + // show childs + this.childs.forEach(function (child) { + table.insertBefore(child.getDom(), append); + child.showChilds(); + }); + } + }; + + /** + * Hide the node with all its childs + */ + Node.prototype.hide = function() { + var tr = this.dom.tr; + var table = tr ? tr.parentNode : undefined; + if (table) { + table.removeChild(tr); + } + this.hideChilds(); + }; + + + /** + * Recursively hide all childs + */ + Node.prototype.hideChilds = function() { + var childs = this.childs; + if (!childs) { + return; + } + if (!this.expanded) { + return; + } + + // hide append row + var append = this.getAppend(); + if (append.parentNode) { + append.parentNode.removeChild(append); + } + + // hide childs + this.childs.forEach(function (child) { + child.hide(); + }); + }; + + + /** + * Add a new child to the node. + * Only applicable when Node value is of type array or object + * @param {Node} node + */ + Node.prototype.appendChild = function(node) { + if (this._hasChilds()) { + // adjust the link to the parent + node.setParent(this); + node.fieldEditable = (this.type == 'object'); + if (this.type == 'array') { + node.index = this.childs.length; + } + this.childs.push(node); + + if (this.expanded) { + // insert into the DOM, before the appendRow + var newTr = node.getDom(); + var appendTr = this.getAppend(); + var table = appendTr ? appendTr.parentNode : undefined; + if (appendTr && table) { + table.insertBefore(newTr, appendTr); + } + + node.showChilds(); + } + + this.updateDom({'updateIndexes': true}); + node.updateDom({'recurse': true}); + } + }; + + + /** + * Move a node from its current parent to this node + * Only applicable when Node value is of type array or object + * @param {Node} node + * @param {Node} beforeNode + */ + Node.prototype.moveBefore = function(node, beforeNode) { + if (this._hasChilds()) { + // create a temporary row, to prevent the scroll position from jumping + // when removing the node + var tbody = (this.dom.tr) ? this.dom.tr.parentNode : undefined; + if (tbody) { + var trTemp = document.createElement('tr'); + trTemp.style.height = tbody.clientHeight + 'px'; + tbody.appendChild(trTemp); + } + + if (node.parent) { + node.parent.removeChild(node); + } + + if (beforeNode instanceof AppendNode) { + this.appendChild(node); + } + else { + this.insertBefore(node, beforeNode); + } + + if (tbody) { + tbody.removeChild(trTemp); + } + } + }; + + /** + * Move a node from its current parent to this node + * Only applicable when Node value is of type array or object. + * If index is out of range, the node will be appended to the end + * @param {Node} node + * @param {Number} index + */ + Node.prototype.moveTo = function (node, index) { + if (node.parent == this) { + // same parent + var currentIndex = this.childs.indexOf(node); + if (currentIndex < index) { + // compensate the index for removal of the node itself + index++; + } + } + + var beforeNode = this.childs[index] || this.append; + this.moveBefore(node, beforeNode); + }; + + /** + * Insert a new child before a given node + * Only applicable when Node value is of type array or object + * @param {Node} node + * @param {Node} beforeNode + */ + Node.prototype.insertBefore = function(node, beforeNode) { + if (this._hasChilds()) { + if (beforeNode == this.append) { + // append to the child nodes + + // adjust the link to the parent + node.setParent(this); + node.fieldEditable = (this.type == 'object'); + this.childs.push(node); + } + else { + // insert before a child node + var index = this.childs.indexOf(beforeNode); + if (index == -1) { + throw new Error('Node not found'); + } + + // adjust the link to the parent + node.setParent(this); + node.fieldEditable = (this.type == 'object'); + this.childs.splice(index, 0, node); + } + + if (this.expanded) { + // insert into the DOM + var newTr = node.getDom(); + var nextTr = beforeNode.getDom(); + var table = nextTr ? nextTr.parentNode : undefined; + if (nextTr && table) { + table.insertBefore(newTr, nextTr); + } + + node.showChilds(); + } + + this.updateDom({'updateIndexes': true}); + node.updateDom({'recurse': true}); + } + }; + + /** + * Insert a new child before a given node + * Only applicable when Node value is of type array or object + * @param {Node} node + * @param {Node} afterNode + */ + Node.prototype.insertAfter = function(node, afterNode) { + if (this._hasChilds()) { + var index = this.childs.indexOf(afterNode); + var beforeNode = this.childs[index + 1]; + if (beforeNode) { + this.insertBefore(node, beforeNode); + } + else { + this.appendChild(node); + } + } + }; + + /** + * Search in this node + * The node will be expanded when the text is found one of its childs, else + * it will be collapsed. Searches are case insensitive. + * @param {String} text + * @return {Node[]} results Array with nodes containing the search text + */ + Node.prototype.search = function(text) { + var results = []; + var index; + var search = text ? text.toLowerCase() : undefined; + + // delete old search data + delete this.searchField; + delete this.searchValue; + + // search in field + if (this.field != undefined) { + var field = String(this.field).toLowerCase(); + index = field.indexOf(search); + if (index != -1) { + this.searchField = true; + results.push({ + 'node': this, + 'elem': 'field' + }); + } + + // update dom + this._updateDomField(); + } + + // search in value + if (this._hasChilds()) { + // array, object + + // search the nodes childs + if (this.childs) { + var childResults = []; + this.childs.forEach(function (child) { + childResults = childResults.concat(child.search(text)); + }); + results = results.concat(childResults); + } + + // update dom + if (search != undefined) { + var recurse = false; + if (childResults.length == 0) { + this.collapse(recurse); + } + else { + this.expand(recurse); + } + } + } + else { + // string, auto + if (this.value != undefined ) { + var value = String(this.value).toLowerCase(); + index = value.indexOf(search); + if (index != -1) { + this.searchValue = true; + results.push({ + 'node': this, + 'elem': 'value' + }); + } + } + + // update dom + this._updateDomValue(); + } + + return results; + }; + + /** + * Move the scroll position such that this node is in the visible area. + * The node will not get the focus + * @param {function(boolean)} [callback] + */ + Node.prototype.scrollTo = function(callback) { + if (!this.dom.tr || !this.dom.tr.parentNode) { + // if the node is not visible, expand its parents + var parent = this.parent; + var recurse = false; + while (parent) { + parent.expand(recurse); + parent = parent.parent; + } + } + + if (this.dom.tr && this.dom.tr.parentNode) { + this.editor.scrollTo(this.dom.tr.offsetTop, callback); + } + }; + + + // stores the element name currently having the focus + Node.focusElement = undefined; + + /** + * Set focus to this node + * @param {String} [elementName] The field name of the element to get the + * focus available values: 'drag', 'menu', + * 'expand', 'field', 'value' (default) + */ + Node.prototype.focus = function(elementName) { + Node.focusElement = elementName; + + if (this.dom.tr && this.dom.tr.parentNode) { + var dom = this.dom; + + switch (elementName) { + case 'drag': + if (dom.drag) { + dom.drag.focus(); + } + else { + dom.menu.focus(); + } + break; + + case 'menu': + dom.menu.focus(); + break; + + case 'expand': + if (this._hasChilds()) { + dom.expand.focus(); + } + else if (dom.field && this.fieldEditable) { + dom.field.focus(); + util.selectContentEditable(dom.field); + } + else if (dom.value && !this._hasChilds()) { + dom.value.focus(); + util.selectContentEditable(dom.value); + } + else { + dom.menu.focus(); + } + break; + + case 'field': + if (dom.field && this.fieldEditable) { + dom.field.focus(); + util.selectContentEditable(dom.field); + } + else if (dom.value && !this._hasChilds()) { + dom.value.focus(); + util.selectContentEditable(dom.value); + } + else if (this._hasChilds()) { + dom.expand.focus(); + } + else { + dom.menu.focus(); + } + break; + + case 'value': + default: + if (dom.value && !this._hasChilds()) { + dom.value.focus(); + util.selectContentEditable(dom.value); + } + else if (dom.field && this.fieldEditable) { + dom.field.focus(); + util.selectContentEditable(dom.field); + } + else if (this._hasChilds()) { + dom.expand.focus(); + } + else { + dom.menu.focus(); + } + break; + } + } + }; + + /** + * Select all text in an editable div after a delay of 0 ms + * @param {Element} editableDiv + */ + Node.select = function(editableDiv) { + setTimeout(function () { + util.selectContentEditable(editableDiv); + }, 0); + }; + + /** + * Update the values from the DOM field and value of this node + */ + Node.prototype.blur = function() { + // retrieve the actual field and value from the DOM. + this._getDomValue(false); + this._getDomField(false); + }; + + /** + * Check if given node is a child. The method will check recursively to find + * this node. + * @param {Node} node + * @return {boolean} containsNode + */ + Node.prototype.containsNode = function(node) { + if (this == node) { + return true; + } + + var childs = this.childs; + if (childs) { + // TODO: use the js5 Array.some() here? + for (var i = 0, iMax = childs.length; i < iMax; i++) { + if (childs[i].containsNode(node)) { + return true; + } + } + } + + return false; + }; + + /** + * Move given node into this node + * @param {Node} node the childNode to be moved + * @param {Node} beforeNode node will be inserted before given + * node. If no beforeNode is given, + * the node is appended at the end + * @private + */ + Node.prototype._move = function(node, beforeNode) { + if (node == beforeNode) { + // nothing to do... + return; + } + + // check if this node is not a child of the node to be moved here + if (node.containsNode(this)) { + throw new Error('Cannot move a field into a child of itself'); + } + + // remove the original node + if (node.parent) { + node.parent.removeChild(node); + } + + // create a clone of the node + var clone = node.clone(); + node.clearDom(); + + // insert or append the node + if (beforeNode) { + this.insertBefore(clone, beforeNode); + } + else { + this.appendChild(clone); + } + + /* TODO: adjust the field name (to prevent equal field names) + if (this.type == 'object') { + } + */ + }; + + /** + * Remove a child from the node. + * Only applicable when Node value is of type array or object + * @param {Node} node The child node to be removed; + * @return {Node | undefined} node The removed node on success, + * else undefined + */ + Node.prototype.removeChild = function(node) { + if (this.childs) { + var index = this.childs.indexOf(node); + + if (index != -1) { + node.hide(); + + // delete old search results + delete node.searchField; + delete node.searchValue; + + var removedNode = this.childs.splice(index, 1)[0]; + removedNode.parent = null; + + this.updateDom({'updateIndexes': true}); + + return removedNode; + } + } + + return undefined; + }; + + /** + * Remove a child node node from this node + * This method is equal to Node.removeChild, except that _remove fire an + * onChange event. + * @param {Node} node + * @private + */ + Node.prototype._remove = function (node) { + this.removeChild(node); + }; + + /** + * Change the type of the value of this Node + * @param {String} newType + */ + Node.prototype.changeType = function (newType) { + var oldType = this.type; + + if (oldType == newType) { + // type is not changed + return; + } + + if ((newType == 'string' || newType == 'auto') && + (oldType == 'string' || oldType == 'auto')) { + // this is an easy change + this.type = newType; + } + else { + // change from array to object, or from string/auto to object/array + var table = this.dom.tr ? this.dom.tr.parentNode : undefined; + var lastTr; + if (this.expanded) { + lastTr = this.getAppend(); + } + else { + lastTr = this.getDom(); + } + var nextTr = (lastTr && lastTr.parentNode) ? lastTr.nextSibling : undefined; + + // hide current field and all its childs + this.hide(); + this.clearDom(); + + // adjust the field and the value + this.type = newType; + + // adjust childs + if (newType == 'object') { + if (!this.childs) { + this.childs = []; + } + + this.childs.forEach(function (child, index) { + child.clearDom(); + delete child.index; + child.fieldEditable = true; + if (child.field == undefined) { + child.field = ''; + } + }); + + if (oldType == 'string' || oldType == 'auto') { + this.expanded = true; + } + } + else if (newType == 'array') { + if (!this.childs) { + this.childs = []; + } + + this.childs.forEach(function (child, index) { + child.clearDom(); + child.fieldEditable = false; + child.index = index; + }); + + if (oldType == 'string' || oldType == 'auto') { + this.expanded = true; + } + } + else { + this.expanded = false; + } + + // create new DOM + if (table) { + if (nextTr) { + table.insertBefore(this.getDom(), nextTr); + } + else { + table.appendChild(this.getDom()); + } + } + this.showChilds(); + } + + if (newType == 'auto' || newType == 'string') { + // cast value to the correct type + if (newType == 'string') { + this.value = String(this.value); + } + else { + this.value = this._stringCast(String(this.value)); + } + + this.focus(); + } + + this.updateDom({'updateIndexes': true}); + }; + + /** + * Retrieve value from DOM + * @param {boolean} [silent] If true (default), no errors will be thrown in + * case of invalid data + * @private + */ + Node.prototype._getDomValue = function(silent) { + if (this.dom.value && this.type != 'array' && this.type != 'object') { + this.valueInnerText = util.getInnerText(this.dom.value); + } + + if (this.valueInnerText != undefined) { + try { + // retrieve the value + var value; + if (this.type == 'string') { + value = this._unescapeHTML(this.valueInnerText); + } + else { + var str = this._unescapeHTML(this.valueInnerText); + value = this._stringCast(str); + } + if (value !== this.value) { + this.value = value; + this._debouncedOnChangeValue(); + } + } + catch (err) { + this.value = undefined; + // TODO: sent an action with the new, invalid value? + if (silent !== true) { + throw err; + } + } + } + }; + + /** + * Handle a changed value + * @private + */ + Node.prototype._onChangeValue = function () { + // get current selection, then override the range such that we can select + // the added/removed text on undo/redo + var oldSelection = this.editor.getSelection(); + if (oldSelection.range) { + var undoDiff = util.textDiff(String(this.value), String(this.previousValue)); + oldSelection.range.startOffset = undoDiff.start; + oldSelection.range.endOffset = undoDiff.end; + } + var newSelection = this.editor.getSelection(); + if (newSelection.range) { + var redoDiff = util.textDiff(String(this.previousValue), String(this.value)); + newSelection.range.startOffset = redoDiff.start; + newSelection.range.endOffset = redoDiff.end; + } + + this.editor._onAction('editValue', { + node: this, + oldValue: this.previousValue, + newValue: this.value, + oldSelection: oldSelection, + newSelection: newSelection + }); + + this.previousValue = this.value; + }; + + /** + * Handle a changed field + * @private + */ + Node.prototype._onChangeField = function () { + // get current selection, then override the range such that we can select + // the added/removed text on undo/redo + var oldSelection = this.editor.getSelection(); + if (oldSelection.range) { + var undoDiff = util.textDiff(this.field, this.previousField); + oldSelection.range.startOffset = undoDiff.start; + oldSelection.range.endOffset = undoDiff.end; + } + var newSelection = this.editor.getSelection(); + if (newSelection.range) { + var redoDiff = util.textDiff(this.previousField, this.field); + newSelection.range.startOffset = redoDiff.start; + newSelection.range.endOffset = redoDiff.end; + } + + this.editor._onAction('editField', { + node: this, + oldValue: this.previousField, + newValue: this.field, + oldSelection: oldSelection, + newSelection: newSelection + }); + + this.previousField = this.field; + }; + + /** + * Update dom value: + * - the text color of the value, depending on the type of the value + * - the height of the field, depending on the width + * - background color in case it is empty + * @private + */ + Node.prototype._updateDomValue = function () { + var domValue = this.dom.value; + if (domValue) { + var classNames = ['jsoneditor-value']; + + + // set text color depending on value type + var value = this.value; + var type = (this.type == 'auto') ? util.type(value) : this.type; + var isUrl = type == 'string' && util.isUrl(value); + classNames.push('jsoneditor-' + type); + if (isUrl) { + classNames.push('jsoneditor-url'); + } + + // visual styling when empty + var isEmpty = (String(this.value) == '' && this.type != 'array' && this.type != 'object'); + if (isEmpty) { + classNames.push('jsoneditor-empty'); + } + + // highlight when there is a search result + if (this.searchValueActive) { + classNames.push('jsoneditor-highlight-active'); + } + if (this.searchValue) { + classNames.push('jsoneditor-highlight'); + } + + domValue.className = classNames.join(' '); + + // update title + if (type == 'array' || type == 'object') { + var count = this.childs ? this.childs.length : 0; + domValue.title = this.type + ' containing ' + count + ' items'; + } + else if (isUrl && this.editable.value) { + domValue.title = 'Ctrl+Click or Ctrl+Enter to open url in new window'; + } + else { + domValue.title = ''; + } + + // show checkbox when the value is a boolean + if (type === 'boolean' && this.editable.value) { + if (!this.dom.checkbox) { + this.dom.checkbox = document.createElement('input'); + this.dom.checkbox.type = 'checkbox'; + this.dom.tdCheckbox = document.createElement('td'); + this.dom.tdCheckbox.className = 'jsoneditor-tree'; + this.dom.tdCheckbox.appendChild(this.dom.checkbox); + + this.dom.tdValue.parentNode.insertBefore(this.dom.tdCheckbox, this.dom.tdValue); + } + + this.dom.checkbox.checked = this.value; + } + else { + // cleanup checkbox when displayed + if (this.dom.tdCheckbox) { + this.dom.tdCheckbox.parentNode.removeChild(this.dom.tdCheckbox); + delete this.dom.tdCheckbox; + delete this.dom.checkbox; + } + } + + if (this.enum && this.editable.value) { + // create select box when this node has an enum object + if (!this.dom.select) { + this.dom.select = document.createElement('select'); + this.id = this.field + "_" + new Date().getUTCMilliseconds(); + this.dom.select.id = this.id; + this.dom.select.name = this.dom.select.id; + + //Create the default empty option + this.dom.select.option = document.createElement('option'); + this.dom.select.option.value = ''; + this.dom.select.option.innerHTML = '--'; + this.dom.select.appendChild(this.dom.select.option); + + //Iterate all enum values and add them as options + for(var i = 0; i < this.enum.length; i++) { + this.dom.select.option = document.createElement('option'); + this.dom.select.option.value = this.enum[i]; + this.dom.select.option.innerHTML = this.enum[i]; + if(this.dom.select.option.value == this.value){ + this.dom.select.option.selected = true; + } + this.dom.select.appendChild(this.dom.select.option); + } + + this.dom.tdSelect = document.createElement('td'); + this.dom.tdSelect.className = 'jsoneditor-tree'; + this.dom.tdSelect.appendChild(this.dom.select); + this.dom.tdValue.parentNode.insertBefore(this.dom.tdSelect, this.dom.tdValue); + } + + // If the enum is inside a composite type display + // both the simple input and the dropdown field + if(this.schema && ( + !this.schema.hasOwnProperty("oneOf") && + !this.schema.hasOwnProperty("anyOf") && + !this.schema.hasOwnProperty("allOf")) + ) { + this.valueFieldHTML = this.dom.tdValue.innerHTML; + this.dom.tdValue.style.visibility = 'hidden'; + this.dom.tdValue.innerHTML = ''; + } else { + delete this.valueFieldHTML; + } + } + else { + // cleanup select box when displayed + if (this.dom.tdSelect) { + this.dom.tdSelect.parentNode.removeChild(this.dom.tdSelect); + delete this.dom.tdSelect; + delete this.dom.select; + this.dom.tdValue.innerHTML = this.valueFieldHTML; + this.dom.tdValue.style.visibility = ''; + delete this.valueFieldHTML; + } + } + + // strip formatting from the contents of the editable div + util.stripFormatting(domValue); + } + }; + + /** + * Update dom field: + * - the text color of the field, depending on the text + * - the height of the field, depending on the width + * - background color in case it is empty + * @private + */ + Node.prototype._updateDomField = function () { + var domField = this.dom.field; + if (domField) { + // make backgound color lightgray when empty + var isEmpty = (String(this.field) == '' && this.parent.type != 'array'); + if (isEmpty) { + util.addClassName(domField, 'jsoneditor-empty'); + } + else { + util.removeClassName(domField, 'jsoneditor-empty'); + } + + // highlight when there is a search result + if (this.searchFieldActive) { + util.addClassName(domField, 'jsoneditor-highlight-active'); + } + else { + util.removeClassName(domField, 'jsoneditor-highlight-active'); + } + if (this.searchField) { + util.addClassName(domField, 'jsoneditor-highlight'); + } + else { + util.removeClassName(domField, 'jsoneditor-highlight'); + } + + // strip formatting from the contents of the editable div + util.stripFormatting(domField); + } + }; + + /** + * Retrieve field from DOM + * @param {boolean} [silent] If true (default), no errors will be thrown in + * case of invalid data + * @private + */ + Node.prototype._getDomField = function(silent) { + if (this.dom.field && this.fieldEditable) { + this.fieldInnerText = util.getInnerText(this.dom.field); + } + + if (this.fieldInnerText != undefined) { + try { + var field = this._unescapeHTML(this.fieldInnerText); + + if (field !== this.field) { + this.field = field; + this._debouncedOnChangeField(); + } + } + catch (err) { + this.field = undefined; + // TODO: sent an action here, with the new, invalid value? + if (silent !== true) { + throw err; + } + } + } + }; + + /** + * Validate this node and all it's childs + * @return {Array.<{node: Node, error: {message: string}}>} Returns a list with duplicates + */ + Node.prototype.validate = function () { + var errors = []; + + // find duplicate keys + if (this.type === 'object') { + var keys = {}; + var duplicateKeys = []; + for (var i = 0; i < this.childs.length; i++) { + var child = this.childs[i]; + if (keys.hasOwnProperty(child.field)) { + duplicateKeys.push(child.field); + } + keys[child.field] = true; + } + + if (duplicateKeys.length > 0) { + errors = this.childs + .filter(function (node) { + return duplicateKeys.indexOf(node.field) !== -1; + }) + .map(function (node) { + return { + node: node, + error: { + message: 'duplicate key "' + node.field + '"' + } + } + }); + } + } + + // recurse over the childs + if (this.childs) { + for (var i = 0; i < this.childs.length; i++) { + var e = this.childs[i].validate(); + if (e.length > 0) { + errors = errors.concat(e); + } + } + } + + return errors; + }; + + /** + * Clear the dom of the node + */ + Node.prototype.clearDom = function() { + // TODO: hide the node first? + //this.hide(); + // TODO: recursively clear dom? + + this.dom = {}; + }; + + /** + * Get the HTML DOM TR element of the node. + * The dom will be generated when not yet created + * @return {Element} tr HTML DOM TR Element + */ + Node.prototype.getDom = function() { + var dom = this.dom; + if (dom.tr) { + return dom.tr; + } + + this._updateEditability(); + + // create row + dom.tr = document.createElement('tr'); + dom.tr.node = this; + + if (this.editor.options.mode === 'tree') { // note: we take here the global setting + var tdDrag = document.createElement('td'); + if (this.editable.field) { + // create draggable area + if (this.parent) { + var domDrag = document.createElement('button'); + domDrag.type = 'button'; + dom.drag = domDrag; + domDrag.className = 'jsoneditor-dragarea'; + domDrag.title = 'Drag to move this field (Alt+Shift+Arrows)'; + tdDrag.appendChild(domDrag); + } + } + dom.tr.appendChild(tdDrag); + + // create context menu + var tdMenu = document.createElement('td'); + var menu = document.createElement('button'); + menu.type = 'button'; + dom.menu = menu; + menu.className = 'jsoneditor-contextmenu'; + menu.title = 'Click to open the actions menu (Ctrl+M)'; + tdMenu.appendChild(dom.menu); + dom.tr.appendChild(tdMenu); + } + + // create tree and field + var tdField = document.createElement('td'); + dom.tr.appendChild(tdField); + dom.tree = this._createDomTree(); + tdField.appendChild(dom.tree); + + this.updateDom({'updateIndexes': true}); + + return dom.tr; + }; + + /** + * DragStart event, fired on mousedown on the dragarea at the left side of a Node + * @param {Node[] | Node} nodes + * @param {Event} event + */ + Node.onDragStart = function (nodes, event) { + if (!Array.isArray(nodes)) { + return Node.onDragStart([nodes], event); + } + if (nodes.length === 0) { + return; + } + + var firstNode = nodes[0]; + var lastNode = nodes[nodes.length - 1]; + var draggedNode = Node.getNodeFromTarget(event.target); + var beforeNode = lastNode._nextSibling(); + var editor = firstNode.editor; + + // in case of multiple selected nodes, offsetY prevents the selection from + // jumping when you start dragging one of the lower down nodes in the selection + var offsetY = util.getAbsoluteTop(draggedNode.dom.tr) - util.getAbsoluteTop(firstNode.dom.tr); + + if (!editor.mousemove) { + editor.mousemove = util.addEventListener(window, 'mousemove', function (event) { + Node.onDrag(nodes, event); + }); + } + + if (!editor.mouseup) { + editor.mouseup = util.addEventListener(window, 'mouseup',function (event ) { + Node.onDragEnd(nodes, event); + }); + } + + editor.highlighter.lock(); + editor.drag = { + oldCursor: document.body.style.cursor, + oldSelection: editor.getSelection(), + oldBeforeNode: beforeNode, + mouseX: event.pageX, + offsetY: offsetY, + level: firstNode.getLevel() + }; + document.body.style.cursor = 'move'; + + event.preventDefault(); + }; + + /** + * Drag event, fired when moving the mouse while dragging a Node + * @param {Node[] | Node} nodes + * @param {Event} event + */ + Node.onDrag = function (nodes, event) { + if (!Array.isArray(nodes)) { + return Node.onDrag([nodes], event); + } + if (nodes.length === 0) { + return; + } + + // TODO: this method has grown too large. Split it in a number of methods + var editor = nodes[0].editor; + var mouseY = event.pageY - editor.drag.offsetY; + var mouseX = event.pageX; + var trThis, trPrev, trNext, trFirst, trLast, trRoot; + var nodePrev, nodeNext; + var topThis, topPrev, topFirst, heightThis, bottomNext, heightNext; + var moved = false; + + // TODO: add an ESC option, which resets to the original position + + // move up/down + var firstNode = nodes[0]; + trThis = firstNode.dom.tr; + topThis = util.getAbsoluteTop(trThis); + heightThis = trThis.offsetHeight; + if (mouseY < topThis) { + // move up + trPrev = trThis; + do { + trPrev = trPrev.previousSibling; + nodePrev = Node.getNodeFromTarget(trPrev); + topPrev = trPrev ? util.getAbsoluteTop(trPrev) : 0; + } + while (trPrev && mouseY < topPrev); + + if (nodePrev && !nodePrev.parent) { + nodePrev = undefined; + } + + if (!nodePrev) { + // move to the first node + trRoot = trThis.parentNode.firstChild; + trPrev = trRoot ? trRoot.nextSibling : undefined; + nodePrev = Node.getNodeFromTarget(trPrev); + if (nodePrev == firstNode) { + nodePrev = undefined; + } + } + + if (nodePrev) { + // check if mouseY is really inside the found node + trPrev = nodePrev.dom.tr; + topPrev = trPrev ? util.getAbsoluteTop(trPrev) : 0; + if (mouseY > topPrev + heightThis) { + nodePrev = undefined; + } + } + + if (nodePrev) { + nodes.forEach(function (node) { + nodePrev.parent.moveBefore(node, nodePrev); + }); + moved = true; + } + } + else { + // move down + var lastNode = nodes[nodes.length - 1]; + trLast = (lastNode.expanded && lastNode.append) ? lastNode.append.getDom() : lastNode.dom.tr; + trFirst = trLast ? trLast.nextSibling : undefined; + if (trFirst) { + topFirst = util.getAbsoluteTop(trFirst); + trNext = trFirst; + do { + nodeNext = Node.getNodeFromTarget(trNext); + if (trNext) { + bottomNext = trNext.nextSibling ? + util.getAbsoluteTop(trNext.nextSibling) : 0; + heightNext = trNext ? (bottomNext - topFirst) : 0; + + if (nodeNext.parent.childs.length == nodes.length && + nodeNext.parent.childs[nodes.length - 1] == lastNode) { + // We are about to remove the last child of this parent, + // which will make the parents appendNode visible. + topThis += 27; + // TODO: dangerous to suppose the height of the appendNode a constant of 27 px. + } + } + + trNext = trNext.nextSibling; + } + while (trNext && mouseY > topThis + heightNext); + + if (nodeNext && nodeNext.parent) { + // calculate the desired level + var diffX = (mouseX - editor.drag.mouseX); + var diffLevel = Math.round(diffX / 24 / 2); + var level = editor.drag.level + diffLevel; // desired level + var levelNext = nodeNext.getLevel(); // level to be + + // find the best fitting level (move upwards over the append nodes) + trPrev = nodeNext.dom.tr.previousSibling; + while (levelNext < level && trPrev) { + nodePrev = Node.getNodeFromTarget(trPrev); + + var isDraggedNode = nodes.some(function (node) { + return node === nodePrev || nodePrev._isChildOf(node); + }); + + if (isDraggedNode) { + // neglect the dragged nodes themselves and their childs + } + else if (nodePrev instanceof AppendNode) { + var childs = nodePrev.parent.childs; + if (childs.length != nodes.length || childs[nodes.length - 1] != lastNode) { + // non-visible append node of a list of childs + // consisting of not only this node (else the + // append node will change into a visible "empty" + // text when removing this node). + nodeNext = Node.getNodeFromTarget(trPrev); + levelNext = nodeNext.getLevel(); + } + else { + break; + } + } + else { + break; + } + + trPrev = trPrev.previousSibling; + } + + // move the node when its position is changed + if (trLast.nextSibling != nodeNext.dom.tr) { + nodes.forEach(function (node) { + nodeNext.parent.moveBefore(node, nodeNext); + }); + moved = true; + } + } + } + } + + if (moved) { + // update the dragging parameters when moved + editor.drag.mouseX = mouseX; + editor.drag.level = firstNode.getLevel(); + } + + // auto scroll when hovering around the top of the editor + editor.startAutoScroll(mouseY); + + event.preventDefault(); + }; + + /** + * Drag event, fired on mouseup after having dragged a node + * @param {Node[] | Node} nodes + * @param {Event} event + */ + Node.onDragEnd = function (nodes, event) { + if (!Array.isArray(nodes)) { + return Node.onDrag([nodes], event); + } + if (nodes.length === 0) { + return; + } + + var firstNode = nodes[0]; + var editor = firstNode.editor; + var parent = firstNode.parent; + var firstIndex = parent.childs.indexOf(firstNode); + var beforeNode = parent.childs[firstIndex + nodes.length] || parent.append; + + // set focus to the context menu button of the first node + if (nodes[0]) { + nodes[0].dom.menu.focus(); + } + + var params = { + nodes: nodes, + oldSelection: editor.drag.oldSelection, + newSelection: editor.getSelection(), + oldBeforeNode: editor.drag.oldBeforeNode, + newBeforeNode: beforeNode + }; + + if (params.oldBeforeNode != params.newBeforeNode) { + // only register this action if the node is actually moved to another place + editor._onAction('moveNodes', params); + } + + document.body.style.cursor = editor.drag.oldCursor; + editor.highlighter.unlock(); + nodes.forEach(function (node) { + if (event.target !== node.dom.drag && event.target !== node.dom.menu) { + editor.highlighter.unhighlight(); + } + }); + delete editor.drag; + + if (editor.mousemove) { + util.removeEventListener(window, 'mousemove', editor.mousemove); + delete editor.mousemove; + } + if (editor.mouseup) { + util.removeEventListener(window, 'mouseup', editor.mouseup); + delete editor.mouseup; + } + + // Stop any running auto scroll + editor.stopAutoScroll(); + + event.preventDefault(); + }; + + /** + * Test if this node is a child of an other node + * @param {Node} node + * @return {boolean} isChild + * @private + */ + Node.prototype._isChildOf = function (node) { + var n = this.parent; + while (n) { + if (n == node) { + return true; + } + n = n.parent; + } + + return false; + }; + + /** + * Create an editable field + * @return {Element} domField + * @private + */ + Node.prototype._createDomField = function () { + return document.createElement('div'); + }; + + /** + * Set highlighting for this node and all its childs. + * Only applied to the currently visible (expanded childs) + * @param {boolean} highlight + */ + Node.prototype.setHighlight = function (highlight) { + if (this.dom.tr) { + if (highlight) { + util.addClassName(this.dom.tr, 'jsoneditor-highlight'); + } + else { + util.removeClassName(this.dom.tr, 'jsoneditor-highlight'); + } + + if (this.append) { + this.append.setHighlight(highlight); + } + + if (this.childs) { + this.childs.forEach(function (child) { + child.setHighlight(highlight); + }); + } + } + }; + + /** + * Select or deselect a node + * @param {boolean} selected + * @param {boolean} [isFirst] + */ + Node.prototype.setSelected = function (selected, isFirst) { + this.selected = selected; + + if (this.dom.tr) { + if (selected) { + util.addClassName(this.dom.tr, 'jsoneditor-selected'); + } + else { + util.removeClassName(this.dom.tr, 'jsoneditor-selected'); + } + + if (isFirst) { + util.addClassName(this.dom.tr, 'jsoneditor-first'); + } + else { + util.removeClassName(this.dom.tr, 'jsoneditor-first'); + } + + if (this.append) { + this.append.setSelected(selected); + } + + if (this.childs) { + this.childs.forEach(function (child) { + child.setSelected(selected); + }); + } + } + }; + + /** + * Update the value of the node. Only primitive types are allowed, no Object + * or Array is allowed. + * @param {String | Number | Boolean | null} value + */ + Node.prototype.updateValue = function (value) { + this.value = value; + this.updateDom(); + }; + + /** + * Update the field of the node. + * @param {String} field + */ + Node.prototype.updateField = function (field) { + this.field = field; + this.updateDom(); + }; + + /** + * Update the HTML DOM, optionally recursing through the childs + * @param {Object} [options] Available parameters: + * {boolean} [recurse] If true, the + * DOM of the childs will be updated recursively. + * False by default. + * {boolean} [updateIndexes] If true, the childs + * indexes of the node will be updated too. False by + * default. + */ + Node.prototype.updateDom = function (options) { + // update level indentation + var domTree = this.dom.tree; + if (domTree) { + domTree.style.marginLeft = this.getLevel() * 24 + 'px'; + } + + // apply field to DOM + var domField = this.dom.field; + if (domField) { + if (this.fieldEditable) { + // parent is an object + domField.contentEditable = this.editable.field; + domField.spellcheck = false; + domField.className = 'jsoneditor-field'; + } + else { + // parent is an array this is the root node + domField.className = 'jsoneditor-readonly'; + } + + var fieldText; + if (this.index != undefined) { + fieldText = this.index; + } + else if (this.field != undefined) { + fieldText = this.field; + } + else if (this._hasChilds()) { + fieldText = this.type; + } + else { + fieldText = ''; + } + domField.innerHTML = this._escapeHTML(fieldText); + + this._updateSchema(); + } + + // apply value to DOM + var domValue = this.dom.value; + if (domValue) { + var count = this.childs ? this.childs.length : 0; + if (this.type == 'array') { + domValue.innerHTML = '[' + count + ']'; + util.addClassName(this.dom.tr, 'jsoneditor-expandable'); + } + else if (this.type == 'object') { + domValue.innerHTML = '{' + count + '}'; + util.addClassName(this.dom.tr, 'jsoneditor-expandable'); + } + else { + domValue.innerHTML = this._escapeHTML(this.value); + util.removeClassName(this.dom.tr, 'jsoneditor-expandable'); + } + } + + // update field and value + this._updateDomField(); + this._updateDomValue(); + + // update childs indexes + if (options && options.updateIndexes === true) { + // updateIndexes is true or undefined + this._updateDomIndexes(); + } + + if (options && options.recurse === true) { + // recurse is true or undefined. update childs recursively + if (this.childs) { + this.childs.forEach(function (child) { + child.updateDom(options); + }); + } + } + + // update row with append button + if (this.append) { + this.append.updateDom(); + } + }; + + /** + * Locate the JSON schema of the node and check for any enum type + * @private + */ + Node.prototype._updateSchema = function () { + //Locating the schema of the node and checking for any enum type + if(this.editor && this.editor.options) { + // find the part of the json schema matching this nodes path + this.schema = Node._findSchema(this.editor.options.schema, this.getPath()); + if (this.schema) { + this.enum = Node._findEnum(this.schema); + } + else { + delete this.enum; + } + } + }; + + /** + * find an enum definition in a JSON schema, as property `enum` or inside + * one of the schemas composites (`oneOf`, `anyOf`, `allOf`) + * @param {Object} schema + * @return {Array | null} Returns the enum when found, null otherwise. + * @private + */ + Node._findEnum = function (schema) { + if (schema.enum) { + return schema.enum; + } + + var composite = schema.oneOf || schema.anyOf || schema.allOf; + if (composite) { + var match = composite.filter(function (entry) {return entry.enum}); + if (match.length > 0) { + return match[0].enum; + } + } + + return null + }; + + /** + * Return the part of a JSON schema matching given path. + * @param {Object} schema + * @param {Array.} path + * @return {Object | null} + * @private + */ + Node._findSchema = function (schema, path) { + var childSchema = schema; + + for (var i = 0; i < path.length && childSchema; i++) { + var key = path[i]; + if (typeof key === 'string' && childSchema.properties) { + childSchema = childSchema.properties[key] || null + } + else if (typeof key === 'number' && childSchema.items) { + childSchema = childSchema.items + } + } + + return childSchema + }; + + /** + * Update the DOM of the childs of a node: update indexes and undefined field + * names. + * Only applicable when structure is an array or object + * @private + */ + Node.prototype._updateDomIndexes = function () { + var domValue = this.dom.value; + var childs = this.childs; + if (domValue && childs) { + if (this.type == 'array') { + childs.forEach(function (child, index) { + child.index = index; + var childField = child.dom.field; + if (childField) { + childField.innerHTML = index; + } + }); + } + else if (this.type == 'object') { + childs.forEach(function (child) { + if (child.index != undefined) { + delete child.index; + + if (child.field == undefined) { + child.field = ''; + } + } + }); + } + } + }; + + /** + * Create an editable value + * @private + */ + Node.prototype._createDomValue = function () { + var domValue; + + if (this.type == 'array') { + domValue = document.createElement('div'); + domValue.innerHTML = '[...]'; + } + else if (this.type == 'object') { + domValue = document.createElement('div'); + domValue.innerHTML = '{...}'; + } + else { + if (!this.editable.value && util.isUrl(this.value)) { + // create a link in case of read-only editor and value containing an url + domValue = document.createElement('a'); + domValue.href = this.value; + domValue.target = '_blank'; + domValue.innerHTML = this._escapeHTML(this.value); + } + else { + // create an editable or read-only div + domValue = document.createElement('div'); + domValue.contentEditable = this.editable.value; + domValue.spellcheck = false; + domValue.innerHTML = this._escapeHTML(this.value); + } + } + + return domValue; + }; + + /** + * Create an expand/collapse button + * @return {Element} expand + * @private + */ + Node.prototype._createDomExpandButton = function () { + // create expand button + var expand = document.createElement('button'); + expand.type = 'button'; + if (this._hasChilds()) { + expand.className = this.expanded ? 'jsoneditor-expanded' : 'jsoneditor-collapsed'; + expand.title = + 'Click to expand/collapse this field (Ctrl+E). \n' + + 'Ctrl+Click to expand/collapse including all childs.'; + } + else { + expand.className = 'jsoneditor-invisible'; + expand.title = ''; + } + + return expand; + }; + + + /** + * Create a DOM tree element, containing the expand/collapse button + * @return {Element} domTree + * @private + */ + Node.prototype._createDomTree = function () { + var dom = this.dom; + var domTree = document.createElement('table'); + var tbody = document.createElement('tbody'); + domTree.style.borderCollapse = 'collapse'; // TODO: put in css + domTree.className = 'jsoneditor-values'; + domTree.appendChild(tbody); + var tr = document.createElement('tr'); + tbody.appendChild(tr); + + // create expand button + var tdExpand = document.createElement('td'); + tdExpand.className = 'jsoneditor-tree'; + tr.appendChild(tdExpand); + dom.expand = this._createDomExpandButton(); + tdExpand.appendChild(dom.expand); + dom.tdExpand = tdExpand; + + // create the field + var tdField = document.createElement('td'); + tdField.className = 'jsoneditor-tree'; + tr.appendChild(tdField); + dom.field = this._createDomField(); + tdField.appendChild(dom.field); + dom.tdField = tdField; + + // create a separator + var tdSeparator = document.createElement('td'); + tdSeparator.className = 'jsoneditor-tree'; + tr.appendChild(tdSeparator); + if (this.type != 'object' && this.type != 'array') { + tdSeparator.appendChild(document.createTextNode(':')); + tdSeparator.className = 'jsoneditor-separator'; + } + dom.tdSeparator = tdSeparator; + + // create the value + var tdValue = document.createElement('td'); + tdValue.className = 'jsoneditor-tree'; + tr.appendChild(tdValue); + dom.value = this._createDomValue(); + tdValue.appendChild(dom.value); + dom.tdValue = tdValue; + + return domTree; + }; + + /** + * Handle an event. The event is caught centrally by the editor + * @param {Event} event + */ + Node.prototype.onEvent = function (event) { + var type = event.type, + target = event.target || event.srcElement, + dom = this.dom, + node = this, + expandable = this._hasChilds(); + + // check if mouse is on menu or on dragarea. + // If so, highlight current row and its childs + if (target == dom.drag || target == dom.menu) { + if (type == 'mouseover') { + this.editor.highlighter.highlight(this); + } + else if (type == 'mouseout') { + this.editor.highlighter.unhighlight(); + } + } + + // context menu events + if (type == 'click' && target == dom.menu) { + var highlighter = node.editor.highlighter; + highlighter.highlight(node); + highlighter.lock(); + util.addClassName(dom.menu, 'jsoneditor-selected'); + this.showContextMenu(dom.menu, function () { + util.removeClassName(dom.menu, 'jsoneditor-selected'); + highlighter.unlock(); + highlighter.unhighlight(); + }); + } + + // expand events + if (type == 'click') { + if (target == dom.expand || + ((node.editor.options.mode === 'view' || node.editor.options.mode === 'form') && target.nodeName === 'DIV')) { + if (expandable) { + var recurse = event.ctrlKey; // with ctrl-key, expand/collapse all + this._onExpand(recurse); + } + } + } + + // swap the value of a boolean when the checkbox displayed left is clicked + if (type == 'change' && target == dom.checkbox) { + this.dom.value.innerHTML = !this.value; + this._getDomValue(); + } + + // update the value of the node based on the selected option + if (type == 'change' && target == dom.select) { + this.dom.value.innerHTML = dom.select.value; + this._getDomValue(); + this._updateDomValue(); + } + + // value events + var domValue = dom.value; + if (target == domValue) { + //noinspection FallthroughInSwitchStatementJS + switch (type) { + case 'blur': + case 'change': + this._getDomValue(true); + this._updateDomValue(); + if (this.value) { + domValue.innerHTML = this._escapeHTML(this.value); + } + break; + + case 'input': + //this._debouncedGetDomValue(true); // TODO + this._getDomValue(true); + this._updateDomValue(); + break; + + case 'keydown': + case 'mousedown': + // TODO: cleanup + this.editor.selection = this.editor.getSelection(); + break; + + case 'click': + if (event.ctrlKey || !this.editable.value) { + if (util.isUrl(this.value)) { + window.open(this.value, '_blank'); + } + } + break; + + case 'keyup': + //this._debouncedGetDomValue(true); // TODO + this._getDomValue(true); + this._updateDomValue(); + break; + + case 'cut': + case 'paste': + setTimeout(function () { + node._getDomValue(true); + node._updateDomValue(); + }, 1); + break; + } + } + + // field events + var domField = dom.field; + if (target == domField) { + switch (type) { + case 'blur': + case 'change': + this._getDomField(true); + this._updateDomField(); + if (this.field) { + domField.innerHTML = this._escapeHTML(this.field); + } + break; + + case 'input': + this._getDomField(true); + this._updateSchema(); + this._updateDomField(); + this._updateDomValue(); + break; + + case 'keydown': + case 'mousedown': + this.editor.selection = this.editor.getSelection(); + break; + + case 'keyup': + this._getDomField(true); + this._updateDomField(); + break; + + case 'cut': + case 'paste': + setTimeout(function () { + node._getDomField(true); + node._updateDomField(); + }, 1); + break; + } + } + + // focus + // when clicked in whitespace left or right from the field or value, set focus + var domTree = dom.tree; + if (target == domTree.parentNode && type == 'click' && !event.hasMoved) { + var left = (event.offsetX != undefined) ? + (event.offsetX < (this.getLevel() + 1) * 24) : + (event.pageX < util.getAbsoluteLeft(dom.tdSeparator));// for FF + if (left || expandable) { + // node is expandable when it is an object or array + if (domField) { + util.setEndOfContentEditable(domField); + domField.focus(); + } + } + else { + if (domValue && !this.enum) { + util.setEndOfContentEditable(domValue); + domValue.focus(); + } + } + } + if (((target == dom.tdExpand && !expandable) || target == dom.tdField || target == dom.tdSeparator) && + (type == 'click' && !event.hasMoved)) { + if (domField) { + util.setEndOfContentEditable(domField); + domField.focus(); + } + } + + if (type == 'keydown') { + this.onKeyDown(event); + } + }; + + /** + * Key down event handler + * @param {Event} event + */ + Node.prototype.onKeyDown = function (event) { + var keynum = event.which || event.keyCode; + var target = event.target || event.srcElement; + var ctrlKey = event.ctrlKey; + var shiftKey = event.shiftKey; + var altKey = event.altKey; + var handled = false; + var prevNode, nextNode, nextDom, nextDom2; + var editable = this.editor.options.mode === 'tree'; + var oldSelection; + var oldBeforeNode; + var nodes; + var multiselection; + var selectedNodes = this.editor.multiselection.nodes.length > 0 + ? this.editor.multiselection.nodes + : [this]; + var firstNode = selectedNodes[0]; + var lastNode = selectedNodes[selectedNodes.length - 1]; + + // console.log(ctrlKey, keynum, event.charCode); // TODO: cleanup + if (keynum == 13) { // Enter + if (target == this.dom.value) { + if (!this.editable.value || event.ctrlKey) { + if (util.isUrl(this.value)) { + window.open(this.value, '_blank'); + handled = true; + } + } + } + else if (target == this.dom.expand) { + var expandable = this._hasChilds(); + if (expandable) { + var recurse = event.ctrlKey; // with ctrl-key, expand/collapse all + this._onExpand(recurse); + target.focus(); + handled = true; + } + } + } + else if (keynum == 68) { // D + if (ctrlKey && editable) { // Ctrl+D + Node.onDuplicate(selectedNodes); + handled = true; + } + } + else if (keynum == 69) { // E + if (ctrlKey) { // Ctrl+E and Ctrl+Shift+E + this._onExpand(shiftKey); // recurse = shiftKey + target.focus(); // TODO: should restore focus in case of recursing expand (which takes DOM offline) + handled = true; + } + } + else if (keynum == 77 && editable) { // M + if (ctrlKey) { // Ctrl+M + this.showContextMenu(target); + handled = true; + } + } + else if (keynum == 46 && editable) { // Del + if (ctrlKey) { // Ctrl+Del + Node.onRemove(selectedNodes); + handled = true; + } + } + else if (keynum == 45 && editable) { // Ins + if (ctrlKey && !shiftKey) { // Ctrl+Ins + this._onInsertBefore(); + handled = true; + } + else if (ctrlKey && shiftKey) { // Ctrl+Shift+Ins + this._onInsertAfter(); + handled = true; + } + } + else if (keynum == 35) { // End + if (altKey) { // Alt+End + // find the last node + var endNode = this._lastNode(); + if (endNode) { + endNode.focus(Node.focusElement || this._getElementName(target)); + } + handled = true; + } + } + else if (keynum == 36) { // Home + if (altKey) { // Alt+Home + // find the first node + var homeNode = this._firstNode(); + if (homeNode) { + homeNode.focus(Node.focusElement || this._getElementName(target)); + } + handled = true; + } + } + else if (keynum == 37) { // Arrow Left + if (altKey && !shiftKey) { // Alt + Arrow Left + // move to left element + var prevElement = this._previousElement(target); + if (prevElement) { + this.focus(this._getElementName(prevElement)); + } + handled = true; + } + else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow left + if (lastNode.expanded) { + var appendDom = lastNode.getAppend(); + nextDom = appendDom ? appendDom.nextSibling : undefined; + } + else { + var dom = lastNode.getDom(); + nextDom = dom.nextSibling; + } + if (nextDom) { + nextNode = Node.getNodeFromTarget(nextDom); + nextDom2 = nextDom.nextSibling; + nextNode2 = Node.getNodeFromTarget(nextDom2); + if (nextNode && nextNode instanceof AppendNode && + !(lastNode.parent.childs.length == 1) && + nextNode2 && nextNode2.parent) { + oldSelection = this.editor.getSelection(); + oldBeforeNode = lastNode._nextSibling(); + + selectedNodes.forEach(function (node) { + nextNode2.parent.moveBefore(node, nextNode2); + }); + this.focus(Node.focusElement || this._getElementName(target)); + + this.editor._onAction('moveNodes', { + nodes: selectedNodes, + oldBeforeNode: oldBeforeNode, + newBeforeNode: nextNode2, + oldSelection: oldSelection, + newSelection: this.editor.getSelection() + }); + } + } + } + } + else if (keynum == 38) { // Arrow Up + if (altKey && !shiftKey) { // Alt + Arrow Up + // find the previous node + prevNode = this._previousNode(); + if (prevNode) { + this.editor.deselect(true); + prevNode.focus(Node.focusElement || this._getElementName(target)); + } + handled = true; + } + else if (!altKey && ctrlKey && shiftKey && editable) { // Ctrl + Shift + Arrow Up + // select multiple nodes + prevNode = this._previousNode(); + if (prevNode) { + multiselection = this.editor.multiselection; + multiselection.start = multiselection.start || this; + multiselection.end = prevNode; + nodes = this.editor._findTopLevelNodes(multiselection.start, multiselection.end); + + this.editor.select(nodes); + prevNode.focus('field'); // select field as we know this always exists + } + handled = true; + } + else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow Up + // find the previous node + prevNode = firstNode._previousNode(); + if (prevNode && prevNode.parent) { + oldSelection = this.editor.getSelection(); + oldBeforeNode = lastNode._nextSibling(); + + selectedNodes.forEach(function (node) { + prevNode.parent.moveBefore(node, prevNode); + }); + this.focus(Node.focusElement || this._getElementName(target)); + + this.editor._onAction('moveNodes', { + nodes: selectedNodes, + oldBeforeNode: oldBeforeNode, + newBeforeNode: prevNode, + oldSelection: oldSelection, + newSelection: this.editor.getSelection() + }); + } + handled = true; + } + } + else if (keynum == 39) { // Arrow Right + if (altKey && !shiftKey) { // Alt + Arrow Right + // move to right element + var nextElement = this._nextElement(target); + if (nextElement) { + this.focus(this._getElementName(nextElement)); + } + handled = true; + } + else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow Right + dom = firstNode.getDom(); + var prevDom = dom.previousSibling; + if (prevDom) { + prevNode = Node.getNodeFromTarget(prevDom); + if (prevNode && prevNode.parent && + (prevNode instanceof AppendNode) + && !prevNode.isVisible()) { + oldSelection = this.editor.getSelection(); + oldBeforeNode = lastNode._nextSibling(); + + selectedNodes.forEach(function (node) { + prevNode.parent.moveBefore(node, prevNode); + }); + this.focus(Node.focusElement || this._getElementName(target)); + + this.editor._onAction('moveNodes', { + nodes: selectedNodes, + oldBeforeNode: oldBeforeNode, + newBeforeNode: prevNode, + oldSelection: oldSelection, + newSelection: this.editor.getSelection() + }); + } + } + } + } + else if (keynum == 40) { // Arrow Down + if (altKey && !shiftKey) { // Alt + Arrow Down + // find the next node + nextNode = this._nextNode(); + if (nextNode) { + this.editor.deselect(true); + nextNode.focus(Node.focusElement || this._getElementName(target)); + } + handled = true; + } + else if (!altKey && ctrlKey && shiftKey && editable) { // Ctrl + Shift + Arrow Down + // select multiple nodes + nextNode = this._nextNode(); + if (nextNode) { + multiselection = this.editor.multiselection; + multiselection.start = multiselection.start || this; + multiselection.end = nextNode; + nodes = this.editor._findTopLevelNodes(multiselection.start, multiselection.end); + + this.editor.select(nodes); + nextNode.focus('field'); // select field as we know this always exists + } + handled = true; + } + else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow Down + // find the 2nd next node and move before that one + if (lastNode.expanded) { + nextNode = lastNode.append ? lastNode.append._nextNode() : undefined; + } + else { + nextNode = lastNode._nextNode(); + } + var nextNode2 = nextNode && (nextNode._nextNode() || nextNode.parent.append); + if (nextNode2 && nextNode2.parent) { + oldSelection = this.editor.getSelection(); + oldBeforeNode = lastNode._nextSibling(); + + selectedNodes.forEach(function (node) { + nextNode2.parent.moveBefore(node, nextNode2); + }); + this.focus(Node.focusElement || this._getElementName(target)); + + this.editor._onAction('moveNodes', { + nodes: selectedNodes, + oldBeforeNode: oldBeforeNode, + newBeforeNode: nextNode2, + oldSelection: oldSelection, + newSelection: this.editor.getSelection() + }); + } + handled = true; + } + } + + if (handled) { + event.preventDefault(); + event.stopPropagation(); + } + }; + + /** + * Handle the expand event, when clicked on the expand button + * @param {boolean} recurse If true, child nodes will be expanded too + * @private + */ + Node.prototype._onExpand = function (recurse) { + if (recurse) { + // Take the table offline + var table = this.dom.tr.parentNode; // TODO: not nice to access the main table like this + var frame = table.parentNode; + var scrollTop = frame.scrollTop; + frame.removeChild(table); + } + + if (this.expanded) { + this.collapse(recurse); + } + else { + this.expand(recurse); + } + + if (recurse) { + // Put the table online again + frame.appendChild(table); + frame.scrollTop = scrollTop; + } + }; + + /** + * Remove nodes + * @param {Node[] | Node} nodes + */ + Node.onRemove = function(nodes) { + if (!Array.isArray(nodes)) { + return Node.onRemove([nodes]); + } + + if (nodes && nodes.length > 0) { + var firstNode = nodes[0]; + var parent = firstNode.parent; + var editor = firstNode.editor; + var firstIndex = firstNode.getIndex(); + editor.highlighter.unhighlight(); + + // adjust the focus + var oldSelection = editor.getSelection(); + Node.blurNodes(nodes); + var newSelection = editor.getSelection(); + + // remove the nodes + nodes.forEach(function (node) { + node.parent._remove(node); + }); + + // store history action + editor._onAction('removeNodes', { + nodes: nodes.slice(0), // store a copy of the array! + parent: parent, + index: firstIndex, + oldSelection: oldSelection, + newSelection: newSelection + }); + } + }; + + + /** + * Duplicate nodes + * duplicated nodes will be added right after the original nodes + * @param {Node[] | Node} nodes + */ + Node.onDuplicate = function(nodes) { + if (!Array.isArray(nodes)) { + return Node.onDuplicate([nodes]); + } + + if (nodes && nodes.length > 0) { + var lastNode = nodes[nodes.length - 1]; + var parent = lastNode.parent; + var editor = lastNode.editor; + + editor.deselect(editor.multiselection.nodes); + + // duplicate the nodes + var oldSelection = editor.getSelection(); + var afterNode = lastNode; + var clones = nodes.map(function (node) { + var clone = node.clone(); + parent.insertAfter(clone, afterNode); + afterNode = clone; + return clone; + }); + + // set selection to the duplicated nodes + if (nodes.length === 1) { + clones[0].focus(); + } + else { + editor.select(clones); + } + var newSelection = editor.getSelection(); + + editor._onAction('duplicateNodes', { + afterNode: lastNode, + nodes: clones, + parent: parent, + oldSelection: oldSelection, + newSelection: newSelection + }); + } + }; + + /** + * Handle insert before event + * @param {String} [field] + * @param {*} [value] + * @param {String} [type] Can be 'auto', 'array', 'object', or 'string' + * @private + */ + Node.prototype._onInsertBefore = function (field, value, type) { + var oldSelection = this.editor.getSelection(); + + var newNode = new Node(this.editor, { + field: (field != undefined) ? field : '', + value: (value != undefined) ? value : '', + type: type + }); + newNode.expand(true); + this.parent.insertBefore(newNode, this); + this.editor.highlighter.unhighlight(); + newNode.focus('field'); + var newSelection = this.editor.getSelection(); + + this.editor._onAction('insertBeforeNodes', { + nodes: [newNode], + beforeNode: this, + parent: this.parent, + oldSelection: oldSelection, + newSelection: newSelection + }); + }; + + /** + * Handle insert after event + * @param {String} [field] + * @param {*} [value] + * @param {String} [type] Can be 'auto', 'array', 'object', or 'string' + * @private + */ + Node.prototype._onInsertAfter = function (field, value, type) { + var oldSelection = this.editor.getSelection(); + + var newNode = new Node(this.editor, { + field: (field != undefined) ? field : '', + value: (value != undefined) ? value : '', + type: type + }); + newNode.expand(true); + this.parent.insertAfter(newNode, this); + this.editor.highlighter.unhighlight(); + newNode.focus('field'); + var newSelection = this.editor.getSelection(); + + this.editor._onAction('insertAfterNodes', { + nodes: [newNode], + afterNode: this, + parent: this.parent, + oldSelection: oldSelection, + newSelection: newSelection + }); + }; + + /** + * Handle append event + * @param {String} [field] + * @param {*} [value] + * @param {String} [type] Can be 'auto', 'array', 'object', or 'string' + * @private + */ + Node.prototype._onAppend = function (field, value, type) { + var oldSelection = this.editor.getSelection(); + + var newNode = new Node(this.editor, { + field: (field != undefined) ? field : '', + value: (value != undefined) ? value : '', + type: type + }); + newNode.expand(true); + this.parent.appendChild(newNode); + this.editor.highlighter.unhighlight(); + newNode.focus('field'); + var newSelection = this.editor.getSelection(); + + this.editor._onAction('appendNodes', { + nodes: [newNode], + parent: this.parent, + oldSelection: oldSelection, + newSelection: newSelection + }); + }; + + /** + * Change the type of the node's value + * @param {String} newType + * @private + */ + Node.prototype._onChangeType = function (newType) { + var oldType = this.type; + if (newType != oldType) { + var oldSelection = this.editor.getSelection(); + this.changeType(newType); + var newSelection = this.editor.getSelection(); + + this.editor._onAction('changeType', { + node: this, + oldType: oldType, + newType: newType, + oldSelection: oldSelection, + newSelection: newSelection + }); + } + }; + + /** + * Sort the child's of the node. Only applicable when the node has type 'object' + * or 'array'. + * @param {String} direction Sorting direction. Available values: "asc", "desc" + * @private + */ + Node.prototype.sort = function (direction) { + if (!this._hasChilds()) { + return; + } + + var order = (direction == 'desc') ? -1 : 1; + var prop = (this.type == 'array') ? 'value': 'field'; + this.hideChilds(); + + var oldChilds = this.childs; + var oldSortOrder = this.sortOrder; + + // copy the array (the old one will be kept for an undo action + this.childs = this.childs.concat(); + + // sort the arrays + this.childs.sort(function (a, b) { + return order * naturalSort(a[prop], b[prop]); + }); + this.sortOrder = (order == 1) ? 'asc' : 'desc'; + + this.editor._onAction('sort', { + node: this, + oldChilds: oldChilds, + oldSort: oldSortOrder, + newChilds: this.childs, + newSort: this.sortOrder + }); + + this.showChilds(); + }; + + /** + * Create a table row with an append button. + * @return {HTMLElement | undefined} buttonAppend or undefined when inapplicable + */ + Node.prototype.getAppend = function () { + if (!this.append) { + this.append = new AppendNode(this.editor); + this.append.setParent(this); + } + return this.append.getDom(); + }; + + /** + * Find the node from an event target + * @param {Node} target + * @return {Node | undefined} node or undefined when not found + * @static + */ + Node.getNodeFromTarget = function (target) { + while (target) { + if (target.node) { + return target.node; + } + target = target.parentNode; + } + + return undefined; + }; + + /** + * Remove the focus of given nodes, and move the focus to the (a) node before, + * (b) the node after, or (c) the parent node. + * @param {Array. | Node} nodes + */ + Node.blurNodes = function (nodes) { + if (!Array.isArray(nodes)) { + Node.blurNodes([nodes]); + return; + } + + var firstNode = nodes[0]; + var parent = firstNode.parent; + var firstIndex = firstNode.getIndex(); + + if (parent.childs[firstIndex + nodes.length]) { + parent.childs[firstIndex + nodes.length].focus(); + } + else if (parent.childs[firstIndex - 1]) { + parent.childs[firstIndex - 1].focus(); + } + else { + parent.focus(); + } + }; + + /** + * Get the next sibling of current node + * @return {Node} nextSibling + * @private + */ + Node.prototype._nextSibling = function () { + var index = this.parent.childs.indexOf(this); + return this.parent.childs[index + 1] || this.parent.append; + }; + + /** + * Get the previously rendered node + * @return {Node | null} previousNode + * @private + */ + Node.prototype._previousNode = function () { + var prevNode = null; + var dom = this.getDom(); + if (dom && dom.parentNode) { + // find the previous field + var prevDom = dom; + do { + prevDom = prevDom.previousSibling; + prevNode = Node.getNodeFromTarget(prevDom); + } + while (prevDom && (prevNode instanceof AppendNode && !prevNode.isVisible())); + } + return prevNode; + }; + + /** + * Get the next rendered node + * @return {Node | null} nextNode + * @private + */ + Node.prototype._nextNode = function () { + var nextNode = null; + var dom = this.getDom(); + if (dom && dom.parentNode) { + // find the previous field + var nextDom = dom; + do { + nextDom = nextDom.nextSibling; + nextNode = Node.getNodeFromTarget(nextDom); + } + while (nextDom && (nextNode instanceof AppendNode && !nextNode.isVisible())); + } + + return nextNode; + }; + + /** + * Get the first rendered node + * @return {Node | null} firstNode + * @private + */ + Node.prototype._firstNode = function () { + var firstNode = null; + var dom = this.getDom(); + if (dom && dom.parentNode) { + var firstDom = dom.parentNode.firstChild; + firstNode = Node.getNodeFromTarget(firstDom); + } + + return firstNode; + }; + + /** + * Get the last rendered node + * @return {Node | null} lastNode + * @private + */ + Node.prototype._lastNode = function () { + var lastNode = null; + var dom = this.getDom(); + if (dom && dom.parentNode) { + var lastDom = dom.parentNode.lastChild; + lastNode = Node.getNodeFromTarget(lastDom); + while (lastDom && (lastNode instanceof AppendNode && !lastNode.isVisible())) { + lastDom = lastDom.previousSibling; + lastNode = Node.getNodeFromTarget(lastDom); + } + } + return lastNode; + }; + + /** + * Get the next element which can have focus. + * @param {Element} elem + * @return {Element | null} nextElem + * @private + */ + Node.prototype._previousElement = function (elem) { + var dom = this.dom; + // noinspection FallthroughInSwitchStatementJS + switch (elem) { + case dom.value: + if (this.fieldEditable) { + return dom.field; + } + // intentional fall through + case dom.field: + if (this._hasChilds()) { + return dom.expand; + } + // intentional fall through + case dom.expand: + return dom.menu; + case dom.menu: + if (dom.drag) { + return dom.drag; + } + // intentional fall through + default: + return null; + } + }; + + /** + * Get the next element which can have focus. + * @param {Element} elem + * @return {Element | null} nextElem + * @private + */ + Node.prototype._nextElement = function (elem) { + var dom = this.dom; + // noinspection FallthroughInSwitchStatementJS + switch (elem) { + case dom.drag: + return dom.menu; + case dom.menu: + if (this._hasChilds()) { + return dom.expand; + } + // intentional fall through + case dom.expand: + if (this.fieldEditable) { + return dom.field; + } + // intentional fall through + case dom.field: + if (!this._hasChilds()) { + return dom.value; + } + default: + return null; + } + }; + + /** + * Get the dom name of given element. returns null if not found. + * For example when element == dom.field, "field" is returned. + * @param {Element} element + * @return {String | null} elementName Available elements with name: 'drag', + * 'menu', 'expand', 'field', 'value' + * @private + */ + Node.prototype._getElementName = function (element) { + var dom = this.dom; + for (var name in dom) { + if (dom.hasOwnProperty(name)) { + if (dom[name] == element) { + return name; + } + } + } + return null; + }; + + /** + * Test if this node has childs. This is the case when the node is an object + * or array. + * @return {boolean} hasChilds + * @private + */ + Node.prototype._hasChilds = function () { + return this.type == 'array' || this.type == 'object'; + }; + + // titles with explanation for the different types + Node.TYPE_TITLES = { + 'auto': 'Field type "auto". ' + + 'The field type is automatically determined from the value ' + + 'and can be a string, number, boolean, or null.', + 'object': 'Field type "object". ' + + 'An object contains an unordered set of key/value pairs.', + 'array': 'Field type "array". ' + + 'An array contains an ordered collection of values.', + 'string': 'Field type "string". ' + + 'Field type is not determined from the value, ' + + 'but always returned as string.' + }; + + /** + * Show a contextmenu for this node + * @param {HTMLElement} anchor Anchor element to attach the context menu to + * as sibling. + * @param {function} [onClose] Callback method called when the context menu + * is being closed. + */ + Node.prototype.showContextMenu = function (anchor, onClose) { + var node = this; + var titles = Node.TYPE_TITLES; + var items = []; + + if (this.editable.value) { + items.push({ + text: 'Type', + title: 'Change the type of this field', + className: 'jsoneditor-type-' + this.type, + submenu: [ + { + text: 'Auto', + className: 'jsoneditor-type-auto' + + (this.type == 'auto' ? ' jsoneditor-selected' : ''), + title: titles.auto, + click: function () { + node._onChangeType('auto'); + } + }, + { + text: 'Array', + className: 'jsoneditor-type-array' + + (this.type == 'array' ? ' jsoneditor-selected' : ''), + title: titles.array, + click: function () { + node._onChangeType('array'); + } + }, + { + text: 'Object', + className: 'jsoneditor-type-object' + + (this.type == 'object' ? ' jsoneditor-selected' : ''), + title: titles.object, + click: function () { + node._onChangeType('object'); + } + }, + { + text: 'String', + className: 'jsoneditor-type-string' + + (this.type == 'string' ? ' jsoneditor-selected' : ''), + title: titles.string, + click: function () { + node._onChangeType('string'); + } + } + ] + }); + } + + if (this._hasChilds()) { + var direction = ((this.sortOrder == 'asc') ? 'desc': 'asc'); + items.push({ + text: 'Sort', + title: 'Sort the childs of this ' + this.type, + className: 'jsoneditor-sort-' + direction, + click: function () { + node.sort(direction); + }, + submenu: [ + { + text: 'Ascending', + className: 'jsoneditor-sort-asc', + title: 'Sort the childs of this ' + this.type + ' in ascending order', + click: function () { + node.sort('asc'); + } + }, + { + text: 'Descending', + className: 'jsoneditor-sort-desc', + title: 'Sort the childs of this ' + this.type +' in descending order', + click: function () { + node.sort('desc'); + } + } + ] + }); + } + + if (this.parent && this.parent._hasChilds()) { + if (items.length) { + // create a separator + items.push({ + 'type': 'separator' + }); + } + + // create append button (for last child node only) + var childs = node.parent.childs; + if (node == childs[childs.length - 1]) { + items.push({ + text: 'Append', + title: 'Append a new field with type \'auto\' after this field (Ctrl+Shift+Ins)', + submenuTitle: 'Select the type of the field to be appended', + className: 'jsoneditor-append', + click: function () { + node._onAppend('', '', 'auto'); + }, + submenu: [ + { + text: 'Auto', + className: 'jsoneditor-type-auto', + title: titles.auto, + click: function () { + node._onAppend('', '', 'auto'); + } + }, + { + text: 'Array', + className: 'jsoneditor-type-array', + title: titles.array, + click: function () { + node._onAppend('', []); + } + }, + { + text: 'Object', + className: 'jsoneditor-type-object', + title: titles.object, + click: function () { + node._onAppend('', {}); + } + }, + { + text: 'String', + className: 'jsoneditor-type-string', + title: titles.string, + click: function () { + node._onAppend('', '', 'string'); + } + } + ] + }); + } + + // create insert button + items.push({ + text: 'Insert', + title: 'Insert a new field with type \'auto\' before this field (Ctrl+Ins)', + submenuTitle: 'Select the type of the field to be inserted', + className: 'jsoneditor-insert', + click: function () { + node._onInsertBefore('', '', 'auto'); + }, + submenu: [ + { + text: 'Auto', + className: 'jsoneditor-type-auto', + title: titles.auto, + click: function () { + node._onInsertBefore('', '', 'auto'); + } + }, + { + text: 'Array', + className: 'jsoneditor-type-array', + title: titles.array, + click: function () { + node._onInsertBefore('', []); + } + }, + { + text: 'Object', + className: 'jsoneditor-type-object', + title: titles.object, + click: function () { + node._onInsertBefore('', {}); + } + }, + { + text: 'String', + className: 'jsoneditor-type-string', + title: titles.string, + click: function () { + node._onInsertBefore('', '', 'string'); + } + } + ] + }); + + if (this.editable.field) { + // create duplicate button + items.push({ + text: 'Duplicate', + title: 'Duplicate this field (Ctrl+D)', + className: 'jsoneditor-duplicate', + click: function () { + Node.onDuplicate(node); + } + }); + + // create remove button + items.push({ + text: 'Remove', + title: 'Remove this field (Ctrl+Del)', + className: 'jsoneditor-remove', + click: function () { + Node.onRemove(node); + } + }); + } + } + + var menu = new ContextMenu(items, {close: onClose}); + menu.show(anchor, this.editor.content); + }; + + /** + * get the type of a value + * @param {*} value + * @return {String} type Can be 'object', 'array', 'string', 'auto' + * @private + */ + Node.prototype._getType = function(value) { + if (value instanceof Array) { + return 'array'; + } + if (value instanceof Object) { + return 'object'; + } + if (typeof(value) == 'string' && typeof(this._stringCast(value)) != 'string') { + return 'string'; + } + + return 'auto'; + }; + + /** + * cast contents of a string to the correct type. This can be a string, + * a number, a boolean, etc + * @param {String} str + * @return {*} castedStr + * @private + */ + Node.prototype._stringCast = function(str) { + var lower = str.toLowerCase(), + num = Number(str), // will nicely fail with '123ab' + numFloat = parseFloat(str); // will nicely fail with ' ' + + if (str == '') { + return ''; + } + else if (lower == 'null') { + return null; + } + else if (lower == 'true') { + return true; + } + else if (lower == 'false') { + return false; + } + else if (!isNaN(num) && !isNaN(numFloat)) { + return num; + } + else { + return str; + } + }; + + /** + * escape a text, such that it can be displayed safely in an HTML element + * @param {String} text + * @return {String} escapedText + * @private + */ + Node.prototype._escapeHTML = function (text) { + if (typeof text !== 'string') { + return String(text); + } + else { + var htmlEscaped = String(text) + .replace(/&/g, '&') // must be replaced first! + .replace(//g, '>') + .replace(/ /g, '  ') // replace double space with an nbsp and space + .replace(/^ /, ' ') // space at start + .replace(/ $/, ' '); // space at end + + var json = JSON.stringify(htmlEscaped); + var html = json.substring(1, json.length - 1); + if (this.editor.options.escapeUnicode === true) { + html = util.escapeUnicodeChars(html); + } + return html; + } + }; + + /** + * unescape a string. + * @param {String} escapedText + * @return {String} text + * @private + */ + Node.prototype._unescapeHTML = function (escapedText) { + var json = '"' + this._escapeJSON(escapedText) + '"'; + var htmlEscaped = util.parse(json); + + return htmlEscaped + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/ |\u00A0/g, ' ') + .replace(/&/g, '&'); // must be replaced last + }; + + /** + * escape a text to make it a valid JSON string. The method will: + * - replace unescaped double quotes with '\"' + * - replace unescaped backslash with '\\' + * - replace returns with '\n' + * @param {String} text + * @return {String} escapedText + * @private + */ + Node.prototype._escapeJSON = function (text) { + // TODO: replace with some smart regex (only when a new solution is faster!) + var escaped = ''; + var i = 0; + while (i < text.length) { + var c = text.charAt(i); + if (c == '\n') { + escaped += '\\n'; + } + else if (c == '\\') { + escaped += c; + i++; + + c = text.charAt(i); + if (c === '' || '"\\/bfnrtu'.indexOf(c) == -1) { + escaped += '\\'; // no valid escape character + } + escaped += c; + } + else if (c == '"') { + escaped += '\\"'; + } + else { + escaped += c; + } + i++; + } + + return escaped; + }; + + // TODO: find a nicer solution to resolve this circular dependency between Node and AppendNode + var AppendNode = appendNodeFactory(Node); + + module.exports = Node; + + +/***/ }, +/* 59 */ +/***/ function(module, exports) { + + /* + * Natural Sort algorithm for Javascript - Version 0.7 - Released under MIT license + * Author: Jim Palmer (based on chunking idea from Dave Koelle) + */ + /*jshint unused:false */ + module.exports = function naturalSort (a, b) { + "use strict"; + var re = /(^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi, + sre = /(^[ ]*|[ ]*$)/g, + dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/, + hre = /^0x[0-9a-f]+$/i, + ore = /^0/, + i = function(s) { return naturalSort.insensitive && ('' + s).toLowerCase() || '' + s; }, + // convert all to strings strip whitespace + x = i(a).replace(sre, '') || '', + y = i(b).replace(sre, '') || '', + // chunk/tokenize + xN = x.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'), + yN = y.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'), + // numeric, hex or date detection + xD = parseInt(x.match(hre), 16) || (xN.length !== 1 && x.match(dre) && Date.parse(x)), + yD = parseInt(y.match(hre), 16) || xD && y.match(dre) && Date.parse(y) || null, + oFxNcL, oFyNcL; + // first try and sort Hex codes or Dates + if (yD) { + if ( xD < yD ) { return -1; } + else if ( xD > yD ) { return 1; } + } + // natural sorting through split numeric strings and default strings + for(var cLoc=0, numS=Math.max(xN.length, yN.length); cLoc < numS; cLoc++) { + // find floats not starting with '0', string or 0 if not defined (Clint Priest) + oFxNcL = !(xN[cLoc] || '').match(ore) && parseFloat(xN[cLoc]) || xN[cLoc] || 0; + oFyNcL = !(yN[cLoc] || '').match(ore) && parseFloat(yN[cLoc]) || yN[cLoc] || 0; + // handle numeric vs string comparison - number < string - (Kyle Adams) + if (isNaN(oFxNcL) !== isNaN(oFyNcL)) { return (isNaN(oFxNcL)) ? 1 : -1; } + // rely on string comparison if different types - i.e. '02' < 2 != '02' < '2' + else if (typeof oFxNcL !== typeof oFyNcL) { + oFxNcL += ''; + oFyNcL += ''; + } + if (oFxNcL < oFyNcL) { return -1; } + if (oFxNcL > oFyNcL) { return 1; } + } + return 0; + }; + + +/***/ }, +/* 60 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var util = __webpack_require__(54); + var ContextMenu = __webpack_require__(57); + + /** + * A factory function to create an AppendNode, which depends on a Node + * @param {Node} Node + */ + function appendNodeFactory(Node) { + /** + * @constructor AppendNode + * @extends Node + * @param {TreeEditor} editor + * Create a new AppendNode. This is a special node which is created at the + * end of the list with childs for an object or array + */ + function AppendNode (editor) { + /** @type {TreeEditor} */ + this.editor = editor; + this.dom = {}; + } + + AppendNode.prototype = new Node(); + + /** + * Return a table row with an append button. + * @return {Element} dom TR element + */ + AppendNode.prototype.getDom = function () { + // TODO: implement a new solution for the append node + var dom = this.dom; + + if (dom.tr) { + return dom.tr; + } + + this._updateEditability(); + + // a row for the append button + var trAppend = document.createElement('tr'); + trAppend.node = this; + dom.tr = trAppend; + + // TODO: consistent naming + + if (this.editor.options.mode === 'tree') { + // a cell for the dragarea column + dom.tdDrag = document.createElement('td'); + + // create context menu + var tdMenu = document.createElement('td'); + dom.tdMenu = tdMenu; + var menu = document.createElement('button'); + menu.type = 'button'; + menu.className = 'jsoneditor-contextmenu'; + menu.title = 'Click to open the actions menu (Ctrl+M)'; + dom.menu = menu; + tdMenu.appendChild(dom.menu); + } + + // a cell for the contents (showing text 'empty') + var tdAppend = document.createElement('td'); + var domText = document.createElement('div'); + domText.innerHTML = '(empty)'; + domText.className = 'jsoneditor-readonly'; + tdAppend.appendChild(domText); + dom.td = tdAppend; + dom.text = domText; + + this.updateDom(); + + return trAppend; + }; + + /** + * Update the HTML dom of the Node + */ + AppendNode.prototype.updateDom = function () { + var dom = this.dom; + var tdAppend = dom.td; + if (tdAppend) { + tdAppend.style.paddingLeft = (this.getLevel() * 24 + 26) + 'px'; + // TODO: not so nice hard coded offset + } + + var domText = dom.text; + if (domText) { + domText.innerHTML = '(empty ' + this.parent.type + ')'; + } + + // attach or detach the contents of the append node: + // hide when the parent has childs, show when the parent has no childs + var trAppend = dom.tr; + if (!this.isVisible()) { + if (dom.tr.firstChild) { + if (dom.tdDrag) { + trAppend.removeChild(dom.tdDrag); + } + if (dom.tdMenu) { + trAppend.removeChild(dom.tdMenu); + } + trAppend.removeChild(tdAppend); + } + } + else { + if (!dom.tr.firstChild) { + if (dom.tdDrag) { + trAppend.appendChild(dom.tdDrag); + } + if (dom.tdMenu) { + trAppend.appendChild(dom.tdMenu); + } + trAppend.appendChild(tdAppend); + } + } + }; + + /** + * Check whether the AppendNode is currently visible. + * the AppendNode is visible when its parent has no childs (i.e. is empty). + * @return {boolean} isVisible + */ + AppendNode.prototype.isVisible = function () { + return (this.parent.childs.length == 0); + }; + + /** + * Show a contextmenu for this node + * @param {HTMLElement} anchor The element to attach the menu to. + * @param {function} [onClose] Callback method called when the context menu + * is being closed. + */ + AppendNode.prototype.showContextMenu = function (anchor, onClose) { + var node = this; + var titles = Node.TYPE_TITLES; + var items = [ + // create append button + { + 'text': 'Append', + 'title': 'Append a new field with type \'auto\' (Ctrl+Shift+Ins)', + 'submenuTitle': 'Select the type of the field to be appended', + 'className': 'jsoneditor-insert', + 'click': function () { + node._onAppend('', '', 'auto'); + }, + 'submenu': [ + { + 'text': 'Auto', + 'className': 'jsoneditor-type-auto', + 'title': titles.auto, + 'click': function () { + node._onAppend('', '', 'auto'); + } + }, + { + 'text': 'Array', + 'className': 'jsoneditor-type-array', + 'title': titles.array, + 'click': function () { + node._onAppend('', []); + } + }, + { + 'text': 'Object', + 'className': 'jsoneditor-type-object', + 'title': titles.object, + 'click': function () { + node._onAppend('', {}); + } + }, + { + 'text': 'String', + 'className': 'jsoneditor-type-string', + 'title': titles.string, + 'click': function () { + node._onAppend('', '', 'string'); + } + } + ] + } + ]; + + var menu = new ContextMenu(items, {close: onClose}); + menu.show(anchor, this.editor.content); + }; + + /** + * Handle an event. The event is catched centrally by the editor + * @param {Event} event + */ + AppendNode.prototype.onEvent = function (event) { + var type = event.type; + var target = event.target || event.srcElement; + var dom = this.dom; + + // highlight the append nodes parent + var menu = dom.menu; + if (target == menu) { + if (type == 'mouseover') { + this.editor.highlighter.highlight(this.parent); + } + else if (type == 'mouseout') { + this.editor.highlighter.unhighlight(); + } + } + + // context menu events + if (type == 'click' && target == dom.menu) { + var highlighter = this.editor.highlighter; + highlighter.highlight(this.parent); + highlighter.lock(); + util.addClassName(dom.menu, 'jsoneditor-selected'); + this.showContextMenu(dom.menu, function () { + util.removeClassName(dom.menu, 'jsoneditor-selected'); + highlighter.unlock(); + highlighter.unhighlight(); + }); + } + + if (type == 'keydown') { + this.onKeyDown(event); + } + }; + + return AppendNode; + } + + module.exports = appendNodeFactory; + + +/***/ }, +/* 61 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var ContextMenu = __webpack_require__(57); + + /** + * Create a select box to be used in the editor menu's, which allows to switch mode + * @param {HTMLElement} container + * @param {String[]} modes Available modes: 'code', 'form', 'text', 'tree', 'view' + * @param {String} current Available modes: 'code', 'form', 'text', 'tree', 'view' + * @param {function(mode: string)} onSwitch Callback invoked on switch + * @constructor + */ + function ModeSwitcher(container, modes, current, onSwitch) { + // available modes + var availableModes = { + code: { + 'text': 'Code', + 'title': 'Switch to code highlighter', + 'click': function () { + onSwitch('code') + } + }, + form: { + 'text': 'Form', + 'title': 'Switch to form editor', + 'click': function () { + onSwitch('form'); + } + }, + text: { + 'text': 'Text', + 'title': 'Switch to plain text editor', + 'click': function () { + onSwitch('text'); + } + }, + tree: { + 'text': 'Tree', + 'title': 'Switch to tree editor', + 'click': function () { + onSwitch('tree'); + } + }, + view: { + 'text': 'View', + 'title': 'Switch to tree view', + 'click': function () { + onSwitch('view'); + } + } + }; + + // list the selected modes + var items = []; + for (var i = 0; i < modes.length; i++) { + var mode = modes[i]; + var item = availableModes[mode]; + if (!item) { + throw new Error('Unknown mode "' + mode + '"'); + } + + item.className = 'jsoneditor-type-modes' + ((current == mode) ? ' jsoneditor-selected' : ''); + items.push(item); + } + + // retrieve the title of current mode + var currentMode = availableModes[current]; + if (!currentMode) { + throw new Error('Unknown mode "' + current + '"'); + } + var currentTitle = currentMode.text; + + // create the html element + var box = document.createElement('button'); + box.type = 'button'; + box.className = 'jsoneditor-modes jsoneditor-separator'; + box.innerHTML = currentTitle + ' ▾'; + box.title = 'Switch editor mode'; + box.onclick = function () { + var menu = new ContextMenu(items); + menu.show(box); + }; + + var frame = document.createElement('div'); + frame.className = 'jsoneditor-modes'; + frame.style.position = 'relative'; + frame.appendChild(box); + + container.appendChild(frame); + + this.dom = { + container: container, + box: box, + frame: frame + }; + } + + /** + * Set focus to switcher + */ + ModeSwitcher.prototype.focus = function () { + this.dom.box.focus(); + }; + + /** + * Destroy the ModeSwitcher, remove from DOM + */ + ModeSwitcher.prototype.destroy = function () { + if (this.dom && this.dom.frame && this.dom.frame.parentNode) { + this.dom.frame.parentNode.removeChild(this.dom.frame); + } + this.dom = null; + }; + + module.exports = ModeSwitcher; + + +/***/ }, +/* 62 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var ace; + try { + ace = __webpack_require__(63); + } + catch (err) { + // failed to load ace, no problem, we will fall back to plain text + } + + var ModeSwitcher = __webpack_require__(61); + var util = __webpack_require__(54); + + // create a mixin with the functions for text mode + var textmode = {}; + + var MAX_ERRORS = 3; // maximum number of displayed errors at the bottom + + /** + * Create a text editor + * @param {Element} container + * @param {Object} [options] Object with options. available options: + * {String} mode Available values: + * "text" (default) + * or "code". + * {Number} indentation Number of indentation + * spaces. 2 by default. + * {function} onChange Callback method + * triggered on change + * {function} onModeChange Callback method + * triggered after setMode + * {Object} ace A custom instance of + * Ace editor. + * {boolean} escapeUnicode If true, unicode + * characters are escaped. + * false by default. + * @private + */ + textmode.create = function (container, options) { + // read options + options = options || {}; + this.options = options; + + // indentation + if (options.indentation) { + this.indentation = Number(options.indentation); + } + else { + this.indentation = 2; // number of spaces + } + + // grab ace from options if provided + var _ace = options.ace ? options.ace : ace; + + // determine mode + this.mode = (options.mode == 'code') ? 'code' : 'text'; + if (this.mode == 'code') { + // verify whether Ace editor is available and supported + if (typeof _ace === 'undefined') { + this.mode = 'text'; + console.warn('Failed to load Ace editor, falling back to plain text mode. Please use a JSONEditor bundle including Ace, or pass Ace as via the configuration option `ace`.'); + } + } + + // determine theme + this.theme = options.theme || 'ace/theme/jsoneditor'; + + var me = this; + this.container = container; + this.dom = {}; + this.aceEditor = undefined; // ace code editor + this.textarea = undefined; // plain text editor (fallback when Ace is not available) + this.validateSchema = null; + + // create a debounced validate function + this._debouncedValidate = util.debounce(this.validate.bind(this), this.DEBOUNCE_INTERVAL); + + this.width = container.clientWidth; + this.height = container.clientHeight; + + this.frame = document.createElement('div'); + this.frame.className = 'jsoneditor jsoneditor-mode-' + this.options.mode; + this.frame.onclick = function (event) { + // prevent default submit action when the editor is located inside a form + event.preventDefault(); + }; + this.frame.onkeydown = function (event) { + me._onKeyDown(event); + }; + + // create menu + this.menu = document.createElement('div'); + this.menu.className = 'jsoneditor-menu'; + this.frame.appendChild(this.menu); + + // create format button + var buttonFormat = document.createElement('button'); + buttonFormat.type = 'button'; + buttonFormat.className = 'jsoneditor-format'; + buttonFormat.title = 'Format JSON data, with proper indentation and line feeds (Ctrl+\\)'; + this.menu.appendChild(buttonFormat); + buttonFormat.onclick = function () { + try { + me.format(); + me._onChange(); + } + catch (err) { + me._onError(err); + } + }; + + // create compact button + var buttonCompact = document.createElement('button'); + buttonCompact.type = 'button'; + buttonCompact.className = 'jsoneditor-compact'; + buttonCompact.title = 'Compact JSON data, remove all whitespaces (Ctrl+Shift+\\)'; + this.menu.appendChild(buttonCompact); + buttonCompact.onclick = function () { + try { + me.compact(); + me._onChange(); + } + catch (err) { + me._onError(err); + } + }; + + // create mode box + if (this.options && this.options.modes && this.options.modes.length) { + this.modeSwitcher = new ModeSwitcher(this.menu, this.options.modes, this.options.mode, function onSwitch(mode) { + // switch mode and restore focus + me.setMode(mode); + me.modeSwitcher.focus(); + }); + } + + this.content = document.createElement('div'); + this.content.className = 'jsoneditor-outer'; + this.frame.appendChild(this.content); + + this.container.appendChild(this.frame); + + if (this.mode == 'code') { + this.editorDom = document.createElement('div'); + this.editorDom.style.height = '100%'; // TODO: move to css + this.editorDom.style.width = '100%'; // TODO: move to css + this.content.appendChild(this.editorDom); + + var aceEditor = _ace.edit(this.editorDom); + aceEditor.$blockScrolling = Infinity; + aceEditor.setTheme(this.theme); + aceEditor.setShowPrintMargin(false); + aceEditor.setFontSize(13); + aceEditor.getSession().setMode('ace/mode/json'); + aceEditor.getSession().setTabSize(this.indentation); + aceEditor.getSession().setUseSoftTabs(true); + aceEditor.getSession().setUseWrapMode(true); + aceEditor.commands.bindKey('Ctrl-L', null); // disable Ctrl+L (is used by the browser to select the address bar) + aceEditor.commands.bindKey('Command-L', null); // disable Ctrl+L (is used by the browser to select the address bar) + this.aceEditor = aceEditor; + + // TODO: deprecated since v5.0.0. Cleanup backward compatibility some day + if (!this.hasOwnProperty('editor')) { + Object.defineProperty(this, 'editor', { + get: function () { + console.warn('Property "editor" has been renamed to "aceEditor".'); + return me.aceEditor; + }, + set: function (aceEditor) { + console.warn('Property "editor" has been renamed to "aceEditor".'); + me.aceEditor = aceEditor; + } + }); + } + + var poweredBy = document.createElement('a'); + poweredBy.appendChild(document.createTextNode('powered by ace')); + poweredBy.href = 'http://ace.ajax.org'; + poweredBy.target = '_blank'; + poweredBy.className = 'jsoneditor-poweredBy'; + poweredBy.onclick = function () { + // TODO: this anchor falls below the margin of the content, + // therefore the normal a.href does not work. We use a click event + // for now, but this should be fixed. + window.open(poweredBy.href, poweredBy.target); + }; + this.menu.appendChild(poweredBy); + + // register onchange event + aceEditor.on('change', this._onChange.bind(this)); + } + else { + // load a plain text textarea + var textarea = document.createElement('textarea'); + textarea.className = 'jsoneditor-text'; + textarea.spellcheck = false; + this.content.appendChild(textarea); + this.textarea = textarea; + + // register onchange event + if (this.textarea.oninput === null) { + this.textarea.oninput = this._onChange.bind(this); + } + else { + // oninput is undefined. For IE8- + this.textarea.onchange = this._onChange.bind(this); + } + } + + this.setSchema(this.options.schema); + }; + + /** + * Handle a change: + * - Validate JSON schema + * - Send a callback to the onChange listener if provided + * @private + */ + textmode._onChange = function () { + // validate JSON schema (if configured) + this._debouncedValidate(); + + // trigger the onChange callback + if (this.options.onChange) { + try { + this.options.onChange(); + } + catch (err) { + console.error('Error in onChange callback: ', err); + } + } + }; + + /** + * Event handler for keydown. Handles shortcut keys + * @param {Event} event + * @private + */ + textmode._onKeyDown = function (event) { + var keynum = event.which || event.keyCode; + var handled = false; + + if (keynum == 220 && event.ctrlKey) { + if (event.shiftKey) { // Ctrl+Shift+\ + this.compact(); + this._onChange(); + } + else { // Ctrl+\ + this.format(); + this._onChange(); + } + handled = true; + } + + if (handled) { + event.preventDefault(); + event.stopPropagation(); + } + }; + + /** + * Destroy the editor. Clean up DOM, event listeners, and web workers. + */ + textmode.destroy = function () { + // remove old ace editor + if (this.aceEditor) { + this.aceEditor.destroy(); + this.aceEditor = null; + } + + if (this.frame && this.container && this.frame.parentNode == this.container) { + this.container.removeChild(this.frame); + } + + if (this.modeSwitcher) { + this.modeSwitcher.destroy(); + this.modeSwitcher = null; + } + + this.textarea = null; + + this._debouncedValidate = null; + }; + + /** + * Compact the code in the formatter + */ + textmode.compact = function () { + var json = this.get(); + var text = JSON.stringify(json); + this.setText(text); + }; + + /** + * Format the code in the formatter + */ + textmode.format = function () { + var json = this.get(); + var text = JSON.stringify(json, null, this.indentation); + this.setText(text); + }; + + /** + * Set focus to the formatter + */ + textmode.focus = function () { + if (this.textarea) { + this.textarea.focus(); + } + if (this.aceEditor) { + this.aceEditor.focus(); + } + }; + + /** + * Resize the formatter + */ + textmode.resize = function () { + if (this.aceEditor) { + var force = false; + this.aceEditor.resize(force); + } + }; + + /** + * Set json data in the formatter + * @param {Object} json + */ + textmode.set = function(json) { + this.setText(JSON.stringify(json, null, this.indentation)); + }; + + /** + * Get json data from the formatter + * @return {Object} json + */ + textmode.get = function() { + var text = this.getText(); + var json; + + try { + json = util.parse(text); // this can throw an error + } + catch (err) { + // try to sanitize json, replace JavaScript notation with JSON notation + text = util.sanitize(text); + + // try to parse again + json = util.parse(text); // this can throw an error + } + + return json; + }; + + /** + * Get the text contents of the editor + * @return {String} jsonText + */ + textmode.getText = function() { + if (this.textarea) { + return this.textarea.value; + } + if (this.aceEditor) { + return this.aceEditor.getValue(); + } + return ''; + }; + + /** + * Set the text contents of the editor + * @param {String} jsonText + */ + textmode.setText = function(jsonText) { + var text; + + if (this.options.escapeUnicode === true) { + text = util.escapeUnicodeChars(jsonText); + } + else { + text = jsonText; + } + + if (this.textarea) { + this.textarea.value = text; + } + if (this.aceEditor) { + // prevent emitting onChange events while setting new text + var originalOnChange = this.options.onChange; + this.options.onChange = null; + + this.aceEditor.setValue(text, -1); + + this.options.onChange = originalOnChange; + } + + // validate JSON schema + this.validate(); + }; + + /** + * Validate current JSON object against the configured JSON schema + * Throws an exception when no JSON schema is configured + */ + textmode.validate = function () { + // clear all current errors + if (this.dom.validationErrors) { + this.dom.validationErrors.parentNode.removeChild(this.dom.validationErrors); + this.dom.validationErrors = null; + + this.content.style.marginBottom = ''; + this.content.style.paddingBottom = ''; + } + + var doValidate = false; + var errors = []; + var json; + try { + json = this.get(); // this can fail when there is no valid json + doValidate = true; + } + catch (err) { + // no valid JSON, don't validate + } + + // only validate the JSON when parsing the JSON succeeded + if (doValidate && this.validateSchema) { + var valid = this.validateSchema(json); + if (!valid) { + errors = this.validateSchema.errors.map(function (error) { + return util.improveSchemaError(error); + }); + } + } + + if (errors.length > 0) { + // limit the number of displayed errors + var limit = errors.length > MAX_ERRORS; + if (limit) { + errors = errors.slice(0, MAX_ERRORS); + var hidden = this.validateSchema.errors.length - MAX_ERRORS; + errors.push('(' + hidden + ' more errors...)') + } + + var validationErrors = document.createElement('div'); + validationErrors.innerHTML = '' + + '' + + errors.map(function (error) { + var message; + if (typeof error === 'string') { + message = ''; + } + else { + message = '' + + ''; + } + + return '' + message + '' + }).join('') + + '' + + '
' + error + '
' + error.dataPath + '' + error.message + '
'; + + this.dom.validationErrors = validationErrors; + this.frame.appendChild(validationErrors); + + var height = validationErrors.clientHeight; + this.content.style.marginBottom = (-height) + 'px'; + this.content.style.paddingBottom = height + 'px'; + } + + // update the height of the ace editor + if (this.aceEditor) { + var force = false; + this.aceEditor.resize(force); + } + }; + + // define modes + module.exports = [ + { + mode: 'text', + mixin: textmode, + data: 'text', + load: textmode.format + }, + { + mode: 'code', + mixin: textmode, + data: 'text', + load: textmode.format + } + ]; + + +/***/ }, +/* 63 */ +/***/ function(module, exports, __webpack_require__) { + + // load brace + var ace = __webpack_require__(64); + + // load required ace modules + __webpack_require__(67); + __webpack_require__(69); + __webpack_require__(70); + + module.exports = ace; + + +/***/ }, +/* 64 */ +/***/ function(module, exports, __webpack_require__) { + + /* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + + /** + * Define a module along with a payload + * @param module a name for the payload + * @param payload a function to call with (acequire, exports, module) params + */ + + (function() { + + var ACE_NAMESPACE = "ace"; + + var global = (function() { return this; })(); + if (!global && typeof window != "undefined") global = window; // strict mode + + + if (!ACE_NAMESPACE && typeof acequirejs !== "undefined") + return; + + + var define = function(module, deps, payload) { + if (typeof module !== "string") { + if (define.original) + define.original.apply(this, arguments); + else { + console.error("dropping module because define wasn\'t a string."); + console.trace(); + } + return; + } + if (arguments.length == 2) + payload = deps; + if (!define.modules[module]) { + define.payloads[module] = payload; + define.modules[module] = null; + } + }; + + define.modules = {}; + define.payloads = {}; + + /** + * Get at functionality define()ed using the function above + */ + var _acequire = function(parentId, module, callback) { + if (typeof module === "string") { + var payload = lookup(parentId, module); + if (payload != undefined) { + callback && callback(); + return payload; + } + } else if (Object.prototype.toString.call(module) === "[object Array]") { + var params = []; + for (var i = 0, l = module.length; i < l; ++i) { + var dep = lookup(parentId, module[i]); + if (dep == undefined && acequire.original) + return; + params.push(dep); + } + return callback && callback.apply(null, params) || true; + } + }; + + var acequire = function(module, callback) { + var packagedModule = _acequire("", module, callback); + if (packagedModule == undefined && acequire.original) + return acequire.original.apply(this, arguments); + return packagedModule; + }; + + var normalizeModule = function(parentId, moduleName) { + // normalize plugin acequires + if (moduleName.indexOf("!") !== -1) { + var chunks = moduleName.split("!"); + return normalizeModule(parentId, chunks[0]) + "!" + normalizeModule(parentId, chunks[1]); + } + // normalize relative acequires + if (moduleName.charAt(0) == ".") { + var base = parentId.split("/").slice(0, -1).join("/"); + moduleName = base + "/" + moduleName; + + while(moduleName.indexOf(".") !== -1 && previous != moduleName) { + var previous = moduleName; + moduleName = moduleName.replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, ""); + } + } + return moduleName; + }; + + /** + * Internal function to lookup moduleNames and resolve them by calling the + * definition function if needed. + */ + var lookup = function(parentId, moduleName) { + moduleName = normalizeModule(parentId, moduleName); + + var module = define.modules[moduleName]; + if (!module) { + module = define.payloads[moduleName]; + if (typeof module === 'function') { + var exports = {}; + var mod = { + id: moduleName, + uri: '', + exports: exports, + packaged: true + }; + + var req = function(module, callback) { + return _acequire(moduleName, module, callback); + }; + + var returnValue = module(req, exports, mod); + exports = returnValue || mod.exports; + define.modules[moduleName] = exports; + delete define.payloads[moduleName]; + } + module = define.modules[moduleName] = exports || module; + } + return module; + }; + + function exportAce(ns) { + var root = global; + if (ns) { + if (!global[ns]) + global[ns] = {}; + root = global[ns]; + } + + if (!root.define || !root.define.packaged) { + define.original = root.define; + root.define = define; + root.define.packaged = true; + } + + if (!root.acequire || !root.acequire.packaged) { + acequire.original = root.acequire; + root.acequire = acequire; + root.acequire.packaged = true; + } + } + + exportAce(ACE_NAMESPACE); + + })(); + + ace.define("ace/lib/regexp",["require","exports","module"], function(acequire, exports, module) { + "use strict"; + + var real = { + exec: RegExp.prototype.exec, + test: RegExp.prototype.test, + match: String.prototype.match, + replace: String.prototype.replace, + split: String.prototype.split + }, + compliantExecNpcg = real.exec.call(/()??/, "")[1] === undefined, // check `exec` handling of nonparticipating capturing groups + compliantLastIndexIncrement = function () { + var x = /^/g; + real.test.call(x, ""); + return !x.lastIndex; + }(); + + if (compliantLastIndexIncrement && compliantExecNpcg) + return; + RegExp.prototype.exec = function (str) { + var match = real.exec.apply(this, arguments), + name, r2; + if ( typeof(str) == 'string' && match) { + if (!compliantExecNpcg && match.length > 1 && indexOf(match, "") > -1) { + r2 = RegExp(this.source, real.replace.call(getNativeFlags(this), "g", "")); + real.replace.call(str.slice(match.index), r2, function () { + for (var i = 1; i < arguments.length - 2; i++) { + if (arguments[i] === undefined) + match[i] = undefined; + } + }); + } + if (this._xregexp && this._xregexp.captureNames) { + for (var i = 1; i < match.length; i++) { + name = this._xregexp.captureNames[i - 1]; + if (name) + match[name] = match[i]; + } + } + if (!compliantLastIndexIncrement && this.global && !match[0].length && (this.lastIndex > match.index)) + this.lastIndex--; + } + return match; + }; + if (!compliantLastIndexIncrement) { + RegExp.prototype.test = function (str) { + var match = real.exec.call(this, str); + if (match && this.global && !match[0].length && (this.lastIndex > match.index)) + this.lastIndex--; + return !!match; + }; + } + + function getNativeFlags (regex) { + return (regex.global ? "g" : "") + + (regex.ignoreCase ? "i" : "") + + (regex.multiline ? "m" : "") + + (regex.extended ? "x" : "") + // Proposed for ES4; included in AS3 + (regex.sticky ? "y" : ""); + } + + function indexOf (array, item, from) { + if (Array.prototype.indexOf) // Use the native array method if available + return array.indexOf(item, from); + for (var i = from || 0; i < array.length; i++) { + if (array[i] === item) + return i; + } + return -1; + } + + }); + + ace.define("ace/lib/es5-shim",["require","exports","module"], function(acequire, exports, module) { + + function Empty() {} + + if (!Function.prototype.bind) { + Function.prototype.bind = function bind(that) { // .length is 1 + var target = this; + if (typeof target != "function") { + throw new TypeError("Function.prototype.bind called on incompatible " + target); + } + var args = slice.call(arguments, 1); // for normal call + var bound = function () { + + if (this instanceof bound) { + + var result = target.apply( + this, + args.concat(slice.call(arguments)) + ); + if (Object(result) === result) { + return result; + } + return this; + + } else { + return target.apply( + that, + args.concat(slice.call(arguments)) + ); + + } + + }; + if(target.prototype) { + Empty.prototype = target.prototype; + bound.prototype = new Empty(); + Empty.prototype = null; + } + return bound; + }; + } + var call = Function.prototype.call; + var prototypeOfArray = Array.prototype; + var prototypeOfObject = Object.prototype; + var slice = prototypeOfArray.slice; + var _toString = call.bind(prototypeOfObject.toString); + var owns = call.bind(prototypeOfObject.hasOwnProperty); + var defineGetter; + var defineSetter; + var lookupGetter; + var lookupSetter; + var supportsAccessors; + if ((supportsAccessors = owns(prototypeOfObject, "__defineGetter__"))) { + defineGetter = call.bind(prototypeOfObject.__defineGetter__); + defineSetter = call.bind(prototypeOfObject.__defineSetter__); + lookupGetter = call.bind(prototypeOfObject.__lookupGetter__); + lookupSetter = call.bind(prototypeOfObject.__lookupSetter__); + } + if ([1,2].splice(0).length != 2) { + if(function() { // test IE < 9 to splice bug - see issue #138 + function makeArray(l) { + var a = new Array(l+2); + a[0] = a[1] = 0; + return a; + } + var array = [], lengthBefore; + + array.splice.apply(array, makeArray(20)); + array.splice.apply(array, makeArray(26)); + + lengthBefore = array.length; //46 + array.splice(5, 0, "XXX"); // add one element + + lengthBefore + 1 == array.length + + if (lengthBefore + 1 == array.length) { + return true;// has right splice implementation without bugs + } + }()) {//IE 6/7 + var array_splice = Array.prototype.splice; + Array.prototype.splice = function(start, deleteCount) { + if (!arguments.length) { + return []; + } else { + return array_splice.apply(this, [ + start === void 0 ? 0 : start, + deleteCount === void 0 ? (this.length - start) : deleteCount + ].concat(slice.call(arguments, 2))) + } + }; + } else {//IE8 + Array.prototype.splice = function(pos, removeCount){ + var length = this.length; + if (pos > 0) { + if (pos > length) + pos = length; + } else if (pos == void 0) { + pos = 0; + } else if (pos < 0) { + pos = Math.max(length + pos, 0); + } + + if (!(pos+removeCount < length)) + removeCount = length - pos; + + var removed = this.slice(pos, pos+removeCount); + var insert = slice.call(arguments, 2); + var add = insert.length; + if (pos === length) { + if (add) { + this.push.apply(this, insert); + } + } else { + var remove = Math.min(removeCount, length - pos); + var tailOldPos = pos + remove; + var tailNewPos = tailOldPos + add - remove; + var tailCount = length - tailOldPos; + var lengthAfterRemove = length - remove; + + if (tailNewPos < tailOldPos) { // case A + for (var i = 0; i < tailCount; ++i) { + this[tailNewPos+i] = this[tailOldPos+i]; + } + } else if (tailNewPos > tailOldPos) { // case B + for (i = tailCount; i--; ) { + this[tailNewPos+i] = this[tailOldPos+i]; + } + } // else, add == remove (nothing to do) + + if (add && pos === lengthAfterRemove) { + this.length = lengthAfterRemove; // truncate array + this.push.apply(this, insert); + } else { + this.length = lengthAfterRemove + add; // reserves space + for (i = 0; i < add; ++i) { + this[pos+i] = insert[i]; + } + } + } + return removed; + }; + } + } + if (!Array.isArray) { + Array.isArray = function isArray(obj) { + return _toString(obj) == "[object Array]"; + }; + } + var boxedString = Object("a"), + splitString = boxedString[0] != "a" || !(0 in boxedString); + + if (!Array.prototype.forEach) { + Array.prototype.forEach = function forEach(fun /*, thisp*/) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + thisp = arguments[1], + i = -1, + length = self.length >>> 0; + if (_toString(fun) != "[object Function]") { + throw new TypeError(); // TODO message + } + + while (++i < length) { + if (i in self) { + fun.call(thisp, self[i], i, object); + } + } + }; + } + if (!Array.prototype.map) { + Array.prototype.map = function map(fun /*, thisp*/) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0, + result = Array(length), + thisp = arguments[1]; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + + for (var i = 0; i < length; i++) { + if (i in self) + result[i] = fun.call(thisp, self[i], i, object); + } + return result; + }; + } + if (!Array.prototype.filter) { + Array.prototype.filter = function filter(fun /*, thisp */) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0, + result = [], + value, + thisp = arguments[1]; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + + for (var i = 0; i < length; i++) { + if (i in self) { + value = self[i]; + if (fun.call(thisp, value, i, object)) { + result.push(value); + } + } + } + return result; + }; + } + if (!Array.prototype.every) { + Array.prototype.every = function every(fun /*, thisp */) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0, + thisp = arguments[1]; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + + for (var i = 0; i < length; i++) { + if (i in self && !fun.call(thisp, self[i], i, object)) { + return false; + } + } + return true; + }; + } + if (!Array.prototype.some) { + Array.prototype.some = function some(fun /*, thisp */) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0, + thisp = arguments[1]; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + + for (var i = 0; i < length; i++) { + if (i in self && fun.call(thisp, self[i], i, object)) { + return true; + } + } + return false; + }; + } + if (!Array.prototype.reduce) { + Array.prototype.reduce = function reduce(fun /*, initial*/) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + if (!length && arguments.length == 1) { + throw new TypeError("reduce of empty array with no initial value"); + } + + var i = 0; + var result; + if (arguments.length >= 2) { + result = arguments[1]; + } else { + do { + if (i in self) { + result = self[i++]; + break; + } + if (++i >= length) { + throw new TypeError("reduce of empty array with no initial value"); + } + } while (true); + } + + for (; i < length; i++) { + if (i in self) { + result = fun.call(void 0, result, self[i], i, object); + } + } + + return result; + }; + } + if (!Array.prototype.reduceRight) { + Array.prototype.reduceRight = function reduceRight(fun /*, initial*/) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + if (!length && arguments.length == 1) { + throw new TypeError("reduceRight of empty array with no initial value"); + } + + var result, i = length - 1; + if (arguments.length >= 2) { + result = arguments[1]; + } else { + do { + if (i in self) { + result = self[i--]; + break; + } + if (--i < 0) { + throw new TypeError("reduceRight of empty array with no initial value"); + } + } while (true); + } + + do { + if (i in this) { + result = fun.call(void 0, result, self[i], i, object); + } + } while (i--); + + return result; + }; + } + if (!Array.prototype.indexOf || ([0, 1].indexOf(1, 2) != -1)) { + Array.prototype.indexOf = function indexOf(sought /*, fromIndex */ ) { + var self = splitString && _toString(this) == "[object String]" ? + this.split("") : + toObject(this), + length = self.length >>> 0; + + if (!length) { + return -1; + } + + var i = 0; + if (arguments.length > 1) { + i = toInteger(arguments[1]); + } + i = i >= 0 ? i : Math.max(0, length + i); + for (; i < length; i++) { + if (i in self && self[i] === sought) { + return i; + } + } + return -1; + }; + } + if (!Array.prototype.lastIndexOf || ([0, 1].lastIndexOf(0, -3) != -1)) { + Array.prototype.lastIndexOf = function lastIndexOf(sought /*, fromIndex */) { + var self = splitString && _toString(this) == "[object String]" ? + this.split("") : + toObject(this), + length = self.length >>> 0; + + if (!length) { + return -1; + } + var i = length - 1; + if (arguments.length > 1) { + i = Math.min(i, toInteger(arguments[1])); + } + i = i >= 0 ? i : length - Math.abs(i); + for (; i >= 0; i--) { + if (i in self && sought === self[i]) { + return i; + } + } + return -1; + }; + } + if (!Object.getPrototypeOf) { + Object.getPrototypeOf = function getPrototypeOf(object) { + return object.__proto__ || ( + object.constructor ? + object.constructor.prototype : + prototypeOfObject + ); + }; + } + if (!Object.getOwnPropertyDescriptor) { + var ERR_NON_OBJECT = "Object.getOwnPropertyDescriptor called on a " + + "non-object: "; + Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) { + if ((typeof object != "object" && typeof object != "function") || object === null) + throw new TypeError(ERR_NON_OBJECT + object); + if (!owns(object, property)) + return; + + var descriptor, getter, setter; + descriptor = { enumerable: true, configurable: true }; + if (supportsAccessors) { + var prototype = object.__proto__; + object.__proto__ = prototypeOfObject; + + var getter = lookupGetter(object, property); + var setter = lookupSetter(object, property); + object.__proto__ = prototype; + + if (getter || setter) { + if (getter) descriptor.get = getter; + if (setter) descriptor.set = setter; + return descriptor; + } + } + descriptor.value = object[property]; + return descriptor; + }; + } + if (!Object.getOwnPropertyNames) { + Object.getOwnPropertyNames = function getOwnPropertyNames(object) { + return Object.keys(object); + }; + } + if (!Object.create) { + var createEmpty; + if (Object.prototype.__proto__ === null) { + createEmpty = function () { + return { "__proto__": null }; + }; + } else { + createEmpty = function () { + var empty = {}; + for (var i in empty) + empty[i] = null; + empty.constructor = + empty.hasOwnProperty = + empty.propertyIsEnumerable = + empty.isPrototypeOf = + empty.toLocaleString = + empty.toString = + empty.valueOf = + empty.__proto__ = null; + return empty; + } + } + + Object.create = function create(prototype, properties) { + var object; + if (prototype === null) { + object = createEmpty(); + } else { + if (typeof prototype != "object") + throw new TypeError("typeof prototype["+(typeof prototype)+"] != 'object'"); + var Type = function () {}; + Type.prototype = prototype; + object = new Type(); + object.__proto__ = prototype; + } + if (properties !== void 0) + Object.defineProperties(object, properties); + return object; + }; + } + + function doesDefinePropertyWork(object) { + try { + Object.defineProperty(object, "sentinel", {}); + return "sentinel" in object; + } catch (exception) { + } + } + if (Object.defineProperty) { + var definePropertyWorksOnObject = doesDefinePropertyWork({}); + var definePropertyWorksOnDom = typeof document == "undefined" || + doesDefinePropertyWork(document.createElement("div")); + if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) { + var definePropertyFallback = Object.defineProperty; + } + } + + if (!Object.defineProperty || definePropertyFallback) { + var ERR_NON_OBJECT_DESCRIPTOR = "Property description must be an object: "; + var ERR_NON_OBJECT_TARGET = "Object.defineProperty called on non-object: " + var ERR_ACCESSORS_NOT_SUPPORTED = "getters & setters can not be defined " + + "on this javascript engine"; + + Object.defineProperty = function defineProperty(object, property, descriptor) { + if ((typeof object != "object" && typeof object != "function") || object === null) + throw new TypeError(ERR_NON_OBJECT_TARGET + object); + if ((typeof descriptor != "object" && typeof descriptor != "function") || descriptor === null) + throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor); + if (definePropertyFallback) { + try { + return definePropertyFallback.call(Object, object, property, descriptor); + } catch (exception) { + } + } + if (owns(descriptor, "value")) { + + if (supportsAccessors && (lookupGetter(object, property) || + lookupSetter(object, property))) + { + var prototype = object.__proto__; + object.__proto__ = prototypeOfObject; + delete object[property]; + object[property] = descriptor.value; + object.__proto__ = prototype; + } else { + object[property] = descriptor.value; + } + } else { + if (!supportsAccessors) + throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED); + if (owns(descriptor, "get")) + defineGetter(object, property, descriptor.get); + if (owns(descriptor, "set")) + defineSetter(object, property, descriptor.set); + } + + return object; + }; + } + if (!Object.defineProperties) { + Object.defineProperties = function defineProperties(object, properties) { + for (var property in properties) { + if (owns(properties, property)) + Object.defineProperty(object, property, properties[property]); + } + return object; + }; + } + if (!Object.seal) { + Object.seal = function seal(object) { + return object; + }; + } + if (!Object.freeze) { + Object.freeze = function freeze(object) { + return object; + }; + } + try { + Object.freeze(function () {}); + } catch (exception) { + Object.freeze = (function freeze(freezeObject) { + return function freeze(object) { + if (typeof object == "function") { + return object; + } else { + return freezeObject(object); + } + }; + })(Object.freeze); + } + if (!Object.preventExtensions) { + Object.preventExtensions = function preventExtensions(object) { + return object; + }; + } + if (!Object.isSealed) { + Object.isSealed = function isSealed(object) { + return false; + }; + } + if (!Object.isFrozen) { + Object.isFrozen = function isFrozen(object) { + return false; + }; + } + if (!Object.isExtensible) { + Object.isExtensible = function isExtensible(object) { + if (Object(object) === object) { + throw new TypeError(); // TODO message + } + var name = ''; + while (owns(object, name)) { + name += '?'; + } + object[name] = true; + var returnValue = owns(object, name); + delete object[name]; + return returnValue; + }; + } + if (!Object.keys) { + var hasDontEnumBug = true, + dontEnums = [ + "toString", + "toLocaleString", + "valueOf", + "hasOwnProperty", + "isPrototypeOf", + "propertyIsEnumerable", + "constructor" + ], + dontEnumsLength = dontEnums.length; + + for (var key in {"toString": null}) { + hasDontEnumBug = false; + } + + Object.keys = function keys(object) { + + if ( + (typeof object != "object" && typeof object != "function") || + object === null + ) { + throw new TypeError("Object.keys called on a non-object"); + } + + var keys = []; + for (var name in object) { + if (owns(object, name)) { + keys.push(name); + } + } + + if (hasDontEnumBug) { + for (var i = 0, ii = dontEnumsLength; i < ii; i++) { + var dontEnum = dontEnums[i]; + if (owns(object, dontEnum)) { + keys.push(dontEnum); + } + } + } + return keys; + }; + + } + if (!Date.now) { + Date.now = function now() { + return new Date().getTime(); + }; + } + var ws = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003" + + "\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028" + + "\u2029\uFEFF"; + if (!String.prototype.trim || ws.trim()) { + ws = "[" + ws + "]"; + var trimBeginRegexp = new RegExp("^" + ws + ws + "*"), + trimEndRegexp = new RegExp(ws + ws + "*$"); + String.prototype.trim = function trim() { + return String(this).replace(trimBeginRegexp, "").replace(trimEndRegexp, ""); + }; + } + + function toInteger(n) { + n = +n; + if (n !== n) { // isNaN + n = 0; + } else if (n !== 0 && n !== (1/0) && n !== -(1/0)) { + n = (n > 0 || -1) * Math.floor(Math.abs(n)); + } + return n; + } + + function isPrimitive(input) { + var type = typeof input; + return ( + input === null || + type === "undefined" || + type === "boolean" || + type === "number" || + type === "string" + ); + } + + function toPrimitive(input) { + var val, valueOf, toString; + if (isPrimitive(input)) { + return input; + } + valueOf = input.valueOf; + if (typeof valueOf === "function") { + val = valueOf.call(input); + if (isPrimitive(val)) { + return val; + } + } + toString = input.toString; + if (typeof toString === "function") { + val = toString.call(input); + if (isPrimitive(val)) { + return val; + } + } + throw new TypeError(); + } + var toObject = function (o) { + if (o == null) { // this matches both null and undefined + throw new TypeError("can't convert "+o+" to object"); + } + return Object(o); + }; + + }); + + ace.define("ace/lib/fixoldbrowsers",["require","exports","module","ace/lib/regexp","ace/lib/es5-shim"], function(acequire, exports, module) { + "use strict"; + + acequire("./regexp"); + acequire("./es5-shim"); + + }); + + ace.define("ace/lib/dom",["require","exports","module"], function(acequire, exports, module) { + "use strict"; + + var XHTML_NS = "http://www.w3.org/1999/xhtml"; + + exports.getDocumentHead = function(doc) { + if (!doc) + doc = document; + return doc.head || doc.getElementsByTagName("head")[0] || doc.documentElement; + }; + + exports.createElement = function(tag, ns) { + return document.createElementNS ? + document.createElementNS(ns || XHTML_NS, tag) : + document.createElement(tag); + }; + + exports.hasCssClass = function(el, name) { + var classes = (el.className || "").split(/\s+/g); + return classes.indexOf(name) !== -1; + }; + exports.addCssClass = function(el, name) { + if (!exports.hasCssClass(el, name)) { + el.className += " " + name; + } + }; + exports.removeCssClass = function(el, name) { + var classes = el.className.split(/\s+/g); + while (true) { + var index = classes.indexOf(name); + if (index == -1) { + break; + } + classes.splice(index, 1); + } + el.className = classes.join(" "); + }; + + exports.toggleCssClass = function(el, name) { + var classes = el.className.split(/\s+/g), add = true; + while (true) { + var index = classes.indexOf(name); + if (index == -1) { + break; + } + add = false; + classes.splice(index, 1); + } + if (add) + classes.push(name); + + el.className = classes.join(" "); + return add; + }; + exports.setCssClass = function(node, className, include) { + if (include) { + exports.addCssClass(node, className); + } else { + exports.removeCssClass(node, className); + } + }; + + exports.hasCssString = function(id, doc) { + var index = 0, sheets; + doc = doc || document; + + if (doc.createStyleSheet && (sheets = doc.styleSheets)) { + while (index < sheets.length) + if (sheets[index++].owningElement.id === id) return true; + } else if ((sheets = doc.getElementsByTagName("style"))) { + while (index < sheets.length) + if (sheets[index++].id === id) return true; + } + + return false; + }; + + exports.importCssString = function importCssString(cssText, id, doc) { + doc = doc || document; + if (id && exports.hasCssString(id, doc)) + return null; + + var style; + + if (id) + cssText += "\n/*# sourceURL=ace/css/" + id + " */"; + + if (doc.createStyleSheet) { + style = doc.createStyleSheet(); + style.cssText = cssText; + if (id) + style.owningElement.id = id; + } else { + style = exports.createElement("style"); + style.appendChild(doc.createTextNode(cssText)); + if (id) + style.id = id; + + exports.getDocumentHead(doc).appendChild(style); + } + }; + + exports.importCssStylsheet = function(uri, doc) { + if (doc.createStyleSheet) { + doc.createStyleSheet(uri); + } else { + var link = exports.createElement('link'); + link.rel = 'stylesheet'; + link.href = uri; + + exports.getDocumentHead(doc).appendChild(link); + } + }; + + exports.getInnerWidth = function(element) { + return ( + parseInt(exports.computedStyle(element, "paddingLeft"), 10) + + parseInt(exports.computedStyle(element, "paddingRight"), 10) + + element.clientWidth + ); + }; + + exports.getInnerHeight = function(element) { + return ( + parseInt(exports.computedStyle(element, "paddingTop"), 10) + + parseInt(exports.computedStyle(element, "paddingBottom"), 10) + + element.clientHeight + ); + }; + + exports.scrollbarWidth = function(document) { + var inner = exports.createElement("ace_inner"); + inner.style.width = "100%"; + inner.style.minWidth = "0px"; + inner.style.height = "200px"; + inner.style.display = "block"; + + var outer = exports.createElement("ace_outer"); + var style = outer.style; + + style.position = "absolute"; + style.left = "-10000px"; + style.overflow = "hidden"; + style.width = "200px"; + style.minWidth = "0px"; + style.height = "150px"; + style.display = "block"; + + outer.appendChild(inner); + + var body = document.documentElement; + body.appendChild(outer); + + var noScrollbar = inner.offsetWidth; + + style.overflow = "scroll"; + var withScrollbar = inner.offsetWidth; + + if (noScrollbar == withScrollbar) { + withScrollbar = outer.clientWidth; + } + + body.removeChild(outer); + + return noScrollbar-withScrollbar; + }; + + if (typeof document == "undefined") { + exports.importCssString = function() {}; + return; + } + + if (window.pageYOffset !== undefined) { + exports.getPageScrollTop = function() { + return window.pageYOffset; + }; + + exports.getPageScrollLeft = function() { + return window.pageXOffset; + }; + } + else { + exports.getPageScrollTop = function() { + return document.body.scrollTop; + }; + + exports.getPageScrollLeft = function() { + return document.body.scrollLeft; + }; + } + + if (window.getComputedStyle) + exports.computedStyle = function(element, style) { + if (style) + return (window.getComputedStyle(element, "") || {})[style] || ""; + return window.getComputedStyle(element, "") || {}; + }; + else + exports.computedStyle = function(element, style) { + if (style) + return element.currentStyle[style]; + return element.currentStyle; + }; + exports.setInnerHtml = function(el, innerHtml) { + var element = el.cloneNode(false);//document.createElement("div"); + element.innerHTML = innerHtml; + el.parentNode.replaceChild(element, el); + return element; + }; + + if ("textContent" in document.documentElement) { + exports.setInnerText = function(el, innerText) { + el.textContent = innerText; + }; + + exports.getInnerText = function(el) { + return el.textContent; + }; + } + else { + exports.setInnerText = function(el, innerText) { + el.innerText = innerText; + }; + + exports.getInnerText = function(el) { + return el.innerText; + }; + } + + exports.getParentWindow = function(document) { + return document.defaultView || document.parentWindow; + }; + + }); + + ace.define("ace/lib/oop",["require","exports","module"], function(acequire, exports, module) { + "use strict"; + + exports.inherits = function(ctor, superCtor) { + ctor.super_ = superCtor; + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; + + exports.mixin = function(obj, mixin) { + for (var key in mixin) { + obj[key] = mixin[key]; + } + return obj; + }; + + exports.implement = function(proto, mixin) { + exports.mixin(proto, mixin); + }; + + }); + + ace.define("ace/lib/keys",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/oop"], function(acequire, exports, module) { + "use strict"; + + acequire("./fixoldbrowsers"); + + var oop = acequire("./oop"); + var Keys = (function() { + var ret = { + MODIFIER_KEYS: { + 16: 'Shift', 17: 'Ctrl', 18: 'Alt', 224: 'Meta' + }, + + KEY_MODS: { + "ctrl": 1, "alt": 2, "option" : 2, "shift": 4, + "super": 8, "meta": 8, "command": 8, "cmd": 8 + }, + + FUNCTION_KEYS : { + 8 : "Backspace", + 9 : "Tab", + 13 : "Return", + 19 : "Pause", + 27 : "Esc", + 32 : "Space", + 33 : "PageUp", + 34 : "PageDown", + 35 : "End", + 36 : "Home", + 37 : "Left", + 38 : "Up", + 39 : "Right", + 40 : "Down", + 44 : "Print", + 45 : "Insert", + 46 : "Delete", + 96 : "Numpad0", + 97 : "Numpad1", + 98 : "Numpad2", + 99 : "Numpad3", + 100: "Numpad4", + 101: "Numpad5", + 102: "Numpad6", + 103: "Numpad7", + 104: "Numpad8", + 105: "Numpad9", + '-13': "NumpadEnter", + 112: "F1", + 113: "F2", + 114: "F3", + 115: "F4", + 116: "F5", + 117: "F6", + 118: "F7", + 119: "F8", + 120: "F9", + 121: "F10", + 122: "F11", + 123: "F12", + 144: "Numlock", + 145: "Scrolllock" + }, + + PRINTABLE_KEYS: { + 32: ' ', 48: '0', 49: '1', 50: '2', 51: '3', 52: '4', 53: '5', + 54: '6', 55: '7', 56: '8', 57: '9', 59: ';', 61: '=', 65: 'a', + 66: 'b', 67: 'c', 68: 'd', 69: 'e', 70: 'f', 71: 'g', 72: 'h', + 73: 'i', 74: 'j', 75: 'k', 76: 'l', 77: 'm', 78: 'n', 79: 'o', + 80: 'p', 81: 'q', 82: 'r', 83: 's', 84: 't', 85: 'u', 86: 'v', + 87: 'w', 88: 'x', 89: 'y', 90: 'z', 107: '+', 109: '-', 110: '.', + 186: ';', 187: '=', 188: ',', 189: '-', 190: '.', 191: '/', 192: '`', + 219: '[', 220: '\\',221: ']', 222: "'", 111: '/', 106: '*' + } + }; + var name, i; + for (i in ret.FUNCTION_KEYS) { + name = ret.FUNCTION_KEYS[i].toLowerCase(); + ret[name] = parseInt(i, 10); + } + for (i in ret.PRINTABLE_KEYS) { + name = ret.PRINTABLE_KEYS[i].toLowerCase(); + ret[name] = parseInt(i, 10); + } + oop.mixin(ret, ret.MODIFIER_KEYS); + oop.mixin(ret, ret.PRINTABLE_KEYS); + oop.mixin(ret, ret.FUNCTION_KEYS); + ret.enter = ret["return"]; + ret.escape = ret.esc; + ret.del = ret["delete"]; + ret[173] = '-'; + + (function() { + var mods = ["cmd", "ctrl", "alt", "shift"]; + for (var i = Math.pow(2, mods.length); i--;) { + ret.KEY_MODS[i] = mods.filter(function(x) { + return i & ret.KEY_MODS[x]; + }).join("-") + "-"; + } + })(); + + ret.KEY_MODS[0] = ""; + ret.KEY_MODS[-1] = "input-"; + + return ret; + })(); + oop.mixin(exports, Keys); + + exports.keyCodeToString = function(keyCode) { + var keyString = Keys[keyCode]; + if (typeof keyString != "string") + keyString = String.fromCharCode(keyCode); + return keyString.toLowerCase(); + }; + + }); + + ace.define("ace/lib/useragent",["require","exports","module"], function(acequire, exports, module) { + "use strict"; + exports.OS = { + LINUX: "LINUX", + MAC: "MAC", + WINDOWS: "WINDOWS" + }; + exports.getOS = function() { + if (exports.isMac) { + return exports.OS.MAC; + } else if (exports.isLinux) { + return exports.OS.LINUX; + } else { + return exports.OS.WINDOWS; + } + }; + if (typeof navigator != "object") + return; + + var os = (navigator.platform.match(/mac|win|linux/i) || ["other"])[0].toLowerCase(); + var ua = navigator.userAgent; + exports.isWin = (os == "win"); + exports.isMac = (os == "mac"); + exports.isLinux = (os == "linux"); + exports.isIE = + (navigator.appName == "Microsoft Internet Explorer" || navigator.appName.indexOf("MSAppHost") >= 0) + ? parseFloat((ua.match(/(?:MSIE |Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/)||[])[1]) + : parseFloat((ua.match(/(?:Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/)||[])[1]); // for ie + + exports.isOldIE = exports.isIE && exports.isIE < 9; + exports.isGecko = exports.isMozilla = (window.Controllers || window.controllers) && window.navigator.product === "Gecko"; + exports.isOldGecko = exports.isGecko && parseInt((ua.match(/rv\:(\d+)/)||[])[1], 10) < 4; + exports.isOpera = window.opera && Object.prototype.toString.call(window.opera) == "[object Opera]"; + exports.isWebKit = parseFloat(ua.split("WebKit/")[1]) || undefined; + + exports.isChrome = parseFloat(ua.split(" Chrome/")[1]) || undefined; + + exports.isAIR = ua.indexOf("AdobeAIR") >= 0; + + exports.isIPad = ua.indexOf("iPad") >= 0; + + exports.isTouchPad = ua.indexOf("TouchPad") >= 0; + + exports.isChromeOS = ua.indexOf(" CrOS ") >= 0; + + }); + + ace.define("ace/lib/event",["require","exports","module","ace/lib/keys","ace/lib/useragent"], function(acequire, exports, module) { + "use strict"; + + var keys = acequire("./keys"); + var useragent = acequire("./useragent"); + + var pressedKeys = null; + var ts = 0; + + exports.addListener = function(elem, type, callback) { + if (elem.addEventListener) { + return elem.addEventListener(type, callback, false); + } + if (elem.attachEvent) { + var wrapper = function() { + callback.call(elem, window.event); + }; + callback._wrapper = wrapper; + elem.attachEvent("on" + type, wrapper); + } + }; + + exports.removeListener = function(elem, type, callback) { + if (elem.removeEventListener) { + return elem.removeEventListener(type, callback, false); + } + if (elem.detachEvent) { + elem.detachEvent("on" + type, callback._wrapper || callback); + } + }; + exports.stopEvent = function(e) { + exports.stopPropagation(e); + exports.preventDefault(e); + return false; + }; + + exports.stopPropagation = function(e) { + if (e.stopPropagation) + e.stopPropagation(); + else + e.cancelBubble = true; + }; + + exports.preventDefault = function(e) { + if (e.preventDefault) + e.preventDefault(); + else + e.returnValue = false; + }; + exports.getButton = function(e) { + if (e.type == "dblclick") + return 0; + if (e.type == "contextmenu" || (useragent.isMac && (e.ctrlKey && !e.altKey && !e.shiftKey))) + return 2; + if (e.preventDefault) { + return e.button; + } + else { + return {1:0, 2:2, 4:1}[e.button]; + } + }; + + exports.capture = function(el, eventHandler, releaseCaptureHandler) { + function onMouseUp(e) { + eventHandler && eventHandler(e); + releaseCaptureHandler && releaseCaptureHandler(e); + + exports.removeListener(document, "mousemove", eventHandler, true); + exports.removeListener(document, "mouseup", onMouseUp, true); + exports.removeListener(document, "dragstart", onMouseUp, true); + } + + exports.addListener(document, "mousemove", eventHandler, true); + exports.addListener(document, "mouseup", onMouseUp, true); + exports.addListener(document, "dragstart", onMouseUp, true); + + return onMouseUp; + }; + + exports.addTouchMoveListener = function (el, callback) { + if ("ontouchmove" in el) { + var startx, starty; + exports.addListener(el, "touchstart", function (e) { + var touchObj = e.changedTouches[0]; + startx = touchObj.clientX; + starty = touchObj.clientY; + }); + exports.addListener(el, "touchmove", function (e) { + var factor = 1, + touchObj = e.changedTouches[0]; + + e.wheelX = -(touchObj.clientX - startx) / factor; + e.wheelY = -(touchObj.clientY - starty) / factor; + + startx = touchObj.clientX; + starty = touchObj.clientY; + + callback(e); + }); + } + }; + + exports.addMouseWheelListener = function(el, callback) { + if ("onmousewheel" in el) { + exports.addListener(el, "mousewheel", function(e) { + var factor = 8; + if (e.wheelDeltaX !== undefined) { + e.wheelX = -e.wheelDeltaX / factor; + e.wheelY = -e.wheelDeltaY / factor; + } else { + e.wheelX = 0; + e.wheelY = -e.wheelDelta / factor; + } + callback(e); + }); + } else if ("onwheel" in el) { + exports.addListener(el, "wheel", function(e) { + var factor = 0.35; + switch (e.deltaMode) { + case e.DOM_DELTA_PIXEL: + e.wheelX = e.deltaX * factor || 0; + e.wheelY = e.deltaY * factor || 0; + break; + case e.DOM_DELTA_LINE: + case e.DOM_DELTA_PAGE: + e.wheelX = (e.deltaX || 0) * 5; + e.wheelY = (e.deltaY || 0) * 5; + break; + } + + callback(e); + }); + } else { + exports.addListener(el, "DOMMouseScroll", function(e) { + if (e.axis && e.axis == e.HORIZONTAL_AXIS) { + e.wheelX = (e.detail || 0) * 5; + e.wheelY = 0; + } else { + e.wheelX = 0; + e.wheelY = (e.detail || 0) * 5; + } + callback(e); + }); + } + }; + + exports.addMultiMouseDownListener = function(elements, timeouts, eventHandler, callbackName) { + var clicks = 0; + var startX, startY, timer; + var eventNames = { + 2: "dblclick", + 3: "tripleclick", + 4: "quadclick" + }; + + function onMousedown(e) { + if (exports.getButton(e) !== 0) { + clicks = 0; + } else if (e.detail > 1) { + clicks++; + if (clicks > 4) + clicks = 1; + } else { + clicks = 1; + } + if (useragent.isIE) { + var isNewClick = Math.abs(e.clientX - startX) > 5 || Math.abs(e.clientY - startY) > 5; + if (!timer || isNewClick) + clicks = 1; + if (timer) + clearTimeout(timer); + timer = setTimeout(function() {timer = null}, timeouts[clicks - 1] || 600); + + if (clicks == 1) { + startX = e.clientX; + startY = e.clientY; + } + } + + e._clicks = clicks; + + eventHandler[callbackName]("mousedown", e); + + if (clicks > 4) + clicks = 0; + else if (clicks > 1) + return eventHandler[callbackName](eventNames[clicks], e); + } + function onDblclick(e) { + clicks = 2; + if (timer) + clearTimeout(timer); + timer = setTimeout(function() {timer = null}, timeouts[clicks - 1] || 600); + eventHandler[callbackName]("mousedown", e); + eventHandler[callbackName](eventNames[clicks], e); + } + if (!Array.isArray(elements)) + elements = [elements]; + elements.forEach(function(el) { + exports.addListener(el, "mousedown", onMousedown); + if (useragent.isOldIE) + exports.addListener(el, "dblclick", onDblclick); + }); + }; + + var getModifierHash = useragent.isMac && useragent.isOpera && !("KeyboardEvent" in window) + ? function(e) { + return 0 | (e.metaKey ? 1 : 0) | (e.altKey ? 2 : 0) | (e.shiftKey ? 4 : 0) | (e.ctrlKey ? 8 : 0); + } + : function(e) { + return 0 | (e.ctrlKey ? 1 : 0) | (e.altKey ? 2 : 0) | (e.shiftKey ? 4 : 0) | (e.metaKey ? 8 : 0); + }; + + exports.getModifierString = function(e) { + return keys.KEY_MODS[getModifierHash(e)]; + }; + + function normalizeCommandKeys(callback, e, keyCode) { + var hashId = getModifierHash(e); + + if (!useragent.isMac && pressedKeys) { + if (pressedKeys.OSKey) + hashId |= 8; + if (pressedKeys.altGr) { + if ((3 & hashId) != 3) + pressedKeys.altGr = 0; + else + return; + } + if (keyCode === 18 || keyCode === 17) { + var location = "location" in e ? e.location : e.keyLocation; + if (keyCode === 17 && location === 1) { + if (pressedKeys[keyCode] == 1) + ts = e.timeStamp; + } else if (keyCode === 18 && hashId === 3 && location === 2) { + var dt = e.timeStamp - ts; + if (dt < 50) + pressedKeys.altGr = true; + } + } + } + + if (keyCode in keys.MODIFIER_KEYS) { + keyCode = -1; + } + if (hashId & 8 && (keyCode >= 91 && keyCode <= 93)) { + keyCode = -1; + } + + if (!hashId && keyCode === 13) { + var location = "location" in e ? e.location : e.keyLocation; + if (location === 3) { + callback(e, hashId, -keyCode); + if (e.defaultPrevented) + return; + } + } + + if (useragent.isChromeOS && hashId & 8) { + callback(e, hashId, keyCode); + if (e.defaultPrevented) + return; + else + hashId &= ~8; + } + if (!hashId && !(keyCode in keys.FUNCTION_KEYS) && !(keyCode in keys.PRINTABLE_KEYS)) { + return false; + } + + return callback(e, hashId, keyCode); + } + + + exports.addCommandKeyListener = function(el, callback) { + var addListener = exports.addListener; + if (useragent.isOldGecko || (useragent.isOpera && !("KeyboardEvent" in window))) { + var lastKeyDownKeyCode = null; + addListener(el, "keydown", function(e) { + lastKeyDownKeyCode = e.keyCode; + }); + addListener(el, "keypress", function(e) { + return normalizeCommandKeys(callback, e, lastKeyDownKeyCode); + }); + } else { + var lastDefaultPrevented = null; + + addListener(el, "keydown", function(e) { + var keyCode = e.keyCode; + pressedKeys[keyCode] = (pressedKeys[keyCode] || 0) + 1; + if (keyCode == 91 || keyCode == 92) { + pressedKeys.OSKey = true; + } else if (pressedKeys.OSKey) { + if (e.timeStamp - pressedKeys.lastT > 200 && pressedKeys.count == 1) + resetPressedKeys(); + } + if (pressedKeys[keyCode] == 1) + pressedKeys.count++; + pressedKeys.lastT = e.timeStamp; + var result = normalizeCommandKeys(callback, e, keyCode); + lastDefaultPrevented = e.defaultPrevented; + return result; + }); + + addListener(el, "keypress", function(e) { + if (lastDefaultPrevented && (e.ctrlKey || e.altKey || e.shiftKey || e.metaKey)) { + exports.stopEvent(e); + lastDefaultPrevented = null; + } + }); + + addListener(el, "keyup", function(e) { + var keyCode = e.keyCode; + if (!pressedKeys[keyCode]) { + resetPressedKeys(); + } else { + pressedKeys.count = Math.max(pressedKeys.count - 1, 0); + } + if (keyCode == 91 || keyCode == 92) { + pressedKeys.OSKey = false; + } + pressedKeys[keyCode] = null; + }); + + if (!pressedKeys) { + resetPressedKeys(); + addListener(window, "focus", resetPressedKeys); + } + } + }; + function resetPressedKeys() { + pressedKeys = Object.create(null); + pressedKeys.count = 0; + pressedKeys.lastT = 0; + } + + if (typeof window == "object" && window.postMessage && !useragent.isOldIE) { + var postMessageId = 1; + exports.nextTick = function(callback, win) { + win = win || window; + var messageName = "zero-timeout-message-" + postMessageId; + exports.addListener(win, "message", function listener(e) { + if (e.data == messageName) { + exports.stopPropagation(e); + exports.removeListener(win, "message", listener); + callback(); + } + }); + win.postMessage(messageName, "*"); + }; + } + + + exports.nextFrame = typeof window == "object" && (window.requestAnimationFrame + || window.mozRequestAnimationFrame + || window.webkitRequestAnimationFrame + || window.msRequestAnimationFrame + || window.oRequestAnimationFrame); + + if (exports.nextFrame) + exports.nextFrame = exports.nextFrame.bind(window); + else + exports.nextFrame = function(callback) { + setTimeout(callback, 17); + }; + }); + + ace.define("ace/lib/lang",["require","exports","module"], function(acequire, exports, module) { + "use strict"; + + exports.last = function(a) { + return a[a.length - 1]; + }; + + exports.stringReverse = function(string) { + return string.split("").reverse().join(""); + }; + + exports.stringRepeat = function (string, count) { + var result = ''; + while (count > 0) { + if (count & 1) + result += string; + + if (count >>= 1) + string += string; + } + return result; + }; + + var trimBeginRegexp = /^\s\s*/; + var trimEndRegexp = /\s\s*$/; + + exports.stringTrimLeft = function (string) { + return string.replace(trimBeginRegexp, ''); + }; + + exports.stringTrimRight = function (string) { + return string.replace(trimEndRegexp, ''); + }; + + exports.copyObject = function(obj) { + var copy = {}; + for (var key in obj) { + copy[key] = obj[key]; + } + return copy; + }; + + exports.copyArray = function(array){ + var copy = []; + for (var i=0, l=array.length; i 1); + return ev.preventDefault(); + }; + + this.startSelect = function(pos, waitForClickSelection) { + pos = pos || this.editor.renderer.screenToTextCoordinates(this.x, this.y); + var editor = this.editor; + editor.$blockScrolling++; + if (this.mousedownEvent.getShiftKey()) + editor.selection.selectToPosition(pos); + else if (!waitForClickSelection) + editor.selection.moveToPosition(pos); + if (!waitForClickSelection) + this.select(); + if (editor.renderer.scroller.setCapture) { + editor.renderer.scroller.setCapture(); + } + editor.setStyle("ace_selecting"); + this.setState("select"); + editor.$blockScrolling--; + }; + + this.select = function() { + var anchor, editor = this.editor; + var cursor = editor.renderer.screenToTextCoordinates(this.x, this.y); + editor.$blockScrolling++; + if (this.$clickSelection) { + var cmp = this.$clickSelection.comparePoint(cursor); + + if (cmp == -1) { + anchor = this.$clickSelection.end; + } else if (cmp == 1) { + anchor = this.$clickSelection.start; + } else { + var orientedRange = calcRangeOrientation(this.$clickSelection, cursor); + cursor = orientedRange.cursor; + anchor = orientedRange.anchor; + } + editor.selection.setSelectionAnchor(anchor.row, anchor.column); + } + editor.selection.selectToPosition(cursor); + editor.$blockScrolling--; + editor.renderer.scrollCursorIntoView(); + }; + + this.extendSelectionBy = function(unitName) { + var anchor, editor = this.editor; + var cursor = editor.renderer.screenToTextCoordinates(this.x, this.y); + var range = editor.selection[unitName](cursor.row, cursor.column); + editor.$blockScrolling++; + if (this.$clickSelection) { + var cmpStart = this.$clickSelection.comparePoint(range.start); + var cmpEnd = this.$clickSelection.comparePoint(range.end); + + if (cmpStart == -1 && cmpEnd <= 0) { + anchor = this.$clickSelection.end; + if (range.end.row != cursor.row || range.end.column != cursor.column) + cursor = range.start; + } else if (cmpEnd == 1 && cmpStart >= 0) { + anchor = this.$clickSelection.start; + if (range.start.row != cursor.row || range.start.column != cursor.column) + cursor = range.end; + } else if (cmpStart == -1 && cmpEnd == 1) { + cursor = range.end; + anchor = range.start; + } else { + var orientedRange = calcRangeOrientation(this.$clickSelection, cursor); + cursor = orientedRange.cursor; + anchor = orientedRange.anchor; + } + editor.selection.setSelectionAnchor(anchor.row, anchor.column); + } + editor.selection.selectToPosition(cursor); + editor.$blockScrolling--; + editor.renderer.scrollCursorIntoView(); + }; + + this.selectEnd = + this.selectAllEnd = + this.selectByWordsEnd = + this.selectByLinesEnd = function() { + this.$clickSelection = null; + this.editor.unsetStyle("ace_selecting"); + if (this.editor.renderer.scroller.releaseCapture) { + this.editor.renderer.scroller.releaseCapture(); + } + }; + + this.focusWait = function() { + var distance = calcDistance(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y); + var time = Date.now(); + + if (distance > DRAG_OFFSET || time - this.mousedownEvent.time > this.$focusTimout) + this.startSelect(this.mousedownEvent.getDocumentPosition()); + }; + + this.onDoubleClick = function(ev) { + var pos = ev.getDocumentPosition(); + var editor = this.editor; + var session = editor.session; + + var range = session.getBracketRange(pos); + if (range) { + if (range.isEmpty()) { + range.start.column--; + range.end.column++; + } + this.setState("select"); + } else { + range = editor.selection.getWordRange(pos.row, pos.column); + this.setState("selectByWords"); + } + this.$clickSelection = range; + this.select(); + }; + + this.onTripleClick = function(ev) { + var pos = ev.getDocumentPosition(); + var editor = this.editor; + + this.setState("selectByLines"); + var range = editor.getSelectionRange(); + if (range.isMultiLine() && range.contains(pos.row, pos.column)) { + this.$clickSelection = editor.selection.getLineRange(range.start.row); + this.$clickSelection.end = editor.selection.getLineRange(range.end.row).end; + } else { + this.$clickSelection = editor.selection.getLineRange(pos.row); + } + this.select(); + }; + + this.onQuadClick = function(ev) { + var editor = this.editor; + + editor.selectAll(); + this.$clickSelection = editor.getSelectionRange(); + this.setState("selectAll"); + }; + + this.onMouseWheel = function(ev) { + if (ev.getAccelKey()) + return; + if (ev.getShiftKey() && ev.wheelY && !ev.wheelX) { + ev.wheelX = ev.wheelY; + ev.wheelY = 0; + } + + var t = ev.domEvent.timeStamp; + var dt = t - (this.$lastScrollTime||0); + + var editor = this.editor; + var isScrolable = editor.renderer.isScrollableBy(ev.wheelX * ev.speed, ev.wheelY * ev.speed); + if (isScrolable || dt < 200) { + this.$lastScrollTime = t; + editor.renderer.scrollBy(ev.wheelX * ev.speed, ev.wheelY * ev.speed); + return ev.stop(); + } + }; + + this.onTouchMove = function (ev) { + var t = ev.domEvent.timeStamp; + var dt = t - (this.$lastScrollTime || 0); + + var editor = this.editor; + var isScrolable = editor.renderer.isScrollableBy(ev.wheelX * ev.speed, ev.wheelY * ev.speed); + if (isScrolable || dt < 200) { + this.$lastScrollTime = t; + editor.renderer.scrollBy(ev.wheelX * ev.speed, ev.wheelY * ev.speed); + return ev.stop(); + } + }; + + }).call(DefaultHandlers.prototype); + + exports.DefaultHandlers = DefaultHandlers; + + function calcDistance(ax, ay, bx, by) { + return Math.sqrt(Math.pow(bx - ax, 2) + Math.pow(by - ay, 2)); + } + + function calcRangeOrientation(range, cursor) { + if (range.start.row == range.end.row) + var cmp = 2 * cursor.column - range.start.column - range.end.column; + else if (range.start.row == range.end.row - 1 && !range.start.column && !range.end.column) + var cmp = cursor.column - 4; + else + var cmp = 2 * cursor.row - range.start.row - range.end.row; + + if (cmp < 0) + return {cursor: range.start, anchor: range.end}; + else + return {cursor: range.end, anchor: range.start}; + } + + }); + + ace.define("ace/tooltip",["require","exports","module","ace/lib/oop","ace/lib/dom"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("./lib/oop"); + var dom = acequire("./lib/dom"); + function Tooltip (parentNode) { + this.isOpen = false; + this.$element = null; + this.$parentNode = parentNode; + } + + (function() { + this.$init = function() { + this.$element = dom.createElement("div"); + this.$element.className = "ace_tooltip"; + this.$element.style.display = "none"; + this.$parentNode.appendChild(this.$element); + return this.$element; + }; + this.getElement = function() { + return this.$element || this.$init(); + }; + this.setText = function(text) { + dom.setInnerText(this.getElement(), text); + }; + this.setHtml = function(html) { + this.getElement().innerHTML = html; + }; + this.setPosition = function(x, y) { + this.getElement().style.left = x + "px"; + this.getElement().style.top = y + "px"; + }; + this.setClassName = function(className) { + dom.addCssClass(this.getElement(), className); + }; + this.show = function(text, x, y) { + if (text != null) + this.setText(text); + if (x != null && y != null) + this.setPosition(x, y); + if (!this.isOpen) { + this.getElement().style.display = "block"; + this.isOpen = true; + } + }; + + this.hide = function() { + if (this.isOpen) { + this.getElement().style.display = "none"; + this.isOpen = false; + } + }; + this.getHeight = function() { + return this.getElement().offsetHeight; + }; + this.getWidth = function() { + return this.getElement().offsetWidth; + }; + + }).call(Tooltip.prototype); + + exports.Tooltip = Tooltip; + }); + + ace.define("ace/mouse/default_gutter_handler",["require","exports","module","ace/lib/dom","ace/lib/oop","ace/lib/event","ace/tooltip"], function(acequire, exports, module) { + "use strict"; + var dom = acequire("../lib/dom"); + var oop = acequire("../lib/oop"); + var event = acequire("../lib/event"); + var Tooltip = acequire("../tooltip").Tooltip; + + function GutterHandler(mouseHandler) { + var editor = mouseHandler.editor; + var gutter = editor.renderer.$gutterLayer; + var tooltip = new GutterTooltip(editor.container); + + mouseHandler.editor.setDefaultHandler("guttermousedown", function(e) { + if (!editor.isFocused() || e.getButton() != 0) + return; + var gutterRegion = gutter.getRegion(e); + + if (gutterRegion == "foldWidgets") + return; + + var row = e.getDocumentPosition().row; + var selection = editor.session.selection; + + if (e.getShiftKey()) + selection.selectTo(row, 0); + else { + if (e.domEvent.detail == 2) { + editor.selectAll(); + return e.preventDefault(); + } + mouseHandler.$clickSelection = editor.selection.getLineRange(row); + } + mouseHandler.setState("selectByLines"); + mouseHandler.captureMouse(e); + return e.preventDefault(); + }); + + + var tooltipTimeout, mouseEvent, tooltipAnnotation; + + function showTooltip() { + var row = mouseEvent.getDocumentPosition().row; + var annotation = gutter.$annotations[row]; + if (!annotation) + return hideTooltip(); + + var maxRow = editor.session.getLength(); + if (row == maxRow) { + var screenRow = editor.renderer.pixelToScreenCoordinates(0, mouseEvent.y).row; + var pos = mouseEvent.$pos; + if (screenRow > editor.session.documentToScreenRow(pos.row, pos.column)) + return hideTooltip(); + } + + if (tooltipAnnotation == annotation) + return; + tooltipAnnotation = annotation.text.join("
"); + + tooltip.setHtml(tooltipAnnotation); + tooltip.show(); + editor.on("mousewheel", hideTooltip); + + if (mouseHandler.$tooltipFollowsMouse) { + moveTooltip(mouseEvent); + } else { + var gutterElement = mouseEvent.domEvent.target; + var rect = gutterElement.getBoundingClientRect(); + var style = tooltip.getElement().style; + style.left = rect.right + "px"; + style.top = rect.bottom + "px"; + } + } + + function hideTooltip() { + if (tooltipTimeout) + tooltipTimeout = clearTimeout(tooltipTimeout); + if (tooltipAnnotation) { + tooltip.hide(); + tooltipAnnotation = null; + editor.removeEventListener("mousewheel", hideTooltip); + } + } + + function moveTooltip(e) { + tooltip.setPosition(e.x, e.y); + } + + mouseHandler.editor.setDefaultHandler("guttermousemove", function(e) { + var target = e.domEvent.target || e.domEvent.srcElement; + if (dom.hasCssClass(target, "ace_fold-widget")) + return hideTooltip(); + + if (tooltipAnnotation && mouseHandler.$tooltipFollowsMouse) + moveTooltip(e); + + mouseEvent = e; + if (tooltipTimeout) + return; + tooltipTimeout = setTimeout(function() { + tooltipTimeout = null; + if (mouseEvent && !mouseHandler.isMousePressed) + showTooltip(); + else + hideTooltip(); + }, 50); + }); + + event.addListener(editor.renderer.$gutter, "mouseout", function(e) { + mouseEvent = null; + if (!tooltipAnnotation || tooltipTimeout) + return; + + tooltipTimeout = setTimeout(function() { + tooltipTimeout = null; + hideTooltip(); + }, 50); + }); + + editor.on("changeSession", hideTooltip); + } + + function GutterTooltip(parentNode) { + Tooltip.call(this, parentNode); + } + + oop.inherits(GutterTooltip, Tooltip); + + (function(){ + this.setPosition = function(x, y) { + var windowWidth = window.innerWidth || document.documentElement.clientWidth; + var windowHeight = window.innerHeight || document.documentElement.clientHeight; + var width = this.getWidth(); + var height = this.getHeight(); + x += 15; + y += 15; + if (x + width > windowWidth) { + x -= (x + width) - windowWidth; + } + if (y + height > windowHeight) { + y -= 20 + height; + } + Tooltip.prototype.setPosition.call(this, x, y); + }; + + }).call(GutterTooltip.prototype); + + + + exports.GutterHandler = GutterHandler; + + }); + + ace.define("ace/mouse/mouse_event",["require","exports","module","ace/lib/event","ace/lib/useragent"], function(acequire, exports, module) { + "use strict"; + + var event = acequire("../lib/event"); + var useragent = acequire("../lib/useragent"); + var MouseEvent = exports.MouseEvent = function(domEvent, editor) { + this.domEvent = domEvent; + this.editor = editor; + + this.x = this.clientX = domEvent.clientX; + this.y = this.clientY = domEvent.clientY; + + this.$pos = null; + this.$inSelection = null; + + this.propagationStopped = false; + this.defaultPrevented = false; + }; + + (function() { + + this.stopPropagation = function() { + event.stopPropagation(this.domEvent); + this.propagationStopped = true; + }; + + this.preventDefault = function() { + event.preventDefault(this.domEvent); + this.defaultPrevented = true; + }; + + this.stop = function() { + this.stopPropagation(); + this.preventDefault(); + }; + this.getDocumentPosition = function() { + if (this.$pos) + return this.$pos; + + this.$pos = this.editor.renderer.screenToTextCoordinates(this.clientX, this.clientY); + return this.$pos; + }; + this.inSelection = function() { + if (this.$inSelection !== null) + return this.$inSelection; + + var editor = this.editor; + + + var selectionRange = editor.getSelectionRange(); + if (selectionRange.isEmpty()) + this.$inSelection = false; + else { + var pos = this.getDocumentPosition(); + this.$inSelection = selectionRange.contains(pos.row, pos.column); + } + + return this.$inSelection; + }; + this.getButton = function() { + return event.getButton(this.domEvent); + }; + this.getShiftKey = function() { + return this.domEvent.shiftKey; + }; + + this.getAccelKey = useragent.isMac + ? function() { return this.domEvent.metaKey; } + : function() { return this.domEvent.ctrlKey; }; + + }).call(MouseEvent.prototype); + + }); + + ace.define("ace/mouse/dragdrop_handler",["require","exports","module","ace/lib/dom","ace/lib/event","ace/lib/useragent"], function(acequire, exports, module) { + "use strict"; + + var dom = acequire("../lib/dom"); + var event = acequire("../lib/event"); + var useragent = acequire("../lib/useragent"); + + var AUTOSCROLL_DELAY = 200; + var SCROLL_CURSOR_DELAY = 200; + var SCROLL_CURSOR_HYSTERESIS = 5; + + function DragdropHandler(mouseHandler) { + + var editor = mouseHandler.editor; + + var blankImage = dom.createElement("img"); + blankImage.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="; + if (useragent.isOpera) + blankImage.style.cssText = "width:1px;height:1px;position:fixed;top:0;left:0;z-index:2147483647;opacity:0;"; + + var exports = ["dragWait", "dragWaitEnd", "startDrag", "dragReadyEnd", "onMouseDrag"]; + + exports.forEach(function(x) { + mouseHandler[x] = this[x]; + }, this); + editor.addEventListener("mousedown", this.onMouseDown.bind(mouseHandler)); + + + var mouseTarget = editor.container; + var dragSelectionMarker, x, y; + var timerId, range; + var dragCursor, counter = 0; + var dragOperation; + var isInternal; + var autoScrollStartTime; + var cursorMovedTime; + var cursorPointOnCaretMoved; + + this.onDragStart = function(e) { + if (this.cancelDrag || !mouseTarget.draggable) { + var self = this; + setTimeout(function(){ + self.startSelect(); + self.captureMouse(e); + }, 0); + return e.preventDefault(); + } + range = editor.getSelectionRange(); + + var dataTransfer = e.dataTransfer; + dataTransfer.effectAllowed = editor.getReadOnly() ? "copy" : "copyMove"; + if (useragent.isOpera) { + editor.container.appendChild(blankImage); + blankImage.scrollTop = 0; + } + dataTransfer.setDragImage && dataTransfer.setDragImage(blankImage, 0, 0); + if (useragent.isOpera) { + editor.container.removeChild(blankImage); + } + dataTransfer.clearData(); + dataTransfer.setData("Text", editor.session.getTextRange()); + + isInternal = true; + this.setState("drag"); + }; + + this.onDragEnd = function(e) { + mouseTarget.draggable = false; + isInternal = false; + this.setState(null); + if (!editor.getReadOnly()) { + var dropEffect = e.dataTransfer.dropEffect; + if (!dragOperation && dropEffect == "move") + editor.session.remove(editor.getSelectionRange()); + editor.renderer.$cursorLayer.setBlinking(true); + } + this.editor.unsetStyle("ace_dragging"); + this.editor.renderer.setCursorStyle(""); + }; + + this.onDragEnter = function(e) { + if (editor.getReadOnly() || !canAccept(e.dataTransfer)) + return; + x = e.clientX; + y = e.clientY; + if (!dragSelectionMarker) + addDragMarker(); + counter++; + e.dataTransfer.dropEffect = dragOperation = getDropEffect(e); + return event.preventDefault(e); + }; + + this.onDragOver = function(e) { + if (editor.getReadOnly() || !canAccept(e.dataTransfer)) + return; + x = e.clientX; + y = e.clientY; + if (!dragSelectionMarker) { + addDragMarker(); + counter++; + } + if (onMouseMoveTimer !== null) + onMouseMoveTimer = null; + + e.dataTransfer.dropEffect = dragOperation = getDropEffect(e); + return event.preventDefault(e); + }; + + this.onDragLeave = function(e) { + counter--; + if (counter <= 0 && dragSelectionMarker) { + clearDragMarker(); + dragOperation = null; + return event.preventDefault(e); + } + }; + + this.onDrop = function(e) { + if (!dragCursor) + return; + var dataTransfer = e.dataTransfer; + if (isInternal) { + switch (dragOperation) { + case "move": + if (range.contains(dragCursor.row, dragCursor.column)) { + range = { + start: dragCursor, + end: dragCursor + }; + } else { + range = editor.moveText(range, dragCursor); + } + break; + case "copy": + range = editor.moveText(range, dragCursor, true); + break; + } + } else { + var dropData = dataTransfer.getData('Text'); + range = { + start: dragCursor, + end: editor.session.insert(dragCursor, dropData) + }; + editor.focus(); + dragOperation = null; + } + clearDragMarker(); + return event.preventDefault(e); + }; + + event.addListener(mouseTarget, "dragstart", this.onDragStart.bind(mouseHandler)); + event.addListener(mouseTarget, "dragend", this.onDragEnd.bind(mouseHandler)); + event.addListener(mouseTarget, "dragenter", this.onDragEnter.bind(mouseHandler)); + event.addListener(mouseTarget, "dragover", this.onDragOver.bind(mouseHandler)); + event.addListener(mouseTarget, "dragleave", this.onDragLeave.bind(mouseHandler)); + event.addListener(mouseTarget, "drop", this.onDrop.bind(mouseHandler)); + + function scrollCursorIntoView(cursor, prevCursor) { + var now = Date.now(); + var vMovement = !prevCursor || cursor.row != prevCursor.row; + var hMovement = !prevCursor || cursor.column != prevCursor.column; + if (!cursorMovedTime || vMovement || hMovement) { + editor.$blockScrolling += 1; + editor.moveCursorToPosition(cursor); + editor.$blockScrolling -= 1; + cursorMovedTime = now; + cursorPointOnCaretMoved = {x: x, y: y}; + } else { + var distance = calcDistance(cursorPointOnCaretMoved.x, cursorPointOnCaretMoved.y, x, y); + if (distance > SCROLL_CURSOR_HYSTERESIS) { + cursorMovedTime = null; + } else if (now - cursorMovedTime >= SCROLL_CURSOR_DELAY) { + editor.renderer.scrollCursorIntoView(); + cursorMovedTime = null; + } + } + } + + function autoScroll(cursor, prevCursor) { + var now = Date.now(); + var lineHeight = editor.renderer.layerConfig.lineHeight; + var characterWidth = editor.renderer.layerConfig.characterWidth; + var editorRect = editor.renderer.scroller.getBoundingClientRect(); + var offsets = { + x: { + left: x - editorRect.left, + right: editorRect.right - x + }, + y: { + top: y - editorRect.top, + bottom: editorRect.bottom - y + } + }; + var nearestXOffset = Math.min(offsets.x.left, offsets.x.right); + var nearestYOffset = Math.min(offsets.y.top, offsets.y.bottom); + var scrollCursor = {row: cursor.row, column: cursor.column}; + if (nearestXOffset / characterWidth <= 2) { + scrollCursor.column += (offsets.x.left < offsets.x.right ? -3 : +2); + } + if (nearestYOffset / lineHeight <= 1) { + scrollCursor.row += (offsets.y.top < offsets.y.bottom ? -1 : +1); + } + var vScroll = cursor.row != scrollCursor.row; + var hScroll = cursor.column != scrollCursor.column; + var vMovement = !prevCursor || cursor.row != prevCursor.row; + if (vScroll || (hScroll && !vMovement)) { + if (!autoScrollStartTime) + autoScrollStartTime = now; + else if (now - autoScrollStartTime >= AUTOSCROLL_DELAY) + editor.renderer.scrollCursorIntoView(scrollCursor); + } else { + autoScrollStartTime = null; + } + } + + function onDragInterval() { + var prevCursor = dragCursor; + dragCursor = editor.renderer.screenToTextCoordinates(x, y); + scrollCursorIntoView(dragCursor, prevCursor); + autoScroll(dragCursor, prevCursor); + } + + function addDragMarker() { + range = editor.selection.toOrientedRange(); + dragSelectionMarker = editor.session.addMarker(range, "ace_selection", editor.getSelectionStyle()); + editor.clearSelection(); + if (editor.isFocused()) + editor.renderer.$cursorLayer.setBlinking(false); + clearInterval(timerId); + onDragInterval(); + timerId = setInterval(onDragInterval, 20); + counter = 0; + event.addListener(document, "mousemove", onMouseMove); + } + + function clearDragMarker() { + clearInterval(timerId); + editor.session.removeMarker(dragSelectionMarker); + dragSelectionMarker = null; + editor.$blockScrolling += 1; + editor.selection.fromOrientedRange(range); + editor.$blockScrolling -= 1; + if (editor.isFocused() && !isInternal) + editor.renderer.$cursorLayer.setBlinking(!editor.getReadOnly()); + range = null; + dragCursor = null; + counter = 0; + autoScrollStartTime = null; + cursorMovedTime = null; + event.removeListener(document, "mousemove", onMouseMove); + } + var onMouseMoveTimer = null; + function onMouseMove() { + if (onMouseMoveTimer == null) { + onMouseMoveTimer = setTimeout(function() { + if (onMouseMoveTimer != null && dragSelectionMarker) + clearDragMarker(); + }, 20); + } + } + + function canAccept(dataTransfer) { + var types = dataTransfer.types; + return !types || Array.prototype.some.call(types, function(type) { + return type == 'text/plain' || type == 'Text'; + }); + } + + function getDropEffect(e) { + var copyAllowed = ['copy', 'copymove', 'all', 'uninitialized']; + var moveAllowed = ['move', 'copymove', 'linkmove', 'all', 'uninitialized']; + + var copyModifierState = useragent.isMac ? e.altKey : e.ctrlKey; + var effectAllowed = "uninitialized"; + try { + effectAllowed = e.dataTransfer.effectAllowed.toLowerCase(); + } catch (e) {} + var dropEffect = "none"; + + if (copyModifierState && copyAllowed.indexOf(effectAllowed) >= 0) + dropEffect = "copy"; + else if (moveAllowed.indexOf(effectAllowed) >= 0) + dropEffect = "move"; + else if (copyAllowed.indexOf(effectAllowed) >= 0) + dropEffect = "copy"; + + return dropEffect; + } + } + + (function() { + + this.dragWait = function() { + var interval = Date.now() - this.mousedownEvent.time; + if (interval > this.editor.getDragDelay()) + this.startDrag(); + }; + + this.dragWaitEnd = function() { + var target = this.editor.container; + target.draggable = false; + this.startSelect(this.mousedownEvent.getDocumentPosition()); + this.selectEnd(); + }; + + this.dragReadyEnd = function(e) { + this.editor.renderer.$cursorLayer.setBlinking(!this.editor.getReadOnly()); + this.editor.unsetStyle("ace_dragging"); + this.editor.renderer.setCursorStyle(""); + this.dragWaitEnd(); + }; + + this.startDrag = function(){ + this.cancelDrag = false; + var editor = this.editor; + var target = editor.container; + target.draggable = true; + editor.renderer.$cursorLayer.setBlinking(false); + editor.setStyle("ace_dragging"); + var cursorStyle = useragent.isWin ? "default" : "move"; + editor.renderer.setCursorStyle(cursorStyle); + this.setState("dragReady"); + }; + + this.onMouseDrag = function(e) { + var target = this.editor.container; + if (useragent.isIE && this.state == "dragReady") { + var distance = calcDistance(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y); + if (distance > 3) + target.dragDrop(); + } + if (this.state === "dragWait") { + var distance = calcDistance(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y); + if (distance > 0) { + target.draggable = false; + this.startSelect(this.mousedownEvent.getDocumentPosition()); + } + } + }; + + this.onMouseDown = function(e) { + if (!this.$dragEnabled) + return; + this.mousedownEvent = e; + var editor = this.editor; + + var inSelection = e.inSelection(); + var button = e.getButton(); + var clickCount = e.domEvent.detail || 1; + if (clickCount === 1 && button === 0 && inSelection) { + if (e.editor.inMultiSelectMode && (e.getAccelKey() || e.getShiftKey())) + return; + this.mousedownEvent.time = Date.now(); + var eventTarget = e.domEvent.target || e.domEvent.srcElement; + if ("unselectable" in eventTarget) + eventTarget.unselectable = "on"; + if (editor.getDragDelay()) { + if (useragent.isWebKit) { + this.cancelDrag = true; + var mouseTarget = editor.container; + mouseTarget.draggable = true; + } + this.setState("dragWait"); + } else { + this.startDrag(); + } + this.captureMouse(e, this.onMouseDrag.bind(this)); + e.defaultPrevented = true; + } + }; + + }).call(DragdropHandler.prototype); + + + function calcDistance(ax, ay, bx, by) { + return Math.sqrt(Math.pow(bx - ax, 2) + Math.pow(by - ay, 2)); + } + + exports.DragdropHandler = DragdropHandler; + + }); + + ace.define("ace/lib/net",["require","exports","module","ace/lib/dom"], function(acequire, exports, module) { + "use strict"; + var dom = acequire("./dom"); + + exports.get = function (url, callback) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, true); + xhr.onreadystatechange = function () { + if (xhr.readyState === 4) { + callback(xhr.responseText); + } + }; + xhr.send(null); + }; + + exports.loadScript = function(path, callback) { + var head = dom.getDocumentHead(); + var s = document.createElement('script'); + + s.src = path; + head.appendChild(s); + + s.onload = s.onreadystatechange = function(_, isAbort) { + if (isAbort || !s.readyState || s.readyState == "loaded" || s.readyState == "complete") { + s = s.onload = s.onreadystatechange = null; + if (!isAbort) + callback(); + } + }; + }; + exports.qualifyURL = function(url) { + var a = document.createElement('a'); + a.href = url; + return a.href; + } + + }); + + ace.define("ace/lib/event_emitter",["require","exports","module"], function(acequire, exports, module) { + "use strict"; + + var EventEmitter = {}; + var stopPropagation = function() { this.propagationStopped = true; }; + var preventDefault = function() { this.defaultPrevented = true; }; + + EventEmitter._emit = + EventEmitter._dispatchEvent = function(eventName, e) { + this._eventRegistry || (this._eventRegistry = {}); + this._defaultHandlers || (this._defaultHandlers = {}); + + var listeners = this._eventRegistry[eventName] || []; + var defaultHandler = this._defaultHandlers[eventName]; + if (!listeners.length && !defaultHandler) + return; + + if (typeof e != "object" || !e) + e = {}; + + if (!e.type) + e.type = eventName; + if (!e.stopPropagation) + e.stopPropagation = stopPropagation; + if (!e.preventDefault) + e.preventDefault = preventDefault; + + listeners = listeners.slice(); + for (var i=0; i 1) + base = parts[parts.length - 2]; + var path = options[component + "Path"]; + if (path == null) { + path = options.basePath; + } else if (sep == "/") { + component = sep = ""; + } + if (path && path.slice(-1) != "/") + path += "/"; + return path + component + sep + base + this.get("suffix"); + }; + + exports.setModuleUrl = function(name, subst) { + return options.$moduleUrls[name] = subst; + }; + + exports.$loading = {}; + exports.loadModule = function(moduleName, onLoad) { + var module, moduleType; + if (Array.isArray(moduleName)) { + moduleType = moduleName[0]; + moduleName = moduleName[1]; + } + + try { + module = acequire(moduleName); + } catch (e) {} + if (module && !exports.$loading[moduleName]) + return onLoad && onLoad(module); + + if (!exports.$loading[moduleName]) + exports.$loading[moduleName] = []; + + exports.$loading[moduleName].push(onLoad); + + if (exports.$loading[moduleName].length > 1) + return; + + var afterLoad = function() { + acequire([moduleName], function(module) { + exports._emit("load.module", {name: moduleName, module: module}); + var listeners = exports.$loading[moduleName]; + exports.$loading[moduleName] = null; + listeners.forEach(function(onLoad) { + onLoad && onLoad(module); + }); + }); + }; + + if (!exports.get("packaged")) + return afterLoad(); + net.loadScript(exports.moduleUrl(moduleName, moduleType), afterLoad); + }; + init(true);function init(packaged) { + + if (!global || !global.document) + return; + + options.packaged = packaged || acequire.packaged || module.packaged || (global.define && __webpack_require__(65).packaged); + + var scriptOptions = {}; + var scriptUrl = ""; + var currentScript = (document.currentScript || document._currentScript ); // native or polyfill + var currentDocument = currentScript && currentScript.ownerDocument || document; + + var scripts = currentDocument.getElementsByTagName("script"); + for (var i=0; i [" + this.end.row + "/" + this.end.column + "]"); + }; + + this.contains = function(row, column) { + return this.compare(row, column) == 0; + }; + this.compareRange = function(range) { + var cmp, + end = range.end, + start = range.start; + + cmp = this.compare(end.row, end.column); + if (cmp == 1) { + cmp = this.compare(start.row, start.column); + if (cmp == 1) { + return 2; + } else if (cmp == 0) { + return 1; + } else { + return 0; + } + } else if (cmp == -1) { + return -2; + } else { + cmp = this.compare(start.row, start.column); + if (cmp == -1) { + return -1; + } else if (cmp == 1) { + return 42; + } else { + return 0; + } + } + }; + this.comparePoint = function(p) { + return this.compare(p.row, p.column); + }; + this.containsRange = function(range) { + return this.comparePoint(range.start) == 0 && this.comparePoint(range.end) == 0; + }; + this.intersects = function(range) { + var cmp = this.compareRange(range); + return (cmp == -1 || cmp == 0 || cmp == 1); + }; + this.isEnd = function(row, column) { + return this.end.row == row && this.end.column == column; + }; + this.isStart = function(row, column) { + return this.start.row == row && this.start.column == column; + }; + this.setStart = function(row, column) { + if (typeof row == "object") { + this.start.column = row.column; + this.start.row = row.row; + } else { + this.start.row = row; + this.start.column = column; + } + }; + this.setEnd = function(row, column) { + if (typeof row == "object") { + this.end.column = row.column; + this.end.row = row.row; + } else { + this.end.row = row; + this.end.column = column; + } + }; + this.inside = function(row, column) { + if (this.compare(row, column) == 0) { + if (this.isEnd(row, column) || this.isStart(row, column)) { + return false; + } else { + return true; + } + } + return false; + }; + this.insideStart = function(row, column) { + if (this.compare(row, column) == 0) { + if (this.isEnd(row, column)) { + return false; + } else { + return true; + } + } + return false; + }; + this.insideEnd = function(row, column) { + if (this.compare(row, column) == 0) { + if (this.isStart(row, column)) { + return false; + } else { + return true; + } + } + return false; + }; + this.compare = function(row, column) { + if (!this.isMultiLine()) { + if (row === this.start.row) { + return column < this.start.column ? -1 : (column > this.end.column ? 1 : 0); + } + } + + if (row < this.start.row) + return -1; + + if (row > this.end.row) + return 1; + + if (this.start.row === row) + return column >= this.start.column ? 0 : -1; + + if (this.end.row === row) + return column <= this.end.column ? 0 : 1; + + return 0; + }; + this.compareStart = function(row, column) { + if (this.start.row == row && this.start.column == column) { + return -1; + } else { + return this.compare(row, column); + } + }; + this.compareEnd = function(row, column) { + if (this.end.row == row && this.end.column == column) { + return 1; + } else { + return this.compare(row, column); + } + }; + this.compareInside = function(row, column) { + if (this.end.row == row && this.end.column == column) { + return 1; + } else if (this.start.row == row && this.start.column == column) { + return -1; + } else { + return this.compare(row, column); + } + }; + this.clipRows = function(firstRow, lastRow) { + if (this.end.row > lastRow) + var end = {row: lastRow + 1, column: 0}; + else if (this.end.row < firstRow) + var end = {row: firstRow, column: 0}; + + if (this.start.row > lastRow) + var start = {row: lastRow + 1, column: 0}; + else if (this.start.row < firstRow) + var start = {row: firstRow, column: 0}; + + return Range.fromPoints(start || this.start, end || this.end); + }; + this.extend = function(row, column) { + var cmp = this.compare(row, column); + + if (cmp == 0) + return this; + else if (cmp == -1) + var start = {row: row, column: column}; + else + var end = {row: row, column: column}; + + return Range.fromPoints(start || this.start, end || this.end); + }; + + this.isEmpty = function() { + return (this.start.row === this.end.row && this.start.column === this.end.column); + }; + this.isMultiLine = function() { + return (this.start.row !== this.end.row); + }; + this.clone = function() { + return Range.fromPoints(this.start, this.end); + }; + this.collapseRows = function() { + if (this.end.column == 0) + return new Range(this.start.row, 0, Math.max(this.start.row, this.end.row-1), 0) + else + return new Range(this.start.row, 0, this.end.row, 0) + }; + this.toScreenRange = function(session) { + var screenPosStart = session.documentToScreenPosition(this.start); + var screenPosEnd = session.documentToScreenPosition(this.end); + + return new Range( + screenPosStart.row, screenPosStart.column, + screenPosEnd.row, screenPosEnd.column + ); + }; + this.moveBy = function(row, column) { + this.start.row += row; + this.start.column += column; + this.end.row += row; + this.end.column += column; + }; + + }).call(Range.prototype); + Range.fromPoints = function(start, end) { + return new Range(start.row, start.column, end.row, end.column); + }; + Range.comparePoints = comparePoints; + + Range.comparePoints = function(p1, p2) { + return p1.row - p2.row || p1.column - p2.column; + }; + + + exports.Range = Range; + }); + + ace.define("ace/selection",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/lib/event_emitter","ace/range"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("./lib/oop"); + var lang = acequire("./lib/lang"); + var EventEmitter = acequire("./lib/event_emitter").EventEmitter; + var Range = acequire("./range").Range; + var Selection = function(session) { + this.session = session; + this.doc = session.getDocument(); + + this.clearSelection(); + this.lead = this.selectionLead = this.doc.createAnchor(0, 0); + this.anchor = this.selectionAnchor = this.doc.createAnchor(0, 0); + + var self = this; + this.lead.on("change", function(e) { + self._emit("changeCursor"); + if (!self.$isEmpty) + self._emit("changeSelection"); + if (!self.$keepDesiredColumnOnChange && e.old.column != e.value.column) + self.$desiredColumn = null; + }); + + this.selectionAnchor.on("change", function() { + if (!self.$isEmpty) + self._emit("changeSelection"); + }); + }; + + (function() { + + oop.implement(this, EventEmitter); + this.isEmpty = function() { + return (this.$isEmpty || ( + this.anchor.row == this.lead.row && + this.anchor.column == this.lead.column + )); + }; + this.isMultiLine = function() { + if (this.isEmpty()) { + return false; + } + + return this.getRange().isMultiLine(); + }; + this.getCursor = function() { + return this.lead.getPosition(); + }; + this.setSelectionAnchor = function(row, column) { + this.anchor.setPosition(row, column); + + if (this.$isEmpty) { + this.$isEmpty = false; + this._emit("changeSelection"); + } + }; + this.getSelectionAnchor = function() { + if (this.$isEmpty) + return this.getSelectionLead(); + else + return this.anchor.getPosition(); + }; + this.getSelectionLead = function() { + return this.lead.getPosition(); + }; + this.shiftSelection = function(columns) { + if (this.$isEmpty) { + this.moveCursorTo(this.lead.row, this.lead.column + columns); + return; + } + + var anchor = this.getSelectionAnchor(); + var lead = this.getSelectionLead(); + + var isBackwards = this.isBackwards(); + + if (!isBackwards || anchor.column !== 0) + this.setSelectionAnchor(anchor.row, anchor.column + columns); + + if (isBackwards || lead.column !== 0) { + this.$moveSelection(function() { + this.moveCursorTo(lead.row, lead.column + columns); + }); + } + }; + this.isBackwards = function() { + var anchor = this.anchor; + var lead = this.lead; + return (anchor.row > lead.row || (anchor.row == lead.row && anchor.column > lead.column)); + }; + this.getRange = function() { + var anchor = this.anchor; + var lead = this.lead; + + if (this.isEmpty()) + return Range.fromPoints(lead, lead); + + if (this.isBackwards()) { + return Range.fromPoints(lead, anchor); + } + else { + return Range.fromPoints(anchor, lead); + } + }; + this.clearSelection = function() { + if (!this.$isEmpty) { + this.$isEmpty = true; + this._emit("changeSelection"); + } + }; + this.selectAll = function() { + var lastRow = this.doc.getLength() - 1; + this.setSelectionAnchor(0, 0); + this.moveCursorTo(lastRow, this.doc.getLine(lastRow).length); + }; + this.setRange = + this.setSelectionRange = function(range, reverse) { + if (reverse) { + this.setSelectionAnchor(range.end.row, range.end.column); + this.selectTo(range.start.row, range.start.column); + } else { + this.setSelectionAnchor(range.start.row, range.start.column); + this.selectTo(range.end.row, range.end.column); + } + if (this.getRange().isEmpty()) + this.$isEmpty = true; + this.$desiredColumn = null; + }; + + this.$moveSelection = function(mover) { + var lead = this.lead; + if (this.$isEmpty) + this.setSelectionAnchor(lead.row, lead.column); + + mover.call(this); + }; + this.selectTo = function(row, column) { + this.$moveSelection(function() { + this.moveCursorTo(row, column); + }); + }; + this.selectToPosition = function(pos) { + this.$moveSelection(function() { + this.moveCursorToPosition(pos); + }); + }; + this.moveTo = function(row, column) { + this.clearSelection(); + this.moveCursorTo(row, column); + }; + this.moveToPosition = function(pos) { + this.clearSelection(); + this.moveCursorToPosition(pos); + }; + this.selectUp = function() { + this.$moveSelection(this.moveCursorUp); + }; + this.selectDown = function() { + this.$moveSelection(this.moveCursorDown); + }; + this.selectRight = function() { + this.$moveSelection(this.moveCursorRight); + }; + this.selectLeft = function() { + this.$moveSelection(this.moveCursorLeft); + }; + this.selectLineStart = function() { + this.$moveSelection(this.moveCursorLineStart); + }; + this.selectLineEnd = function() { + this.$moveSelection(this.moveCursorLineEnd); + }; + this.selectFileEnd = function() { + this.$moveSelection(this.moveCursorFileEnd); + }; + this.selectFileStart = function() { + this.$moveSelection(this.moveCursorFileStart); + }; + this.selectWordRight = function() { + this.$moveSelection(this.moveCursorWordRight); + }; + this.selectWordLeft = function() { + this.$moveSelection(this.moveCursorWordLeft); + }; + this.getWordRange = function(row, column) { + if (typeof column == "undefined") { + var cursor = row || this.lead; + row = cursor.row; + column = cursor.column; + } + return this.session.getWordRange(row, column); + }; + this.selectWord = function() { + this.setSelectionRange(this.getWordRange()); + }; + this.selectAWord = function() { + var cursor = this.getCursor(); + var range = this.session.getAWordRange(cursor.row, cursor.column); + this.setSelectionRange(range); + }; + + this.getLineRange = function(row, excludeLastChar) { + var rowStart = typeof row == "number" ? row : this.lead.row; + var rowEnd; + + var foldLine = this.session.getFoldLine(rowStart); + if (foldLine) { + rowStart = foldLine.start.row; + rowEnd = foldLine.end.row; + } else { + rowEnd = rowStart; + } + if (excludeLastChar === true) + return new Range(rowStart, 0, rowEnd, this.session.getLine(rowEnd).length); + else + return new Range(rowStart, 0, rowEnd + 1, 0); + }; + this.selectLine = function() { + this.setSelectionRange(this.getLineRange()); + }; + this.moveCursorUp = function() { + this.moveCursorBy(-1, 0); + }; + this.moveCursorDown = function() { + this.moveCursorBy(1, 0); + }; + this.moveCursorLeft = function() { + var cursor = this.lead.getPosition(), + fold; + + if (fold = this.session.getFoldAt(cursor.row, cursor.column, -1)) { + this.moveCursorTo(fold.start.row, fold.start.column); + } else if (cursor.column === 0) { + if (cursor.row > 0) { + this.moveCursorTo(cursor.row - 1, this.doc.getLine(cursor.row - 1).length); + } + } + else { + var tabSize = this.session.getTabSize(); + if (this.session.isTabStop(cursor) && this.doc.getLine(cursor.row).slice(cursor.column-tabSize, cursor.column).split(" ").length-1 == tabSize) + this.moveCursorBy(0, -tabSize); + else + this.moveCursorBy(0, -1); + } + }; + this.moveCursorRight = function() { + var cursor = this.lead.getPosition(), + fold; + if (fold = this.session.getFoldAt(cursor.row, cursor.column, 1)) { + this.moveCursorTo(fold.end.row, fold.end.column); + } + else if (this.lead.column == this.doc.getLine(this.lead.row).length) { + if (this.lead.row < this.doc.getLength() - 1) { + this.moveCursorTo(this.lead.row + 1, 0); + } + } + else { + var tabSize = this.session.getTabSize(); + var cursor = this.lead; + if (this.session.isTabStop(cursor) && this.doc.getLine(cursor.row).slice(cursor.column, cursor.column+tabSize).split(" ").length-1 == tabSize) + this.moveCursorBy(0, tabSize); + else + this.moveCursorBy(0, 1); + } + }; + this.moveCursorLineStart = function() { + var row = this.lead.row; + var column = this.lead.column; + var screenRow = this.session.documentToScreenRow(row, column); + var firstColumnPosition = this.session.screenToDocumentPosition(screenRow, 0); + var beforeCursor = this.session.getDisplayLine( + row, null, firstColumnPosition.row, + firstColumnPosition.column + ); + + var leadingSpace = beforeCursor.match(/^\s*/); + if (leadingSpace[0].length != column && !this.session.$useEmacsStyleLineStart) + firstColumnPosition.column += leadingSpace[0].length; + this.moveCursorToPosition(firstColumnPosition); + }; + this.moveCursorLineEnd = function() { + var lead = this.lead; + var lineEnd = this.session.getDocumentLastRowColumnPosition(lead.row, lead.column); + if (this.lead.column == lineEnd.column) { + var line = this.session.getLine(lineEnd.row); + if (lineEnd.column == line.length) { + var textEnd = line.search(/\s+$/); + if (textEnd > 0) + lineEnd.column = textEnd; + } + } + + this.moveCursorTo(lineEnd.row, lineEnd.column); + }; + this.moveCursorFileEnd = function() { + var row = this.doc.getLength() - 1; + var column = this.doc.getLine(row).length; + this.moveCursorTo(row, column); + }; + this.moveCursorFileStart = function() { + this.moveCursorTo(0, 0); + }; + this.moveCursorLongWordRight = function() { + var row = this.lead.row; + var column = this.lead.column; + var line = this.doc.getLine(row); + var rightOfCursor = line.substring(column); + + var match; + this.session.nonTokenRe.lastIndex = 0; + this.session.tokenRe.lastIndex = 0; + var fold = this.session.getFoldAt(row, column, 1); + if (fold) { + this.moveCursorTo(fold.end.row, fold.end.column); + return; + } + if (match = this.session.nonTokenRe.exec(rightOfCursor)) { + column += this.session.nonTokenRe.lastIndex; + this.session.nonTokenRe.lastIndex = 0; + rightOfCursor = line.substring(column); + } + if (column >= line.length) { + this.moveCursorTo(row, line.length); + this.moveCursorRight(); + if (row < this.doc.getLength() - 1) + this.moveCursorWordRight(); + return; + } + if (match = this.session.tokenRe.exec(rightOfCursor)) { + column += this.session.tokenRe.lastIndex; + this.session.tokenRe.lastIndex = 0; + } + + this.moveCursorTo(row, column); + }; + this.moveCursorLongWordLeft = function() { + var row = this.lead.row; + var column = this.lead.column; + var fold; + if (fold = this.session.getFoldAt(row, column, -1)) { + this.moveCursorTo(fold.start.row, fold.start.column); + return; + } + + var str = this.session.getFoldStringAt(row, column, -1); + if (str == null) { + str = this.doc.getLine(row).substring(0, column); + } + + var leftOfCursor = lang.stringReverse(str); + var match; + this.session.nonTokenRe.lastIndex = 0; + this.session.tokenRe.lastIndex = 0; + if (match = this.session.nonTokenRe.exec(leftOfCursor)) { + column -= this.session.nonTokenRe.lastIndex; + leftOfCursor = leftOfCursor.slice(this.session.nonTokenRe.lastIndex); + this.session.nonTokenRe.lastIndex = 0; + } + if (column <= 0) { + this.moveCursorTo(row, 0); + this.moveCursorLeft(); + if (row > 0) + this.moveCursorWordLeft(); + return; + } + if (match = this.session.tokenRe.exec(leftOfCursor)) { + column -= this.session.tokenRe.lastIndex; + this.session.tokenRe.lastIndex = 0; + } + + this.moveCursorTo(row, column); + }; + + this.$shortWordEndIndex = function(rightOfCursor) { + var match, index = 0, ch; + var whitespaceRe = /\s/; + var tokenRe = this.session.tokenRe; + + tokenRe.lastIndex = 0; + if (match = this.session.tokenRe.exec(rightOfCursor)) { + index = this.session.tokenRe.lastIndex; + } else { + while ((ch = rightOfCursor[index]) && whitespaceRe.test(ch)) + index ++; + + if (index < 1) { + tokenRe.lastIndex = 0; + while ((ch = rightOfCursor[index]) && !tokenRe.test(ch)) { + tokenRe.lastIndex = 0; + index ++; + if (whitespaceRe.test(ch)) { + if (index > 2) { + index--; + break; + } else { + while ((ch = rightOfCursor[index]) && whitespaceRe.test(ch)) + index ++; + if (index > 2) + break; + } + } + } + } + } + tokenRe.lastIndex = 0; + + return index; + }; + + this.moveCursorShortWordRight = function() { + var row = this.lead.row; + var column = this.lead.column; + var line = this.doc.getLine(row); + var rightOfCursor = line.substring(column); + + var fold = this.session.getFoldAt(row, column, 1); + if (fold) + return this.moveCursorTo(fold.end.row, fold.end.column); + + if (column == line.length) { + var l = this.doc.getLength(); + do { + row++; + rightOfCursor = this.doc.getLine(row); + } while (row < l && /^\s*$/.test(rightOfCursor)); + + if (!/^\s+/.test(rightOfCursor)) + rightOfCursor = ""; + column = 0; + } + + var index = this.$shortWordEndIndex(rightOfCursor); + + this.moveCursorTo(row, column + index); + }; + + this.moveCursorShortWordLeft = function() { + var row = this.lead.row; + var column = this.lead.column; + + var fold; + if (fold = this.session.getFoldAt(row, column, -1)) + return this.moveCursorTo(fold.start.row, fold.start.column); + + var line = this.session.getLine(row).substring(0, column); + if (column === 0) { + do { + row--; + line = this.doc.getLine(row); + } while (row > 0 && /^\s*$/.test(line)); + + column = line.length; + if (!/\s+$/.test(line)) + line = ""; + } + + var leftOfCursor = lang.stringReverse(line); + var index = this.$shortWordEndIndex(leftOfCursor); + + return this.moveCursorTo(row, column - index); + }; + + this.moveCursorWordRight = function() { + if (this.session.$selectLongWords) + this.moveCursorLongWordRight(); + else + this.moveCursorShortWordRight(); + }; + + this.moveCursorWordLeft = function() { + if (this.session.$selectLongWords) + this.moveCursorLongWordLeft(); + else + this.moveCursorShortWordLeft(); + }; + this.moveCursorBy = function(rows, chars) { + var screenPos = this.session.documentToScreenPosition( + this.lead.row, + this.lead.column + ); + + if (chars === 0) { + if (this.$desiredColumn) + screenPos.column = this.$desiredColumn; + else + this.$desiredColumn = screenPos.column; + } + + var docPos = this.session.screenToDocumentPosition(screenPos.row + rows, screenPos.column); + + if (rows !== 0 && chars === 0 && docPos.row === this.lead.row && docPos.column === this.lead.column) { + if (this.session.lineWidgets && this.session.lineWidgets[docPos.row]) { + if (docPos.row > 0 || rows > 0) + docPos.row++; + } + } + this.moveCursorTo(docPos.row, docPos.column + chars, chars === 0); + }; + this.moveCursorToPosition = function(position) { + this.moveCursorTo(position.row, position.column); + }; + this.moveCursorTo = function(row, column, keepDesiredColumn) { + var fold = this.session.getFoldAt(row, column, 1); + if (fold) { + row = fold.start.row; + column = fold.start.column; + } + + this.$keepDesiredColumnOnChange = true; + this.lead.setPosition(row, column); + this.$keepDesiredColumnOnChange = false; + + if (!keepDesiredColumn) + this.$desiredColumn = null; + }; + this.moveCursorToScreen = function(row, column, keepDesiredColumn) { + var pos = this.session.screenToDocumentPosition(row, column); + this.moveCursorTo(pos.row, pos.column, keepDesiredColumn); + }; + this.detach = function() { + this.lead.detach(); + this.anchor.detach(); + this.session = this.doc = null; + }; + + this.fromOrientedRange = function(range) { + this.setSelectionRange(range, range.cursor == range.start); + this.$desiredColumn = range.desiredColumn || this.$desiredColumn; + }; + + this.toOrientedRange = function(range) { + var r = this.getRange(); + if (range) { + range.start.column = r.start.column; + range.start.row = r.start.row; + range.end.column = r.end.column; + range.end.row = r.end.row; + } else { + range = r; + } + + range.cursor = this.isBackwards() ? range.start : range.end; + range.desiredColumn = this.$desiredColumn; + return range; + }; + this.getRangeOfMovements = function(func) { + var start = this.getCursor(); + try { + func(this); + var end = this.getCursor(); + return Range.fromPoints(start,end); + } catch(e) { + return Range.fromPoints(start,start); + } finally { + this.moveCursorToPosition(start); + } + }; + + this.toJSON = function() { + if (this.rangeCount) { + var data = this.ranges.map(function(r) { + var r1 = r.clone(); + r1.isBackwards = r.cursor == r.start; + return r1; + }); + } else { + var data = this.getRange(); + data.isBackwards = this.isBackwards(); + } + return data; + }; + + this.fromJSON = function(data) { + if (data.start == undefined) { + if (this.rangeList) { + this.toSingleRange(data[0]); + for (var i = data.length; i--; ) { + var r = Range.fromPoints(data[i].start, data[i].end); + if (data[i].isBackwards) + r.cursor = r.start; + this.addRange(r, true); + } + return; + } else + data = data[0]; + } + if (this.rangeList) + this.toSingleRange(data); + this.setSelectionRange(data, data.isBackwards); + }; + + this.isEqual = function(data) { + if ((data.length || this.rangeCount) && data.length != this.rangeCount) + return false; + if (!data.length || !this.ranges) + return this.getRange().isEqual(data); + + for (var i = this.ranges.length; i--; ) { + if (!this.ranges[i].isEqual(data[i])) + return false; + } + return true; + }; + + }).call(Selection.prototype); + + exports.Selection = Selection; + }); + + ace.define("ace/tokenizer",["require","exports","module","ace/config"], function(acequire, exports, module) { + "use strict"; + + var config = acequire("./config"); + var MAX_TOKEN_COUNT = 2000; + var Tokenizer = function(rules) { + this.states = rules; + + this.regExps = {}; + this.matchMappings = {}; + for (var key in this.states) { + var state = this.states[key]; + var ruleRegExps = []; + var matchTotal = 0; + var mapping = this.matchMappings[key] = {defaultToken: "text"}; + var flag = "g"; + + var splitterRurles = []; + for (var i = 0; i < state.length; i++) { + var rule = state[i]; + if (rule.defaultToken) + mapping.defaultToken = rule.defaultToken; + if (rule.caseInsensitive) + flag = "gi"; + if (rule.regex == null) + continue; + + if (rule.regex instanceof RegExp) + rule.regex = rule.regex.toString().slice(1, -1); + var adjustedregex = rule.regex; + var matchcount = new RegExp("(?:(" + adjustedregex + ")|(.))").exec("a").length - 2; + if (Array.isArray(rule.token)) { + if (rule.token.length == 1 || matchcount == 1) { + rule.token = rule.token[0]; + } else if (matchcount - 1 != rule.token.length) { + this.reportError("number of classes and regexp groups doesn't match", { + rule: rule, + groupCount: matchcount - 1 + }); + rule.token = rule.token[0]; + } else { + rule.tokenArray = rule.token; + rule.token = null; + rule.onMatch = this.$arrayTokens; + } + } else if (typeof rule.token == "function" && !rule.onMatch) { + if (matchcount > 1) + rule.onMatch = this.$applyToken; + else + rule.onMatch = rule.token; + } + + if (matchcount > 1) { + if (/\\\d/.test(rule.regex)) { + adjustedregex = rule.regex.replace(/\\([0-9]+)/g, function(match, digit) { + return "\\" + (parseInt(digit, 10) + matchTotal + 1); + }); + } else { + matchcount = 1; + adjustedregex = this.removeCapturingGroups(rule.regex); + } + if (!rule.splitRegex && typeof rule.token != "string") + splitterRurles.push(rule); // flag will be known only at the very end + } + + mapping[matchTotal] = i; + matchTotal += matchcount; + + ruleRegExps.push(adjustedregex); + if (!rule.onMatch) + rule.onMatch = null; + } + + if (!ruleRegExps.length) { + mapping[0] = 0; + ruleRegExps.push("$"); + } + + splitterRurles.forEach(function(rule) { + rule.splitRegex = this.createSplitterRegexp(rule.regex, flag); + }, this); + + this.regExps[key] = new RegExp("(" + ruleRegExps.join(")|(") + ")|($)", flag); + } + }; + + (function() { + this.$setMaxTokenCount = function(m) { + MAX_TOKEN_COUNT = m | 0; + }; + + this.$applyToken = function(str) { + var values = this.splitRegex.exec(str).slice(1); + var types = this.token.apply(this, values); + if (typeof types === "string") + return [{type: types, value: str}]; + + var tokens = []; + for (var i = 0, l = types.length; i < l; i++) { + if (values[i]) + tokens[tokens.length] = { + type: types[i], + value: values[i] + }; + } + return tokens; + }; + + this.$arrayTokens = function(str) { + if (!str) + return []; + var values = this.splitRegex.exec(str); + if (!values) + return "text"; + var tokens = []; + var types = this.tokenArray; + for (var i = 0, l = types.length; i < l; i++) { + if (values[i + 1]) + tokens[tokens.length] = { + type: types[i], + value: values[i + 1] + }; + } + return tokens; + }; + + this.removeCapturingGroups = function(src) { + var r = src.replace( + /\[(?:\\.|[^\]])*?\]|\\.|\(\?[:=!]|(\()/g, + function(x, y) {return y ? "(?:" : x;} + ); + return r; + }; + + this.createSplitterRegexp = function(src, flag) { + if (src.indexOf("(?=") != -1) { + var stack = 0; + var inChClass = false; + var lastCapture = {}; + src.replace(/(\\.)|(\((?:\?[=!])?)|(\))|([\[\]])/g, function( + m, esc, parenOpen, parenClose, square, index + ) { + if (inChClass) { + inChClass = square != "]"; + } else if (square) { + inChClass = true; + } else if (parenClose) { + if (stack == lastCapture.stack) { + lastCapture.end = index+1; + lastCapture.stack = -1; + } + stack--; + } else if (parenOpen) { + stack++; + if (parenOpen.length != 1) { + lastCapture.stack = stack + lastCapture.start = index; + } + } + return m; + }); + + if (lastCapture.end != null && /^\)*$/.test(src.substr(lastCapture.end))) + src = src.substring(0, lastCapture.start) + src.substr(lastCapture.end); + } + if (src.charAt(0) != "^") src = "^" + src; + if (src.charAt(src.length - 1) != "$") src += "$"; + + return new RegExp(src, (flag||"").replace("g", "")); + }; + this.getLineTokens = function(line, startState) { + if (startState && typeof startState != "string") { + var stack = startState.slice(0); + startState = stack[0]; + if (startState === "#tmp") { + stack.shift() + startState = stack.shift() + } + } else + var stack = []; + + var currentState = startState || "start"; + var state = this.states[currentState]; + if (!state) { + currentState = "start"; + state = this.states[currentState]; + } + var mapping = this.matchMappings[currentState]; + var re = this.regExps[currentState]; + re.lastIndex = 0; + + var match, tokens = []; + var lastIndex = 0; + var matchAttempts = 0; + + var token = {type: null, value: ""}; + + while (match = re.exec(line)) { + var type = mapping.defaultToken; + var rule = null; + var value = match[0]; + var index = re.lastIndex; + + if (index - value.length > lastIndex) { + var skipped = line.substring(lastIndex, index - value.length); + if (token.type == type) { + token.value += skipped; + } else { + if (token.type) + tokens.push(token); + token = {type: type, value: skipped}; + } + } + + for (var i = 0; i < match.length-2; i++) { + if (match[i + 1] === undefined) + continue; + + rule = state[mapping[i]]; + + if (rule.onMatch) + type = rule.onMatch(value, currentState, stack); + else + type = rule.token; + + if (rule.next) { + if (typeof rule.next == "string") { + currentState = rule.next; + } else { + currentState = rule.next(currentState, stack); + } + + state = this.states[currentState]; + if (!state) { + this.reportError("state doesn't exist", currentState); + currentState = "start"; + state = this.states[currentState]; + } + mapping = this.matchMappings[currentState]; + lastIndex = index; + re = this.regExps[currentState]; + re.lastIndex = index; + } + break; + } + + if (value) { + if (typeof type === "string") { + if ((!rule || rule.merge !== false) && token.type === type) { + token.value += value; + } else { + if (token.type) + tokens.push(token); + token = {type: type, value: value}; + } + } else if (type) { + if (token.type) + tokens.push(token); + token = {type: null, value: ""}; + for (var i = 0; i < type.length; i++) + tokens.push(type[i]); + } + } + + if (lastIndex == line.length) + break; + + lastIndex = index; + + if (matchAttempts++ > MAX_TOKEN_COUNT) { + if (matchAttempts > 2 * line.length) { + this.reportError("infinite loop with in ace tokenizer", { + startState: startState, + line: line + }); + } + while (lastIndex < line.length) { + if (token.type) + tokens.push(token); + token = { + value: line.substring(lastIndex, lastIndex += 2000), + type: "overflow" + }; + } + currentState = "start"; + stack = []; + break; + } + } + + if (token.type) + tokens.push(token); + + if (stack.length > 1) { + if (stack[0] !== currentState) + stack.unshift("#tmp", currentState); + } + return { + tokens : tokens, + state : stack.length ? stack : currentState + }; + }; + + this.reportError = config.reportError; + + }).call(Tokenizer.prototype); + + exports.Tokenizer = Tokenizer; + }); + + ace.define("ace/mode/text_highlight_rules",["require","exports","module","ace/lib/lang"], function(acequire, exports, module) { + "use strict"; + + var lang = acequire("../lib/lang"); + + var TextHighlightRules = function() { + + this.$rules = { + "start" : [{ + token : "empty_line", + regex : '^$' + }, { + defaultToken : "text" + }] + }; + }; + + (function() { + + this.addRules = function(rules, prefix) { + if (!prefix) { + for (var key in rules) + this.$rules[key] = rules[key]; + return; + } + for (var key in rules) { + var state = rules[key]; + for (var i = 0; i < state.length; i++) { + var rule = state[i]; + if (rule.next || rule.onMatch) { + if (typeof rule.next == "string") { + if (rule.next.indexOf(prefix) !== 0) + rule.next = prefix + rule.next; + } + if (rule.nextState && rule.nextState.indexOf(prefix) !== 0) + rule.nextState = prefix + rule.nextState; + } + } + this.$rules[prefix + key] = state; + } + }; + + this.getRules = function() { + return this.$rules; + }; + + this.embedRules = function (HighlightRules, prefix, escapeRules, states, append) { + var embedRules = typeof HighlightRules == "function" + ? new HighlightRules().getRules() + : HighlightRules; + if (states) { + for (var i = 0; i < states.length; i++) + states[i] = prefix + states[i]; + } else { + states = []; + for (var key in embedRules) + states.push(prefix + key); + } + + this.addRules(embedRules, prefix); + + if (escapeRules) { + var addRules = Array.prototype[append ? "push" : "unshift"]; + for (var i = 0; i < states.length; i++) + addRules.apply(this.$rules[states[i]], lang.deepCopy(escapeRules)); + } + + if (!this.$embeds) + this.$embeds = []; + this.$embeds.push(prefix); + }; + + this.getEmbeds = function() { + return this.$embeds; + }; + + var pushState = function(currentState, stack) { + if (currentState != "start" || stack.length) + stack.unshift(this.nextState, currentState); + return this.nextState; + }; + var popState = function(currentState, stack) { + stack.shift(); + return stack.shift() || "start"; + }; + + this.normalizeRules = function() { + var id = 0; + var rules = this.$rules; + function processState(key) { + var state = rules[key]; + state.processed = true; + for (var i = 0; i < state.length; i++) { + var rule = state[i]; + if (!rule.regex && rule.start) { + rule.regex = rule.start; + if (!rule.next) + rule.next = []; + rule.next.push({ + defaultToken: rule.token + }, { + token: rule.token + ".end", + regex: rule.end || rule.start, + next: "pop" + }); + rule.token = rule.token + ".start"; + rule.push = true; + } + var next = rule.next || rule.push; + if (next && Array.isArray(next)) { + var stateName = rule.stateName; + if (!stateName) { + stateName = rule.token; + if (typeof stateName != "string") + stateName = stateName[0] || ""; + if (rules[stateName]) + stateName += id++; + } + rules[stateName] = next; + rule.next = stateName; + processState(stateName); + } else if (next == "pop") { + rule.next = popState; + } + + if (rule.push) { + rule.nextState = rule.next || rule.push; + rule.next = pushState; + delete rule.push; + } + + if (rule.rules) { + for (var r in rule.rules) { + if (rules[r]) { + if (rules[r].push) + rules[r].push.apply(rules[r], rule.rules[r]); + } else { + rules[r] = rule.rules[r]; + } + } + } + if (rule.include || typeof rule == "string") { + var includeName = rule.include || rule; + var toInsert = rules[includeName]; + } else if (Array.isArray(rule)) + toInsert = rule; + + if (toInsert) { + var args = [i, 1].concat(toInsert); + if (rule.noEscape) + args = args.filter(function(x) {return !x.next;}); + state.splice.apply(state, args); + i--; + toInsert = null; + } + + if (rule.keywordMap) { + rule.token = this.createKeywordMapper( + rule.keywordMap, rule.defaultToken || "text", rule.caseInsensitive + ); + delete rule.defaultToken; + } + } + } + Object.keys(rules).forEach(processState, this); + }; + + this.createKeywordMapper = function(map, defaultToken, ignoreCase, splitChar) { + var keywords = Object.create(null); + Object.keys(map).forEach(function(className) { + var a = map[className]; + if (ignoreCase) + a = a.toLowerCase(); + var list = a.split(splitChar || "|"); + for (var i = list.length; i--; ) + keywords[list[i]] = className; + }); + if (Object.getPrototypeOf(keywords)) { + keywords.__proto__ = null; + } + this.$keywordList = Object.keys(keywords); + map = null; + return ignoreCase + ? function(value) {return keywords[value.toLowerCase()] || defaultToken } + : function(value) {return keywords[value] || defaultToken }; + }; + + this.getKeywords = function() { + return this.$keywords; + }; + + }).call(TextHighlightRules.prototype); + + exports.TextHighlightRules = TextHighlightRules; + }); + + ace.define("ace/mode/behaviour",["require","exports","module"], function(acequire, exports, module) { + "use strict"; + + var Behaviour = function() { + this.$behaviours = {}; + }; + + (function () { + + this.add = function (name, action, callback) { + switch (undefined) { + case this.$behaviours: + this.$behaviours = {}; + case this.$behaviours[name]: + this.$behaviours[name] = {}; + } + this.$behaviours[name][action] = callback; + } + + this.addBehaviours = function (behaviours) { + for (var key in behaviours) { + for (var action in behaviours[key]) { + this.add(key, action, behaviours[key][action]); + } + } + } + + this.remove = function (name) { + if (this.$behaviours && this.$behaviours[name]) { + delete this.$behaviours[name]; + } + } + + this.inherit = function (mode, filter) { + if (typeof mode === "function") { + var behaviours = new mode().getBehaviours(filter); + } else { + var behaviours = mode.getBehaviours(filter); + } + this.addBehaviours(behaviours); + } + + this.getBehaviours = function (filter) { + if (!filter) { + return this.$behaviours; + } else { + var ret = {} + for (var i = 0; i < filter.length; i++) { + if (this.$behaviours[filter[i]]) { + ret[filter[i]] = this.$behaviours[filter[i]]; + } + } + return ret; + } + } + + }).call(Behaviour.prototype); + + exports.Behaviour = Behaviour; + }); + + ace.define("ace/unicode",["require","exports","module"], function(acequire, exports, module) { + "use strict"; + exports.packages = {}; + + addUnicodePackage({ + L: "0041-005A0061-007A00AA00B500BA00C0-00D600D8-00F600F8-02C102C6-02D102E0-02E402EC02EE0370-037403760377037A-037D03860388-038A038C038E-03A103A3-03F503F7-0481048A-05250531-055605590561-058705D0-05EA05F0-05F20621-064A066E066F0671-06D306D506E506E606EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA07F407F507FA0800-0815081A082408280904-0939093D09500958-0961097109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E460E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EC60EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10A0-10C510D0-10FA10FC1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317D717DC1820-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541AA71B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C7D1CE9-1CEC1CEE-1CF11D00-1DBF1E00-1F151F18-1F1D1F20-1F451F48-1F4D1F50-1F571F591F5B1F5D1F5F-1F7D1F80-1FB41FB6-1FBC1FBE1FC2-1FC41FC6-1FCC1FD0-1FD31FD6-1FDB1FE0-1FEC1FF2-1FF41FF6-1FFC2071207F2090-209421022107210A-211321152119-211D212421262128212A-212D212F-2139213C-213F2145-2149214E218321842C00-2C2E2C30-2C5E2C60-2CE42CEB-2CEE2D00-2D252D30-2D652D6F2D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE2E2F300530063031-3035303B303C3041-3096309D-309F30A1-30FA30FC-30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A48CA4D0-A4FDA500-A60CA610-A61FA62AA62BA640-A65FA662-A66EA67F-A697A6A0-A6E5A717-A71FA722-A788A78BA78CA7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2A9CFAA00-AA28AA40-AA42AA44-AA4BAA60-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADB-AADDABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB00-FB06FB13-FB17FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF21-FF3AFF41-FF5AFF66-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC", + Ll: "0061-007A00AA00B500BA00DF-00F600F8-00FF01010103010501070109010B010D010F01110113011501170119011B011D011F01210123012501270129012B012D012F01310133013501370138013A013C013E014001420144014601480149014B014D014F01510153015501570159015B015D015F01610163016501670169016B016D016F0171017301750177017A017C017E-0180018301850188018C018D019201950199-019B019E01A101A301A501A801AA01AB01AD01B001B401B601B901BA01BD-01BF01C601C901CC01CE01D001D201D401D601D801DA01DC01DD01DF01E101E301E501E701E901EB01ED01EF01F001F301F501F901FB01FD01FF02010203020502070209020B020D020F02110213021502170219021B021D021F02210223022502270229022B022D022F02310233-0239023C023F0240024202470249024B024D024F-02930295-02AF037103730377037B-037D039003AC-03CE03D003D103D5-03D703D903DB03DD03DF03E103E303E503E703E903EB03ED03EF-03F303F503F803FB03FC0430-045F04610463046504670469046B046D046F04710473047504770479047B047D047F0481048B048D048F04910493049504970499049B049D049F04A104A304A504A704A904AB04AD04AF04B104B304B504B704B904BB04BD04BF04C204C404C604C804CA04CC04CE04CF04D104D304D504D704D904DB04DD04DF04E104E304E504E704E904EB04ED04EF04F104F304F504F704F904FB04FD04FF05010503050505070509050B050D050F05110513051505170519051B051D051F0521052305250561-05871D00-1D2B1D62-1D771D79-1D9A1E011E031E051E071E091E0B1E0D1E0F1E111E131E151E171E191E1B1E1D1E1F1E211E231E251E271E291E2B1E2D1E2F1E311E331E351E371E391E3B1E3D1E3F1E411E431E451E471E491E4B1E4D1E4F1E511E531E551E571E591E5B1E5D1E5F1E611E631E651E671E691E6B1E6D1E6F1E711E731E751E771E791E7B1E7D1E7F1E811E831E851E871E891E8B1E8D1E8F1E911E931E95-1E9D1E9F1EA11EA31EA51EA71EA91EAB1EAD1EAF1EB11EB31EB51EB71EB91EBB1EBD1EBF1EC11EC31EC51EC71EC91ECB1ECD1ECF1ED11ED31ED51ED71ED91EDB1EDD1EDF1EE11EE31EE51EE71EE91EEB1EED1EEF1EF11EF31EF51EF71EF91EFB1EFD1EFF-1F071F10-1F151F20-1F271F30-1F371F40-1F451F50-1F571F60-1F671F70-1F7D1F80-1F871F90-1F971FA0-1FA71FB0-1FB41FB61FB71FBE1FC2-1FC41FC61FC71FD0-1FD31FD61FD71FE0-1FE71FF2-1FF41FF61FF7210A210E210F2113212F21342139213C213D2146-2149214E21842C30-2C5E2C612C652C662C682C6A2C6C2C712C732C742C76-2C7C2C812C832C852C872C892C8B2C8D2C8F2C912C932C952C972C992C9B2C9D2C9F2CA12CA32CA52CA72CA92CAB2CAD2CAF2CB12CB32CB52CB72CB92CBB2CBD2CBF2CC12CC32CC52CC72CC92CCB2CCD2CCF2CD12CD32CD52CD72CD92CDB2CDD2CDF2CE12CE32CE42CEC2CEE2D00-2D25A641A643A645A647A649A64BA64DA64FA651A653A655A657A659A65BA65DA65FA663A665A667A669A66BA66DA681A683A685A687A689A68BA68DA68FA691A693A695A697A723A725A727A729A72BA72DA72F-A731A733A735A737A739A73BA73DA73FA741A743A745A747A749A74BA74DA74FA751A753A755A757A759A75BA75DA75FA761A763A765A767A769A76BA76DA76FA771-A778A77AA77CA77FA781A783A785A787A78CFB00-FB06FB13-FB17FF41-FF5A", + Lu: "0041-005A00C0-00D600D8-00DE01000102010401060108010A010C010E01100112011401160118011A011C011E01200122012401260128012A012C012E01300132013401360139013B013D013F0141014301450147014A014C014E01500152015401560158015A015C015E01600162016401660168016A016C016E017001720174017601780179017B017D018101820184018601870189-018B018E-0191019301940196-0198019C019D019F01A001A201A401A601A701A901AC01AE01AF01B1-01B301B501B701B801BC01C401C701CA01CD01CF01D101D301D501D701D901DB01DE01E001E201E401E601E801EA01EC01EE01F101F401F6-01F801FA01FC01FE02000202020402060208020A020C020E02100212021402160218021A021C021E02200222022402260228022A022C022E02300232023A023B023D023E02410243-02460248024A024C024E03700372037603860388-038A038C038E038F0391-03A103A3-03AB03CF03D2-03D403D803DA03DC03DE03E003E203E403E603E803EA03EC03EE03F403F703F903FA03FD-042F04600462046404660468046A046C046E04700472047404760478047A047C047E0480048A048C048E04900492049404960498049A049C049E04A004A204A404A604A804AA04AC04AE04B004B204B404B604B804BA04BC04BE04C004C104C304C504C704C904CB04CD04D004D204D404D604D804DA04DC04DE04E004E204E404E604E804EA04EC04EE04F004F204F404F604F804FA04FC04FE05000502050405060508050A050C050E05100512051405160518051A051C051E0520052205240531-055610A0-10C51E001E021E041E061E081E0A1E0C1E0E1E101E121E141E161E181E1A1E1C1E1E1E201E221E241E261E281E2A1E2C1E2E1E301E321E341E361E381E3A1E3C1E3E1E401E421E441E461E481E4A1E4C1E4E1E501E521E541E561E581E5A1E5C1E5E1E601E621E641E661E681E6A1E6C1E6E1E701E721E741E761E781E7A1E7C1E7E1E801E821E841E861E881E8A1E8C1E8E1E901E921E941E9E1EA01EA21EA41EA61EA81EAA1EAC1EAE1EB01EB21EB41EB61EB81EBA1EBC1EBE1EC01EC21EC41EC61EC81ECA1ECC1ECE1ED01ED21ED41ED61ED81EDA1EDC1EDE1EE01EE21EE41EE61EE81EEA1EEC1EEE1EF01EF21EF41EF61EF81EFA1EFC1EFE1F08-1F0F1F18-1F1D1F28-1F2F1F38-1F3F1F48-1F4D1F591F5B1F5D1F5F1F68-1F6F1FB8-1FBB1FC8-1FCB1FD8-1FDB1FE8-1FEC1FF8-1FFB21022107210B-210D2110-211221152119-211D212421262128212A-212D2130-2133213E213F214521832C00-2C2E2C602C62-2C642C672C692C6B2C6D-2C702C722C752C7E-2C802C822C842C862C882C8A2C8C2C8E2C902C922C942C962C982C9A2C9C2C9E2CA02CA22CA42CA62CA82CAA2CAC2CAE2CB02CB22CB42CB62CB82CBA2CBC2CBE2CC02CC22CC42CC62CC82CCA2CCC2CCE2CD02CD22CD42CD62CD82CDA2CDC2CDE2CE02CE22CEB2CEDA640A642A644A646A648A64AA64CA64EA650A652A654A656A658A65AA65CA65EA662A664A666A668A66AA66CA680A682A684A686A688A68AA68CA68EA690A692A694A696A722A724A726A728A72AA72CA72EA732A734A736A738A73AA73CA73EA740A742A744A746A748A74AA74CA74EA750A752A754A756A758A75AA75CA75EA760A762A764A766A768A76AA76CA76EA779A77BA77DA77EA780A782A784A786A78BFF21-FF3A", + Lt: "01C501C801CB01F21F88-1F8F1F98-1F9F1FA8-1FAF1FBC1FCC1FFC", + Lm: "02B0-02C102C6-02D102E0-02E402EC02EE0374037A0559064006E506E607F407F507FA081A0824082809710E460EC610FC17D718431AA71C78-1C7D1D2C-1D611D781D9B-1DBF2071207F2090-20942C7D2D6F2E2F30053031-3035303B309D309E30FC-30FEA015A4F8-A4FDA60CA67FA717-A71FA770A788A9CFAA70AADDFF70FF9EFF9F", + Lo: "01BB01C0-01C3029405D0-05EA05F0-05F20621-063F0641-064A066E066F0671-06D306D506EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA0800-08150904-0939093D09500958-096109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E450E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10D0-10FA1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317DC1820-18421844-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C771CE9-1CEC1CEE-1CF12135-21382D30-2D652D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE3006303C3041-3096309F30A1-30FA30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A014A016-A48CA4D0-A4F7A500-A60BA610-A61FA62AA62BA66EA6A0-A6E5A7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2AA00-AA28AA40-AA42AA44-AA4BAA60-AA6FAA71-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADBAADCABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF66-FF6FFF71-FF9DFFA0-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC", + M: "0300-036F0483-04890591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DE-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0903093C093E-094E0951-0955096209630981-098309BC09BE-09C409C709C809CB-09CD09D709E209E30A01-0A030A3C0A3E-0A420A470A480A4B-0A4D0A510A700A710A750A81-0A830ABC0ABE-0AC50AC7-0AC90ACB-0ACD0AE20AE30B01-0B030B3C0B3E-0B440B470B480B4B-0B4D0B560B570B620B630B820BBE-0BC20BC6-0BC80BCA-0BCD0BD70C01-0C030C3E-0C440C46-0C480C4A-0C4D0C550C560C620C630C820C830CBC0CBE-0CC40CC6-0CC80CCA-0CCD0CD50CD60CE20CE30D020D030D3E-0D440D46-0D480D4A-0D4D0D570D620D630D820D830DCA0DCF-0DD40DD60DD8-0DDF0DF20DF30E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F3E0F3F0F71-0F840F860F870F90-0F970F99-0FBC0FC6102B-103E1056-1059105E-10601062-10641067-106D1071-10741082-108D108F109A-109D135F1712-17141732-1734175217531772177317B6-17D317DD180B-180D18A91920-192B1930-193B19B0-19C019C819C91A17-1A1B1A55-1A5E1A60-1A7C1A7F1B00-1B041B34-1B441B6B-1B731B80-1B821BA1-1BAA1C24-1C371CD0-1CD21CD4-1CE81CED1CF21DC0-1DE61DFD-1DFF20D0-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66F-A672A67CA67DA6F0A6F1A802A806A80BA823-A827A880A881A8B4-A8C4A8E0-A8F1A926-A92DA947-A953A980-A983A9B3-A9C0AA29-AA36AA43AA4CAA4DAA7BAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE3-ABEAABECABEDFB1EFE00-FE0FFE20-FE26", + Mn: "0300-036F0483-04870591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DF-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0902093C0941-0948094D0951-095509620963098109BC09C1-09C409CD09E209E30A010A020A3C0A410A420A470A480A4B-0A4D0A510A700A710A750A810A820ABC0AC1-0AC50AC70AC80ACD0AE20AE30B010B3C0B3F0B41-0B440B4D0B560B620B630B820BC00BCD0C3E-0C400C46-0C480C4A-0C4D0C550C560C620C630CBC0CBF0CC60CCC0CCD0CE20CE30D41-0D440D4D0D620D630DCA0DD2-0DD40DD60E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F71-0F7E0F80-0F840F860F870F90-0F970F99-0FBC0FC6102D-10301032-10371039103A103D103E10581059105E-10601071-1074108210851086108D109D135F1712-17141732-1734175217531772177317B7-17BD17C617C9-17D317DD180B-180D18A91920-19221927192819321939-193B1A171A181A561A58-1A5E1A601A621A65-1A6C1A73-1A7C1A7F1B00-1B031B341B36-1B3A1B3C1B421B6B-1B731B801B811BA2-1BA51BA81BA91C2C-1C331C361C371CD0-1CD21CD4-1CE01CE2-1CE81CED1DC0-1DE61DFD-1DFF20D0-20DC20E120E5-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66FA67CA67DA6F0A6F1A802A806A80BA825A826A8C4A8E0-A8F1A926-A92DA947-A951A980-A982A9B3A9B6-A9B9A9BCAA29-AA2EAA31AA32AA35AA36AA43AA4CAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE5ABE8ABEDFB1EFE00-FE0FFE20-FE26", + Mc: "0903093E-09400949-094C094E0982098309BE-09C009C709C809CB09CC09D70A030A3E-0A400A830ABE-0AC00AC90ACB0ACC0B020B030B3E0B400B470B480B4B0B4C0B570BBE0BBF0BC10BC20BC6-0BC80BCA-0BCC0BD70C01-0C030C41-0C440C820C830CBE0CC0-0CC40CC70CC80CCA0CCB0CD50CD60D020D030D3E-0D400D46-0D480D4A-0D4C0D570D820D830DCF-0DD10DD8-0DDF0DF20DF30F3E0F3F0F7F102B102C10311038103B103C105610571062-10641067-106D108310841087-108C108F109A-109C17B617BE-17C517C717C81923-19261929-192B193019311933-193819B0-19C019C819C91A19-1A1B1A551A571A611A631A641A6D-1A721B041B351B3B1B3D-1B411B431B441B821BA11BA61BA71BAA1C24-1C2B1C341C351CE11CF2A823A824A827A880A881A8B4-A8C3A952A953A983A9B4A9B5A9BAA9BBA9BD-A9C0AA2FAA30AA33AA34AA4DAA7BABE3ABE4ABE6ABE7ABE9ABEAABEC", + Me: "0488048906DE20DD-20E020E2-20E4A670-A672", + N: "0030-003900B200B300B900BC-00BE0660-066906F0-06F907C0-07C90966-096F09E6-09EF09F4-09F90A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BF20C66-0C6F0C78-0C7E0CE6-0CEF0D66-0D750E50-0E590ED0-0ED90F20-0F331040-10491090-10991369-137C16EE-16F017E0-17E917F0-17F91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C5920702074-20792080-20892150-21822185-21892460-249B24EA-24FF2776-27932CFD30073021-30293038-303A3192-31953220-32293251-325F3280-328932B1-32BFA620-A629A6E6-A6EFA830-A835A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19", + Nd: "0030-00390660-066906F0-06F907C0-07C90966-096F09E6-09EF0A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BEF0C66-0C6F0CE6-0CEF0D66-0D6F0E50-0E590ED0-0ED90F20-0F291040-10491090-109917E0-17E91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C59A620-A629A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19", + Nl: "16EE-16F02160-21822185-218830073021-30293038-303AA6E6-A6EF", + No: "00B200B300B900BC-00BE09F4-09F90BF0-0BF20C78-0C7E0D70-0D750F2A-0F331369-137C17F0-17F920702074-20792080-20892150-215F21892460-249B24EA-24FF2776-27932CFD3192-31953220-32293251-325F3280-328932B1-32BFA830-A835", + P: "0021-00230025-002A002C-002F003A003B003F0040005B-005D005F007B007D00A100AB00B700BB00BF037E0387055A-055F0589058A05BE05C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F3A-0F3D0F850FD0-0FD4104A-104F10FB1361-13681400166D166E169B169C16EB-16ED1735173617D4-17D617D8-17DA1800-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD32010-20272030-20432045-20512053-205E207D207E208D208E2329232A2768-277527C527C627E6-27EF2983-299829D8-29DB29FC29FD2CF9-2CFC2CFE2CFF2E00-2E2E2E302E313001-30033008-30113014-301F3030303D30A030FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFD3EFD3FFE10-FE19FE30-FE52FE54-FE61FE63FE68FE6AFE6BFF01-FF03FF05-FF0AFF0C-FF0FFF1AFF1BFF1FFF20FF3B-FF3DFF3FFF5BFF5DFF5F-FF65", + Pd: "002D058A05BE140018062010-20152E172E1A301C303030A0FE31FE32FE58FE63FF0D", + Ps: "0028005B007B0F3A0F3C169B201A201E2045207D208D23292768276A276C276E27702772277427C527E627E827EA27EC27EE2983298529872989298B298D298F299129932995299729D829DA29FC2E222E242E262E283008300A300C300E3010301430163018301A301DFD3EFE17FE35FE37FE39FE3BFE3DFE3FFE41FE43FE47FE59FE5BFE5DFF08FF3BFF5BFF5FFF62", + Pe: "0029005D007D0F3B0F3D169C2046207E208E232A2769276B276D276F27712773277527C627E727E927EB27ED27EF298429862988298A298C298E2990299229942996299829D929DB29FD2E232E252E272E293009300B300D300F3011301530173019301B301E301FFD3FFE18FE36FE38FE3AFE3CFE3EFE40FE42FE44FE48FE5AFE5CFE5EFF09FF3DFF5DFF60FF63", + Pi: "00AB2018201B201C201F20392E022E042E092E0C2E1C2E20", + Pf: "00BB2019201D203A2E032E052E0A2E0D2E1D2E21", + Pc: "005F203F20402054FE33FE34FE4D-FE4FFF3F", + Po: "0021-00230025-0027002A002C002E002F003A003B003F0040005C00A100B700BF037E0387055A-055F058905C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F850FD0-0FD4104A-104F10FB1361-1368166D166E16EB-16ED1735173617D4-17D617D8-17DA1800-18051807-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD3201620172020-20272030-2038203B-203E2041-20432047-205120532055-205E2CF9-2CFC2CFE2CFF2E002E012E06-2E082E0B2E0E-2E162E182E192E1B2E1E2E1F2E2A-2E2E2E302E313001-3003303D30FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFE10-FE16FE19FE30FE45FE46FE49-FE4CFE50-FE52FE54-FE57FE5F-FE61FE68FE6AFE6BFF01-FF03FF05-FF07FF0AFF0CFF0EFF0FFF1AFF1BFF1FFF20FF3CFF61FF64FF65", + S: "0024002B003C-003E005E0060007C007E00A2-00A900AC00AE-00B100B400B600B800D700F702C2-02C502D2-02DF02E5-02EB02ED02EF-02FF03750384038503F604820606-0608060B060E060F06E906FD06FE07F609F209F309FA09FB0AF10B700BF3-0BFA0C7F0CF10CF20D790E3F0F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-139917DB194019E0-19FF1B61-1B6A1B74-1B7C1FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE20442052207A-207C208A-208C20A0-20B8210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B2140-2144214A-214D214F2190-2328232B-23E82400-24262440-244A249C-24E92500-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE27C0-27C427C7-27CA27CC27D0-27E527F0-29822999-29D729DC-29FB29FE-2B4C2B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F309B309C319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A700-A716A720A721A789A78AA828-A82BA836-A839AA77-AA79FB29FDFCFDFDFE62FE64-FE66FE69FF04FF0BFF1C-FF1EFF3EFF40FF5CFF5EFFE0-FFE6FFE8-FFEEFFFCFFFD", + Sm: "002B003C-003E007C007E00AC00B100D700F703F60606-060820442052207A-207C208A-208C2140-2144214B2190-2194219A219B21A021A321A621AE21CE21CF21D221D421F4-22FF2308-230B23202321237C239B-23B323DC-23E125B725C125F8-25FF266F27C0-27C427C7-27CA27CC27D0-27E527F0-27FF2900-29822999-29D729DC-29FB29FE-2AFF2B30-2B442B47-2B4CFB29FE62FE64-FE66FF0BFF1C-FF1EFF5CFF5EFFE2FFE9-FFEC", + Sc: "002400A2-00A5060B09F209F309FB0AF10BF90E3F17DB20A0-20B8A838FDFCFE69FF04FFE0FFE1FFE5FFE6", + Sk: "005E006000A800AF00B400B802C2-02C502D2-02DF02E5-02EB02ED02EF-02FF0375038403851FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE309B309CA700-A716A720A721A789A78AFF3EFF40FFE3", + So: "00A600A700A900AE00B000B60482060E060F06E906FD06FE07F609FA0B700BF3-0BF80BFA0C7F0CF10CF20D790F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-1399194019E0-19FF1B61-1B6A1B74-1B7C210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B214A214C214D214F2195-2199219C-219F21A121A221A421A521A7-21AD21AF-21CD21D021D121D321D5-21F32300-2307230C-231F2322-2328232B-237B237D-239A23B4-23DB23E2-23E82400-24262440-244A249C-24E92500-25B625B8-25C025C2-25F72600-266E2670-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE2800-28FF2B00-2B2F2B452B462B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A828-A82BA836A837A839AA77-AA79FDFDFFE4FFE8FFEDFFEEFFFCFFFD", + Z: "002000A01680180E2000-200A20282029202F205F3000", + Zs: "002000A01680180E2000-200A202F205F3000", + Zl: "2028", + Zp: "2029", + C: "0000-001F007F-009F00AD03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-0605061C061D0620065F06DD070E070F074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17B417B517DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF200B-200F202A-202E2060-206F20722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-F8FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFD-FF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFFBFFFEFFFF", + Cc: "0000-001F007F-009F", + Cf: "00AD0600-060306DD070F17B417B5200B-200F202A-202E2060-2064206A-206FFEFFFFF9-FFFB", + Co: "E000-F8FF", + Cs: "D800-DFFF", + Cn: "03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-05FF06040605061C061D0620065F070E074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF2065-206920722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-D7FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFDFEFEFF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFF8FFFEFFFF" + }); + + function addUnicodePackage (pack) { + var codePoint = /\w{4}/g; + for (var name in pack) + exports.packages[name] = pack[name].replace(codePoint, "\\u$&"); + } + + }); + + ace.define("ace/token_iterator",["require","exports","module"], function(acequire, exports, module) { + "use strict"; + var TokenIterator = function(session, initialRow, initialColumn) { + this.$session = session; + this.$row = initialRow; + this.$rowTokens = session.getTokens(initialRow); + + var token = session.getTokenAt(initialRow, initialColumn); + this.$tokenIndex = token ? token.index : -1; + }; + + (function() { + this.stepBackward = function() { + this.$tokenIndex -= 1; + + while (this.$tokenIndex < 0) { + this.$row -= 1; + if (this.$row < 0) { + this.$row = 0; + return null; + } + + this.$rowTokens = this.$session.getTokens(this.$row); + this.$tokenIndex = this.$rowTokens.length - 1; + } + + return this.$rowTokens[this.$tokenIndex]; + }; + this.stepForward = function() { + this.$tokenIndex += 1; + var rowCount; + while (this.$tokenIndex >= this.$rowTokens.length) { + this.$row += 1; + if (!rowCount) + rowCount = this.$session.getLength(); + if (this.$row >= rowCount) { + this.$row = rowCount - 1; + return null; + } + + this.$rowTokens = this.$session.getTokens(this.$row); + this.$tokenIndex = 0; + } + + return this.$rowTokens[this.$tokenIndex]; + }; + this.getCurrentToken = function () { + return this.$rowTokens[this.$tokenIndex]; + }; + this.getCurrentTokenRow = function () { + return this.$row; + }; + this.getCurrentTokenColumn = function() { + var rowTokens = this.$rowTokens; + var tokenIndex = this.$tokenIndex; + var column = rowTokens[tokenIndex].start; + if (column !== undefined) + return column; + + column = 0; + while (tokenIndex > 0) { + tokenIndex -= 1; + column += rowTokens[tokenIndex].value.length; + } + + return column; + }; + this.getCurrentTokenPosition = function() { + return {row: this.$row, column: this.getCurrentTokenColumn()}; + }; + + }).call(TokenIterator.prototype); + + exports.TokenIterator = TokenIterator; + }); + + ace.define("ace/mode/text",["require","exports","module","ace/tokenizer","ace/mode/text_highlight_rules","ace/mode/behaviour","ace/unicode","ace/lib/lang","ace/token_iterator","ace/range"], function(acequire, exports, module) { + "use strict"; + + var Tokenizer = acequire("../tokenizer").Tokenizer; + var TextHighlightRules = acequire("./text_highlight_rules").TextHighlightRules; + var Behaviour = acequire("./behaviour").Behaviour; + var unicode = acequire("../unicode"); + var lang = acequire("../lib/lang"); + var TokenIterator = acequire("../token_iterator").TokenIterator; + var Range = acequire("../range").Range; + + var Mode = function() { + this.HighlightRules = TextHighlightRules; + this.$behaviour = new Behaviour(); + }; + + (function() { + + this.tokenRe = new RegExp("^[" + + unicode.packages.L + + unicode.packages.Mn + unicode.packages.Mc + + unicode.packages.Nd + + unicode.packages.Pc + "\\$_]+", "g" + ); + + this.nonTokenRe = new RegExp("^(?:[^" + + unicode.packages.L + + unicode.packages.Mn + unicode.packages.Mc + + unicode.packages.Nd + + unicode.packages.Pc + "\\$_]|\\s])+", "g" + ); + + this.getTokenizer = function() { + if (!this.$tokenizer) { + this.$highlightRules = this.$highlightRules || new this.HighlightRules(); + this.$tokenizer = new Tokenizer(this.$highlightRules.getRules()); + } + return this.$tokenizer; + }; + + this.lineCommentStart = ""; + this.blockComment = ""; + + this.toggleCommentLines = function(state, session, startRow, endRow) { + var doc = session.doc; + + var ignoreBlankLines = true; + var shouldRemove = true; + var minIndent = Infinity; + var tabSize = session.getTabSize(); + var insertAtTabStop = false; + + if (!this.lineCommentStart) { + if (!this.blockComment) + return false; + var lineCommentStart = this.blockComment.start; + var lineCommentEnd = this.blockComment.end; + var regexpStart = new RegExp("^(\\s*)(?:" + lang.escapeRegExp(lineCommentStart) + ")"); + var regexpEnd = new RegExp("(?:" + lang.escapeRegExp(lineCommentEnd) + ")\\s*$"); + + var comment = function(line, i) { + if (testRemove(line, i)) + return; + if (!ignoreBlankLines || /\S/.test(line)) { + doc.insertInLine({row: i, column: line.length}, lineCommentEnd); + doc.insertInLine({row: i, column: minIndent}, lineCommentStart); + } + }; + + var uncomment = function(line, i) { + var m; + if (m = line.match(regexpEnd)) + doc.removeInLine(i, line.length - m[0].length, line.length); + if (m = line.match(regexpStart)) + doc.removeInLine(i, m[1].length, m[0].length); + }; + + var testRemove = function(line, row) { + if (regexpStart.test(line)) + return true; + var tokens = session.getTokens(row); + for (var i = 0; i < tokens.length; i++) { + if (tokens[i].type === "comment") + return true; + } + }; + } else { + if (Array.isArray(this.lineCommentStart)) { + var regexpStart = this.lineCommentStart.map(lang.escapeRegExp).join("|"); + var lineCommentStart = this.lineCommentStart[0]; + } else { + var regexpStart = lang.escapeRegExp(this.lineCommentStart); + var lineCommentStart = this.lineCommentStart; + } + regexpStart = new RegExp("^(\\s*)(?:" + regexpStart + ") ?"); + + insertAtTabStop = session.getUseSoftTabs(); + + var uncomment = function(line, i) { + var m = line.match(regexpStart); + if (!m) return; + var start = m[1].length, end = m[0].length; + if (!shouldInsertSpace(line, start, end) && m[0][end - 1] == " ") + end--; + doc.removeInLine(i, start, end); + }; + var commentWithSpace = lineCommentStart + " "; + var comment = function(line, i) { + if (!ignoreBlankLines || /\S/.test(line)) { + if (shouldInsertSpace(line, minIndent, minIndent)) + doc.insertInLine({row: i, column: minIndent}, commentWithSpace); + else + doc.insertInLine({row: i, column: minIndent}, lineCommentStart); + } + }; + var testRemove = function(line, i) { + return regexpStart.test(line); + }; + + var shouldInsertSpace = function(line, before, after) { + var spaces = 0; + while (before-- && line.charAt(before) == " ") + spaces++; + if (spaces % tabSize != 0) + return false; + var spaces = 0; + while (line.charAt(after++) == " ") + spaces++; + if (tabSize > 2) + return spaces % tabSize != tabSize - 1; + else + return spaces % tabSize == 0; + return true; + }; + } + + function iter(fun) { + for (var i = startRow; i <= endRow; i++) + fun(doc.getLine(i), i); + } + + + var minEmptyLength = Infinity; + iter(function(line, i) { + var indent = line.search(/\S/); + if (indent !== -1) { + if (indent < minIndent) + minIndent = indent; + if (shouldRemove && !testRemove(line, i)) + shouldRemove = false; + } else if (minEmptyLength > line.length) { + minEmptyLength = line.length; + } + }); + + if (minIndent == Infinity) { + minIndent = minEmptyLength; + ignoreBlankLines = false; + shouldRemove = false; + } + + if (insertAtTabStop && minIndent % tabSize != 0) + minIndent = Math.floor(minIndent / tabSize) * tabSize; + + iter(shouldRemove ? uncomment : comment); + }; + + this.toggleBlockComment = function(state, session, range, cursor) { + var comment = this.blockComment; + if (!comment) + return; + if (!comment.start && comment[0]) + comment = comment[0]; + + var iterator = new TokenIterator(session, cursor.row, cursor.column); + var token = iterator.getCurrentToken(); + + var sel = session.selection; + var initialRange = session.selection.toOrientedRange(); + var startRow, colDiff; + + if (token && /comment/.test(token.type)) { + var startRange, endRange; + while (token && /comment/.test(token.type)) { + var i = token.value.indexOf(comment.start); + if (i != -1) { + var row = iterator.getCurrentTokenRow(); + var column = iterator.getCurrentTokenColumn() + i; + startRange = new Range(row, column, row, column + comment.start.length); + break; + } + token = iterator.stepBackward(); + } + + var iterator = new TokenIterator(session, cursor.row, cursor.column); + var token = iterator.getCurrentToken(); + while (token && /comment/.test(token.type)) { + var i = token.value.indexOf(comment.end); + if (i != -1) { + var row = iterator.getCurrentTokenRow(); + var column = iterator.getCurrentTokenColumn() + i; + endRange = new Range(row, column, row, column + comment.end.length); + break; + } + token = iterator.stepForward(); + } + if (endRange) + session.remove(endRange); + if (startRange) { + session.remove(startRange); + startRow = startRange.start.row; + colDiff = -comment.start.length; + } + } else { + colDiff = comment.start.length; + startRow = range.start.row; + session.insert(range.end, comment.end); + session.insert(range.start, comment.start); + } + if (initialRange.start.row == startRow) + initialRange.start.column += colDiff; + if (initialRange.end.row == startRow) + initialRange.end.column += colDiff; + session.selection.fromOrientedRange(initialRange); + }; + + this.getNextLineIndent = function(state, line, tab) { + return this.$getIndent(line); + }; + + this.checkOutdent = function(state, line, input) { + return false; + }; + + this.autoOutdent = function(state, doc, row) { + }; + + this.$getIndent = function(line) { + return line.match(/^\s*/)[0]; + }; + + this.createWorker = function(session) { + return null; + }; + + this.createModeDelegates = function (mapping) { + this.$embeds = []; + this.$modes = {}; + for (var i in mapping) { + if (mapping[i]) { + this.$embeds.push(i); + this.$modes[i] = new mapping[i](); + } + } + + var delegations = ["toggleBlockComment", "toggleCommentLines", "getNextLineIndent", + "checkOutdent", "autoOutdent", "transformAction", "getCompletions"]; + + for (var i = 0; i < delegations.length; i++) { + (function(scope) { + var functionName = delegations[i]; + var defaultHandler = scope[functionName]; + scope[delegations[i]] = function() { + return this.$delegator(functionName, arguments, defaultHandler); + }; + }(this)); + } + }; + + this.$delegator = function(method, args, defaultHandler) { + var state = args[0]; + if (typeof state != "string") + state = state[0]; + for (var i = 0; i < this.$embeds.length; i++) { + if (!this.$modes[this.$embeds[i]]) continue; + + var split = state.split(this.$embeds[i]); + if (!split[0] && split[1]) { + args[0] = split[1]; + var mode = this.$modes[this.$embeds[i]]; + return mode[method].apply(mode, args); + } + } + var ret = defaultHandler.apply(this, args); + return defaultHandler ? ret : undefined; + }; + + this.transformAction = function(state, action, editor, session, param) { + if (this.$behaviour) { + var behaviours = this.$behaviour.getBehaviours(); + for (var key in behaviours) { + if (behaviours[key][action]) { + var ret = behaviours[key][action].apply(this, arguments); + if (ret) { + return ret; + } + } + } + } + }; + + this.getKeywords = function(append) { + if (!this.completionKeywords) { + var rules = this.$tokenizer.rules; + var completionKeywords = []; + for (var rule in rules) { + var ruleItr = rules[rule]; + for (var r = 0, l = ruleItr.length; r < l; r++) { + if (typeof ruleItr[r].token === "string") { + if (/keyword|support|storage/.test(ruleItr[r].token)) + completionKeywords.push(ruleItr[r].regex); + } + else if (typeof ruleItr[r].token === "object") { + for (var a = 0, aLength = ruleItr[r].token.length; a < aLength; a++) { + if (/keyword|support|storage/.test(ruleItr[r].token[a])) { + var rule = ruleItr[r].regex.match(/\(.+?\)/g)[a]; + completionKeywords.push(rule.substr(1, rule.length - 2)); + } + } + } + } + } + this.completionKeywords = completionKeywords; + } + if (!append) + return this.$keywordList; + return completionKeywords.concat(this.$keywordList || []); + }; + + this.$createKeywordList = function() { + if (!this.$highlightRules) + this.getTokenizer(); + return this.$keywordList = this.$highlightRules.$keywordList || []; + }; + + this.getCompletions = function(state, session, pos, prefix) { + var keywords = this.$keywordList || this.$createKeywordList(); + return keywords.map(function(word) { + return { + name: word, + value: word, + score: 0, + meta: "keyword" + }; + }); + }; + + this.$id = "ace/mode/text"; + }).call(Mode.prototype); + + exports.Mode = Mode; + }); + + ace.define("ace/apply_delta",["require","exports","module"], function(acequire, exports, module) { + "use strict"; + + function throwDeltaError(delta, errorText){ + console.log("Invalid Delta:", delta); + throw "Invalid Delta: " + errorText; + } + + function positionInDocument(docLines, position) { + return position.row >= 0 && position.row < docLines.length && + position.column >= 0 && position.column <= docLines[position.row].length; + } + + function validateDelta(docLines, delta) { + if (delta.action != "insert" && delta.action != "remove") + throwDeltaError(delta, "delta.action must be 'insert' or 'remove'"); + if (!(delta.lines instanceof Array)) + throwDeltaError(delta, "delta.lines must be an Array"); + if (!delta.start || !delta.end) + throwDeltaError(delta, "delta.start/end must be an present"); + var start = delta.start; + if (!positionInDocument(docLines, delta.start)) + throwDeltaError(delta, "delta.start must be contained in document"); + var end = delta.end; + if (delta.action == "remove" && !positionInDocument(docLines, end)) + throwDeltaError(delta, "delta.end must contained in document for 'remove' actions"); + var numRangeRows = end.row - start.row; + var numRangeLastLineChars = (end.column - (numRangeRows == 0 ? start.column : 0)); + if (numRangeRows != delta.lines.length - 1 || delta.lines[numRangeRows].length != numRangeLastLineChars) + throwDeltaError(delta, "delta.range must match delta lines"); + } + + exports.applyDelta = function(docLines, delta, doNotValidate) { + + var row = delta.start.row; + var startColumn = delta.start.column; + var line = docLines[row] || ""; + switch (delta.action) { + case "insert": + var lines = delta.lines; + if (lines.length === 1) { + docLines[row] = line.substring(0, startColumn) + delta.lines[0] + line.substring(startColumn); + } else { + var args = [row, 1].concat(delta.lines); + docLines.splice.apply(docLines, args); + docLines[row] = line.substring(0, startColumn) + docLines[row]; + docLines[row + delta.lines.length - 1] += line.substring(startColumn); + } + break; + case "remove": + var endColumn = delta.end.column; + var endRow = delta.end.row; + if (row === endRow) { + docLines[row] = line.substring(0, startColumn) + line.substring(endColumn); + } else { + docLines.splice( + row, endRow - row + 1, + line.substring(0, startColumn) + docLines[endRow].substring(endColumn) + ); + } + break; + } + } + }); + + ace.define("ace/anchor",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("./lib/oop"); + var EventEmitter = acequire("./lib/event_emitter").EventEmitter; + + var Anchor = exports.Anchor = function(doc, row, column) { + this.$onChange = this.onChange.bind(this); + this.attach(doc); + + if (typeof column == "undefined") + this.setPosition(row.row, row.column); + else + this.setPosition(row, column); + }; + + (function() { + + oop.implement(this, EventEmitter); + this.getPosition = function() { + return this.$clipPositionToDocument(this.row, this.column); + }; + this.getDocument = function() { + return this.document; + }; + this.$insertRight = false; + this.onChange = function(delta) { + if (delta.start.row == delta.end.row && delta.start.row != this.row) + return; + + if (delta.start.row > this.row) + return; + + var point = $getTransformedPoint(delta, {row: this.row, column: this.column}, this.$insertRight); + this.setPosition(point.row, point.column, true); + }; + + function $pointsInOrder(point1, point2, equalPointsInOrder) { + var bColIsAfter = equalPointsInOrder ? point1.column <= point2.column : point1.column < point2.column; + return (point1.row < point2.row) || (point1.row == point2.row && bColIsAfter); + } + + function $getTransformedPoint(delta, point, moveIfEqual) { + var deltaIsInsert = delta.action == "insert"; + var deltaRowShift = (deltaIsInsert ? 1 : -1) * (delta.end.row - delta.start.row); + var deltaColShift = (deltaIsInsert ? 1 : -1) * (delta.end.column - delta.start.column); + var deltaStart = delta.start; + var deltaEnd = deltaIsInsert ? deltaStart : delta.end; // Collapse insert range. + if ($pointsInOrder(point, deltaStart, moveIfEqual)) { + return { + row: point.row, + column: point.column + }; + } + if ($pointsInOrder(deltaEnd, point, !moveIfEqual)) { + return { + row: point.row + deltaRowShift, + column: point.column + (point.row == deltaEnd.row ? deltaColShift : 0) + }; + } + + return { + row: deltaStart.row, + column: deltaStart.column + }; + } + this.setPosition = function(row, column, noClip) { + var pos; + if (noClip) { + pos = { + row: row, + column: column + }; + } else { + pos = this.$clipPositionToDocument(row, column); + } + + if (this.row == pos.row && this.column == pos.column) + return; + + var old = { + row: this.row, + column: this.column + }; + + this.row = pos.row; + this.column = pos.column; + this._signal("change", { + old: old, + value: pos + }); + }; + this.detach = function() { + this.document.removeEventListener("change", this.$onChange); + }; + this.attach = function(doc) { + this.document = doc || this.document; + this.document.on("change", this.$onChange); + }; + this.$clipPositionToDocument = function(row, column) { + var pos = {}; + + if (row >= this.document.getLength()) { + pos.row = Math.max(0, this.document.getLength() - 1); + pos.column = this.document.getLine(pos.row).length; + } + else if (row < 0) { + pos.row = 0; + pos.column = 0; + } + else { + pos.row = row; + pos.column = Math.min(this.document.getLine(pos.row).length, Math.max(0, column)); + } + + if (column < 0) + pos.column = 0; + + return pos; + }; + + }).call(Anchor.prototype); + + }); + + ace.define("ace/document",["require","exports","module","ace/lib/oop","ace/apply_delta","ace/lib/event_emitter","ace/range","ace/anchor"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("./lib/oop"); + var applyDelta = acequire("./apply_delta").applyDelta; + var EventEmitter = acequire("./lib/event_emitter").EventEmitter; + var Range = acequire("./range").Range; + var Anchor = acequire("./anchor").Anchor; + + var Document = function(textOrLines) { + this.$lines = [""]; + if (textOrLines.length === 0) { + this.$lines = [""]; + } else if (Array.isArray(textOrLines)) { + this.insertMergedLines({row: 0, column: 0}, textOrLines); + } else { + this.insert({row: 0, column:0}, textOrLines); + } + }; + + (function() { + + oop.implement(this, EventEmitter); + this.setValue = function(text) { + var len = this.getLength() - 1; + this.remove(new Range(0, 0, len, this.getLine(len).length)); + this.insert({row: 0, column: 0}, text); + }; + this.getValue = function() { + return this.getAllLines().join(this.getNewLineCharacter()); + }; + this.createAnchor = function(row, column) { + return new Anchor(this, row, column); + }; + if ("aaa".split(/a/).length === 0) { + this.$split = function(text) { + return text.replace(/\r\n|\r/g, "\n").split("\n"); + }; + } else { + this.$split = function(text) { + return text.split(/\r\n|\r|\n/); + }; + } + + + this.$detectNewLine = function(text) { + var match = text.match(/^.*?(\r\n|\r|\n)/m); + this.$autoNewLine = match ? match[1] : "\n"; + this._signal("changeNewLineMode"); + }; + this.getNewLineCharacter = function() { + switch (this.$newLineMode) { + case "windows": + return "\r\n"; + case "unix": + return "\n"; + default: + return this.$autoNewLine || "\n"; + } + }; + + this.$autoNewLine = ""; + this.$newLineMode = "auto"; + this.setNewLineMode = function(newLineMode) { + if (this.$newLineMode === newLineMode) + return; + + this.$newLineMode = newLineMode; + this._signal("changeNewLineMode"); + }; + this.getNewLineMode = function() { + return this.$newLineMode; + }; + this.isNewLine = function(text) { + return (text == "\r\n" || text == "\r" || text == "\n"); + }; + this.getLine = function(row) { + return this.$lines[row] || ""; + }; + this.getLines = function(firstRow, lastRow) { + return this.$lines.slice(firstRow, lastRow + 1); + }; + this.getAllLines = function() { + return this.getLines(0, this.getLength()); + }; + this.getLength = function() { + return this.$lines.length; + }; + this.getTextRange = function(range) { + return this.getLinesForRange(range).join(this.getNewLineCharacter()); + }; + this.getLinesForRange = function(range) { + var lines; + if (range.start.row === range.end.row) { + lines = [this.getLine(range.start.row).substring(range.start.column, range.end.column)]; + } else { + lines = this.getLines(range.start.row, range.end.row); + lines[0] = (lines[0] || "").substring(range.start.column); + var l = lines.length - 1; + if (range.end.row - range.start.row == l) + lines[l] = lines[l].substring(0, range.end.column); + } + return lines; + }; + this.insertLines = function(row, lines) { + console.warn("Use of document.insertLines is deprecated. Use the insertFullLines method instead."); + return this.insertFullLines(row, lines); + }; + this.removeLines = function(firstRow, lastRow) { + console.warn("Use of document.removeLines is deprecated. Use the removeFullLines method instead."); + return this.removeFullLines(firstRow, lastRow); + }; + this.insertNewLine = function(position) { + console.warn("Use of document.insertNewLine is deprecated. Use insertMergedLines(position, [\'\', \'\']) instead."); + return this.insertMergedLines(position, ["", ""]); + }; + this.insert = function(position, text) { + if (this.getLength() <= 1) + this.$detectNewLine(text); + + return this.insertMergedLines(position, this.$split(text)); + }; + this.insertInLine = function(position, text) { + var start = this.clippedPos(position.row, position.column); + var end = this.pos(position.row, position.column + text.length); + + this.applyDelta({ + start: start, + end: end, + action: "insert", + lines: [text] + }, true); + + return this.clonePos(end); + }; + + this.clippedPos = function(row, column) { + var length = this.getLength(); + if (row === undefined) { + row = length; + } else if (row < 0) { + row = 0; + } else if (row >= length) { + row = length - 1; + column = undefined; + } + var line = this.getLine(row); + if (column == undefined) + column = line.length; + column = Math.min(Math.max(column, 0), line.length); + return {row: row, column: column}; + }; + + this.clonePos = function(pos) { + return {row: pos.row, column: pos.column}; + }; + + this.pos = function(row, column) { + return {row: row, column: column}; + }; + + this.$clipPosition = function(position) { + var length = this.getLength(); + if (position.row >= length) { + position.row = Math.max(0, length - 1); + position.column = this.getLine(length - 1).length; + } else { + position.row = Math.max(0, position.row); + position.column = Math.min(Math.max(position.column, 0), this.getLine(position.row).length); + } + return position; + }; + this.insertFullLines = function(row, lines) { + row = Math.min(Math.max(row, 0), this.getLength()); + var column = 0; + if (row < this.getLength()) { + lines = lines.concat([""]); + column = 0; + } else { + lines = [""].concat(lines); + row--; + column = this.$lines[row].length; + } + this.insertMergedLines({row: row, column: column}, lines); + }; + this.insertMergedLines = function(position, lines) { + var start = this.clippedPos(position.row, position.column); + var end = { + row: start.row + lines.length - 1, + column: (lines.length == 1 ? start.column : 0) + lines[lines.length - 1].length + }; + + this.applyDelta({ + start: start, + end: end, + action: "insert", + lines: lines + }); + + return this.clonePos(end); + }; + this.remove = function(range) { + var start = this.clippedPos(range.start.row, range.start.column); + var end = this.clippedPos(range.end.row, range.end.column); + this.applyDelta({ + start: start, + end: end, + action: "remove", + lines: this.getLinesForRange({start: start, end: end}) + }); + return this.clonePos(start); + }; + this.removeInLine = function(row, startColumn, endColumn) { + var start = this.clippedPos(row, startColumn); + var end = this.clippedPos(row, endColumn); + + this.applyDelta({ + start: start, + end: end, + action: "remove", + lines: this.getLinesForRange({start: start, end: end}) + }, true); + + return this.clonePos(start); + }; + this.removeFullLines = function(firstRow, lastRow) { + firstRow = Math.min(Math.max(0, firstRow), this.getLength() - 1); + lastRow = Math.min(Math.max(0, lastRow ), this.getLength() - 1); + var deleteFirstNewLine = lastRow == this.getLength() - 1 && firstRow > 0; + var deleteLastNewLine = lastRow < this.getLength() - 1; + var startRow = ( deleteFirstNewLine ? firstRow - 1 : firstRow ); + var startCol = ( deleteFirstNewLine ? this.getLine(startRow).length : 0 ); + var endRow = ( deleteLastNewLine ? lastRow + 1 : lastRow ); + var endCol = ( deleteLastNewLine ? 0 : this.getLine(endRow).length ); + var range = new Range(startRow, startCol, endRow, endCol); + var deletedLines = this.$lines.slice(firstRow, lastRow + 1); + + this.applyDelta({ + start: range.start, + end: range.end, + action: "remove", + lines: this.getLinesForRange(range) + }); + return deletedLines; + }; + this.removeNewLine = function(row) { + if (row < this.getLength() - 1 && row >= 0) { + this.applyDelta({ + start: this.pos(row, this.getLine(row).length), + end: this.pos(row + 1, 0), + action: "remove", + lines: ["", ""] + }); + } + }; + this.replace = function(range, text) { + if (!(range instanceof Range)) + range = Range.fromPoints(range.start, range.end); + if (text.length === 0 && range.isEmpty()) + return range.start; + if (text == this.getTextRange(range)) + return range.end; + + this.remove(range); + var end; + if (text) { + end = this.insert(range.start, text); + } + else { + end = range.start; + } + + return end; + }; + this.applyDeltas = function(deltas) { + for (var i=0; i=0; i--) { + this.revertDelta(deltas[i]); + } + }; + this.applyDelta = function(delta, doNotValidate) { + var isInsert = delta.action == "insert"; + if (isInsert ? delta.lines.length <= 1 && !delta.lines[0] + : !Range.comparePoints(delta.start, delta.end)) { + return; + } + + if (isInsert && delta.lines.length > 20000) + this.$splitAndapplyLargeDelta(delta, 20000); + applyDelta(this.$lines, delta, doNotValidate); + this._signal("change", delta); + }; + + this.$splitAndapplyLargeDelta = function(delta, MAX) { + var lines = delta.lines; + var l = lines.length; + var row = delta.start.row; + var column = delta.start.column; + var from = 0, to = 0; + do { + from = to; + to += MAX - 1; + var chunk = lines.slice(from, to); + if (to > l) { + delta.lines = chunk; + delta.start.row = row + from; + delta.start.column = column; + break; + } + chunk.push(""); + this.applyDelta({ + start: this.pos(row + from, column), + end: this.pos(row + to, column = 0), + action: delta.action, + lines: chunk + }, true); + } while(true); + }; + this.revertDelta = function(delta) { + this.applyDelta({ + start: this.clonePos(delta.start), + end: this.clonePos(delta.end), + action: (delta.action == "insert" ? "remove" : "insert"), + lines: delta.lines.slice() + }); + }; + this.indexToPosition = function(index, startRow) { + var lines = this.$lines || this.getAllLines(); + var newlineLength = this.getNewLineCharacter().length; + for (var i = startRow || 0, l = lines.length; i < l; i++) { + index -= lines[i].length + newlineLength; + if (index < 0) + return {row: i, column: index + lines[i].length + newlineLength}; + } + return {row: l-1, column: lines[l-1].length}; + }; + this.positionToIndex = function(pos, startRow) { + var lines = this.$lines || this.getAllLines(); + var newlineLength = this.getNewLineCharacter().length; + var index = 0; + var row = Math.min(pos.row, lines.length); + for (var i = startRow || 0; i < row; ++i) + index += lines[i].length + newlineLength; + + return index + pos.column; + }; + + }).call(Document.prototype); + + exports.Document = Document; + }); + + ace.define("ace/background_tokenizer",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("./lib/oop"); + var EventEmitter = acequire("./lib/event_emitter").EventEmitter; + + var BackgroundTokenizer = function(tokenizer, editor) { + this.running = false; + this.lines = []; + this.states = []; + this.currentLine = 0; + this.tokenizer = tokenizer; + + var self = this; + + this.$worker = function() { + if (!self.running) { return; } + + var workerStart = new Date(); + var currentLine = self.currentLine; + var endLine = -1; + var doc = self.doc; + + var startLine = currentLine; + while (self.lines[currentLine]) + currentLine++; + + var len = doc.getLength(); + var processedLines = 0; + self.running = false; + while (currentLine < len) { + self.$tokenizeRow(currentLine); + endLine = currentLine; + do { + currentLine++; + } while (self.lines[currentLine]); + processedLines ++; + if ((processedLines % 5 === 0) && (new Date() - workerStart) > 20) { + self.running = setTimeout(self.$worker, 20); + break; + } + } + self.currentLine = currentLine; + + if (startLine <= endLine) + self.fireUpdateEvent(startLine, endLine); + }; + }; + + (function(){ + + oop.implement(this, EventEmitter); + this.setTokenizer = function(tokenizer) { + this.tokenizer = tokenizer; + this.lines = []; + this.states = []; + + this.start(0); + }; + this.setDocument = function(doc) { + this.doc = doc; + this.lines = []; + this.states = []; + + this.stop(); + }; + this.fireUpdateEvent = function(firstRow, lastRow) { + var data = { + first: firstRow, + last: lastRow + }; + this._signal("update", {data: data}); + }; + this.start = function(startRow) { + this.currentLine = Math.min(startRow || 0, this.currentLine, this.doc.getLength()); + this.lines.splice(this.currentLine, this.lines.length); + this.states.splice(this.currentLine, this.states.length); + + this.stop(); + this.running = setTimeout(this.$worker, 700); + }; + + this.scheduleStart = function() { + if (!this.running) + this.running = setTimeout(this.$worker, 700); + } + + this.$updateOnChange = function(delta) { + var startRow = delta.start.row; + var len = delta.end.row - startRow; + + if (len === 0) { + this.lines[startRow] = null; + } else if (delta.action == "remove") { + this.lines.splice(startRow, len + 1, null); + this.states.splice(startRow, len + 1, null); + } else { + var args = Array(len + 1); + args.unshift(startRow, 1); + this.lines.splice.apply(this.lines, args); + this.states.splice.apply(this.states, args); + } + + this.currentLine = Math.min(startRow, this.currentLine, this.doc.getLength()); + + this.stop(); + }; + this.stop = function() { + if (this.running) + clearTimeout(this.running); + this.running = false; + }; + this.getTokens = function(row) { + return this.lines[row] || this.$tokenizeRow(row); + }; + this.getState = function(row) { + if (this.currentLine == row) + this.$tokenizeRow(row); + return this.states[row] || "start"; + }; + + this.$tokenizeRow = function(row) { + var line = this.doc.getLine(row); + var state = this.states[row - 1]; + + var data = this.tokenizer.getLineTokens(line, state, row); + + if (this.states[row] + "" !== data.state + "") { + this.states[row] = data.state; + this.lines[row + 1] = null; + if (this.currentLine > row + 1) + this.currentLine = row + 1; + } else if (this.currentLine == row) { + this.currentLine = row + 1; + } + + return this.lines[row] = data.tokens; + }; + + }).call(BackgroundTokenizer.prototype); + + exports.BackgroundTokenizer = BackgroundTokenizer; + }); + + ace.define("ace/search_highlight",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/range"], function(acequire, exports, module) { + "use strict"; + + var lang = acequire("./lib/lang"); + var oop = acequire("./lib/oop"); + var Range = acequire("./range").Range; + + var SearchHighlight = function(regExp, clazz, type) { + this.setRegexp(regExp); + this.clazz = clazz; + this.type = type || "text"; + }; + + (function() { + this.MAX_RANGES = 500; + + this.setRegexp = function(regExp) { + if (this.regExp+"" == regExp+"") + return; + this.regExp = regExp; + this.cache = []; + }; + + this.update = function(html, markerLayer, session, config) { + if (!this.regExp) + return; + var start = config.firstRow, end = config.lastRow; + + for (var i = start; i <= end; i++) { + var ranges = this.cache[i]; + if (ranges == null) { + ranges = lang.getMatchOffsets(session.getLine(i), this.regExp); + if (ranges.length > this.MAX_RANGES) + ranges = ranges.slice(0, this.MAX_RANGES); + ranges = ranges.map(function(match) { + return new Range(i, match.offset, i, match.offset + match.length); + }); + this.cache[i] = ranges.length ? ranges : ""; + } + + for (var j = ranges.length; j --; ) { + markerLayer.drawSingleLineMarker( + html, ranges[j].toScreenRange(session), this.clazz, config); + } + } + }; + + }).call(SearchHighlight.prototype); + + exports.SearchHighlight = SearchHighlight; + }); + + ace.define("ace/edit_session/fold_line",["require","exports","module","ace/range"], function(acequire, exports, module) { + "use strict"; + + var Range = acequire("../range").Range; + function FoldLine(foldData, folds) { + this.foldData = foldData; + if (Array.isArray(folds)) { + this.folds = folds; + } else { + folds = this.folds = [ folds ]; + } + + var last = folds[folds.length - 1]; + this.range = new Range(folds[0].start.row, folds[0].start.column, + last.end.row, last.end.column); + this.start = this.range.start; + this.end = this.range.end; + + this.folds.forEach(function(fold) { + fold.setFoldLine(this); + }, this); + } + + (function() { + this.shiftRow = function(shift) { + this.start.row += shift; + this.end.row += shift; + this.folds.forEach(function(fold) { + fold.start.row += shift; + fold.end.row += shift; + }); + }; + + this.addFold = function(fold) { + if (fold.sameRow) { + if (fold.start.row < this.startRow || fold.endRow > this.endRow) { + throw new Error("Can't add a fold to this FoldLine as it has no connection"); + } + this.folds.push(fold); + this.folds.sort(function(a, b) { + return -a.range.compareEnd(b.start.row, b.start.column); + }); + if (this.range.compareEnd(fold.start.row, fold.start.column) > 0) { + this.end.row = fold.end.row; + this.end.column = fold.end.column; + } else if (this.range.compareStart(fold.end.row, fold.end.column) < 0) { + this.start.row = fold.start.row; + this.start.column = fold.start.column; + } + } else if (fold.start.row == this.end.row) { + this.folds.push(fold); + this.end.row = fold.end.row; + this.end.column = fold.end.column; + } else if (fold.end.row == this.start.row) { + this.folds.unshift(fold); + this.start.row = fold.start.row; + this.start.column = fold.start.column; + } else { + throw new Error("Trying to add fold to FoldRow that doesn't have a matching row"); + } + fold.foldLine = this; + }; + + this.containsRow = function(row) { + return row >= this.start.row && row <= this.end.row; + }; + + this.walk = function(callback, endRow, endColumn) { + var lastEnd = 0, + folds = this.folds, + fold, + cmp, stop, isNewRow = true; + + if (endRow == null) { + endRow = this.end.row; + endColumn = this.end.column; + } + + for (var i = 0; i < folds.length; i++) { + fold = folds[i]; + + cmp = fold.range.compareStart(endRow, endColumn); + if (cmp == -1) { + callback(null, endRow, endColumn, lastEnd, isNewRow); + return; + } + + stop = callback(null, fold.start.row, fold.start.column, lastEnd, isNewRow); + stop = !stop && callback(fold.placeholder, fold.start.row, fold.start.column, lastEnd); + if (stop || cmp === 0) { + return; + } + isNewRow = !fold.sameRow; + lastEnd = fold.end.column; + } + callback(null, endRow, endColumn, lastEnd, isNewRow); + }; + + this.getNextFoldTo = function(row, column) { + var fold, cmp; + for (var i = 0; i < this.folds.length; i++) { + fold = this.folds[i]; + cmp = fold.range.compareEnd(row, column); + if (cmp == -1) { + return { + fold: fold, + kind: "after" + }; + } else if (cmp === 0) { + return { + fold: fold, + kind: "inside" + }; + } + } + return null; + }; + + this.addRemoveChars = function(row, column, len) { + var ret = this.getNextFoldTo(row, column), + fold, folds; + if (ret) { + fold = ret.fold; + if (ret.kind == "inside" + && fold.start.column != column + && fold.start.row != row) + { + window.console && window.console.log(row, column, fold); + } else if (fold.start.row == row) { + folds = this.folds; + var i = folds.indexOf(fold); + if (i === 0) { + this.start.column += len; + } + for (i; i < folds.length; i++) { + fold = folds[i]; + fold.start.column += len; + if (!fold.sameRow) { + return; + } + fold.end.column += len; + } + this.end.column += len; + } + } + }; + + this.split = function(row, column) { + var pos = this.getNextFoldTo(row, column); + + if (!pos || pos.kind == "inside") + return null; + + var fold = pos.fold; + var folds = this.folds; + var foldData = this.foldData; + + var i = folds.indexOf(fold); + var foldBefore = folds[i - 1]; + this.end.row = foldBefore.end.row; + this.end.column = foldBefore.end.column; + folds = folds.splice(i, folds.length - i); + + var newFoldLine = new FoldLine(foldData, folds); + foldData.splice(foldData.indexOf(this) + 1, 0, newFoldLine); + return newFoldLine; + }; + + this.merge = function(foldLineNext) { + var folds = foldLineNext.folds; + for (var i = 0; i < folds.length; i++) { + this.addFold(folds[i]); + } + var foldData = this.foldData; + foldData.splice(foldData.indexOf(foldLineNext), 1); + }; + + this.toString = function() { + var ret = [this.range.toString() + ": [" ]; + + this.folds.forEach(function(fold) { + ret.push(" " + fold.toString()); + }); + ret.push("]"); + return ret.join("\n"); + }; + + this.idxToPosition = function(idx) { + var lastFoldEndColumn = 0; + + for (var i = 0; i < this.folds.length; i++) { + var fold = this.folds[i]; + + idx -= fold.start.column - lastFoldEndColumn; + if (idx < 0) { + return { + row: fold.start.row, + column: fold.start.column + idx + }; + } + + idx -= fold.placeholder.length; + if (idx < 0) { + return fold.start; + } + + lastFoldEndColumn = fold.end.column; + } + + return { + row: this.end.row, + column: this.end.column + idx + }; + }; + }).call(FoldLine.prototype); + + exports.FoldLine = FoldLine; + }); + + ace.define("ace/range_list",["require","exports","module","ace/range"], function(acequire, exports, module) { + "use strict"; + var Range = acequire("./range").Range; + var comparePoints = Range.comparePoints; + + var RangeList = function() { + this.ranges = []; + }; + + (function() { + this.comparePoints = comparePoints; + + this.pointIndex = function(pos, excludeEdges, startIndex) { + var list = this.ranges; + + for (var i = startIndex || 0; i < list.length; i++) { + var range = list[i]; + var cmpEnd = comparePoints(pos, range.end); + if (cmpEnd > 0) + continue; + var cmpStart = comparePoints(pos, range.start); + if (cmpEnd === 0) + return excludeEdges && cmpStart !== 0 ? -i-2 : i; + if (cmpStart > 0 || (cmpStart === 0 && !excludeEdges)) + return i; + + return -i-1; + } + return -i - 1; + }; + + this.add = function(range) { + var excludeEdges = !range.isEmpty(); + var startIndex = this.pointIndex(range.start, excludeEdges); + if (startIndex < 0) + startIndex = -startIndex - 1; + + var endIndex = this.pointIndex(range.end, excludeEdges, startIndex); + + if (endIndex < 0) + endIndex = -endIndex - 1; + else + endIndex++; + return this.ranges.splice(startIndex, endIndex - startIndex, range); + }; + + this.addList = function(list) { + var removed = []; + for (var i = list.length; i--; ) { + removed.push.apply(removed, this.add(list[i])); + } + return removed; + }; + + this.substractPoint = function(pos) { + var i = this.pointIndex(pos); + + if (i >= 0) + return this.ranges.splice(i, 1); + }; + this.merge = function() { + var removed = []; + var list = this.ranges; + + list = list.sort(function(a, b) { + return comparePoints(a.start, b.start); + }); + + var next = list[0], range; + for (var i = 1; i < list.length; i++) { + range = next; + next = list[i]; + var cmp = comparePoints(range.end, next.start); + if (cmp < 0) + continue; + + if (cmp == 0 && !range.isEmpty() && !next.isEmpty()) + continue; + + if (comparePoints(range.end, next.end) < 0) { + range.end.row = next.end.row; + range.end.column = next.end.column; + } + + list.splice(i, 1); + removed.push(next); + next = range; + i--; + } + + this.ranges = list; + + return removed; + }; + + this.contains = function(row, column) { + return this.pointIndex({row: row, column: column}) >= 0; + }; + + this.containsPoint = function(pos) { + return this.pointIndex(pos) >= 0; + }; + + this.rangeAtPoint = function(pos) { + var i = this.pointIndex(pos); + if (i >= 0) + return this.ranges[i]; + }; + + + this.clipRows = function(startRow, endRow) { + var list = this.ranges; + if (list[0].start.row > endRow || list[list.length - 1].start.row < startRow) + return []; + + var startIndex = this.pointIndex({row: startRow, column: 0}); + if (startIndex < 0) + startIndex = -startIndex - 1; + var endIndex = this.pointIndex({row: endRow, column: 0}, startIndex); + if (endIndex < 0) + endIndex = -endIndex - 1; + + var clipped = []; + for (var i = startIndex; i < endIndex; i++) { + clipped.push(list[i]); + } + return clipped; + }; + + this.removeAll = function() { + return this.ranges.splice(0, this.ranges.length); + }; + + this.attach = function(session) { + if (this.session) + this.detach(); + + this.session = session; + this.onChange = this.$onChange.bind(this); + + this.session.on('change', this.onChange); + }; + + this.detach = function() { + if (!this.session) + return; + this.session.removeListener('change', this.onChange); + this.session = null; + }; + + this.$onChange = function(delta) { + if (delta.action == "insert"){ + var start = delta.start; + var end = delta.end; + } else { + var end = delta.start; + var start = delta.end; + } + var startRow = start.row; + var endRow = end.row; + var lineDif = endRow - startRow; + + var colDiff = -start.column + end.column; + var ranges = this.ranges; + + for (var i = 0, n = ranges.length; i < n; i++) { + var r = ranges[i]; + if (r.end.row < startRow) + continue; + if (r.start.row > startRow) + break; + + if (r.start.row == startRow && r.start.column >= start.column ) { + if (r.start.column == start.column && this.$insertRight) { + } else { + r.start.column += colDiff; + r.start.row += lineDif; + } + } + if (r.end.row == startRow && r.end.column >= start.column) { + if (r.end.column == start.column && this.$insertRight) { + continue; + } + if (r.end.column == start.column && colDiff > 0 && i < n - 1) { + if (r.end.column > r.start.column && r.end.column == ranges[i+1].start.column) + r.end.column -= colDiff; + } + r.end.column += colDiff; + r.end.row += lineDif; + } + } + + if (lineDif != 0 && i < n) { + for (; i < n; i++) { + var r = ranges[i]; + r.start.row += lineDif; + r.end.row += lineDif; + } + } + }; + + }).call(RangeList.prototype); + + exports.RangeList = RangeList; + }); + + ace.define("ace/edit_session/fold",["require","exports","module","ace/range","ace/range_list","ace/lib/oop"], function(acequire, exports, module) { + "use strict"; + + var Range = acequire("../range").Range; + var RangeList = acequire("../range_list").RangeList; + var oop = acequire("../lib/oop") + var Fold = exports.Fold = function(range, placeholder) { + this.foldLine = null; + this.placeholder = placeholder; + this.range = range; + this.start = range.start; + this.end = range.end; + + this.sameRow = range.start.row == range.end.row; + this.subFolds = this.ranges = []; + }; + + oop.inherits(Fold, RangeList); + + (function() { + + this.toString = function() { + return '"' + this.placeholder + '" ' + this.range.toString(); + }; + + this.setFoldLine = function(foldLine) { + this.foldLine = foldLine; + this.subFolds.forEach(function(fold) { + fold.setFoldLine(foldLine); + }); + }; + + this.clone = function() { + var range = this.range.clone(); + var fold = new Fold(range, this.placeholder); + this.subFolds.forEach(function(subFold) { + fold.subFolds.push(subFold.clone()); + }); + fold.collapseChildren = this.collapseChildren; + return fold; + }; + + this.addSubFold = function(fold) { + if (this.range.isEqual(fold)) + return; + + if (!this.range.containsRange(fold)) + throw new Error("A fold can't intersect already existing fold" + fold.range + this.range); + consumeRange(fold, this.start); + + var row = fold.start.row, column = fold.start.column; + for (var i = 0, cmp = -1; i < this.subFolds.length; i++) { + cmp = this.subFolds[i].range.compare(row, column); + if (cmp != 1) + break; + } + var afterStart = this.subFolds[i]; + + if (cmp == 0) + return afterStart.addSubFold(fold); + var row = fold.range.end.row, column = fold.range.end.column; + for (var j = i, cmp = -1; j < this.subFolds.length; j++) { + cmp = this.subFolds[j].range.compare(row, column); + if (cmp != 1) + break; + } + var afterEnd = this.subFolds[j]; + + if (cmp == 0) + throw new Error("A fold can't intersect already existing fold" + fold.range + this.range); + + var consumedFolds = this.subFolds.splice(i, j - i, fold); + fold.setFoldLine(this.foldLine); + + return fold; + }; + + this.restoreRange = function(range) { + return restoreRange(range, this.start); + }; + + }).call(Fold.prototype); + + function consumePoint(point, anchor) { + point.row -= anchor.row; + if (point.row == 0) + point.column -= anchor.column; + } + function consumeRange(range, anchor) { + consumePoint(range.start, anchor); + consumePoint(range.end, anchor); + } + function restorePoint(point, anchor) { + if (point.row == 0) + point.column += anchor.column; + point.row += anchor.row; + } + function restoreRange(range, anchor) { + restorePoint(range.start, anchor); + restorePoint(range.end, anchor); + } + + }); + + ace.define("ace/edit_session/folding",["require","exports","module","ace/range","ace/edit_session/fold_line","ace/edit_session/fold","ace/token_iterator"], function(acequire, exports, module) { + "use strict"; + + var Range = acequire("../range").Range; + var FoldLine = acequire("./fold_line").FoldLine; + var Fold = acequire("./fold").Fold; + var TokenIterator = acequire("../token_iterator").TokenIterator; + + function Folding() { + this.getFoldAt = function(row, column, side) { + var foldLine = this.getFoldLine(row); + if (!foldLine) + return null; + + var folds = foldLine.folds; + for (var i = 0; i < folds.length; i++) { + var fold = folds[i]; + if (fold.range.contains(row, column)) { + if (side == 1 && fold.range.isEnd(row, column)) { + continue; + } else if (side == -1 && fold.range.isStart(row, column)) { + continue; + } + return fold; + } + } + }; + this.getFoldsInRange = function(range) { + var start = range.start; + var end = range.end; + var foldLines = this.$foldData; + var foundFolds = []; + + start.column += 1; + end.column -= 1; + + for (var i = 0; i < foldLines.length; i++) { + var cmp = foldLines[i].range.compareRange(range); + if (cmp == 2) { + continue; + } + else if (cmp == -2) { + break; + } + + var folds = foldLines[i].folds; + for (var j = 0; j < folds.length; j++) { + var fold = folds[j]; + cmp = fold.range.compareRange(range); + if (cmp == -2) { + break; + } else if (cmp == 2) { + continue; + } else + if (cmp == 42) { + break; + } + foundFolds.push(fold); + } + } + start.column -= 1; + end.column += 1; + + return foundFolds; + }; + + this.getFoldsInRangeList = function(ranges) { + if (Array.isArray(ranges)) { + var folds = []; + ranges.forEach(function(range) { + folds = folds.concat(this.getFoldsInRange(range)); + }, this); + } else { + var folds = this.getFoldsInRange(ranges); + } + return folds; + }; + this.getAllFolds = function() { + var folds = []; + var foldLines = this.$foldData; + + for (var i = 0; i < foldLines.length; i++) + for (var j = 0; j < foldLines[i].folds.length; j++) + folds.push(foldLines[i].folds[j]); + + return folds; + }; + this.getFoldStringAt = function(row, column, trim, foldLine) { + foldLine = foldLine || this.getFoldLine(row); + if (!foldLine) + return null; + + var lastFold = { + end: { column: 0 } + }; + var str, fold; + for (var i = 0; i < foldLine.folds.length; i++) { + fold = foldLine.folds[i]; + var cmp = fold.range.compareEnd(row, column); + if (cmp == -1) { + str = this + .getLine(fold.start.row) + .substring(lastFold.end.column, fold.start.column); + break; + } + else if (cmp === 0) { + return null; + } + lastFold = fold; + } + if (!str) + str = this.getLine(fold.start.row).substring(lastFold.end.column); + + if (trim == -1) + return str.substring(0, column - lastFold.end.column); + else if (trim == 1) + return str.substring(column - lastFold.end.column); + else + return str; + }; + + this.getFoldLine = function(docRow, startFoldLine) { + var foldData = this.$foldData; + var i = 0; + if (startFoldLine) + i = foldData.indexOf(startFoldLine); + if (i == -1) + i = 0; + for (i; i < foldData.length; i++) { + var foldLine = foldData[i]; + if (foldLine.start.row <= docRow && foldLine.end.row >= docRow) { + return foldLine; + } else if (foldLine.end.row > docRow) { + return null; + } + } + return null; + }; + this.getNextFoldLine = function(docRow, startFoldLine) { + var foldData = this.$foldData; + var i = 0; + if (startFoldLine) + i = foldData.indexOf(startFoldLine); + if (i == -1) + i = 0; + for (i; i < foldData.length; i++) { + var foldLine = foldData[i]; + if (foldLine.end.row >= docRow) { + return foldLine; + } + } + return null; + }; + + this.getFoldedRowCount = function(first, last) { + var foldData = this.$foldData, rowCount = last-first+1; + for (var i = 0; i < foldData.length; i++) { + var foldLine = foldData[i], + end = foldLine.end.row, + start = foldLine.start.row; + if (end >= last) { + if (start < last) { + if (start >= first) + rowCount -= last-start; + else + rowCount = 0; // in one fold + } + break; + } else if (end >= first){ + if (start >= first) // fold inside range + rowCount -= end-start; + else + rowCount -= end-first+1; + } + } + return rowCount; + }; + + this.$addFoldLine = function(foldLine) { + this.$foldData.push(foldLine); + this.$foldData.sort(function(a, b) { + return a.start.row - b.start.row; + }); + return foldLine; + }; + this.addFold = function(placeholder, range) { + var foldData = this.$foldData; + var added = false; + var fold; + + if (placeholder instanceof Fold) + fold = placeholder; + else { + fold = new Fold(range, placeholder); + fold.collapseChildren = range.collapseChildren; + } + this.$clipRangeToDocument(fold.range); + + var startRow = fold.start.row; + var startColumn = fold.start.column; + var endRow = fold.end.row; + var endColumn = fold.end.column; + if (!(startRow < endRow || + startRow == endRow && startColumn <= endColumn - 2)) + throw new Error("The range has to be at least 2 characters width"); + + var startFold = this.getFoldAt(startRow, startColumn, 1); + var endFold = this.getFoldAt(endRow, endColumn, -1); + if (startFold && endFold == startFold) + return startFold.addSubFold(fold); + + if (startFold && !startFold.range.isStart(startRow, startColumn)) + this.removeFold(startFold); + + if (endFold && !endFold.range.isEnd(endRow, endColumn)) + this.removeFold(endFold); + var folds = this.getFoldsInRange(fold.range); + if (folds.length > 0) { + this.removeFolds(folds); + folds.forEach(function(subFold) { + fold.addSubFold(subFold); + }); + } + + for (var i = 0; i < foldData.length; i++) { + var foldLine = foldData[i]; + if (endRow == foldLine.start.row) { + foldLine.addFold(fold); + added = true; + break; + } else if (startRow == foldLine.end.row) { + foldLine.addFold(fold); + added = true; + if (!fold.sameRow) { + var foldLineNext = foldData[i + 1]; + if (foldLineNext && foldLineNext.start.row == endRow) { + foldLine.merge(foldLineNext); + break; + } + } + break; + } else if (endRow <= foldLine.start.row) { + break; + } + } + + if (!added) + foldLine = this.$addFoldLine(new FoldLine(this.$foldData, fold)); + + if (this.$useWrapMode) + this.$updateWrapData(foldLine.start.row, foldLine.start.row); + else + this.$updateRowLengthCache(foldLine.start.row, foldLine.start.row); + this.$modified = true; + this._signal("changeFold", { data: fold, action: "add" }); + + return fold; + }; + + this.addFolds = function(folds) { + folds.forEach(function(fold) { + this.addFold(fold); + }, this); + }; + + this.removeFold = function(fold) { + var foldLine = fold.foldLine; + var startRow = foldLine.start.row; + var endRow = foldLine.end.row; + + var foldLines = this.$foldData; + var folds = foldLine.folds; + if (folds.length == 1) { + foldLines.splice(foldLines.indexOf(foldLine), 1); + } else + if (foldLine.range.isEnd(fold.end.row, fold.end.column)) { + folds.pop(); + foldLine.end.row = folds[folds.length - 1].end.row; + foldLine.end.column = folds[folds.length - 1].end.column; + } else + if (foldLine.range.isStart(fold.start.row, fold.start.column)) { + folds.shift(); + foldLine.start.row = folds[0].start.row; + foldLine.start.column = folds[0].start.column; + } else + if (fold.sameRow) { + folds.splice(folds.indexOf(fold), 1); + } else + { + var newFoldLine = foldLine.split(fold.start.row, fold.start.column); + folds = newFoldLine.folds; + folds.shift(); + newFoldLine.start.row = folds[0].start.row; + newFoldLine.start.column = folds[0].start.column; + } + + if (!this.$updating) { + if (this.$useWrapMode) + this.$updateWrapData(startRow, endRow); + else + this.$updateRowLengthCache(startRow, endRow); + } + this.$modified = true; + this._signal("changeFold", { data: fold, action: "remove" }); + }; + + this.removeFolds = function(folds) { + var cloneFolds = []; + for (var i = 0; i < folds.length; i++) { + cloneFolds.push(folds[i]); + } + + cloneFolds.forEach(function(fold) { + this.removeFold(fold); + }, this); + this.$modified = true; + }; + + this.expandFold = function(fold) { + this.removeFold(fold); + fold.subFolds.forEach(function(subFold) { + fold.restoreRange(subFold); + this.addFold(subFold); + }, this); + if (fold.collapseChildren > 0) { + this.foldAll(fold.start.row+1, fold.end.row, fold.collapseChildren-1); + } + fold.subFolds = []; + }; + + this.expandFolds = function(folds) { + folds.forEach(function(fold) { + this.expandFold(fold); + }, this); + }; + + this.unfold = function(location, expandInner) { + var range, folds; + if (location == null) { + range = new Range(0, 0, this.getLength(), 0); + expandInner = true; + } else if (typeof location == "number") + range = new Range(location, 0, location, this.getLine(location).length); + else if ("row" in location) + range = Range.fromPoints(location, location); + else + range = location; + + folds = this.getFoldsInRangeList(range); + if (expandInner) { + this.removeFolds(folds); + } else { + var subFolds = folds; + while (subFolds.length) { + this.expandFolds(subFolds); + subFolds = this.getFoldsInRangeList(range); + } + } + if (folds.length) + return folds; + }; + this.isRowFolded = function(docRow, startFoldRow) { + return !!this.getFoldLine(docRow, startFoldRow); + }; + + this.getRowFoldEnd = function(docRow, startFoldRow) { + var foldLine = this.getFoldLine(docRow, startFoldRow); + return foldLine ? foldLine.end.row : docRow; + }; + + this.getRowFoldStart = function(docRow, startFoldRow) { + var foldLine = this.getFoldLine(docRow, startFoldRow); + return foldLine ? foldLine.start.row : docRow; + }; + + this.getFoldDisplayLine = function(foldLine, endRow, endColumn, startRow, startColumn) { + if (startRow == null) + startRow = foldLine.start.row; + if (startColumn == null) + startColumn = 0; + if (endRow == null) + endRow = foldLine.end.row; + if (endColumn == null) + endColumn = this.getLine(endRow).length; + var doc = this.doc; + var textLine = ""; + + foldLine.walk(function(placeholder, row, column, lastColumn) { + if (row < startRow) + return; + if (row == startRow) { + if (column < startColumn) + return; + lastColumn = Math.max(startColumn, lastColumn); + } + + if (placeholder != null) { + textLine += placeholder; + } else { + textLine += doc.getLine(row).substring(lastColumn, column); + } + }, endRow, endColumn); + return textLine; + }; + + this.getDisplayLine = function(row, endColumn, startRow, startColumn) { + var foldLine = this.getFoldLine(row); + + if (!foldLine) { + var line; + line = this.doc.getLine(row); + return line.substring(startColumn || 0, endColumn || line.length); + } else { + return this.getFoldDisplayLine( + foldLine, row, endColumn, startRow, startColumn); + } + }; + + this.$cloneFoldData = function() { + var fd = []; + fd = this.$foldData.map(function(foldLine) { + var folds = foldLine.folds.map(function(fold) { + return fold.clone(); + }); + return new FoldLine(fd, folds); + }); + + return fd; + }; + + this.toggleFold = function(tryToUnfold) { + var selection = this.selection; + var range = selection.getRange(); + var fold; + var bracketPos; + + if (range.isEmpty()) { + var cursor = range.start; + fold = this.getFoldAt(cursor.row, cursor.column); + + if (fold) { + this.expandFold(fold); + return; + } else if (bracketPos = this.findMatchingBracket(cursor)) { + if (range.comparePoint(bracketPos) == 1) { + range.end = bracketPos; + } else { + range.start = bracketPos; + range.start.column++; + range.end.column--; + } + } else if (bracketPos = this.findMatchingBracket({row: cursor.row, column: cursor.column + 1})) { + if (range.comparePoint(bracketPos) == 1) + range.end = bracketPos; + else + range.start = bracketPos; + + range.start.column++; + } else { + range = this.getCommentFoldRange(cursor.row, cursor.column) || range; + } + } else { + var folds = this.getFoldsInRange(range); + if (tryToUnfold && folds.length) { + this.expandFolds(folds); + return; + } else if (folds.length == 1 ) { + fold = folds[0]; + } + } + + if (!fold) + fold = this.getFoldAt(range.start.row, range.start.column); + + if (fold && fold.range.toString() == range.toString()) { + this.expandFold(fold); + return; + } + + var placeholder = "..."; + if (!range.isMultiLine()) { + placeholder = this.getTextRange(range); + if (placeholder.length < 4) + return; + placeholder = placeholder.trim().substring(0, 2) + ".."; + } + + this.addFold(placeholder, range); + }; + + this.getCommentFoldRange = function(row, column, dir) { + var iterator = new TokenIterator(this, row, column); + var token = iterator.getCurrentToken(); + if (token && /^comment|string/.test(token.type)) { + var range = new Range(); + var re = new RegExp(token.type.replace(/\..*/, "\\.")); + if (dir != 1) { + do { + token = iterator.stepBackward(); + } while (token && re.test(token.type)); + iterator.stepForward(); + } + + range.start.row = iterator.getCurrentTokenRow(); + range.start.column = iterator.getCurrentTokenColumn() + 2; + + iterator = new TokenIterator(this, row, column); + + if (dir != -1) { + do { + token = iterator.stepForward(); + } while (token && re.test(token.type)); + token = iterator.stepBackward(); + } else + token = iterator.getCurrentToken(); + + range.end.row = iterator.getCurrentTokenRow(); + range.end.column = iterator.getCurrentTokenColumn() + token.value.length - 2; + return range; + } + }; + + this.foldAll = function(startRow, endRow, depth) { + if (depth == undefined) + depth = 100000; // JSON.stringify doesn't hanle Infinity + var foldWidgets = this.foldWidgets; + if (!foldWidgets) + return; // mode doesn't support folding + endRow = endRow || this.getLength(); + startRow = startRow || 0; + for (var row = startRow; row < endRow; row++) { + if (foldWidgets[row] == null) + foldWidgets[row] = this.getFoldWidget(row); + if (foldWidgets[row] != "start") + continue; + + var range = this.getFoldWidgetRange(row); + if (range && range.isMultiLine() + && range.end.row <= endRow + && range.start.row >= startRow + ) { + row = range.end.row; + try { + var fold = this.addFold("...", range); + if (fold) + fold.collapseChildren = depth; + } catch(e) {} + } + } + }; + this.$foldStyles = { + "manual": 1, + "markbegin": 1, + "markbeginend": 1 + }; + this.$foldStyle = "markbegin"; + this.setFoldStyle = function(style) { + if (!this.$foldStyles[style]) + throw new Error("invalid fold style: " + style + "[" + Object.keys(this.$foldStyles).join(", ") + "]"); + + if (this.$foldStyle == style) + return; + + this.$foldStyle = style; + + if (style == "manual") + this.unfold(); + var mode = this.$foldMode; + this.$setFolding(null); + this.$setFolding(mode); + }; + + this.$setFolding = function(foldMode) { + if (this.$foldMode == foldMode) + return; + + this.$foldMode = foldMode; + + this.off('change', this.$updateFoldWidgets); + this.off('tokenizerUpdate', this.$tokenizerUpdateFoldWidgets); + this._signal("changeAnnotation"); + + if (!foldMode || this.$foldStyle == "manual") { + this.foldWidgets = null; + return; + } + + this.foldWidgets = []; + this.getFoldWidget = foldMode.getFoldWidget.bind(foldMode, this, this.$foldStyle); + this.getFoldWidgetRange = foldMode.getFoldWidgetRange.bind(foldMode, this, this.$foldStyle); + + this.$updateFoldWidgets = this.updateFoldWidgets.bind(this); + this.$tokenizerUpdateFoldWidgets = this.tokenizerUpdateFoldWidgets.bind(this); + this.on('change', this.$updateFoldWidgets); + this.on('tokenizerUpdate', this.$tokenizerUpdateFoldWidgets); + }; + + this.getParentFoldRangeData = function (row, ignoreCurrent) { + var fw = this.foldWidgets; + if (!fw || (ignoreCurrent && fw[row])) + return {}; + + var i = row - 1, firstRange; + while (i >= 0) { + var c = fw[i]; + if (c == null) + c = fw[i] = this.getFoldWidget(i); + + if (c == "start") { + var range = this.getFoldWidgetRange(i); + if (!firstRange) + firstRange = range; + if (range && range.end.row >= row) + break; + } + i--; + } + + return { + range: i !== -1 && range, + firstRange: firstRange + }; + }; + + this.onFoldWidgetClick = function(row, e) { + e = e.domEvent; + var options = { + children: e.shiftKey, + all: e.ctrlKey || e.metaKey, + siblings: e.altKey + }; + + var range = this.$toggleFoldWidget(row, options); + if (!range) { + var el = (e.target || e.srcElement); + if (el && /ace_fold-widget/.test(el.className)) + el.className += " ace_invalid"; + } + }; + + this.$toggleFoldWidget = function(row, options) { + if (!this.getFoldWidget) + return; + var type = this.getFoldWidget(row); + var line = this.getLine(row); + + var dir = type === "end" ? -1 : 1; + var fold = this.getFoldAt(row, dir === -1 ? 0 : line.length, dir); + + if (fold) { + if (options.children || options.all) + this.removeFold(fold); + else + this.expandFold(fold); + return; + } + + var range = this.getFoldWidgetRange(row, true); + if (range && !range.isMultiLine()) { + fold = this.getFoldAt(range.start.row, range.start.column, 1); + if (fold && range.isEqual(fold.range)) { + this.removeFold(fold); + return; + } + } + + if (options.siblings) { + var data = this.getParentFoldRangeData(row); + if (data.range) { + var startRow = data.range.start.row + 1; + var endRow = data.range.end.row; + } + this.foldAll(startRow, endRow, options.all ? 10000 : 0); + } else if (options.children) { + endRow = range ? range.end.row : this.getLength(); + this.foldAll(row + 1, endRow, options.all ? 10000 : 0); + } else if (range) { + if (options.all) + range.collapseChildren = 10000; + this.addFold("...", range); + } + + return range; + }; + + + + this.toggleFoldWidget = function(toggleParent) { + var row = this.selection.getCursor().row; + row = this.getRowFoldStart(row); + var range = this.$toggleFoldWidget(row, {}); + + if (range) + return; + var data = this.getParentFoldRangeData(row, true); + range = data.range || data.firstRange; + + if (range) { + row = range.start.row; + var fold = this.getFoldAt(row, this.getLine(row).length, 1); + + if (fold) { + this.removeFold(fold); + } else { + this.addFold("...", range); + } + } + }; + + this.updateFoldWidgets = function(delta) { + var firstRow = delta.start.row; + var len = delta.end.row - firstRow; + + if (len === 0) { + this.foldWidgets[firstRow] = null; + } else if (delta.action == 'remove') { + this.foldWidgets.splice(firstRow, len + 1, null); + } else { + var args = Array(len + 1); + args.unshift(firstRow, 1); + this.foldWidgets.splice.apply(this.foldWidgets, args); + } + }; + this.tokenizerUpdateFoldWidgets = function(e) { + var rows = e.data; + if (rows.first != rows.last) { + if (this.foldWidgets.length > rows.first) + this.foldWidgets.splice(rows.first, this.foldWidgets.length); + } + }; + } + + exports.Folding = Folding; + + }); + + ace.define("ace/edit_session/bracket_match",["require","exports","module","ace/token_iterator","ace/range"], function(acequire, exports, module) { + "use strict"; + + var TokenIterator = acequire("../token_iterator").TokenIterator; + var Range = acequire("../range").Range; + + + function BracketMatch() { + + this.findMatchingBracket = function(position, chr) { + if (position.column == 0) return null; + + var charBeforeCursor = chr || this.getLine(position.row).charAt(position.column-1); + if (charBeforeCursor == "") return null; + + var match = charBeforeCursor.match(/([\(\[\{])|([\)\]\}])/); + if (!match) + return null; + + if (match[1]) + return this.$findClosingBracket(match[1], position); + else + return this.$findOpeningBracket(match[2], position); + }; + + this.getBracketRange = function(pos) { + var line = this.getLine(pos.row); + var before = true, range; + + var chr = line.charAt(pos.column-1); + var match = chr && chr.match(/([\(\[\{])|([\)\]\}])/); + if (!match) { + chr = line.charAt(pos.column); + pos = {row: pos.row, column: pos.column + 1}; + match = chr && chr.match(/([\(\[\{])|([\)\]\}])/); + before = false; + } + if (!match) + return null; + + if (match[1]) { + var bracketPos = this.$findClosingBracket(match[1], pos); + if (!bracketPos) + return null; + range = Range.fromPoints(pos, bracketPos); + if (!before) { + range.end.column++; + range.start.column--; + } + range.cursor = range.end; + } else { + var bracketPos = this.$findOpeningBracket(match[2], pos); + if (!bracketPos) + return null; + range = Range.fromPoints(bracketPos, pos); + if (!before) { + range.start.column++; + range.end.column--; + } + range.cursor = range.start; + } + + return range; + }; + + this.$brackets = { + ")": "(", + "(": ")", + "]": "[", + "[": "]", + "{": "}", + "}": "{" + }; + + this.$findOpeningBracket = function(bracket, position, typeRe) { + var openBracket = this.$brackets[bracket]; + var depth = 1; + + var iterator = new TokenIterator(this, position.row, position.column); + var token = iterator.getCurrentToken(); + if (!token) + token = iterator.stepForward(); + if (!token) + return; + + if (!typeRe){ + typeRe = new RegExp( + "(\\.?" + + token.type.replace(".", "\\.").replace("rparen", ".paren") + .replace(/\b(?:end)\b/, "(?:start|begin|end)") + + ")+" + ); + } + var valueIndex = position.column - iterator.getCurrentTokenColumn() - 2; + var value = token.value; + + while (true) { + + while (valueIndex >= 0) { + var chr = value.charAt(valueIndex); + if (chr == openBracket) { + depth -= 1; + if (depth == 0) { + return {row: iterator.getCurrentTokenRow(), + column: valueIndex + iterator.getCurrentTokenColumn()}; + } + } + else if (chr == bracket) { + depth += 1; + } + valueIndex -= 1; + } + do { + token = iterator.stepBackward(); + } while (token && !typeRe.test(token.type)); + + if (token == null) + break; + + value = token.value; + valueIndex = value.length - 1; + } + + return null; + }; + + this.$findClosingBracket = function(bracket, position, typeRe) { + var closingBracket = this.$brackets[bracket]; + var depth = 1; + + var iterator = new TokenIterator(this, position.row, position.column); + var token = iterator.getCurrentToken(); + if (!token) + token = iterator.stepForward(); + if (!token) + return; + + if (!typeRe){ + typeRe = new RegExp( + "(\\.?" + + token.type.replace(".", "\\.").replace("lparen", ".paren") + .replace(/\b(?:start|begin)\b/, "(?:start|begin|end)") + + ")+" + ); + } + var valueIndex = position.column - iterator.getCurrentTokenColumn(); + + while (true) { + + var value = token.value; + var valueLength = value.length; + while (valueIndex < valueLength) { + var chr = value.charAt(valueIndex); + if (chr == closingBracket) { + depth -= 1; + if (depth == 0) { + return {row: iterator.getCurrentTokenRow(), + column: valueIndex + iterator.getCurrentTokenColumn()}; + } + } + else if (chr == bracket) { + depth += 1; + } + valueIndex += 1; + } + do { + token = iterator.stepForward(); + } while (token && !typeRe.test(token.type)); + + if (token == null) + break; + + valueIndex = 0; + } + + return null; + }; + } + exports.BracketMatch = BracketMatch; + + }); + + ace.define("ace/edit_session",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/config","ace/lib/event_emitter","ace/selection","ace/mode/text","ace/range","ace/document","ace/background_tokenizer","ace/search_highlight","ace/edit_session/folding","ace/edit_session/bracket_match"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("./lib/oop"); + var lang = acequire("./lib/lang"); + var config = acequire("./config"); + var EventEmitter = acequire("./lib/event_emitter").EventEmitter; + var Selection = acequire("./selection").Selection; + var TextMode = acequire("./mode/text").Mode; + var Range = acequire("./range").Range; + var Document = acequire("./document").Document; + var BackgroundTokenizer = acequire("./background_tokenizer").BackgroundTokenizer; + var SearchHighlight = acequire("./search_highlight").SearchHighlight; + + var EditSession = function(text, mode) { + this.$breakpoints = []; + this.$decorations = []; + this.$frontMarkers = {}; + this.$backMarkers = {}; + this.$markerId = 1; + this.$undoSelect = true; + + this.$foldData = []; + this.$foldData.toString = function() { + return this.join("\n"); + }; + this.on("changeFold", this.onChangeFold.bind(this)); + this.$onChange = this.onChange.bind(this); + + if (typeof text != "object" || !text.getLine) + text = new Document(text); + + this.setDocument(text); + this.selection = new Selection(this); + + config.resetOptions(this); + this.setMode(mode); + config._signal("session", this); + }; + + + (function() { + + oop.implement(this, EventEmitter); + this.setDocument = function(doc) { + if (this.doc) + this.doc.removeListener("change", this.$onChange); + + this.doc = doc; + doc.on("change", this.$onChange); + + if (this.bgTokenizer) + this.bgTokenizer.setDocument(this.getDocument()); + + this.resetCaches(); + }; + this.getDocument = function() { + return this.doc; + }; + this.$resetRowCache = function(docRow) { + if (!docRow) { + this.$docRowCache = []; + this.$screenRowCache = []; + return; + } + var l = this.$docRowCache.length; + var i = this.$getRowCacheIndex(this.$docRowCache, docRow) + 1; + if (l > i) { + this.$docRowCache.splice(i, l); + this.$screenRowCache.splice(i, l); + } + }; + + this.$getRowCacheIndex = function(cacheArray, val) { + var low = 0; + var hi = cacheArray.length - 1; + + while (low <= hi) { + var mid = (low + hi) >> 1; + var c = cacheArray[mid]; + + if (val > c) + low = mid + 1; + else if (val < c) + hi = mid - 1; + else + return mid; + } + + return low -1; + }; + + this.resetCaches = function() { + this.$modified = true; + this.$wrapData = []; + this.$rowLengthCache = []; + this.$resetRowCache(0); + if (this.bgTokenizer) + this.bgTokenizer.start(0); + }; + + this.onChangeFold = function(e) { + var fold = e.data; + this.$resetRowCache(fold.start.row); + }; + + this.onChange = function(delta) { + this.$modified = true; + + this.$resetRowCache(delta.start.row); + + var removedFolds = this.$updateInternalDataOnChange(delta); + if (!this.$fromUndo && this.$undoManager && !delta.ignore) { + this.$deltasDoc.push(delta); + if (removedFolds && removedFolds.length != 0) { + this.$deltasFold.push({ + action: "removeFolds", + folds: removedFolds + }); + } + + this.$informUndoManager.schedule(); + } + + this.bgTokenizer && this.bgTokenizer.$updateOnChange(delta); + this._signal("change", delta); + }; + this.setValue = function(text) { + this.doc.setValue(text); + this.selection.moveTo(0, 0); + + this.$resetRowCache(0); + this.$deltas = []; + this.$deltasDoc = []; + this.$deltasFold = []; + this.setUndoManager(this.$undoManager); + this.getUndoManager().reset(); + }; + this.getValue = + this.toString = function() { + return this.doc.getValue(); + }; + this.getSelection = function() { + return this.selection; + }; + this.getState = function(row) { + return this.bgTokenizer.getState(row); + }; + this.getTokens = function(row) { + return this.bgTokenizer.getTokens(row); + }; + this.getTokenAt = function(row, column) { + var tokens = this.bgTokenizer.getTokens(row); + var token, c = 0; + if (column == null) { + i = tokens.length - 1; + c = this.getLine(row).length; + } else { + for (var i = 0; i < tokens.length; i++) { + c += tokens[i].value.length; + if (c >= column) + break; + } + } + token = tokens[i]; + if (!token) + return null; + token.index = i; + token.start = c - token.value.length; + return token; + }; + this.setUndoManager = function(undoManager) { + this.$undoManager = undoManager; + this.$deltas = []; + this.$deltasDoc = []; + this.$deltasFold = []; + + if (this.$informUndoManager) + this.$informUndoManager.cancel(); + + if (undoManager) { + var self = this; + + this.$syncInformUndoManager = function() { + self.$informUndoManager.cancel(); + + if (self.$deltasFold.length) { + self.$deltas.push({ + group: "fold", + deltas: self.$deltasFold + }); + self.$deltasFold = []; + } + + if (self.$deltasDoc.length) { + self.$deltas.push({ + group: "doc", + deltas: self.$deltasDoc + }); + self.$deltasDoc = []; + } + + if (self.$deltas.length > 0) { + undoManager.execute({ + action: "aceupdate", + args: [self.$deltas, self], + merge: self.mergeUndoDeltas + }); + } + self.mergeUndoDeltas = false; + self.$deltas = []; + }; + this.$informUndoManager = lang.delayedCall(this.$syncInformUndoManager); + } + }; + this.markUndoGroup = function() { + if (this.$syncInformUndoManager) + this.$syncInformUndoManager(); + }; + + this.$defaultUndoManager = { + undo: function() {}, + redo: function() {}, + reset: function() {} + }; + this.getUndoManager = function() { + return this.$undoManager || this.$defaultUndoManager; + }; + this.getTabString = function() { + if (this.getUseSoftTabs()) { + return lang.stringRepeat(" ", this.getTabSize()); + } else { + return "\t"; + } + }; + this.setUseSoftTabs = function(val) { + this.setOption("useSoftTabs", val); + }; + this.getUseSoftTabs = function() { + return this.$useSoftTabs && !this.$mode.$indentWithTabs; + }; + this.setTabSize = function(tabSize) { + this.setOption("tabSize", tabSize); + }; + this.getTabSize = function() { + return this.$tabSize; + }; + this.isTabStop = function(position) { + return this.$useSoftTabs && (position.column % this.$tabSize === 0); + }; + + this.$overwrite = false; + this.setOverwrite = function(overwrite) { + this.setOption("overwrite", overwrite); + }; + this.getOverwrite = function() { + return this.$overwrite; + }; + this.toggleOverwrite = function() { + this.setOverwrite(!this.$overwrite); + }; + this.addGutterDecoration = function(row, className) { + if (!this.$decorations[row]) + this.$decorations[row] = ""; + this.$decorations[row] += " " + className; + this._signal("changeBreakpoint", {}); + }; + this.removeGutterDecoration = function(row, className) { + this.$decorations[row] = (this.$decorations[row] || "").replace(" " + className, ""); + this._signal("changeBreakpoint", {}); + }; + this.getBreakpoints = function() { + return this.$breakpoints; + }; + this.setBreakpoints = function(rows) { + this.$breakpoints = []; + for (var i=0; i 0) + inToken = !!line.charAt(column - 1).match(this.tokenRe); + + if (!inToken) + inToken = !!line.charAt(column).match(this.tokenRe); + + if (inToken) + var re = this.tokenRe; + else if (/^\s+$/.test(line.slice(column-1, column+1))) + var re = /\s/; + else + var re = this.nonTokenRe; + + var start = column; + if (start > 0) { + do { + start--; + } + while (start >= 0 && line.charAt(start).match(re)); + start++; + } + + var end = column; + while (end < line.length && line.charAt(end).match(re)) { + end++; + } + + return new Range(row, start, row, end); + }; + this.getAWordRange = function(row, column) { + var wordRange = this.getWordRange(row, column); + var line = this.getLine(wordRange.end.row); + + while (line.charAt(wordRange.end.column).match(/[ \t]/)) { + wordRange.end.column += 1; + } + return wordRange; + }; + this.setNewLineMode = function(newLineMode) { + this.doc.setNewLineMode(newLineMode); + }; + this.getNewLineMode = function() { + return this.doc.getNewLineMode(); + }; + this.setUseWorker = function(useWorker) { this.setOption("useWorker", useWorker); }; + this.getUseWorker = function() { return this.$useWorker; }; + this.onReloadTokenizer = function(e) { + var rows = e.data; + this.bgTokenizer.start(rows.first); + this._signal("tokenizerUpdate", e); + }; + + this.$modes = {}; + this.$mode = null; + this.$modeId = null; + this.setMode = function(mode, cb) { + if (mode && typeof mode === "object") { + if (mode.getTokenizer) + return this.$onChangeMode(mode); + var options = mode; + var path = options.path; + } else { + path = mode || "ace/mode/text"; + } + if (!this.$modes["ace/mode/text"]) + this.$modes["ace/mode/text"] = new TextMode(); + + if (this.$modes[path] && !options) { + this.$onChangeMode(this.$modes[path]); + cb && cb(); + return; + } + this.$modeId = path; + config.loadModule(["mode", path], function(m) { + if (this.$modeId !== path) + return cb && cb(); + if (this.$modes[path] && !options) { + this.$onChangeMode(this.$modes[path]); + } else if (m && m.Mode) { + m = new m.Mode(options); + if (!options) { + this.$modes[path] = m; + m.$id = path; + } + this.$onChangeMode(m); + } + cb && cb(); + }.bind(this)); + if (!this.$mode) + this.$onChangeMode(this.$modes["ace/mode/text"], true); + }; + + this.$onChangeMode = function(mode, $isPlaceholder) { + if (!$isPlaceholder) + this.$modeId = mode.$id; + if (this.$mode === mode) + return; + + this.$mode = mode; + + this.$stopWorker(); + + if (this.$useWorker) + this.$startWorker(); + + var tokenizer = mode.getTokenizer(); + + if(tokenizer.addEventListener !== undefined) { + var onReloadTokenizer = this.onReloadTokenizer.bind(this); + tokenizer.addEventListener("update", onReloadTokenizer); + } + + if (!this.bgTokenizer) { + this.bgTokenizer = new BackgroundTokenizer(tokenizer); + var _self = this; + this.bgTokenizer.addEventListener("update", function(e) { + _self._signal("tokenizerUpdate", e); + }); + } else { + this.bgTokenizer.setTokenizer(tokenizer); + } + + this.bgTokenizer.setDocument(this.getDocument()); + + this.tokenRe = mode.tokenRe; + this.nonTokenRe = mode.nonTokenRe; + + + if (!$isPlaceholder) { + if (mode.attachToSession) + mode.attachToSession(this); + this.$options.wrapMethod.set.call(this, this.$wrapMethod); + this.$setFolding(mode.foldingRules); + this.bgTokenizer.start(0); + this._emit("changeMode"); + } + }; + + this.$stopWorker = function() { + if (this.$worker) { + this.$worker.terminate(); + this.$worker = null; + } + }; + + this.$startWorker = function() { + try { + this.$worker = this.$mode.createWorker(this); + } catch (e) { + config.warn("Could not load worker", e); + this.$worker = null; + } + }; + this.getMode = function() { + return this.$mode; + }; + + this.$scrollTop = 0; + this.setScrollTop = function(scrollTop) { + if (this.$scrollTop === scrollTop || isNaN(scrollTop)) + return; + + this.$scrollTop = scrollTop; + this._signal("changeScrollTop", scrollTop); + }; + this.getScrollTop = function() { + return this.$scrollTop; + }; + + this.$scrollLeft = 0; + this.setScrollLeft = function(scrollLeft) { + if (this.$scrollLeft === scrollLeft || isNaN(scrollLeft)) + return; + + this.$scrollLeft = scrollLeft; + this._signal("changeScrollLeft", scrollLeft); + }; + this.getScrollLeft = function() { + return this.$scrollLeft; + }; + this.getScreenWidth = function() { + this.$computeWidth(); + if (this.lineWidgets) + return Math.max(this.getLineWidgetMaxWidth(), this.screenWidth); + return this.screenWidth; + }; + + this.getLineWidgetMaxWidth = function() { + if (this.lineWidgetsWidth != null) return this.lineWidgetsWidth; + var width = 0; + this.lineWidgets.forEach(function(w) { + if (w && w.screenWidth > width) + width = w.screenWidth; + }); + return this.lineWidgetWidth = width; + }; + + this.$computeWidth = function(force) { + if (this.$modified || force) { + this.$modified = false; + + if (this.$useWrapMode) + return this.screenWidth = this.$wrapLimit; + + var lines = this.doc.getAllLines(); + var cache = this.$rowLengthCache; + var longestScreenLine = 0; + var foldIndex = 0; + var foldLine = this.$foldData[foldIndex]; + var foldStart = foldLine ? foldLine.start.row : Infinity; + var len = lines.length; + + for (var i = 0; i < len; i++) { + if (i > foldStart) { + i = foldLine.end.row + 1; + if (i >= len) + break; + foldLine = this.$foldData[foldIndex++]; + foldStart = foldLine ? foldLine.start.row : Infinity; + } + + if (cache[i] == null) + cache[i] = this.$getStringScreenWidth(lines[i])[0]; + + if (cache[i] > longestScreenLine) + longestScreenLine = cache[i]; + } + this.screenWidth = longestScreenLine; + } + }; + this.getLine = function(row) { + return this.doc.getLine(row); + }; + this.getLines = function(firstRow, lastRow) { + return this.doc.getLines(firstRow, lastRow); + }; + this.getLength = function() { + return this.doc.getLength(); + }; + this.getTextRange = function(range) { + return this.doc.getTextRange(range || this.selection.getRange()); + }; + this.insert = function(position, text) { + return this.doc.insert(position, text); + }; + this.remove = function(range) { + return this.doc.remove(range); + }; + this.removeFullLines = function(firstRow, lastRow){ + return this.doc.removeFullLines(firstRow, lastRow); + }; + this.undoChanges = function(deltas, dontSelect) { + if (!deltas.length) + return; + + this.$fromUndo = true; + var lastUndoRange = null; + for (var i = deltas.length - 1; i != -1; i--) { + var delta = deltas[i]; + if (delta.group == "doc") { + this.doc.revertDeltas(delta.deltas); + lastUndoRange = + this.$getUndoSelection(delta.deltas, true, lastUndoRange); + } else { + delta.deltas.forEach(function(foldDelta) { + this.addFolds(foldDelta.folds); + }, this); + } + } + this.$fromUndo = false; + lastUndoRange && + this.$undoSelect && + !dontSelect && + this.selection.setSelectionRange(lastUndoRange); + return lastUndoRange; + }; + this.redoChanges = function(deltas, dontSelect) { + if (!deltas.length) + return; + + this.$fromUndo = true; + var lastUndoRange = null; + for (var i = 0; i < deltas.length; i++) { + var delta = deltas[i]; + if (delta.group == "doc") { + this.doc.applyDeltas(delta.deltas); + lastUndoRange = + this.$getUndoSelection(delta.deltas, false, lastUndoRange); + } + } + this.$fromUndo = false; + lastUndoRange && + this.$undoSelect && + !dontSelect && + this.selection.setSelectionRange(lastUndoRange); + return lastUndoRange; + }; + this.setUndoSelect = function(enable) { + this.$undoSelect = enable; + }; + + this.$getUndoSelection = function(deltas, isUndo, lastUndoRange) { + function isInsert(delta) { + return isUndo ? delta.action !== "insert" : delta.action === "insert"; + } + + var delta = deltas[0]; + var range, point; + var lastDeltaIsInsert = false; + if (isInsert(delta)) { + range = Range.fromPoints(delta.start, delta.end); + lastDeltaIsInsert = true; + } else { + range = Range.fromPoints(delta.start, delta.start); + lastDeltaIsInsert = false; + } + + for (var i = 1; i < deltas.length; i++) { + delta = deltas[i]; + if (isInsert(delta)) { + point = delta.start; + if (range.compare(point.row, point.column) == -1) { + range.setStart(point); + } + point = delta.end; + if (range.compare(point.row, point.column) == 1) { + range.setEnd(point); + } + lastDeltaIsInsert = true; + } else { + point = delta.start; + if (range.compare(point.row, point.column) == -1) { + range = Range.fromPoints(delta.start, delta.start); + } + lastDeltaIsInsert = false; + } + } + if (lastUndoRange != null) { + if (Range.comparePoints(lastUndoRange.start, range.start) === 0) { + lastUndoRange.start.column += range.end.column - range.start.column; + lastUndoRange.end.column += range.end.column - range.start.column; + } + + var cmp = lastUndoRange.compareRange(range); + if (cmp == 1) { + range.setStart(lastUndoRange.start); + } else if (cmp == -1) { + range.setEnd(lastUndoRange.end); + } + } + + return range; + }; + this.replace = function(range, text) { + return this.doc.replace(range, text); + }; + this.moveText = function(fromRange, toPosition, copy) { + var text = this.getTextRange(fromRange); + var folds = this.getFoldsInRange(fromRange); + + var toRange = Range.fromPoints(toPosition, toPosition); + if (!copy) { + this.remove(fromRange); + var rowDiff = fromRange.start.row - fromRange.end.row; + var collDiff = rowDiff ? -fromRange.end.column : fromRange.start.column - fromRange.end.column; + if (collDiff) { + if (toRange.start.row == fromRange.end.row && toRange.start.column > fromRange.end.column) + toRange.start.column += collDiff; + if (toRange.end.row == fromRange.end.row && toRange.end.column > fromRange.end.column) + toRange.end.column += collDiff; + } + if (rowDiff && toRange.start.row >= fromRange.end.row) { + toRange.start.row += rowDiff; + toRange.end.row += rowDiff; + } + } + + toRange.end = this.insert(toRange.start, text); + if (folds.length) { + var oldStart = fromRange.start; + var newStart = toRange.start; + var rowDiff = newStart.row - oldStart.row; + var collDiff = newStart.column - oldStart.column; + this.addFolds(folds.map(function(x) { + x = x.clone(); + if (x.start.row == oldStart.row) + x.start.column += collDiff; + if (x.end.row == oldStart.row) + x.end.column += collDiff; + x.start.row += rowDiff; + x.end.row += rowDiff; + return x; + })); + } + + return toRange; + }; + this.indentRows = function(startRow, endRow, indentString) { + indentString = indentString.replace(/\t/g, this.getTabString()); + for (var row=startRow; row<=endRow; row++) + this.doc.insertInLine({row: row, column: 0}, indentString); + }; + this.outdentRows = function (range) { + var rowRange = range.collapseRows(); + var deleteRange = new Range(0, 0, 0, 0); + var size = this.getTabSize(); + + for (var i = rowRange.start.row; i <= rowRange.end.row; ++i) { + var line = this.getLine(i); + + deleteRange.start.row = i; + deleteRange.end.row = i; + for (var j = 0; j < size; ++j) + if (line.charAt(j) != ' ') + break; + if (j < size && line.charAt(j) == '\t') { + deleteRange.start.column = j; + deleteRange.end.column = j + 1; + } else { + deleteRange.start.column = 0; + deleteRange.end.column = j; + } + this.remove(deleteRange); + } + }; + + this.$moveLines = function(firstRow, lastRow, dir) { + firstRow = this.getRowFoldStart(firstRow); + lastRow = this.getRowFoldEnd(lastRow); + if (dir < 0) { + var row = this.getRowFoldStart(firstRow + dir); + if (row < 0) return 0; + var diff = row-firstRow; + } else if (dir > 0) { + var row = this.getRowFoldEnd(lastRow + dir); + if (row > this.doc.getLength()-1) return 0; + var diff = row-lastRow; + } else { + firstRow = this.$clipRowToDocument(firstRow); + lastRow = this.$clipRowToDocument(lastRow); + var diff = lastRow - firstRow + 1; + } + + var range = new Range(firstRow, 0, lastRow, Number.MAX_VALUE); + var folds = this.getFoldsInRange(range).map(function(x){ + x = x.clone(); + x.start.row += diff; + x.end.row += diff; + return x; + }); + + var lines = dir == 0 + ? this.doc.getLines(firstRow, lastRow) + : this.doc.removeFullLines(firstRow, lastRow); + this.doc.insertFullLines(firstRow+diff, lines); + folds.length && this.addFolds(folds); + return diff; + }; + this.moveLinesUp = function(firstRow, lastRow) { + return this.$moveLines(firstRow, lastRow, -1); + }; + this.moveLinesDown = function(firstRow, lastRow) { + return this.$moveLines(firstRow, lastRow, 1); + }; + this.duplicateLines = function(firstRow, lastRow) { + return this.$moveLines(firstRow, lastRow, 0); + }; + + + this.$clipRowToDocument = function(row) { + return Math.max(0, Math.min(row, this.doc.getLength()-1)); + }; + + this.$clipColumnToRow = function(row, column) { + if (column < 0) + return 0; + return Math.min(this.doc.getLine(row).length, column); + }; + + + this.$clipPositionToDocument = function(row, column) { + column = Math.max(0, column); + + if (row < 0) { + row = 0; + column = 0; + } else { + var len = this.doc.getLength(); + if (row >= len) { + row = len - 1; + column = this.doc.getLine(len-1).length; + } else { + column = Math.min(this.doc.getLine(row).length, column); + } + } + + return { + row: row, + column: column + }; + }; + + this.$clipRangeToDocument = function(range) { + if (range.start.row < 0) { + range.start.row = 0; + range.start.column = 0; + } else { + range.start.column = this.$clipColumnToRow( + range.start.row, + range.start.column + ); + } + + var len = this.doc.getLength() - 1; + if (range.end.row > len) { + range.end.row = len; + range.end.column = this.doc.getLine(len).length; + } else { + range.end.column = this.$clipColumnToRow( + range.end.row, + range.end.column + ); + } + return range; + }; + this.$wrapLimit = 80; + this.$useWrapMode = false; + this.$wrapLimitRange = { + min : null, + max : null + }; + this.setUseWrapMode = function(useWrapMode) { + if (useWrapMode != this.$useWrapMode) { + this.$useWrapMode = useWrapMode; + this.$modified = true; + this.$resetRowCache(0); + if (useWrapMode) { + var len = this.getLength(); + this.$wrapData = Array(len); + this.$updateWrapData(0, len - 1); + } + + this._signal("changeWrapMode"); + } + }; + this.getUseWrapMode = function() { + return this.$useWrapMode; + }; + this.setWrapLimitRange = function(min, max) { + if (this.$wrapLimitRange.min !== min || this.$wrapLimitRange.max !== max) { + this.$wrapLimitRange = { min: min, max: max }; + this.$modified = true; + if (this.$useWrapMode) + this._signal("changeWrapMode"); + } + }; + this.adjustWrapLimit = function(desiredLimit, $printMargin) { + var limits = this.$wrapLimitRange; + if (limits.max < 0) + limits = {min: $printMargin, max: $printMargin}; + var wrapLimit = this.$constrainWrapLimit(desiredLimit, limits.min, limits.max); + if (wrapLimit != this.$wrapLimit && wrapLimit > 1) { + this.$wrapLimit = wrapLimit; + this.$modified = true; + if (this.$useWrapMode) { + this.$updateWrapData(0, this.getLength() - 1); + this.$resetRowCache(0); + this._signal("changeWrapLimit"); + } + return true; + } + return false; + }; + + this.$constrainWrapLimit = function(wrapLimit, min, max) { + if (min) + wrapLimit = Math.max(min, wrapLimit); + + if (max) + wrapLimit = Math.min(max, wrapLimit); + + return wrapLimit; + }; + this.getWrapLimit = function() { + return this.$wrapLimit; + }; + this.setWrapLimit = function (limit) { + this.setWrapLimitRange(limit, limit); + }; + this.getWrapLimitRange = function() { + return { + min : this.$wrapLimitRange.min, + max : this.$wrapLimitRange.max + }; + }; + + this.$updateInternalDataOnChange = function(delta) { + var useWrapMode = this.$useWrapMode; + var action = delta.action; + var start = delta.start; + var end = delta.end; + var firstRow = start.row; + var lastRow = end.row; + var len = lastRow - firstRow; + var removedFolds = null; + + this.$updating = true; + if (len != 0) { + if (action === "remove") { + this[useWrapMode ? "$wrapData" : "$rowLengthCache"].splice(firstRow, len); + + var foldLines = this.$foldData; + removedFolds = this.getFoldsInRange(delta); + this.removeFolds(removedFolds); + + var foldLine = this.getFoldLine(end.row); + var idx = 0; + if (foldLine) { + foldLine.addRemoveChars(end.row, end.column, start.column - end.column); + foldLine.shiftRow(-len); + + var foldLineBefore = this.getFoldLine(firstRow); + if (foldLineBefore && foldLineBefore !== foldLine) { + foldLineBefore.merge(foldLine); + foldLine = foldLineBefore; + } + idx = foldLines.indexOf(foldLine) + 1; + } + + for (idx; idx < foldLines.length; idx++) { + var foldLine = foldLines[idx]; + if (foldLine.start.row >= end.row) { + foldLine.shiftRow(-len); + } + } + + lastRow = firstRow; + } else { + var args = Array(len); + args.unshift(firstRow, 0); + var arr = useWrapMode ? this.$wrapData : this.$rowLengthCache + arr.splice.apply(arr, args); + var foldLines = this.$foldData; + var foldLine = this.getFoldLine(firstRow); + var idx = 0; + if (foldLine) { + var cmp = foldLine.range.compareInside(start.row, start.column); + if (cmp == 0) { + foldLine = foldLine.split(start.row, start.column); + if (foldLine) { + foldLine.shiftRow(len); + foldLine.addRemoveChars(lastRow, 0, end.column - start.column); + } + } else + if (cmp == -1) { + foldLine.addRemoveChars(firstRow, 0, end.column - start.column); + foldLine.shiftRow(len); + } + idx = foldLines.indexOf(foldLine) + 1; + } + + for (idx; idx < foldLines.length; idx++) { + var foldLine = foldLines[idx]; + if (foldLine.start.row >= firstRow) { + foldLine.shiftRow(len); + } + } + } + } else { + len = Math.abs(delta.start.column - delta.end.column); + if (action === "remove") { + removedFolds = this.getFoldsInRange(delta); + this.removeFolds(removedFolds); + + len = -len; + } + var foldLine = this.getFoldLine(firstRow); + if (foldLine) { + foldLine.addRemoveChars(firstRow, start.column, len); + } + } + + if (useWrapMode && this.$wrapData.length != this.doc.getLength()) { + console.error("doc.getLength() and $wrapData.length have to be the same!"); + } + this.$updating = false; + + if (useWrapMode) + this.$updateWrapData(firstRow, lastRow); + else + this.$updateRowLengthCache(firstRow, lastRow); + + return removedFolds; + }; + + this.$updateRowLengthCache = function(firstRow, lastRow, b) { + this.$rowLengthCache[firstRow] = null; + this.$rowLengthCache[lastRow] = null; + }; + + this.$updateWrapData = function(firstRow, lastRow) { + var lines = this.doc.getAllLines(); + var tabSize = this.getTabSize(); + var wrapData = this.$wrapData; + var wrapLimit = this.$wrapLimit; + var tokens; + var foldLine; + + var row = firstRow; + lastRow = Math.min(lastRow, lines.length - 1); + while (row <= lastRow) { + foldLine = this.getFoldLine(row, foldLine); + if (!foldLine) { + tokens = this.$getDisplayTokens(lines[row]); + wrapData[row] = this.$computeWrapSplits(tokens, wrapLimit, tabSize); + row ++; + } else { + tokens = []; + foldLine.walk(function(placeholder, row, column, lastColumn) { + var walkTokens; + if (placeholder != null) { + walkTokens = this.$getDisplayTokens( + placeholder, tokens.length); + walkTokens[0] = PLACEHOLDER_START; + for (var i = 1; i < walkTokens.length; i++) { + walkTokens[i] = PLACEHOLDER_BODY; + } + } else { + walkTokens = this.$getDisplayTokens( + lines[row].substring(lastColumn, column), + tokens.length); + } + tokens = tokens.concat(walkTokens); + }.bind(this), + foldLine.end.row, + lines[foldLine.end.row].length + 1 + ); + + wrapData[foldLine.start.row] = this.$computeWrapSplits(tokens, wrapLimit, tabSize); + row = foldLine.end.row + 1; + } + } + }; + var CHAR = 1, + CHAR_EXT = 2, + PLACEHOLDER_START = 3, + PLACEHOLDER_BODY = 4, + PUNCTUATION = 9, + SPACE = 10, + TAB = 11, + TAB_SPACE = 12; + + + this.$computeWrapSplits = function(tokens, wrapLimit, tabSize) { + if (tokens.length == 0) { + return []; + } + + var splits = []; + var displayLength = tokens.length; + var lastSplit = 0, lastDocSplit = 0; + + var isCode = this.$wrapAsCode; + + var indentedSoftWrap = this.$indentedSoftWrap; + var maxIndent = wrapLimit <= Math.max(2 * tabSize, 8) + || indentedSoftWrap === false ? 0 : Math.floor(wrapLimit / 2); + + function getWrapIndent() { + var indentation = 0; + if (maxIndent === 0) + return indentation; + if (indentedSoftWrap) { + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i]; + if (token == SPACE) + indentation += 1; + else if (token == TAB) + indentation += tabSize; + else if (token == TAB_SPACE) + continue; + else + break; + } + } + if (isCode && indentedSoftWrap !== false) + indentation += tabSize; + return Math.min(indentation, maxIndent); + } + function addSplit(screenPos) { + var displayed = tokens.slice(lastSplit, screenPos); + var len = displayed.length; + displayed.join("") + .replace(/12/g, function() { + len -= 1; + }) + .replace(/2/g, function() { + len -= 1; + }); + + if (!splits.length) { + indent = getWrapIndent(); + splits.indent = indent; + } + lastDocSplit += len; + splits.push(lastDocSplit); + lastSplit = screenPos; + } + var indent = 0; + while (displayLength - lastSplit > wrapLimit - indent) { + var split = lastSplit + wrapLimit - indent; + if (tokens[split - 1] >= SPACE && tokens[split] >= SPACE) { + addSplit(split); + continue; + } + if (tokens[split] == PLACEHOLDER_START || tokens[split] == PLACEHOLDER_BODY) { + for (split; split != lastSplit - 1; split--) { + if (tokens[split] == PLACEHOLDER_START) { + break; + } + } + if (split > lastSplit) { + addSplit(split); + continue; + } + split = lastSplit + wrapLimit; + for (split; split < tokens.length; split++) { + if (tokens[split] != PLACEHOLDER_BODY) { + break; + } + } + if (split == tokens.length) { + break; // Breaks the while-loop. + } + addSplit(split); + continue; + } + var minSplit = Math.max(split - (wrapLimit -(wrapLimit>>2)), lastSplit - 1); + while (split > minSplit && tokens[split] < PLACEHOLDER_START) { + split --; + } + if (isCode) { + while (split > minSplit && tokens[split] < PLACEHOLDER_START) { + split --; + } + while (split > minSplit && tokens[split] == PUNCTUATION) { + split --; + } + } else { + while (split > minSplit && tokens[split] < SPACE) { + split --; + } + } + if (split > minSplit) { + addSplit(++split); + continue; + } + split = lastSplit + wrapLimit; + if (tokens[split] == CHAR_EXT) + split--; + addSplit(split - indent); + } + return splits; + }; + this.$getDisplayTokens = function(str, offset) { + var arr = []; + var tabSize; + offset = offset || 0; + + for (var i = 0; i < str.length; i++) { + var c = str.charCodeAt(i); + if (c == 9) { + tabSize = this.getScreenTabSize(arr.length + offset); + arr.push(TAB); + for (var n = 1; n < tabSize; n++) { + arr.push(TAB_SPACE); + } + } + else if (c == 32) { + arr.push(SPACE); + } else if((c > 39 && c < 48) || (c > 57 && c < 64)) { + arr.push(PUNCTUATION); + } + else if (c >= 0x1100 && isFullWidth(c)) { + arr.push(CHAR, CHAR_EXT); + } else { + arr.push(CHAR); + } + } + return arr; + }; + this.$getStringScreenWidth = function(str, maxScreenColumn, screenColumn) { + if (maxScreenColumn == 0) + return [0, 0]; + if (maxScreenColumn == null) + maxScreenColumn = Infinity; + screenColumn = screenColumn || 0; + + var c, column; + for (column = 0; column < str.length; column++) { + c = str.charCodeAt(column); + if (c == 9) { + screenColumn += this.getScreenTabSize(screenColumn); + } + else if (c >= 0x1100 && isFullWidth(c)) { + screenColumn += 2; + } else { + screenColumn += 1; + } + if (screenColumn > maxScreenColumn) { + break; + } + } + + return [screenColumn, column]; + }; + + this.lineWidgets = null; + this.getRowLength = function(row) { + if (this.lineWidgets) + var h = this.lineWidgets[row] && this.lineWidgets[row].rowCount || 0; + else + h = 0 + if (!this.$useWrapMode || !this.$wrapData[row]) { + return 1 + h; + } else { + return this.$wrapData[row].length + 1 + h; + } + }; + this.getRowLineCount = function(row) { + if (!this.$useWrapMode || !this.$wrapData[row]) { + return 1; + } else { + return this.$wrapData[row].length + 1; + } + }; + + this.getRowWrapIndent = function(screenRow) { + if (this.$useWrapMode) { + var pos = this.screenToDocumentPosition(screenRow, Number.MAX_VALUE); + var splits = this.$wrapData[pos.row]; + return splits.length && splits[0] < pos.column ? splits.indent : 0; + } else { + return 0; + } + } + this.getScreenLastRowColumn = function(screenRow) { + var pos = this.screenToDocumentPosition(screenRow, Number.MAX_VALUE); + return this.documentToScreenColumn(pos.row, pos.column); + }; + this.getDocumentLastRowColumn = function(docRow, docColumn) { + var screenRow = this.documentToScreenRow(docRow, docColumn); + return this.getScreenLastRowColumn(screenRow); + }; + this.getDocumentLastRowColumnPosition = function(docRow, docColumn) { + var screenRow = this.documentToScreenRow(docRow, docColumn); + return this.screenToDocumentPosition(screenRow, Number.MAX_VALUE / 10); + }; + this.getRowSplitData = function(row) { + if (!this.$useWrapMode) { + return undefined; + } else { + return this.$wrapData[row]; + } + }; + this.getScreenTabSize = function(screenColumn) { + return this.$tabSize - screenColumn % this.$tabSize; + }; + + + this.screenToDocumentRow = function(screenRow, screenColumn) { + return this.screenToDocumentPosition(screenRow, screenColumn).row; + }; + + + this.screenToDocumentColumn = function(screenRow, screenColumn) { + return this.screenToDocumentPosition(screenRow, screenColumn).column; + }; + this.screenToDocumentPosition = function(screenRow, screenColumn) { + if (screenRow < 0) + return {row: 0, column: 0}; + + var line; + var docRow = 0; + var docColumn = 0; + var column; + var row = 0; + var rowLength = 0; + + var rowCache = this.$screenRowCache; + var i = this.$getRowCacheIndex(rowCache, screenRow); + var l = rowCache.length; + if (l && i >= 0) { + var row = rowCache[i]; + var docRow = this.$docRowCache[i]; + var doCache = screenRow > rowCache[l - 1]; + } else { + var doCache = !l; + } + + var maxRow = this.getLength() - 1; + var foldLine = this.getNextFoldLine(docRow); + var foldStart = foldLine ? foldLine.start.row : Infinity; + + while (row <= screenRow) { + rowLength = this.getRowLength(docRow); + if (row + rowLength > screenRow || docRow >= maxRow) { + break; + } else { + row += rowLength; + docRow++; + if (docRow > foldStart) { + docRow = foldLine.end.row+1; + foldLine = this.getNextFoldLine(docRow, foldLine); + foldStart = foldLine ? foldLine.start.row : Infinity; + } + } + + if (doCache) { + this.$docRowCache.push(docRow); + this.$screenRowCache.push(row); + } + } + + if (foldLine && foldLine.start.row <= docRow) { + line = this.getFoldDisplayLine(foldLine); + docRow = foldLine.start.row; + } else if (row + rowLength <= screenRow || docRow > maxRow) { + return { + row: maxRow, + column: this.getLine(maxRow).length + }; + } else { + line = this.getLine(docRow); + foldLine = null; + } + var wrapIndent = 0; + if (this.$useWrapMode) { + var splits = this.$wrapData[docRow]; + if (splits) { + var splitIndex = Math.floor(screenRow - row); + column = splits[splitIndex]; + if(splitIndex > 0 && splits.length) { + wrapIndent = splits.indent; + docColumn = splits[splitIndex - 1] || splits[splits.length - 1]; + line = line.substring(docColumn); + } + } + } + + docColumn += this.$getStringScreenWidth(line, screenColumn - wrapIndent)[1]; + if (this.$useWrapMode && docColumn >= column) + docColumn = column - 1; + + if (foldLine) + return foldLine.idxToPosition(docColumn); + + return {row: docRow, column: docColumn}; + }; + this.documentToScreenPosition = function(docRow, docColumn) { + if (typeof docColumn === "undefined") + var pos = this.$clipPositionToDocument(docRow.row, docRow.column); + else + pos = this.$clipPositionToDocument(docRow, docColumn); + + docRow = pos.row; + docColumn = pos.column; + + var screenRow = 0; + var foldStartRow = null; + var fold = null; + fold = this.getFoldAt(docRow, docColumn, 1); + if (fold) { + docRow = fold.start.row; + docColumn = fold.start.column; + } + + var rowEnd, row = 0; + + + var rowCache = this.$docRowCache; + var i = this.$getRowCacheIndex(rowCache, docRow); + var l = rowCache.length; + if (l && i >= 0) { + var row = rowCache[i]; + var screenRow = this.$screenRowCache[i]; + var doCache = docRow > rowCache[l - 1]; + } else { + var doCache = !l; + } + + var foldLine = this.getNextFoldLine(row); + var foldStart = foldLine ?foldLine.start.row :Infinity; + + while (row < docRow) { + if (row >= foldStart) { + rowEnd = foldLine.end.row + 1; + if (rowEnd > docRow) + break; + foldLine = this.getNextFoldLine(rowEnd, foldLine); + foldStart = foldLine ?foldLine.start.row :Infinity; + } + else { + rowEnd = row + 1; + } + + screenRow += this.getRowLength(row); + row = rowEnd; + + if (doCache) { + this.$docRowCache.push(row); + this.$screenRowCache.push(screenRow); + } + } + var textLine = ""; + if (foldLine && row >= foldStart) { + textLine = this.getFoldDisplayLine(foldLine, docRow, docColumn); + foldStartRow = foldLine.start.row; + } else { + textLine = this.getLine(docRow).substring(0, docColumn); + foldStartRow = docRow; + } + var wrapIndent = 0; + if (this.$useWrapMode) { + var wrapRow = this.$wrapData[foldStartRow]; + if (wrapRow) { + var screenRowOffset = 0; + while (textLine.length >= wrapRow[screenRowOffset]) { + screenRow ++; + screenRowOffset++; + } + textLine = textLine.substring( + wrapRow[screenRowOffset - 1] || 0, textLine.length + ); + wrapIndent = screenRowOffset > 0 ? wrapRow.indent : 0; + } + } + + return { + row: screenRow, + column: wrapIndent + this.$getStringScreenWidth(textLine)[0] + }; + }; + this.documentToScreenColumn = function(row, docColumn) { + return this.documentToScreenPosition(row, docColumn).column; + }; + this.documentToScreenRow = function(docRow, docColumn) { + return this.documentToScreenPosition(docRow, docColumn).row; + }; + this.getScreenLength = function() { + var screenRows = 0; + var fold = null; + if (!this.$useWrapMode) { + screenRows = this.getLength(); + var foldData = this.$foldData; + for (var i = 0; i < foldData.length; i++) { + fold = foldData[i]; + screenRows -= fold.end.row - fold.start.row; + } + } else { + var lastRow = this.$wrapData.length; + var row = 0, i = 0; + var fold = this.$foldData[i++]; + var foldStart = fold ? fold.start.row :Infinity; + + while (row < lastRow) { + var splits = this.$wrapData[row]; + screenRows += splits ? splits.length + 1 : 1; + row ++; + if (row > foldStart) { + row = fold.end.row+1; + fold = this.$foldData[i++]; + foldStart = fold ?fold.start.row :Infinity; + } + } + } + if (this.lineWidgets) + screenRows += this.$getWidgetScreenLength(); + + return screenRows; + }; + this.$setFontMetrics = function(fm) { + if (!this.$enableVarChar) return; + this.$getStringScreenWidth = function(str, maxScreenColumn, screenColumn) { + if (maxScreenColumn === 0) + return [0, 0]; + if (!maxScreenColumn) + maxScreenColumn = Infinity; + screenColumn = screenColumn || 0; + + var c, column; + for (column = 0; column < str.length; column++) { + c = str.charAt(column); + if (c === "\t") { + screenColumn += this.getScreenTabSize(screenColumn); + } else { + screenColumn += fm.getCharacterWidth(c); + } + if (screenColumn > maxScreenColumn) { + break; + } + } + + return [screenColumn, column]; + }; + }; + + this.destroy = function() { + if (this.bgTokenizer) { + this.bgTokenizer.setDocument(null); + this.bgTokenizer = null; + } + this.$stopWorker(); + }; + function isFullWidth(c) { + if (c < 0x1100) + return false; + return c >= 0x1100 && c <= 0x115F || + c >= 0x11A3 && c <= 0x11A7 || + c >= 0x11FA && c <= 0x11FF || + c >= 0x2329 && c <= 0x232A || + c >= 0x2E80 && c <= 0x2E99 || + c >= 0x2E9B && c <= 0x2EF3 || + c >= 0x2F00 && c <= 0x2FD5 || + c >= 0x2FF0 && c <= 0x2FFB || + c >= 0x3000 && c <= 0x303E || + c >= 0x3041 && c <= 0x3096 || + c >= 0x3099 && c <= 0x30FF || + c >= 0x3105 && c <= 0x312D || + c >= 0x3131 && c <= 0x318E || + c >= 0x3190 && c <= 0x31BA || + c >= 0x31C0 && c <= 0x31E3 || + c >= 0x31F0 && c <= 0x321E || + c >= 0x3220 && c <= 0x3247 || + c >= 0x3250 && c <= 0x32FE || + c >= 0x3300 && c <= 0x4DBF || + c >= 0x4E00 && c <= 0xA48C || + c >= 0xA490 && c <= 0xA4C6 || + c >= 0xA960 && c <= 0xA97C || + c >= 0xAC00 && c <= 0xD7A3 || + c >= 0xD7B0 && c <= 0xD7C6 || + c >= 0xD7CB && c <= 0xD7FB || + c >= 0xF900 && c <= 0xFAFF || + c >= 0xFE10 && c <= 0xFE19 || + c >= 0xFE30 && c <= 0xFE52 || + c >= 0xFE54 && c <= 0xFE66 || + c >= 0xFE68 && c <= 0xFE6B || + c >= 0xFF01 && c <= 0xFF60 || + c >= 0xFFE0 && c <= 0xFFE6; + } + + }).call(EditSession.prototype); + + acequire("./edit_session/folding").Folding.call(EditSession.prototype); + acequire("./edit_session/bracket_match").BracketMatch.call(EditSession.prototype); + + + config.defineOptions(EditSession.prototype, "session", { + wrap: { + set: function(value) { + if (!value || value == "off") + value = false; + else if (value == "free") + value = true; + else if (value == "printMargin") + value = -1; + else if (typeof value == "string") + value = parseInt(value, 10) || false; + + if (this.$wrap == value) + return; + this.$wrap = value; + if (!value) { + this.setUseWrapMode(false); + } else { + var col = typeof value == "number" ? value : null; + this.setWrapLimitRange(col, col); + this.setUseWrapMode(true); + } + }, + get: function() { + if (this.getUseWrapMode()) { + if (this.$wrap == -1) + return "printMargin"; + if (!this.getWrapLimitRange().min) + return "free"; + return this.$wrap; + } + return "off"; + }, + handlesSet: true + }, + wrapMethod: { + set: function(val) { + val = val == "auto" + ? this.$mode.type != "text" + : val != "text"; + if (val != this.$wrapAsCode) { + this.$wrapAsCode = val; + if (this.$useWrapMode) { + this.$modified = true; + this.$resetRowCache(0); + this.$updateWrapData(0, this.getLength() - 1); + } + } + }, + initialValue: "auto" + }, + indentedSoftWrap: { initialValue: true }, + firstLineNumber: { + set: function() {this._signal("changeBreakpoint");}, + initialValue: 1 + }, + useWorker: { + set: function(useWorker) { + this.$useWorker = useWorker; + + this.$stopWorker(); + if (useWorker) + this.$startWorker(); + }, + initialValue: true + }, + useSoftTabs: {initialValue: true}, + tabSize: { + set: function(tabSize) { + if (isNaN(tabSize) || this.$tabSize === tabSize) return; + + this.$modified = true; + this.$rowLengthCache = []; + this.$tabSize = tabSize; + this._signal("changeTabSize"); + }, + initialValue: 4, + handlesSet: true + }, + overwrite: { + set: function(val) {this._signal("changeOverwrite");}, + initialValue: false + }, + newLineMode: { + set: function(val) {this.doc.setNewLineMode(val)}, + get: function() {return this.doc.getNewLineMode()}, + handlesSet: true + }, + mode: { + set: function(val) { this.setMode(val) }, + get: function() { return this.$modeId } + } + }); + + exports.EditSession = EditSession; + }); + + ace.define("ace/search",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/range"], function(acequire, exports, module) { + "use strict"; + + var lang = acequire("./lib/lang"); + var oop = acequire("./lib/oop"); + var Range = acequire("./range").Range; + + var Search = function() { + this.$options = {}; + }; + + (function() { + this.set = function(options) { + oop.mixin(this.$options, options); + return this; + }; + this.getOptions = function() { + return lang.copyObject(this.$options); + }; + this.setOptions = function(options) { + this.$options = options; + }; + this.find = function(session) { + var options = this.$options; + var iterator = this.$matchIterator(session, options); + if (!iterator) + return false; + + var firstRange = null; + iterator.forEach(function(range, row, offset) { + if (!range.start) { + var column = range.offset + (offset || 0); + firstRange = new Range(row, column, row, column + range.length); + if (!range.length && options.start && options.start.start + && options.skipCurrent != false && firstRange.isEqual(options.start) + ) { + firstRange = null; + return false; + } + } else + firstRange = range; + return true; + }); + + return firstRange; + }; + this.findAll = function(session) { + var options = this.$options; + if (!options.needle) + return []; + this.$assembleRegExp(options); + + var range = options.range; + var lines = range + ? session.getLines(range.start.row, range.end.row) + : session.doc.getAllLines(); + + var ranges = []; + var re = options.re; + if (options.$isMultiLine) { + var len = re.length; + var maxRow = lines.length - len; + var prevRange; + outer: for (var row = re.offset || 0; row <= maxRow; row++) { + for (var j = 0; j < len; j++) + if (lines[row + j].search(re[j]) == -1) + continue outer; + + var startLine = lines[row]; + var line = lines[row + len - 1]; + var startIndex = startLine.length - startLine.match(re[0])[0].length; + var endIndex = line.match(re[len - 1])[0].length; + + if (prevRange && prevRange.end.row === row && + prevRange.end.column > startIndex + ) { + continue; + } + ranges.push(prevRange = new Range( + row, startIndex, row + len - 1, endIndex + )); + if (len > 2) + row = row + len - 2; + } + } else { + for (var i = 0; i < lines.length; i++) { + var matches = lang.getMatchOffsets(lines[i], re); + for (var j = 0; j < matches.length; j++) { + var match = matches[j]; + ranges.push(new Range(i, match.offset, i, match.offset + match.length)); + } + } + } + + if (range) { + var startColumn = range.start.column; + var endColumn = range.start.column; + var i = 0, j = ranges.length - 1; + while (i < j && ranges[i].start.column < startColumn && ranges[i].start.row == range.start.row) + i++; + + while (i < j && ranges[j].end.column > endColumn && ranges[j].end.row == range.end.row) + j--; + + ranges = ranges.slice(i, j + 1); + for (i = 0, j = ranges.length; i < j; i++) { + ranges[i].start.row += range.start.row; + ranges[i].end.row += range.start.row; + } + } + + return ranges; + }; + this.replace = function(input, replacement) { + var options = this.$options; + + var re = this.$assembleRegExp(options); + if (options.$isMultiLine) + return replacement; + + if (!re) + return; + + var match = re.exec(input); + if (!match || match[0].length != input.length) + return null; + + replacement = input.replace(re, replacement); + if (options.preserveCase) { + replacement = replacement.split(""); + for (var i = Math.min(input.length, input.length); i--; ) { + var ch = input[i]; + if (ch && ch.toLowerCase() != ch) + replacement[i] = replacement[i].toUpperCase(); + else + replacement[i] = replacement[i].toLowerCase(); + } + replacement = replacement.join(""); + } + + return replacement; + }; + + this.$matchIterator = function(session, options) { + var re = this.$assembleRegExp(options); + if (!re) + return false; + + var callback; + if (options.$isMultiLine) { + var len = re.length; + var matchIterator = function(line, row, offset) { + var startIndex = line.search(re[0]); + if (startIndex == -1) + return; + for (var i = 1; i < len; i++) { + line = session.getLine(row + i); + if (line.search(re[i]) == -1) + return; + } + + var endIndex = line.match(re[len - 1])[0].length; + + var range = new Range(row, startIndex, row + len - 1, endIndex); + if (re.offset == 1) { + range.start.row--; + range.start.column = Number.MAX_VALUE; + } else if (offset) + range.start.column += offset; + + if (callback(range)) + return true; + }; + } else if (options.backwards) { + var matchIterator = function(line, row, startIndex) { + var matches = lang.getMatchOffsets(line, re); + for (var i = matches.length-1; i >= 0; i--) + if (callback(matches[i], row, startIndex)) + return true; + }; + } else { + var matchIterator = function(line, row, startIndex) { + var matches = lang.getMatchOffsets(line, re); + for (var i = 0; i < matches.length; i++) + if (callback(matches[i], row, startIndex)) + return true; + }; + } + + var lineIterator = this.$lineIterator(session, options); + + return { + forEach: function(_callback) { + callback = _callback; + lineIterator.forEach(matchIterator); + } + }; + }; + + this.$assembleRegExp = function(options, $disableFakeMultiline) { + if (options.needle instanceof RegExp) + return options.re = options.needle; + + var needle = options.needle; + + if (!options.needle) + return options.re = false; + + if (!options.regExp) + needle = lang.escapeRegExp(needle); + + if (options.wholeWord) + needle = "\\b" + needle + "\\b"; + + var modifier = options.caseSensitive ? "gm" : "gmi"; + + options.$isMultiLine = !$disableFakeMultiline && /[\n\r]/.test(needle); + if (options.$isMultiLine) + return options.re = this.$assembleMultilineRegExp(needle, modifier); + + try { + var re = new RegExp(needle, modifier); + } catch(e) { + re = false; + } + return options.re = re; + }; + + this.$assembleMultilineRegExp = function(needle, modifier) { + var parts = needle.replace(/\r\n|\r|\n/g, "$\n^").split("\n"); + var re = []; + for (var i = 0; i < parts.length; i++) try { + re.push(new RegExp(parts[i], modifier)); + } catch(e) { + return false; + } + if (parts[0] == "") { + re.shift(); + re.offset = 1; + } else { + re.offset = 0; + } + return re; + }; + + this.$lineIterator = function(session, options) { + var backwards = options.backwards == true; + var skipCurrent = options.skipCurrent != false; + + var range = options.range; + var start = options.start; + if (!start) + start = range ? range[backwards ? "end" : "start"] : session.selection.getRange(); + + if (start.start) + start = start[skipCurrent != backwards ? "end" : "start"]; + + var firstRow = range ? range.start.row : 0; + var lastRow = range ? range.end.row : session.getLength() - 1; + + var forEach = backwards ? function(callback) { + var row = start.row; + + var line = session.getLine(row).substring(0, start.column); + if (callback(line, row)) + return; + + for (row--; row >= firstRow; row--) + if (callback(session.getLine(row), row)) + return; + + if (options.wrap == false) + return; + + for (row = lastRow, firstRow = start.row; row >= firstRow; row--) + if (callback(session.getLine(row), row)) + return; + } : function(callback) { + var row = start.row; + + var line = session.getLine(row).substr(start.column); + if (callback(line, row, start.column)) + return; + + for (row = row+1; row <= lastRow; row++) + if (callback(session.getLine(row), row)) + return; + + if (options.wrap == false) + return; + + for (row = firstRow, lastRow = start.row; row <= lastRow; row++) + if (callback(session.getLine(row), row)) + return; + }; + + return {forEach: forEach}; + }; + + }).call(Search.prototype); + + exports.Search = Search; + }); + + ace.define("ace/keyboard/hash_handler",["require","exports","module","ace/lib/keys","ace/lib/useragent"], function(acequire, exports, module) { + "use strict"; + + var keyUtil = acequire("../lib/keys"); + var useragent = acequire("../lib/useragent"); + var KEY_MODS = keyUtil.KEY_MODS; + + function HashHandler(config, platform) { + this.platform = platform || (useragent.isMac ? "mac" : "win"); + this.commands = {}; + this.commandKeyBinding = {}; + this.addCommands(config); + this.$singleCommand = true; + } + + function MultiHashHandler(config, platform) { + HashHandler.call(this, config, platform); + this.$singleCommand = false; + } + + MultiHashHandler.prototype = HashHandler.prototype; + + (function() { + + + this.addCommand = function(command) { + if (this.commands[command.name]) + this.removeCommand(command); + + this.commands[command.name] = command; + + if (command.bindKey) + this._buildKeyHash(command); + }; + + this.removeCommand = function(command, keepCommand) { + var name = command && (typeof command === 'string' ? command : command.name); + command = this.commands[name]; + if (!keepCommand) + delete this.commands[name]; + var ckb = this.commandKeyBinding; + for (var keyId in ckb) { + var cmdGroup = ckb[keyId]; + if (cmdGroup == command) { + delete ckb[keyId]; + } else if (Array.isArray(cmdGroup)) { + var i = cmdGroup.indexOf(command); + if (i != -1) { + cmdGroup.splice(i, 1); + if (cmdGroup.length == 1) + ckb[keyId] = cmdGroup[0]; + } + } + } + }; + + this.bindKey = function(key, command, position) { + if (typeof key == "object" && key) { + if (position == undefined) + position = key.position; + key = key[this.platform]; + } + if (!key) + return; + if (typeof command == "function") + return this.addCommand({exec: command, bindKey: key, name: command.name || key}); + + key.split("|").forEach(function(keyPart) { + var chain = ""; + if (keyPart.indexOf(" ") != -1) { + var parts = keyPart.split(/\s+/); + keyPart = parts.pop(); + parts.forEach(function(keyPart) { + var binding = this.parseKeys(keyPart); + var id = KEY_MODS[binding.hashId] + binding.key; + chain += (chain ? " " : "") + id; + this._addCommandToBinding(chain, "chainKeys"); + }, this); + chain += " "; + } + var binding = this.parseKeys(keyPart); + var id = KEY_MODS[binding.hashId] + binding.key; + this._addCommandToBinding(chain + id, command, position); + }, this); + }; + + function getPosition(command) { + return typeof command == "object" && command.bindKey + && command.bindKey.position || 0; + } + this._addCommandToBinding = function(keyId, command, position) { + var ckb = this.commandKeyBinding, i; + if (!command) { + delete ckb[keyId]; + } else if (!ckb[keyId] || this.$singleCommand) { + ckb[keyId] = command; + } else { + if (!Array.isArray(ckb[keyId])) { + ckb[keyId] = [ckb[keyId]]; + } else if ((i = ckb[keyId].indexOf(command)) != -1) { + ckb[keyId].splice(i, 1); + } + + if (typeof position != "number") { + if (position || command.isDefault) + position = -100; + else + position = getPosition(command); + } + var commands = ckb[keyId]; + for (i = 0; i < commands.length; i++) { + var other = commands[i]; + var otherPos = getPosition(other); + if (otherPos > position) + break; + } + commands.splice(i, 0, command); + } + }; + + this.addCommands = function(commands) { + commands && Object.keys(commands).forEach(function(name) { + var command = commands[name]; + if (!command) + return; + + if (typeof command === "string") + return this.bindKey(command, name); + + if (typeof command === "function") + command = { exec: command }; + + if (typeof command !== "object") + return; + + if (!command.name) + command.name = name; + + this.addCommand(command); + }, this); + }; + + this.removeCommands = function(commands) { + Object.keys(commands).forEach(function(name) { + this.removeCommand(commands[name]); + }, this); + }; + + this.bindKeys = function(keyList) { + Object.keys(keyList).forEach(function(key) { + this.bindKey(key, keyList[key]); + }, this); + }; + + this._buildKeyHash = function(command) { + this.bindKey(command.bindKey, command); + }; + this.parseKeys = function(keys) { + var parts = keys.toLowerCase().split(/[\-\+]([\-\+])?/).filter(function(x){return x}); + var key = parts.pop(); + + var keyCode = keyUtil[key]; + if (keyUtil.FUNCTION_KEYS[keyCode]) + key = keyUtil.FUNCTION_KEYS[keyCode].toLowerCase(); + else if (!parts.length) + return {key: key, hashId: -1}; + else if (parts.length == 1 && parts[0] == "shift") + return {key: key.toUpperCase(), hashId: -1}; + + var hashId = 0; + for (var i = parts.length; i--;) { + var modifier = keyUtil.KEY_MODS[parts[i]]; + if (modifier == null) { + if (typeof console != "undefined") + console.error("invalid modifier " + parts[i] + " in " + keys); + return false; + } + hashId |= modifier; + } + return {key: key, hashId: hashId}; + }; + + this.findKeyCommand = function findKeyCommand(hashId, keyString) { + var key = KEY_MODS[hashId] + keyString; + return this.commandKeyBinding[key]; + }; + + this.handleKeyboard = function(data, hashId, keyString, keyCode) { + if (keyCode < 0) return; + var key = KEY_MODS[hashId] + keyString; + var command = this.commandKeyBinding[key]; + if (data.$keyChain) { + data.$keyChain += " " + key; + command = this.commandKeyBinding[data.$keyChain] || command; + } + + if (command) { + if (command == "chainKeys" || command[command.length - 1] == "chainKeys") { + data.$keyChain = data.$keyChain || key; + return {command: "null"}; + } + } + + if (data.$keyChain) { + if ((!hashId || hashId == 4) && keyString.length == 1) + data.$keyChain = data.$keyChain.slice(0, -key.length - 1); // wait for input + else if (hashId == -1 || keyCode > 0) + data.$keyChain = ""; // reset keyChain + } + return {command: command}; + }; + + this.getStatusText = function(editor, data) { + return data.$keyChain || ""; + }; + + }).call(HashHandler.prototype); + + exports.HashHandler = HashHandler; + exports.MultiHashHandler = MultiHashHandler; + }); + + ace.define("ace/commands/command_manager",["require","exports","module","ace/lib/oop","ace/keyboard/hash_handler","ace/lib/event_emitter"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("../lib/oop"); + var MultiHashHandler = acequire("../keyboard/hash_handler").MultiHashHandler; + var EventEmitter = acequire("../lib/event_emitter").EventEmitter; + + var CommandManager = function(platform, commands) { + MultiHashHandler.call(this, commands, platform); + this.byName = this.commands; + this.setDefaultHandler("exec", function(e) { + return e.command.exec(e.editor, e.args || {}); + }); + }; + + oop.inherits(CommandManager, MultiHashHandler); + + (function() { + + oop.implement(this, EventEmitter); + + this.exec = function(command, editor, args) { + if (Array.isArray(command)) { + for (var i = command.length; i--; ) { + if (this.exec(command[i], editor, args)) return true; + } + return false; + } + + if (typeof command === "string") + command = this.commands[command]; + + if (!command) + return false; + + if (editor && editor.$readOnly && !command.readOnly) + return false; + + var e = {editor: editor, command: command, args: args}; + e.returnValue = this._emit("exec", e); + this._signal("afterExec", e); + + return e.returnValue === false ? false : true; + }; + + this.toggleRecording = function(editor) { + if (this.$inReplay) + return; + + editor && editor._emit("changeStatus"); + if (this.recording) { + this.macro.pop(); + this.removeEventListener("exec", this.$addCommandToMacro); + + if (!this.macro.length) + this.macro = this.oldMacro; + + return this.recording = false; + } + if (!this.$addCommandToMacro) { + this.$addCommandToMacro = function(e) { + this.macro.push([e.command, e.args]); + }.bind(this); + } + + this.oldMacro = this.macro; + this.macro = []; + this.on("exec", this.$addCommandToMacro); + return this.recording = true; + }; + + this.replay = function(editor) { + if (this.$inReplay || !this.macro) + return; + + if (this.recording) + return this.toggleRecording(editor); + + try { + this.$inReplay = true; + this.macro.forEach(function(x) { + if (typeof x == "string") + this.exec(x, editor); + else + this.exec(x[0], editor, x[1]); + }, this); + } finally { + this.$inReplay = false; + } + }; + + this.trimMacro = function(m) { + return m.map(function(x){ + if (typeof x[0] != "string") + x[0] = x[0].name; + if (!x[1]) + x = x[0]; + return x; + }); + }; + + }).call(CommandManager.prototype); + + exports.CommandManager = CommandManager; + + }); + + ace.define("ace/commands/default_commands",["require","exports","module","ace/lib/lang","ace/config","ace/range"], function(acequire, exports, module) { + "use strict"; + + var lang = acequire("../lib/lang"); + var config = acequire("../config"); + var Range = acequire("../range").Range; + + function bindKey(win, mac) { + return {win: win, mac: mac}; + } + exports.commands = [{ + name: "showSettingsMenu", + bindKey: bindKey("Ctrl-,", "Command-,"), + exec: function(editor) { + config.loadModule("ace/ext/settings_menu", function(module) { + module.init(editor); + editor.showSettingsMenu(); + }); + }, + readOnly: true + }, { + name: "goToNextError", + bindKey: bindKey("Alt-E", "Ctrl-E"), + exec: function(editor) { + config.loadModule("ace/ext/error_marker", function(module) { + module.showErrorMarker(editor, 1); + }); + }, + scrollIntoView: "animate", + readOnly: true + }, { + name: "goToPreviousError", + bindKey: bindKey("Alt-Shift-E", "Ctrl-Shift-E"), + exec: function(editor) { + config.loadModule("ace/ext/error_marker", function(module) { + module.showErrorMarker(editor, -1); + }); + }, + scrollIntoView: "animate", + readOnly: true + }, { + name: "selectall", + bindKey: bindKey("Ctrl-A", "Command-A"), + exec: function(editor) { editor.selectAll(); }, + readOnly: true + }, { + name: "centerselection", + bindKey: bindKey(null, "Ctrl-L"), + exec: function(editor) { editor.centerSelection(); }, + readOnly: true + }, { + name: "gotoline", + bindKey: bindKey("Ctrl-L", "Command-L"), + exec: function(editor) { + var line = parseInt(prompt("Enter line number:"), 10); + if (!isNaN(line)) { + editor.gotoLine(line); + } + }, + readOnly: true + }, { + name: "fold", + bindKey: bindKey("Alt-L|Ctrl-F1", "Command-Alt-L|Command-F1"), + exec: function(editor) { editor.session.toggleFold(false); }, + multiSelectAction: "forEach", + scrollIntoView: "center", + readOnly: true + }, { + name: "unfold", + bindKey: bindKey("Alt-Shift-L|Ctrl-Shift-F1", "Command-Alt-Shift-L|Command-Shift-F1"), + exec: function(editor) { editor.session.toggleFold(true); }, + multiSelectAction: "forEach", + scrollIntoView: "center", + readOnly: true + }, { + name: "toggleFoldWidget", + bindKey: bindKey("F2", "F2"), + exec: function(editor) { editor.session.toggleFoldWidget(); }, + multiSelectAction: "forEach", + scrollIntoView: "center", + readOnly: true + }, { + name: "toggleParentFoldWidget", + bindKey: bindKey("Alt-F2", "Alt-F2"), + exec: function(editor) { editor.session.toggleFoldWidget(true); }, + multiSelectAction: "forEach", + scrollIntoView: "center", + readOnly: true + }, { + name: "foldall", + bindKey: bindKey(null, "Ctrl-Command-Option-0"), + exec: function(editor) { editor.session.foldAll(); }, + scrollIntoView: "center", + readOnly: true + }, { + name: "foldOther", + bindKey: bindKey("Alt-0", "Command-Option-0"), + exec: function(editor) { + editor.session.foldAll(); + editor.session.unfold(editor.selection.getAllRanges()); + }, + scrollIntoView: "center", + readOnly: true + }, { + name: "unfoldall", + bindKey: bindKey("Alt-Shift-0", "Command-Option-Shift-0"), + exec: function(editor) { editor.session.unfold(); }, + scrollIntoView: "center", + readOnly: true + }, { + name: "findnext", + bindKey: bindKey("Ctrl-K", "Command-G"), + exec: function(editor) { editor.findNext(); }, + multiSelectAction: "forEach", + scrollIntoView: "center", + readOnly: true + }, { + name: "findprevious", + bindKey: bindKey("Ctrl-Shift-K", "Command-Shift-G"), + exec: function(editor) { editor.findPrevious(); }, + multiSelectAction: "forEach", + scrollIntoView: "center", + readOnly: true + }, { + name: "selectOrFindNext", + bindKey: bindKey("Alt-K", "Ctrl-G"), + exec: function(editor) { + if (editor.selection.isEmpty()) + editor.selection.selectWord(); + else + editor.findNext(); + }, + readOnly: true + }, { + name: "selectOrFindPrevious", + bindKey: bindKey("Alt-Shift-K", "Ctrl-Shift-G"), + exec: function(editor) { + if (editor.selection.isEmpty()) + editor.selection.selectWord(); + else + editor.findPrevious(); + }, + readOnly: true + }, { + name: "find", + bindKey: bindKey("Ctrl-F", "Command-F"), + exec: function(editor) { + config.loadModule("ace/ext/searchbox", function(e) {e.Search(editor)}); + }, + readOnly: true + }, { + name: "overwrite", + bindKey: "Insert", + exec: function(editor) { editor.toggleOverwrite(); }, + readOnly: true + }, { + name: "selecttostart", + bindKey: bindKey("Ctrl-Shift-Home", "Command-Shift-Up"), + exec: function(editor) { editor.getSelection().selectFileStart(); }, + multiSelectAction: "forEach", + readOnly: true, + scrollIntoView: "animate", + aceCommandGroup: "fileJump" + }, { + name: "gotostart", + bindKey: bindKey("Ctrl-Home", "Command-Home|Command-Up"), + exec: function(editor) { editor.navigateFileStart(); }, + multiSelectAction: "forEach", + readOnly: true, + scrollIntoView: "animate", + aceCommandGroup: "fileJump" + }, { + name: "selectup", + bindKey: bindKey("Shift-Up", "Shift-Up"), + exec: function(editor) { editor.getSelection().selectUp(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "golineup", + bindKey: bindKey("Up", "Up|Ctrl-P"), + exec: function(editor, args) { editor.navigateUp(args.times); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "selecttoend", + bindKey: bindKey("Ctrl-Shift-End", "Command-Shift-Down"), + exec: function(editor) { editor.getSelection().selectFileEnd(); }, + multiSelectAction: "forEach", + readOnly: true, + scrollIntoView: "animate", + aceCommandGroup: "fileJump" + }, { + name: "gotoend", + bindKey: bindKey("Ctrl-End", "Command-End|Command-Down"), + exec: function(editor) { editor.navigateFileEnd(); }, + multiSelectAction: "forEach", + readOnly: true, + scrollIntoView: "animate", + aceCommandGroup: "fileJump" + }, { + name: "selectdown", + bindKey: bindKey("Shift-Down", "Shift-Down"), + exec: function(editor) { editor.getSelection().selectDown(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "golinedown", + bindKey: bindKey("Down", "Down|Ctrl-N"), + exec: function(editor, args) { editor.navigateDown(args.times); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "selectwordleft", + bindKey: bindKey("Ctrl-Shift-Left", "Option-Shift-Left"), + exec: function(editor) { editor.getSelection().selectWordLeft(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "gotowordleft", + bindKey: bindKey("Ctrl-Left", "Option-Left"), + exec: function(editor) { editor.navigateWordLeft(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "selecttolinestart", + bindKey: bindKey("Alt-Shift-Left", "Command-Shift-Left"), + exec: function(editor) { editor.getSelection().selectLineStart(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "gotolinestart", + bindKey: bindKey("Alt-Left|Home", "Command-Left|Home|Ctrl-A"), + exec: function(editor) { editor.navigateLineStart(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "selectleft", + bindKey: bindKey("Shift-Left", "Shift-Left"), + exec: function(editor) { editor.getSelection().selectLeft(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "gotoleft", + bindKey: bindKey("Left", "Left|Ctrl-B"), + exec: function(editor, args) { editor.navigateLeft(args.times); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "selectwordright", + bindKey: bindKey("Ctrl-Shift-Right", "Option-Shift-Right"), + exec: function(editor) { editor.getSelection().selectWordRight(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "gotowordright", + bindKey: bindKey("Ctrl-Right", "Option-Right"), + exec: function(editor) { editor.navigateWordRight(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "selecttolineend", + bindKey: bindKey("Alt-Shift-Right", "Command-Shift-Right"), + exec: function(editor) { editor.getSelection().selectLineEnd(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "gotolineend", + bindKey: bindKey("Alt-Right|End", "Command-Right|End|Ctrl-E"), + exec: function(editor) { editor.navigateLineEnd(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "selectright", + bindKey: bindKey("Shift-Right", "Shift-Right"), + exec: function(editor) { editor.getSelection().selectRight(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "gotoright", + bindKey: bindKey("Right", "Right|Ctrl-F"), + exec: function(editor, args) { editor.navigateRight(args.times); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "selectpagedown", + bindKey: "Shift-PageDown", + exec: function(editor) { editor.selectPageDown(); }, + readOnly: true + }, { + name: "pagedown", + bindKey: bindKey(null, "Option-PageDown"), + exec: function(editor) { editor.scrollPageDown(); }, + readOnly: true + }, { + name: "gotopagedown", + bindKey: bindKey("PageDown", "PageDown|Ctrl-V"), + exec: function(editor) { editor.gotoPageDown(); }, + readOnly: true + }, { + name: "selectpageup", + bindKey: "Shift-PageUp", + exec: function(editor) { editor.selectPageUp(); }, + readOnly: true + }, { + name: "pageup", + bindKey: bindKey(null, "Option-PageUp"), + exec: function(editor) { editor.scrollPageUp(); }, + readOnly: true + }, { + name: "gotopageup", + bindKey: "PageUp", + exec: function(editor) { editor.gotoPageUp(); }, + readOnly: true + }, { + name: "scrollup", + bindKey: bindKey("Ctrl-Up", null), + exec: function(e) { e.renderer.scrollBy(0, -2 * e.renderer.layerConfig.lineHeight); }, + readOnly: true + }, { + name: "scrolldown", + bindKey: bindKey("Ctrl-Down", null), + exec: function(e) { e.renderer.scrollBy(0, 2 * e.renderer.layerConfig.lineHeight); }, + readOnly: true + }, { + name: "selectlinestart", + bindKey: "Shift-Home", + exec: function(editor) { editor.getSelection().selectLineStart(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "selectlineend", + bindKey: "Shift-End", + exec: function(editor) { editor.getSelection().selectLineEnd(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "togglerecording", + bindKey: bindKey("Ctrl-Alt-E", "Command-Option-E"), + exec: function(editor) { editor.commands.toggleRecording(editor); }, + readOnly: true + }, { + name: "replaymacro", + bindKey: bindKey("Ctrl-Shift-E", "Command-Shift-E"), + exec: function(editor) { editor.commands.replay(editor); }, + readOnly: true + }, { + name: "jumptomatching", + bindKey: bindKey("Ctrl-P", "Ctrl-P"), + exec: function(editor) { editor.jumpToMatching(); }, + multiSelectAction: "forEach", + scrollIntoView: "animate", + readOnly: true + }, { + name: "selecttomatching", + bindKey: bindKey("Ctrl-Shift-P", "Ctrl-Shift-P"), + exec: function(editor) { editor.jumpToMatching(true); }, + multiSelectAction: "forEach", + scrollIntoView: "animate", + readOnly: true + }, { + name: "expandToMatching", + bindKey: bindKey("Ctrl-Shift-M", "Ctrl-Shift-M"), + exec: function(editor) { editor.jumpToMatching(true, true); }, + multiSelectAction: "forEach", + scrollIntoView: "animate", + readOnly: true + }, { + name: "passKeysToBrowser", + bindKey: bindKey(null, null), + exec: function() {}, + passEvent: true, + readOnly: true + }, { + name: "copy", + exec: function(editor) { + }, + readOnly: true + }, + { + name: "cut", + exec: function(editor) { + var range = editor.getSelectionRange(); + editor._emit("cut", range); + + if (!editor.selection.isEmpty()) { + editor.session.remove(range); + editor.clearSelection(); + } + }, + scrollIntoView: "cursor", + multiSelectAction: "forEach" + }, { + name: "paste", + exec: function(editor, args) { + editor.$handlePaste(args); + }, + scrollIntoView: "cursor" + }, { + name: "removeline", + bindKey: bindKey("Ctrl-D", "Command-D"), + exec: function(editor) { editor.removeLines(); }, + scrollIntoView: "cursor", + multiSelectAction: "forEachLine" + }, { + name: "duplicateSelection", + bindKey: bindKey("Ctrl-Shift-D", "Command-Shift-D"), + exec: function(editor) { editor.duplicateSelection(); }, + scrollIntoView: "cursor", + multiSelectAction: "forEach" + }, { + name: "sortlines", + bindKey: bindKey("Ctrl-Alt-S", "Command-Alt-S"), + exec: function(editor) { editor.sortLines(); }, + scrollIntoView: "selection", + multiSelectAction: "forEachLine" + }, { + name: "togglecomment", + bindKey: bindKey("Ctrl-/", "Command-/"), + exec: function(editor) { editor.toggleCommentLines(); }, + multiSelectAction: "forEachLine", + scrollIntoView: "selectionPart" + }, { + name: "toggleBlockComment", + bindKey: bindKey("Ctrl-Shift-/", "Command-Shift-/"), + exec: function(editor) { editor.toggleBlockComment(); }, + multiSelectAction: "forEach", + scrollIntoView: "selectionPart" + }, { + name: "modifyNumberUp", + bindKey: bindKey("Ctrl-Shift-Up", "Alt-Shift-Up"), + exec: function(editor) { editor.modifyNumber(1); }, + scrollIntoView: "cursor", + multiSelectAction: "forEach" + }, { + name: "modifyNumberDown", + bindKey: bindKey("Ctrl-Shift-Down", "Alt-Shift-Down"), + exec: function(editor) { editor.modifyNumber(-1); }, + scrollIntoView: "cursor", + multiSelectAction: "forEach" + }, { + name: "replace", + bindKey: bindKey("Ctrl-H", "Command-Option-F"), + exec: function(editor) { + config.loadModule("ace/ext/searchbox", function(e) {e.Search(editor, true)}); + } + }, { + name: "undo", + bindKey: bindKey("Ctrl-Z", "Command-Z"), + exec: function(editor) { editor.undo(); } + }, { + name: "redo", + bindKey: bindKey("Ctrl-Shift-Z|Ctrl-Y", "Command-Shift-Z|Command-Y"), + exec: function(editor) { editor.redo(); } + }, { + name: "copylinesup", + bindKey: bindKey("Alt-Shift-Up", "Command-Option-Up"), + exec: function(editor) { editor.copyLinesUp(); }, + scrollIntoView: "cursor" + }, { + name: "movelinesup", + bindKey: bindKey("Alt-Up", "Option-Up"), + exec: function(editor) { editor.moveLinesUp(); }, + scrollIntoView: "cursor" + }, { + name: "copylinesdown", + bindKey: bindKey("Alt-Shift-Down", "Command-Option-Down"), + exec: function(editor) { editor.copyLinesDown(); }, + scrollIntoView: "cursor" + }, { + name: "movelinesdown", + bindKey: bindKey("Alt-Down", "Option-Down"), + exec: function(editor) { editor.moveLinesDown(); }, + scrollIntoView: "cursor" + }, { + name: "del", + bindKey: bindKey("Delete", "Delete|Ctrl-D|Shift-Delete"), + exec: function(editor) { editor.remove("right"); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" + }, { + name: "backspace", + bindKey: bindKey( + "Shift-Backspace|Backspace", + "Ctrl-Backspace|Shift-Backspace|Backspace|Ctrl-H" + ), + exec: function(editor) { editor.remove("left"); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" + }, { + name: "cut_or_delete", + bindKey: bindKey("Shift-Delete", null), + exec: function(editor) { + if (editor.selection.isEmpty()) { + editor.remove("left"); + } else { + return false; + } + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" + }, { + name: "removetolinestart", + bindKey: bindKey("Alt-Backspace", "Command-Backspace"), + exec: function(editor) { editor.removeToLineStart(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" + }, { + name: "removetolineend", + bindKey: bindKey("Alt-Delete", "Ctrl-K"), + exec: function(editor) { editor.removeToLineEnd(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" + }, { + name: "removewordleft", + bindKey: bindKey("Ctrl-Backspace", "Alt-Backspace|Ctrl-Alt-Backspace"), + exec: function(editor) { editor.removeWordLeft(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" + }, { + name: "removewordright", + bindKey: bindKey("Ctrl-Delete", "Alt-Delete"), + exec: function(editor) { editor.removeWordRight(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" + }, { + name: "outdent", + bindKey: bindKey("Shift-Tab", "Shift-Tab"), + exec: function(editor) { editor.blockOutdent(); }, + multiSelectAction: "forEach", + scrollIntoView: "selectionPart" + }, { + name: "indent", + bindKey: bindKey("Tab", "Tab"), + exec: function(editor) { editor.indent(); }, + multiSelectAction: "forEach", + scrollIntoView: "selectionPart" + }, { + name: "blockoutdent", + bindKey: bindKey("Ctrl-[", "Ctrl-["), + exec: function(editor) { editor.blockOutdent(); }, + multiSelectAction: "forEachLine", + scrollIntoView: "selectionPart" + }, { + name: "blockindent", + bindKey: bindKey("Ctrl-]", "Ctrl-]"), + exec: function(editor) { editor.blockIndent(); }, + multiSelectAction: "forEachLine", + scrollIntoView: "selectionPart" + }, { + name: "insertstring", + exec: function(editor, str) { editor.insert(str); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" + }, { + name: "inserttext", + exec: function(editor, args) { + editor.insert(lang.stringRepeat(args.text || "", args.times || 1)); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" + }, { + name: "splitline", + bindKey: bindKey(null, "Ctrl-O"), + exec: function(editor) { editor.splitLine(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" + }, { + name: "transposeletters", + bindKey: bindKey("Ctrl-T", "Ctrl-T"), + exec: function(editor) { editor.transposeLetters(); }, + multiSelectAction: function(editor) {editor.transposeSelections(1); }, + scrollIntoView: "cursor" + }, { + name: "touppercase", + bindKey: bindKey("Ctrl-U", "Ctrl-U"), + exec: function(editor) { editor.toUpperCase(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" + }, { + name: "tolowercase", + bindKey: bindKey("Ctrl-Shift-U", "Ctrl-Shift-U"), + exec: function(editor) { editor.toLowerCase(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" + }, { + name: "expandtoline", + bindKey: bindKey("Ctrl-Shift-L", "Command-Shift-L"), + exec: function(editor) { + var range = editor.selection.getRange(); + + range.start.column = range.end.column = 0; + range.end.row++; + editor.selection.setRange(range, false); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "joinlines", + bindKey: bindKey(null, null), + exec: function(editor) { + var isBackwards = editor.selection.isBackwards(); + var selectionStart = isBackwards ? editor.selection.getSelectionLead() : editor.selection.getSelectionAnchor(); + var selectionEnd = isBackwards ? editor.selection.getSelectionAnchor() : editor.selection.getSelectionLead(); + var firstLineEndCol = editor.session.doc.getLine(selectionStart.row).length; + var selectedText = editor.session.doc.getTextRange(editor.selection.getRange()); + var selectedCount = selectedText.replace(/\n\s*/, " ").length; + var insertLine = editor.session.doc.getLine(selectionStart.row); + + for (var i = selectionStart.row + 1; i <= selectionEnd.row + 1; i++) { + var curLine = lang.stringTrimLeft(lang.stringTrimRight(editor.session.doc.getLine(i))); + if (curLine.length !== 0) { + curLine = " " + curLine; + } + insertLine += curLine; + } + + if (selectionEnd.row + 1 < (editor.session.doc.getLength() - 1)) { + insertLine += editor.session.doc.getNewLineCharacter(); + } + + editor.clearSelection(); + editor.session.doc.replace(new Range(selectionStart.row, 0, selectionEnd.row + 2, 0), insertLine); + + if (selectedCount > 0) { + editor.selection.moveCursorTo(selectionStart.row, selectionStart.column); + editor.selection.selectTo(selectionStart.row, selectionStart.column + selectedCount); + } else { + firstLineEndCol = editor.session.doc.getLine(selectionStart.row).length > firstLineEndCol ? (firstLineEndCol + 1) : firstLineEndCol; + editor.selection.moveCursorTo(selectionStart.row, firstLineEndCol); + } + }, + multiSelectAction: "forEach", + readOnly: true + }, { + name: "invertSelection", + bindKey: bindKey(null, null), + exec: function(editor) { + var endRow = editor.session.doc.getLength() - 1; + var endCol = editor.session.doc.getLine(endRow).length; + var ranges = editor.selection.rangeList.ranges; + var newRanges = []; + if (ranges.length < 1) { + ranges = [editor.selection.getRange()]; + } + + for (var i = 0; i < ranges.length; i++) { + if (i == (ranges.length - 1)) { + if (!(ranges[i].end.row === endRow && ranges[i].end.column === endCol)) { + newRanges.push(new Range(ranges[i].end.row, ranges[i].end.column, endRow, endCol)); + } + } + + if (i === 0) { + if (!(ranges[i].start.row === 0 && ranges[i].start.column === 0)) { + newRanges.push(new Range(0, 0, ranges[i].start.row, ranges[i].start.column)); + } + } else { + newRanges.push(new Range(ranges[i-1].end.row, ranges[i-1].end.column, ranges[i].start.row, ranges[i].start.column)); + } + } + + editor.exitMultiSelectMode(); + editor.clearSelection(); + + for(var i = 0; i < newRanges.length; i++) { + editor.selection.addRange(newRanges[i], false); + } + }, + readOnly: true, + scrollIntoView: "none" + }]; + + }); + + ace.define("ace/editor",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/useragent","ace/keyboard/textinput","ace/mouse/mouse_handler","ace/mouse/fold_handler","ace/keyboard/keybinding","ace/edit_session","ace/search","ace/range","ace/lib/event_emitter","ace/commands/command_manager","ace/commands/default_commands","ace/config","ace/token_iterator"], function(acequire, exports, module) { + "use strict"; + + acequire("./lib/fixoldbrowsers"); + + var oop = acequire("./lib/oop"); + var dom = acequire("./lib/dom"); + var lang = acequire("./lib/lang"); + var useragent = acequire("./lib/useragent"); + var TextInput = acequire("./keyboard/textinput").TextInput; + var MouseHandler = acequire("./mouse/mouse_handler").MouseHandler; + var FoldHandler = acequire("./mouse/fold_handler").FoldHandler; + var KeyBinding = acequire("./keyboard/keybinding").KeyBinding; + var EditSession = acequire("./edit_session").EditSession; + var Search = acequire("./search").Search; + var Range = acequire("./range").Range; + var EventEmitter = acequire("./lib/event_emitter").EventEmitter; + var CommandManager = acequire("./commands/command_manager").CommandManager; + var defaultCommands = acequire("./commands/default_commands").commands; + var config = acequire("./config"); + var TokenIterator = acequire("./token_iterator").TokenIterator; + var Editor = function(renderer, session) { + var container = renderer.getContainerElement(); + this.container = container; + this.renderer = renderer; + + this.commands = new CommandManager(useragent.isMac ? "mac" : "win", defaultCommands); + this.textInput = new TextInput(renderer.getTextAreaContainer(), this); + this.renderer.textarea = this.textInput.getElement(); + this.keyBinding = new KeyBinding(this); + this.$mouseHandler = new MouseHandler(this); + new FoldHandler(this); + + this.$blockScrolling = 0; + this.$search = new Search().set({ + wrap: true + }); + + this.$historyTracker = this.$historyTracker.bind(this); + this.commands.on("exec", this.$historyTracker); + + this.$initOperationListeners(); + + this._$emitInputEvent = lang.delayedCall(function() { + this._signal("input", {}); + if (this.session && this.session.bgTokenizer) + this.session.bgTokenizer.scheduleStart(); + }.bind(this)); + + this.on("change", function(_, _self) { + _self._$emitInputEvent.schedule(31); + }); + + this.setSession(session || new EditSession("")); + config.resetOptions(this); + config._signal("editor", this); + }; + + (function(){ + + oop.implement(this, EventEmitter); + + this.$initOperationListeners = function() { + function last(a) {return a[a.length - 1]} + + this.selections = []; + this.commands.on("exec", this.startOperation.bind(this), true); + this.commands.on("afterExec", this.endOperation.bind(this), true); + + this.$opResetTimer = lang.delayedCall(this.endOperation.bind(this)); + + this.on("change", function() { + this.curOp || this.startOperation(); + this.curOp.docChanged = true; + }.bind(this), true); + + this.on("changeSelection", function() { + this.curOp || this.startOperation(); + this.curOp.selectionChanged = true; + }.bind(this), true); + }; + + this.curOp = null; + this.prevOp = {}; + this.startOperation = function(commadEvent) { + if (this.curOp) { + if (!commadEvent || this.curOp.command) + return; + this.prevOp = this.curOp; + } + if (!commadEvent) { + this.previousCommand = null; + commadEvent = {}; + } + + this.$opResetTimer.schedule(); + this.curOp = { + command: commadEvent.command || {}, + args: commadEvent.args, + scrollTop: this.renderer.scrollTop + }; + if (this.curOp.command.name && this.curOp.command.scrollIntoView !== undefined) + this.$blockScrolling++; + }; + + this.endOperation = function(e) { + if (this.curOp) { + if (e && e.returnValue === false) + return this.curOp = null; + this._signal("beforeEndOperation"); + var command = this.curOp.command; + if (command.name && this.$blockScrolling > 0) + this.$blockScrolling--; + var scrollIntoView = command && command.scrollIntoView; + if (scrollIntoView) { + switch (scrollIntoView) { + case "center-animate": + scrollIntoView = "animate"; + case "center": + this.renderer.scrollCursorIntoView(null, 0.5); + break; + case "animate": + case "cursor": + this.renderer.scrollCursorIntoView(); + break; + case "selectionPart": + var range = this.selection.getRange(); + var config = this.renderer.layerConfig; + if (range.start.row >= config.lastRow || range.end.row <= config.firstRow) { + this.renderer.scrollSelectionIntoView(this.selection.anchor, this.selection.lead); + } + break; + default: + break; + } + if (scrollIntoView == "animate") + this.renderer.animateScrolling(this.curOp.scrollTop); + } + + this.prevOp = this.curOp; + this.curOp = null; + } + }; + this.$mergeableCommands = ["backspace", "del", "insertstring"]; + this.$historyTracker = function(e) { + if (!this.$mergeUndoDeltas) + return; + + var prev = this.prevOp; + var mergeableCommands = this.$mergeableCommands; + var shouldMerge = prev.command && (e.command.name == prev.command.name); + if (e.command.name == "insertstring") { + var text = e.args; + if (this.mergeNextCommand === undefined) + this.mergeNextCommand = true; + + shouldMerge = shouldMerge + && this.mergeNextCommand // previous command allows to coalesce with + && (!/\s/.test(text) || /\s/.test(prev.args)); // previous insertion was of same type + + this.mergeNextCommand = true; + } else { + shouldMerge = shouldMerge + && mergeableCommands.indexOf(e.command.name) !== -1; // the command is mergeable + } + + if ( + this.$mergeUndoDeltas != "always" + && Date.now() - this.sequenceStartTime > 2000 + ) { + shouldMerge = false; // the sequence is too long + } + + if (shouldMerge) + this.session.mergeUndoDeltas = true; + else if (mergeableCommands.indexOf(e.command.name) !== -1) + this.sequenceStartTime = Date.now(); + }; + this.setKeyboardHandler = function(keyboardHandler, cb) { + if (keyboardHandler && typeof keyboardHandler === "string") { + this.$keybindingId = keyboardHandler; + var _self = this; + config.loadModule(["keybinding", keyboardHandler], function(module) { + if (_self.$keybindingId == keyboardHandler) + _self.keyBinding.setKeyboardHandler(module && module.handler); + cb && cb(); + }); + } else { + this.$keybindingId = null; + this.keyBinding.setKeyboardHandler(keyboardHandler); + cb && cb(); + } + }; + this.getKeyboardHandler = function() { + return this.keyBinding.getKeyboardHandler(); + }; + this.setSession = function(session) { + if (this.session == session) + return; + if (this.curOp) this.endOperation(); + this.curOp = {}; + + var oldSession = this.session; + if (oldSession) { + this.session.off("change", this.$onDocumentChange); + this.session.off("changeMode", this.$onChangeMode); + this.session.off("tokenizerUpdate", this.$onTokenizerUpdate); + this.session.off("changeTabSize", this.$onChangeTabSize); + this.session.off("changeWrapLimit", this.$onChangeWrapLimit); + this.session.off("changeWrapMode", this.$onChangeWrapMode); + this.session.off("changeFold", this.$onChangeFold); + this.session.off("changeFrontMarker", this.$onChangeFrontMarker); + this.session.off("changeBackMarker", this.$onChangeBackMarker); + this.session.off("changeBreakpoint", this.$onChangeBreakpoint); + this.session.off("changeAnnotation", this.$onChangeAnnotation); + this.session.off("changeOverwrite", this.$onCursorChange); + this.session.off("changeScrollTop", this.$onScrollTopChange); + this.session.off("changeScrollLeft", this.$onScrollLeftChange); + + var selection = this.session.getSelection(); + selection.off("changeCursor", this.$onCursorChange); + selection.off("changeSelection", this.$onSelectionChange); + } + + this.session = session; + if (session) { + this.$onDocumentChange = this.onDocumentChange.bind(this); + session.on("change", this.$onDocumentChange); + this.renderer.setSession(session); + + this.$onChangeMode = this.onChangeMode.bind(this); + session.on("changeMode", this.$onChangeMode); + + this.$onTokenizerUpdate = this.onTokenizerUpdate.bind(this); + session.on("tokenizerUpdate", this.$onTokenizerUpdate); + + this.$onChangeTabSize = this.renderer.onChangeTabSize.bind(this.renderer); + session.on("changeTabSize", this.$onChangeTabSize); + + this.$onChangeWrapLimit = this.onChangeWrapLimit.bind(this); + session.on("changeWrapLimit", this.$onChangeWrapLimit); + + this.$onChangeWrapMode = this.onChangeWrapMode.bind(this); + session.on("changeWrapMode", this.$onChangeWrapMode); + + this.$onChangeFold = this.onChangeFold.bind(this); + session.on("changeFold", this.$onChangeFold); + + this.$onChangeFrontMarker = this.onChangeFrontMarker.bind(this); + this.session.on("changeFrontMarker", this.$onChangeFrontMarker); + + this.$onChangeBackMarker = this.onChangeBackMarker.bind(this); + this.session.on("changeBackMarker", this.$onChangeBackMarker); + + this.$onChangeBreakpoint = this.onChangeBreakpoint.bind(this); + this.session.on("changeBreakpoint", this.$onChangeBreakpoint); + + this.$onChangeAnnotation = this.onChangeAnnotation.bind(this); + this.session.on("changeAnnotation", this.$onChangeAnnotation); + + this.$onCursorChange = this.onCursorChange.bind(this); + this.session.on("changeOverwrite", this.$onCursorChange); + + this.$onScrollTopChange = this.onScrollTopChange.bind(this); + this.session.on("changeScrollTop", this.$onScrollTopChange); + + this.$onScrollLeftChange = this.onScrollLeftChange.bind(this); + this.session.on("changeScrollLeft", this.$onScrollLeftChange); + + this.selection = session.getSelection(); + this.selection.on("changeCursor", this.$onCursorChange); + + this.$onSelectionChange = this.onSelectionChange.bind(this); + this.selection.on("changeSelection", this.$onSelectionChange); + + this.onChangeMode(); + + this.$blockScrolling += 1; + this.onCursorChange(); + this.$blockScrolling -= 1; + + this.onScrollTopChange(); + this.onScrollLeftChange(); + this.onSelectionChange(); + this.onChangeFrontMarker(); + this.onChangeBackMarker(); + this.onChangeBreakpoint(); + this.onChangeAnnotation(); + this.session.getUseWrapMode() && this.renderer.adjustWrapLimit(); + this.renderer.updateFull(); + } else { + this.selection = null; + this.renderer.setSession(session); + } + + this._signal("changeSession", { + session: session, + oldSession: oldSession + }); + + this.curOp = null; + + oldSession && oldSession._signal("changeEditor", {oldEditor: this}); + session && session._signal("changeEditor", {editor: this}); + }; + this.getSession = function() { + return this.session; + }; + this.setValue = function(val, cursorPos) { + this.session.doc.setValue(val); + + if (!cursorPos) + this.selectAll(); + else if (cursorPos == 1) + this.navigateFileEnd(); + else if (cursorPos == -1) + this.navigateFileStart(); + + return val; + }; + this.getValue = function() { + return this.session.getValue(); + }; + this.getSelection = function() { + return this.selection; + }; + this.resize = function(force) { + this.renderer.onResize(force); + }; + this.setTheme = function(theme, cb) { + this.renderer.setTheme(theme, cb); + }; + this.getTheme = function() { + return this.renderer.getTheme(); + }; + this.setStyle = function(style) { + this.renderer.setStyle(style); + }; + this.unsetStyle = function(style) { + this.renderer.unsetStyle(style); + }; + this.getFontSize = function () { + return this.getOption("fontSize") || + dom.computedStyle(this.container, "fontSize"); + }; + this.setFontSize = function(size) { + this.setOption("fontSize", size); + }; + + this.$highlightBrackets = function() { + if (this.session.$bracketHighlight) { + this.session.removeMarker(this.session.$bracketHighlight); + this.session.$bracketHighlight = null; + } + + if (this.$highlightPending) { + return; + } + var self = this; + this.$highlightPending = true; + setTimeout(function() { + self.$highlightPending = false; + var session = self.session; + if (!session || !session.bgTokenizer) return; + var pos = session.findMatchingBracket(self.getCursorPosition()); + if (pos) { + var range = new Range(pos.row, pos.column, pos.row, pos.column + 1); + } else if (session.$mode.getMatching) { + var range = session.$mode.getMatching(self.session); + } + if (range) + session.$bracketHighlight = session.addMarker(range, "ace_bracket", "text"); + }, 50); + }; + this.$highlightTags = function() { + if (this.$highlightTagPending) + return; + var self = this; + this.$highlightTagPending = true; + setTimeout(function() { + self.$highlightTagPending = false; + + var session = self.session; + if (!session || !session.bgTokenizer) return; + + var pos = self.getCursorPosition(); + var iterator = new TokenIterator(self.session, pos.row, pos.column); + var token = iterator.getCurrentToken(); + + if (!token || !/\b(?:tag-open|tag-name)/.test(token.type)) { + session.removeMarker(session.$tagHighlight); + session.$tagHighlight = null; + return; + } + + if (token.type.indexOf("tag-open") != -1) { + token = iterator.stepForward(); + if (!token) + return; + } + + var tag = token.value; + var depth = 0; + var prevToken = iterator.stepBackward(); + + if (prevToken.value == '<'){ + do { + prevToken = token; + token = iterator.stepForward(); + + if (token && token.value === tag && token.type.indexOf('tag-name') !== -1) { + if (prevToken.value === '<'){ + depth++; + } else if (prevToken.value === '= 0); + } else { + do { + token = prevToken; + prevToken = iterator.stepBackward(); + + if (token && token.value === tag && token.type.indexOf('tag-name') !== -1) { + if (prevToken.value === '<') { + depth++; + } else if (prevToken.value === ' 1)) + highlight = false; + } + + if (session.$highlightLineMarker && !highlight) { + session.removeMarker(session.$highlightLineMarker.id); + session.$highlightLineMarker = null; + } else if (!session.$highlightLineMarker && highlight) { + var range = new Range(highlight.row, highlight.column, highlight.row, Infinity); + range.id = session.addMarker(range, "ace_active-line", "screenLine"); + session.$highlightLineMarker = range; + } else if (highlight) { + session.$highlightLineMarker.start.row = highlight.row; + session.$highlightLineMarker.end.row = highlight.row; + session.$highlightLineMarker.start.column = highlight.column; + session._signal("changeBackMarker"); + } + }; + + this.onSelectionChange = function(e) { + var session = this.session; + + if (session.$selectionMarker) { + session.removeMarker(session.$selectionMarker); + } + session.$selectionMarker = null; + + if (!this.selection.isEmpty()) { + var range = this.selection.getRange(); + var style = this.getSelectionStyle(); + session.$selectionMarker = session.addMarker(range, "ace_selection", style); + } else { + this.$updateHighlightActiveLine(); + } + + var re = this.$highlightSelectedWord && this.$getSelectionHighLightRegexp(); + this.session.highlight(re); + + this._signal("changeSelection"); + }; + + this.$getSelectionHighLightRegexp = function() { + var session = this.session; + + var selection = this.getSelectionRange(); + if (selection.isEmpty() || selection.isMultiLine()) + return; + + var startOuter = selection.start.column - 1; + var endOuter = selection.end.column + 1; + var line = session.getLine(selection.start.row); + var lineCols = line.length; + var needle = line.substring(Math.max(startOuter, 0), + Math.min(endOuter, lineCols)); + if ((startOuter >= 0 && /^[\w\d]/.test(needle)) || + (endOuter <= lineCols && /[\w\d]$/.test(needle))) + return; + + needle = line.substring(selection.start.column, selection.end.column); + if (!/^[\w\d]+$/.test(needle)) + return; + + var re = this.$search.$assembleRegExp({ + wholeWord: true, + caseSensitive: true, + needle: needle + }); + + return re; + }; + + + this.onChangeFrontMarker = function() { + this.renderer.updateFrontMarkers(); + }; + + this.onChangeBackMarker = function() { + this.renderer.updateBackMarkers(); + }; + + + this.onChangeBreakpoint = function() { + this.renderer.updateBreakpoints(); + }; + + this.onChangeAnnotation = function() { + this.renderer.setAnnotations(this.session.getAnnotations()); + }; + + + this.onChangeMode = function(e) { + this.renderer.updateText(); + this._emit("changeMode", e); + }; + + + this.onChangeWrapLimit = function() { + this.renderer.updateFull(); + }; + + this.onChangeWrapMode = function() { + this.renderer.onResize(true); + }; + + + this.onChangeFold = function() { + this.$updateHighlightActiveLine(); + this.renderer.updateFull(); + }; + this.getSelectedText = function() { + return this.session.getTextRange(this.getSelectionRange()); + }; + this.getCopyText = function() { + var text = this.getSelectedText(); + this._signal("copy", text); + return text; + }; + this.onCopy = function() { + this.commands.exec("copy", this); + }; + this.onCut = function() { + this.commands.exec("cut", this); + }; + this.onPaste = function(text, event) { + var e = {text: text, event: event}; + this.commands.exec("paste", this, e); + }; + + this.$handlePaste = function(e) { + if (typeof e == "string") + e = {text: e}; + this._signal("paste", e); + var text = e.text; + if (!this.inMultiSelectMode || this.inVirtualSelectionMode) { + this.insert(text); + } else { + var lines = text.split(/\r\n|\r|\n/); + var ranges = this.selection.rangeList.ranges; + + if (lines.length > ranges.length || lines.length < 2 || !lines[1]) + return this.commands.exec("insertstring", this, text); + + for (var i = ranges.length; i--;) { + var range = ranges[i]; + if (!range.isEmpty()) + this.session.remove(range); + + this.session.insert(range.start, lines[i]); + } + } + }; + + this.execCommand = function(command, args) { + return this.commands.exec(command, this, args); + }; + this.insert = function(text, pasted) { + var session = this.session; + var mode = session.getMode(); + var cursor = this.getCursorPosition(); + + if (this.getBehavioursEnabled() && !pasted) { + var transform = mode.transformAction(session.getState(cursor.row), 'insertion', this, session, text); + if (transform) { + if (text !== transform.text) { + this.session.mergeUndoDeltas = false; + this.$mergeNextCommand = false; + } + text = transform.text; + + } + } + + if (text == "\t") + text = this.session.getTabString(); + if (!this.selection.isEmpty()) { + var range = this.getSelectionRange(); + cursor = this.session.remove(range); + this.clearSelection(); + } + else if (this.session.getOverwrite()) { + var range = new Range.fromPoints(cursor, cursor); + range.end.column += text.length; + this.session.remove(range); + } + + if (text == "\n" || text == "\r\n") { + var line = session.getLine(cursor.row); + if (cursor.column > line.search(/\S|$/)) { + var d = line.substr(cursor.column).search(/\S|$/); + session.doc.removeInLine(cursor.row, cursor.column, cursor.column + d); + } + } + this.clearSelection(); + + var start = cursor.column; + var lineState = session.getState(cursor.row); + var line = session.getLine(cursor.row); + var shouldOutdent = mode.checkOutdent(lineState, line, text); + var end = session.insert(cursor, text); + + if (transform && transform.selection) { + if (transform.selection.length == 2) { // Transform relative to the current column + this.selection.setSelectionRange( + new Range(cursor.row, start + transform.selection[0], + cursor.row, start + transform.selection[1])); + } else { // Transform relative to the current row. + this.selection.setSelectionRange( + new Range(cursor.row + transform.selection[0], + transform.selection[1], + cursor.row + transform.selection[2], + transform.selection[3])); + } + } + + if (session.getDocument().isNewLine(text)) { + var lineIndent = mode.getNextLineIndent(lineState, line.slice(0, cursor.column), session.getTabString()); + + session.insert({row: cursor.row+1, column: 0}, lineIndent); + } + if (shouldOutdent) + mode.autoOutdent(lineState, session, cursor.row); + }; + + this.onTextInput = function(text) { + this.keyBinding.onTextInput(text); + }; + + this.onCommandKey = function(e, hashId, keyCode) { + this.keyBinding.onCommandKey(e, hashId, keyCode); + }; + this.setOverwrite = function(overwrite) { + this.session.setOverwrite(overwrite); + }; + this.getOverwrite = function() { + return this.session.getOverwrite(); + }; + this.toggleOverwrite = function() { + this.session.toggleOverwrite(); + }; + this.setScrollSpeed = function(speed) { + this.setOption("scrollSpeed", speed); + }; + this.getScrollSpeed = function() { + return this.getOption("scrollSpeed"); + }; + this.setDragDelay = function(dragDelay) { + this.setOption("dragDelay", dragDelay); + }; + this.getDragDelay = function() { + return this.getOption("dragDelay"); + }; + this.setSelectionStyle = function(val) { + this.setOption("selectionStyle", val); + }; + this.getSelectionStyle = function() { + return this.getOption("selectionStyle"); + }; + this.setHighlightActiveLine = function(shouldHighlight) { + this.setOption("highlightActiveLine", shouldHighlight); + }; + this.getHighlightActiveLine = function() { + return this.getOption("highlightActiveLine"); + }; + this.setHighlightGutterLine = function(shouldHighlight) { + this.setOption("highlightGutterLine", shouldHighlight); + }; + + this.getHighlightGutterLine = function() { + return this.getOption("highlightGutterLine"); + }; + this.setHighlightSelectedWord = function(shouldHighlight) { + this.setOption("highlightSelectedWord", shouldHighlight); + }; + this.getHighlightSelectedWord = function() { + return this.$highlightSelectedWord; + }; + + this.setAnimatedScroll = function(shouldAnimate){ + this.renderer.setAnimatedScroll(shouldAnimate); + }; + + this.getAnimatedScroll = function(){ + return this.renderer.getAnimatedScroll(); + }; + this.setShowInvisibles = function(showInvisibles) { + this.renderer.setShowInvisibles(showInvisibles); + }; + this.getShowInvisibles = function() { + return this.renderer.getShowInvisibles(); + }; + + this.setDisplayIndentGuides = function(display) { + this.renderer.setDisplayIndentGuides(display); + }; + + this.getDisplayIndentGuides = function() { + return this.renderer.getDisplayIndentGuides(); + }; + this.setShowPrintMargin = function(showPrintMargin) { + this.renderer.setShowPrintMargin(showPrintMargin); + }; + this.getShowPrintMargin = function() { + return this.renderer.getShowPrintMargin(); + }; + this.setPrintMarginColumn = function(showPrintMargin) { + this.renderer.setPrintMarginColumn(showPrintMargin); + }; + this.getPrintMarginColumn = function() { + return this.renderer.getPrintMarginColumn(); + }; + this.setReadOnly = function(readOnly) { + this.setOption("readOnly", readOnly); + }; + this.getReadOnly = function() { + return this.getOption("readOnly"); + }; + this.setBehavioursEnabled = function (enabled) { + this.setOption("behavioursEnabled", enabled); + }; + this.getBehavioursEnabled = function () { + return this.getOption("behavioursEnabled"); + }; + this.setWrapBehavioursEnabled = function (enabled) { + this.setOption("wrapBehavioursEnabled", enabled); + }; + this.getWrapBehavioursEnabled = function () { + return this.getOption("wrapBehavioursEnabled"); + }; + this.setShowFoldWidgets = function(show) { + this.setOption("showFoldWidgets", show); + + }; + this.getShowFoldWidgets = function() { + return this.getOption("showFoldWidgets"); + }; + + this.setFadeFoldWidgets = function(fade) { + this.setOption("fadeFoldWidgets", fade); + }; + + this.getFadeFoldWidgets = function() { + return this.getOption("fadeFoldWidgets"); + }; + this.remove = function(dir) { + if (this.selection.isEmpty()){ + if (dir == "left") + this.selection.selectLeft(); + else + this.selection.selectRight(); + } + + var range = this.getSelectionRange(); + if (this.getBehavioursEnabled()) { + var session = this.session; + var state = session.getState(range.start.row); + var new_range = session.getMode().transformAction(state, 'deletion', this, session, range); + + if (range.end.column === 0) { + var text = session.getTextRange(range); + if (text[text.length - 1] == "\n") { + var line = session.getLine(range.end.row); + if (/^\s+$/.test(line)) { + range.end.column = line.length; + } + } + } + if (new_range) + range = new_range; + } + + this.session.remove(range); + this.clearSelection(); + }; + this.removeWordRight = function() { + if (this.selection.isEmpty()) + this.selection.selectWordRight(); + + this.session.remove(this.getSelectionRange()); + this.clearSelection(); + }; + this.removeWordLeft = function() { + if (this.selection.isEmpty()) + this.selection.selectWordLeft(); + + this.session.remove(this.getSelectionRange()); + this.clearSelection(); + }; + this.removeToLineStart = function() { + if (this.selection.isEmpty()) + this.selection.selectLineStart(); + + this.session.remove(this.getSelectionRange()); + this.clearSelection(); + }; + this.removeToLineEnd = function() { + if (this.selection.isEmpty()) + this.selection.selectLineEnd(); + + var range = this.getSelectionRange(); + if (range.start.column == range.end.column && range.start.row == range.end.row) { + range.end.column = 0; + range.end.row++; + } + + this.session.remove(range); + this.clearSelection(); + }; + this.splitLine = function() { + if (!this.selection.isEmpty()) { + this.session.remove(this.getSelectionRange()); + this.clearSelection(); + } + + var cursor = this.getCursorPosition(); + this.insert("\n"); + this.moveCursorToPosition(cursor); + }; + this.transposeLetters = function() { + if (!this.selection.isEmpty()) { + return; + } + + var cursor = this.getCursorPosition(); + var column = cursor.column; + if (column === 0) + return; + + var line = this.session.getLine(cursor.row); + var swap, range; + if (column < line.length) { + swap = line.charAt(column) + line.charAt(column-1); + range = new Range(cursor.row, column-1, cursor.row, column+1); + } + else { + swap = line.charAt(column-1) + line.charAt(column-2); + range = new Range(cursor.row, column-2, cursor.row, column); + } + this.session.replace(range, swap); + }; + this.toLowerCase = function() { + var originalRange = this.getSelectionRange(); + if (this.selection.isEmpty()) { + this.selection.selectWord(); + } + + var range = this.getSelectionRange(); + var text = this.session.getTextRange(range); + this.session.replace(range, text.toLowerCase()); + this.selection.setSelectionRange(originalRange); + }; + this.toUpperCase = function() { + var originalRange = this.getSelectionRange(); + if (this.selection.isEmpty()) { + this.selection.selectWord(); + } + + var range = this.getSelectionRange(); + var text = this.session.getTextRange(range); + this.session.replace(range, text.toUpperCase()); + this.selection.setSelectionRange(originalRange); + }; + this.indent = function() { + var session = this.session; + var range = this.getSelectionRange(); + + if (range.start.row < range.end.row) { + var rows = this.$getSelectedRows(); + session.indentRows(rows.first, rows.last, "\t"); + return; + } else if (range.start.column < range.end.column) { + var text = session.getTextRange(range); + if (!/^\s+$/.test(text)) { + var rows = this.$getSelectedRows(); + session.indentRows(rows.first, rows.last, "\t"); + return; + } + } + + var line = session.getLine(range.start.row); + var position = range.start; + var size = session.getTabSize(); + var column = session.documentToScreenColumn(position.row, position.column); + + if (this.session.getUseSoftTabs()) { + var count = (size - column % size); + var indentString = lang.stringRepeat(" ", count); + } else { + var count = column % size; + while (line[range.start.column] == " " && count) { + range.start.column--; + count--; + } + this.selection.setSelectionRange(range); + indentString = "\t"; + } + return this.insert(indentString); + }; + this.blockIndent = function() { + var rows = this.$getSelectedRows(); + this.session.indentRows(rows.first, rows.last, "\t"); + }; + this.blockOutdent = function() { + var selection = this.session.getSelection(); + this.session.outdentRows(selection.getRange()); + }; + this.sortLines = function() { + var rows = this.$getSelectedRows(); + var session = this.session; + + var lines = []; + for (i = rows.first; i <= rows.last; i++) + lines.push(session.getLine(i)); + + lines.sort(function(a, b) { + if (a.toLowerCase() < b.toLowerCase()) return -1; + if (a.toLowerCase() > b.toLowerCase()) return 1; + return 0; + }); + + var deleteRange = new Range(0, 0, 0, 0); + for (var i = rows.first; i <= rows.last; i++) { + var line = session.getLine(i); + deleteRange.start.row = i; + deleteRange.end.row = i; + deleteRange.end.column = line.length; + session.replace(deleteRange, lines[i-rows.first]); + } + }; + this.toggleCommentLines = function() { + var state = this.session.getState(this.getCursorPosition().row); + var rows = this.$getSelectedRows(); + this.session.getMode().toggleCommentLines(state, this.session, rows.first, rows.last); + }; + + this.toggleBlockComment = function() { + var cursor = this.getCursorPosition(); + var state = this.session.getState(cursor.row); + var range = this.getSelectionRange(); + this.session.getMode().toggleBlockComment(state, this.session, range, cursor); + }; + this.getNumberAt = function(row, column) { + var _numberRx = /[\-]?[0-9]+(?:\.[0-9]+)?/g; + _numberRx.lastIndex = 0; + + var s = this.session.getLine(row); + while (_numberRx.lastIndex < column) { + var m = _numberRx.exec(s); + if(m.index <= column && m.index+m[0].length >= column){ + var number = { + value: m[0], + start: m.index, + end: m.index+m[0].length + }; + return number; + } + } + return null; + }; + this.modifyNumber = function(amount) { + var row = this.selection.getCursor().row; + var column = this.selection.getCursor().column; + var charRange = new Range(row, column-1, row, column); + + var c = this.session.getTextRange(charRange); + if (!isNaN(parseFloat(c)) && isFinite(c)) { + var nr = this.getNumberAt(row, column); + if (nr) { + var fp = nr.value.indexOf(".") >= 0 ? nr.start + nr.value.indexOf(".") + 1 : nr.end; + var decimals = nr.start + nr.value.length - fp; + + var t = parseFloat(nr.value); + t *= Math.pow(10, decimals); + + + if(fp !== nr.end && column < fp){ + amount *= Math.pow(10, nr.end - column - 1); + } else { + amount *= Math.pow(10, nr.end - column); + } + + t += amount; + t /= Math.pow(10, decimals); + var nnr = t.toFixed(decimals); + var replaceRange = new Range(row, nr.start, row, nr.end); + this.session.replace(replaceRange, nnr); + this.moveCursorTo(row, Math.max(nr.start +1, column + nnr.length - nr.value.length)); + + } + } + }; + this.removeLines = function() { + var rows = this.$getSelectedRows(); + this.session.removeFullLines(rows.first, rows.last); + this.clearSelection(); + }; + + this.duplicateSelection = function() { + var sel = this.selection; + var doc = this.session; + var range = sel.getRange(); + var reverse = sel.isBackwards(); + if (range.isEmpty()) { + var row = range.start.row; + doc.duplicateLines(row, row); + } else { + var point = reverse ? range.start : range.end; + var endPoint = doc.insert(point, doc.getTextRange(range), false); + range.start = point; + range.end = endPoint; + + sel.setSelectionRange(range, reverse); + } + }; + this.moveLinesDown = function() { + this.$moveLines(1, false); + }; + this.moveLinesUp = function() { + this.$moveLines(-1, false); + }; + this.moveText = function(range, toPosition, copy) { + return this.session.moveText(range, toPosition, copy); + }; + this.copyLinesUp = function() { + this.$moveLines(-1, true); + }; + this.copyLinesDown = function() { + this.$moveLines(1, true); + }; + this.$moveLines = function(dir, copy) { + var rows, moved; + var selection = this.selection; + if (!selection.inMultiSelectMode || this.inVirtualSelectionMode) { + var range = selection.toOrientedRange(); + rows = this.$getSelectedRows(range); + moved = this.session.$moveLines(rows.first, rows.last, copy ? 0 : dir); + if (copy && dir == -1) moved = 0; + range.moveBy(moved, 0); + selection.fromOrientedRange(range); + } else { + var ranges = selection.rangeList.ranges; + selection.rangeList.detach(this.session); + this.inVirtualSelectionMode = true; + + var diff = 0; + var totalDiff = 0; + var l = ranges.length; + for (var i = 0; i < l; i++) { + var rangeIndex = i; + ranges[i].moveBy(diff, 0); + rows = this.$getSelectedRows(ranges[i]); + var first = rows.first; + var last = rows.last; + while (++i < l) { + if (totalDiff) ranges[i].moveBy(totalDiff, 0); + var subRows = this.$getSelectedRows(ranges[i]); + if (copy && subRows.first != last) + break; + else if (!copy && subRows.first > last + 1) + break; + last = subRows.last; + } + i--; + diff = this.session.$moveLines(first, last, copy ? 0 : dir); + if (copy && dir == -1) rangeIndex = i + 1; + while (rangeIndex <= i) { + ranges[rangeIndex].moveBy(diff, 0); + rangeIndex++; + } + if (!copy) diff = 0; + totalDiff += diff; + } + + selection.fromOrientedRange(selection.ranges[0]); + selection.rangeList.attach(this.session); + this.inVirtualSelectionMode = false; + } + }; + this.$getSelectedRows = function(range) { + range = (range || this.getSelectionRange()).collapseRows(); + + return { + first: this.session.getRowFoldStart(range.start.row), + last: this.session.getRowFoldEnd(range.end.row) + }; + }; + + this.onCompositionStart = function(text) { + this.renderer.showComposition(this.getCursorPosition()); + }; + + this.onCompositionUpdate = function(text) { + this.renderer.setCompositionText(text); + }; + + this.onCompositionEnd = function() { + this.renderer.hideComposition(); + }; + this.getFirstVisibleRow = function() { + return this.renderer.getFirstVisibleRow(); + }; + this.getLastVisibleRow = function() { + return this.renderer.getLastVisibleRow(); + }; + this.isRowVisible = function(row) { + return (row >= this.getFirstVisibleRow() && row <= this.getLastVisibleRow()); + }; + this.isRowFullyVisible = function(row) { + return (row >= this.renderer.getFirstFullyVisibleRow() && row <= this.renderer.getLastFullyVisibleRow()); + }; + this.$getVisibleRowCount = function() { + return this.renderer.getScrollBottomRow() - this.renderer.getScrollTopRow() + 1; + }; + + this.$moveByPage = function(dir, select) { + var renderer = this.renderer; + var config = this.renderer.layerConfig; + var rows = dir * Math.floor(config.height / config.lineHeight); + + this.$blockScrolling++; + if (select === true) { + this.selection.$moveSelection(function(){ + this.moveCursorBy(rows, 0); + }); + } else if (select === false) { + this.selection.moveCursorBy(rows, 0); + this.selection.clearSelection(); + } + this.$blockScrolling--; + + var scrollTop = renderer.scrollTop; + + renderer.scrollBy(0, rows * config.lineHeight); + if (select != null) + renderer.scrollCursorIntoView(null, 0.5); + + renderer.animateScrolling(scrollTop); + }; + this.selectPageDown = function() { + this.$moveByPage(1, true); + }; + this.selectPageUp = function() { + this.$moveByPage(-1, true); + }; + this.gotoPageDown = function() { + this.$moveByPage(1, false); + }; + this.gotoPageUp = function() { + this.$moveByPage(-1, false); + }; + this.scrollPageDown = function() { + this.$moveByPage(1); + }; + this.scrollPageUp = function() { + this.$moveByPage(-1); + }; + this.scrollToRow = function(row) { + this.renderer.scrollToRow(row); + }; + this.scrollToLine = function(line, center, animate, callback) { + this.renderer.scrollToLine(line, center, animate, callback); + }; + this.centerSelection = function() { + var range = this.getSelectionRange(); + var pos = { + row: Math.floor(range.start.row + (range.end.row - range.start.row) / 2), + column: Math.floor(range.start.column + (range.end.column - range.start.column) / 2) + }; + this.renderer.alignCursor(pos, 0.5); + }; + this.getCursorPosition = function() { + return this.selection.getCursor(); + }; + this.getCursorPositionScreen = function() { + return this.session.documentToScreenPosition(this.getCursorPosition()); + }; + this.getSelectionRange = function() { + return this.selection.getRange(); + }; + this.selectAll = function() { + this.$blockScrolling += 1; + this.selection.selectAll(); + this.$blockScrolling -= 1; + }; + this.clearSelection = function() { + this.selection.clearSelection(); + }; + this.moveCursorTo = function(row, column) { + this.selection.moveCursorTo(row, column); + }; + this.moveCursorToPosition = function(pos) { + this.selection.moveCursorToPosition(pos); + }; + this.jumpToMatching = function(select, expand) { + var cursor = this.getCursorPosition(); + var iterator = new TokenIterator(this.session, cursor.row, cursor.column); + var prevToken = iterator.getCurrentToken(); + var token = prevToken || iterator.stepForward(); + + if (!token) return; + var matchType; + var found = false; + var depth = {}; + var i = cursor.column - token.start; + var bracketType; + var brackets = { + ")": "(", + "(": "(", + "]": "[", + "[": "[", + "{": "{", + "}": "{" + }; + + do { + if (token.value.match(/[{}()\[\]]/g)) { + for (; i < token.value.length && !found; i++) { + if (!brackets[token.value[i]]) { + continue; + } + + bracketType = brackets[token.value[i]] + '.' + token.type.replace("rparen", "lparen"); + + if (isNaN(depth[bracketType])) { + depth[bracketType] = 0; + } + + switch (token.value[i]) { + case '(': + case '[': + case '{': + depth[bracketType]++; + break; + case ')': + case ']': + case '}': + depth[bracketType]--; + + if (depth[bracketType] === -1) { + matchType = 'bracket'; + found = true; + } + break; + } + } + } + else if (token && token.type.indexOf('tag-name') !== -1) { + if (isNaN(depth[token.value])) { + depth[token.value] = 0; + } + + if (prevToken.value === '<') { + depth[token.value]++; + } + else if (prevToken.value === '= 0; --i) { + if(this.$tryReplace(ranges[i], replacement)) { + replaced++; + } + } + + this.selection.setSelectionRange(selection); + this.$blockScrolling -= 1; + + return replaced; + }; + + this.$tryReplace = function(range, replacement) { + var input = this.session.getTextRange(range); + replacement = this.$search.replace(input, replacement); + if (replacement !== null) { + range.end = this.session.replace(range, replacement); + return range; + } else { + return null; + } + }; + this.getLastSearchOptions = function() { + return this.$search.getOptions(); + }; + this.find = function(needle, options, animate) { + if (!options) + options = {}; + + if (typeof needle == "string" || needle instanceof RegExp) + options.needle = needle; + else if (typeof needle == "object") + oop.mixin(options, needle); + + var range = this.selection.getRange(); + if (options.needle == null) { + needle = this.session.getTextRange(range) + || this.$search.$options.needle; + if (!needle) { + range = this.session.getWordRange(range.start.row, range.start.column); + needle = this.session.getTextRange(range); + } + this.$search.set({needle: needle}); + } + + this.$search.set(options); + if (!options.start) + this.$search.set({start: range}); + + var newRange = this.$search.find(this.session); + if (options.preventScroll) + return newRange; + if (newRange) { + this.revealRange(newRange, animate); + return newRange; + } + if (options.backwards) + range.start = range.end; + else + range.end = range.start; + this.selection.setRange(range); + }; + this.findNext = function(options, animate) { + this.find({skipCurrent: true, backwards: false}, options, animate); + }; + this.findPrevious = function(options, animate) { + this.find(options, {skipCurrent: true, backwards: true}, animate); + }; + + this.revealRange = function(range, animate) { + this.$blockScrolling += 1; + this.session.unfold(range); + this.selection.setSelectionRange(range); + this.$blockScrolling -= 1; + + var scrollTop = this.renderer.scrollTop; + this.renderer.scrollSelectionIntoView(range.start, range.end, 0.5); + if (animate !== false) + this.renderer.animateScrolling(scrollTop); + }; + this.undo = function() { + this.$blockScrolling++; + this.session.getUndoManager().undo(); + this.$blockScrolling--; + this.renderer.scrollCursorIntoView(null, 0.5); + }; + this.redo = function() { + this.$blockScrolling++; + this.session.getUndoManager().redo(); + this.$blockScrolling--; + this.renderer.scrollCursorIntoView(null, 0.5); + }; + this.destroy = function() { + this.renderer.destroy(); + this._signal("destroy", this); + if (this.session) { + this.session.destroy(); + } + }; + this.setAutoScrollEditorIntoView = function(enable) { + if (!enable) + return; + var rect; + var self = this; + var shouldScroll = false; + if (!this.$scrollAnchor) + this.$scrollAnchor = document.createElement("div"); + var scrollAnchor = this.$scrollAnchor; + scrollAnchor.style.cssText = "position:absolute"; + this.container.insertBefore(scrollAnchor, this.container.firstChild); + var onChangeSelection = this.on("changeSelection", function() { + shouldScroll = true; + }); + var onBeforeRender = this.renderer.on("beforeRender", function() { + if (shouldScroll) + rect = self.renderer.container.getBoundingClientRect(); + }); + var onAfterRender = this.renderer.on("afterRender", function() { + if (shouldScroll && rect && (self.isFocused() + || self.searchBox && self.searchBox.isFocused()) + ) { + var renderer = self.renderer; + var pos = renderer.$cursorLayer.$pixelPos; + var config = renderer.layerConfig; + var top = pos.top - config.offset; + if (pos.top >= 0 && top + rect.top < 0) { + shouldScroll = true; + } else if (pos.top < config.height && + pos.top + rect.top + config.lineHeight > window.innerHeight) { + shouldScroll = false; + } else { + shouldScroll = null; + } + if (shouldScroll != null) { + scrollAnchor.style.top = top + "px"; + scrollAnchor.style.left = pos.left + "px"; + scrollAnchor.style.height = config.lineHeight + "px"; + scrollAnchor.scrollIntoView(shouldScroll); + } + shouldScroll = rect = null; + } + }); + this.setAutoScrollEditorIntoView = function(enable) { + if (enable) + return; + delete this.setAutoScrollEditorIntoView; + this.off("changeSelection", onChangeSelection); + this.renderer.off("afterRender", onAfterRender); + this.renderer.off("beforeRender", onBeforeRender); + }; + }; + + + this.$resetCursorStyle = function() { + var style = this.$cursorStyle || "ace"; + var cursorLayer = this.renderer.$cursorLayer; + if (!cursorLayer) + return; + cursorLayer.setSmoothBlinking(/smooth/.test(style)); + cursorLayer.isBlinking = !this.$readOnly && style != "wide"; + dom.setCssClass(cursorLayer.element, "ace_slim-cursors", /slim/.test(style)); + }; + + }).call(Editor.prototype); + + + + config.defineOptions(Editor.prototype, "editor", { + selectionStyle: { + set: function(style) { + this.onSelectionChange(); + this._signal("changeSelectionStyle", {data: style}); + }, + initialValue: "line" + }, + highlightActiveLine: { + set: function() {this.$updateHighlightActiveLine();}, + initialValue: true + }, + highlightSelectedWord: { + set: function(shouldHighlight) {this.$onSelectionChange();}, + initialValue: true + }, + readOnly: { + set: function(readOnly) { + this.$resetCursorStyle(); + }, + initialValue: false + }, + cursorStyle: { + set: function(val) { this.$resetCursorStyle(); }, + values: ["ace", "slim", "smooth", "wide"], + initialValue: "ace" + }, + mergeUndoDeltas: { + values: [false, true, "always"], + initialValue: true + }, + behavioursEnabled: {initialValue: true}, + wrapBehavioursEnabled: {initialValue: true}, + autoScrollEditorIntoView: { + set: function(val) {this.setAutoScrollEditorIntoView(val)} + }, + keyboardHandler: { + set: function(val) { this.setKeyboardHandler(val); }, + get: function() { return this.keybindingId; }, + handlesSet: true + }, + + hScrollBarAlwaysVisible: "renderer", + vScrollBarAlwaysVisible: "renderer", + highlightGutterLine: "renderer", + animatedScroll: "renderer", + showInvisibles: "renderer", + showPrintMargin: "renderer", + printMarginColumn: "renderer", + printMargin: "renderer", + fadeFoldWidgets: "renderer", + showFoldWidgets: "renderer", + showLineNumbers: "renderer", + showGutter: "renderer", + displayIndentGuides: "renderer", + fontSize: "renderer", + fontFamily: "renderer", + maxLines: "renderer", + minLines: "renderer", + scrollPastEnd: "renderer", + fixedWidthGutter: "renderer", + theme: "renderer", + + scrollSpeed: "$mouseHandler", + dragDelay: "$mouseHandler", + dragEnabled: "$mouseHandler", + focusTimout: "$mouseHandler", + tooltipFollowsMouse: "$mouseHandler", + + firstLineNumber: "session", + overwrite: "session", + newLineMode: "session", + useWorker: "session", + useSoftTabs: "session", + tabSize: "session", + wrap: "session", + indentedSoftWrap: "session", + foldStyle: "session", + mode: "session" + }); + + exports.Editor = Editor; + }); + + ace.define("ace/undomanager",["require","exports","module"], function(acequire, exports, module) { + "use strict"; + var UndoManager = function() { + this.reset(); + }; + + (function() { + this.execute = function(options) { + var deltaSets = options.args[0]; + this.$doc = options.args[1]; + if (options.merge && this.hasUndo()){ + this.dirtyCounter--; + deltaSets = this.$undoStack.pop().concat(deltaSets); + } + this.$undoStack.push(deltaSets); + this.$redoStack = []; + if (this.dirtyCounter < 0) { + this.dirtyCounter = NaN; + } + this.dirtyCounter++; + }; + this.undo = function(dontSelect) { + var deltaSets = this.$undoStack.pop(); + var undoSelectionRange = null; + if (deltaSets) { + undoSelectionRange = this.$doc.undoChanges(deltaSets, dontSelect); + this.$redoStack.push(deltaSets); + this.dirtyCounter--; + } + + return undoSelectionRange; + }; + this.redo = function(dontSelect) { + var deltaSets = this.$redoStack.pop(); + var redoSelectionRange = null; + if (deltaSets) { + redoSelectionRange = + this.$doc.redoChanges(this.$deserializeDeltas(deltaSets), dontSelect); + this.$undoStack.push(deltaSets); + this.dirtyCounter++; + } + return redoSelectionRange; + }; + this.reset = function() { + this.$undoStack = []; + this.$redoStack = []; + this.dirtyCounter = 0; + }; + this.hasUndo = function() { + return this.$undoStack.length > 0; + }; + this.hasRedo = function() { + return this.$redoStack.length > 0; + }; + this.markClean = function() { + this.dirtyCounter = 0; + }; + this.isClean = function() { + return this.dirtyCounter === 0; + }; + this.$serializeDeltas = function(deltaSets) { + return cloneDeltaSetsObj(deltaSets, $serializeDelta); + }; + this.$deserializeDeltas = function(deltaSets) { + return cloneDeltaSetsObj(deltaSets, $deserializeDelta); + }; + + function $serializeDelta(delta){ + return { + action: delta.action, + start: delta.start, + end: delta.end, + lines: delta.lines.length == 1 ? null : delta.lines, + text: delta.lines.length == 1 ? delta.lines[0] : null + }; + } + + function $deserializeDelta(delta) { + return { + action: delta.action, + start: delta.start, + end: delta.end, + lines: delta.lines || [delta.text] + }; + } + + function cloneDeltaSetsObj(deltaSets_old, fnGetModifiedDelta) { + var deltaSets_new = new Array(deltaSets_old.length); + for (var i = 0; i < deltaSets_old.length; i++) { + var deltaSet_old = deltaSets_old[i]; + var deltaSet_new = { group: deltaSet_old.group, deltas: new Array(deltaSet_old.length)}; + + for (var j = 0; j < deltaSet_old.deltas.length; j++) { + var delta_old = deltaSet_old.deltas[j]; + deltaSet_new.deltas[j] = fnGetModifiedDelta(delta_old); + } + + deltaSets_new[i] = deltaSet_new; + } + return deltaSets_new; + } + + }).call(UndoManager.prototype); + + exports.UndoManager = UndoManager; + }); + + ace.define("ace/layer/gutter",["require","exports","module","ace/lib/dom","ace/lib/oop","ace/lib/lang","ace/lib/event_emitter"], function(acequire, exports, module) { + "use strict"; + + var dom = acequire("../lib/dom"); + var oop = acequire("../lib/oop"); + var lang = acequire("../lib/lang"); + var EventEmitter = acequire("../lib/event_emitter").EventEmitter; + + var Gutter = function(parentEl) { + this.element = dom.createElement("div"); + this.element.className = "ace_layer ace_gutter-layer"; + parentEl.appendChild(this.element); + this.setShowFoldWidgets(this.$showFoldWidgets); + + this.gutterWidth = 0; + + this.$annotations = []; + this.$updateAnnotations = this.$updateAnnotations.bind(this); + + this.$cells = []; + }; + + (function() { + + oop.implement(this, EventEmitter); + + this.setSession = function(session) { + if (this.session) + this.session.removeEventListener("change", this.$updateAnnotations); + this.session = session; + if (session) + session.on("change", this.$updateAnnotations); + }; + + this.addGutterDecoration = function(row, className){ + if (window.console) + console.warn && console.warn("deprecated use session.addGutterDecoration"); + this.session.addGutterDecoration(row, className); + }; + + this.removeGutterDecoration = function(row, className){ + if (window.console) + console.warn && console.warn("deprecated use session.removeGutterDecoration"); + this.session.removeGutterDecoration(row, className); + }; + + this.setAnnotations = function(annotations) { + this.$annotations = []; + for (var i = 0; i < annotations.length; i++) { + var annotation = annotations[i]; + var row = annotation.row; + var rowInfo = this.$annotations[row]; + if (!rowInfo) + rowInfo = this.$annotations[row] = {text: []}; + + var annoText = annotation.text; + annoText = annoText ? lang.escapeHTML(annoText) : annotation.html || ""; + + if (rowInfo.text.indexOf(annoText) === -1) + rowInfo.text.push(annoText); + + var type = annotation.type; + if (type == "error") + rowInfo.className = " ace_error"; + else if (type == "warning" && rowInfo.className != " ace_error") + rowInfo.className = " ace_warning"; + else if (type == "info" && (!rowInfo.className)) + rowInfo.className = " ace_info"; + } + }; + + this.$updateAnnotations = function (delta) { + if (!this.$annotations.length) + return; + var firstRow = delta.start.row; + var len = delta.end.row - firstRow; + if (len === 0) { + } else if (delta.action == 'remove') { + this.$annotations.splice(firstRow, len + 1, null); + } else { + var args = new Array(len + 1); + args.unshift(firstRow, 1); + this.$annotations.splice.apply(this.$annotations, args); + } + }; + + this.update = function(config) { + var session = this.session; + var firstRow = config.firstRow; + var lastRow = Math.min(config.lastRow + config.gutterOffset, // needed to compensate for hor scollbar + session.getLength() - 1); + var fold = session.getNextFoldLine(firstRow); + var foldStart = fold ? fold.start.row : Infinity; + var foldWidgets = this.$showFoldWidgets && session.foldWidgets; + var breakpoints = session.$breakpoints; + var decorations = session.$decorations; + var firstLineNumber = session.$firstLineNumber; + var lastLineNumber = 0; + + var gutterRenderer = session.gutterRenderer || this.$renderer; + + var cell = null; + var index = -1; + var row = firstRow; + while (true) { + if (row > foldStart) { + row = fold.end.row + 1; + fold = session.getNextFoldLine(row, fold); + foldStart = fold ? fold.start.row : Infinity; + } + if (row > lastRow) { + while (this.$cells.length > index + 1) { + cell = this.$cells.pop(); + this.element.removeChild(cell.element); + } + break; + } + + cell = this.$cells[++index]; + if (!cell) { + cell = {element: null, textNode: null, foldWidget: null}; + cell.element = dom.createElement("div"); + cell.textNode = document.createTextNode(''); + cell.element.appendChild(cell.textNode); + this.element.appendChild(cell.element); + this.$cells[index] = cell; + } + + var className = "ace_gutter-cell "; + if (breakpoints[row]) + className += breakpoints[row]; + if (decorations[row]) + className += decorations[row]; + if (this.$annotations[row]) + className += this.$annotations[row].className; + if (cell.element.className != className) + cell.element.className = className; + + var height = session.getRowLength(row) * config.lineHeight + "px"; + if (height != cell.element.style.height) + cell.element.style.height = height; + + if (foldWidgets) { + var c = foldWidgets[row]; + if (c == null) + c = foldWidgets[row] = session.getFoldWidget(row); + } + + if (c) { + if (!cell.foldWidget) { + cell.foldWidget = dom.createElement("span"); + cell.element.appendChild(cell.foldWidget); + } + var className = "ace_fold-widget ace_" + c; + if (c == "start" && row == foldStart && row < fold.end.row) + className += " ace_closed"; + else + className += " ace_open"; + if (cell.foldWidget.className != className) + cell.foldWidget.className = className; + + var height = config.lineHeight + "px"; + if (cell.foldWidget.style.height != height) + cell.foldWidget.style.height = height; + } else { + if (cell.foldWidget) { + cell.element.removeChild(cell.foldWidget); + cell.foldWidget = null; + } + } + + var text = lastLineNumber = gutterRenderer + ? gutterRenderer.getText(session, row) + : row + firstLineNumber; + if (text != cell.textNode.data) + cell.textNode.data = text; + + row++; + } + + this.element.style.height = config.minHeight + "px"; + + if (this.$fixedWidth || session.$useWrapMode) + lastLineNumber = session.getLength() + firstLineNumber; + + var gutterWidth = gutterRenderer + ? gutterRenderer.getWidth(session, lastLineNumber, config) + : lastLineNumber.toString().length * config.characterWidth; + + var padding = this.$padding || this.$computePadding(); + gutterWidth += padding.left + padding.right; + if (gutterWidth !== this.gutterWidth && !isNaN(gutterWidth)) { + this.gutterWidth = gutterWidth; + this.element.style.width = Math.ceil(this.gutterWidth) + "px"; + this._emit("changeGutterWidth", gutterWidth); + } + }; + + this.$fixedWidth = false; + + this.$showLineNumbers = true; + this.$renderer = ""; + this.setShowLineNumbers = function(show) { + this.$renderer = !show && { + getWidth: function() {return ""}, + getText: function() {return ""} + }; + }; + + this.getShowLineNumbers = function() { + return this.$showLineNumbers; + }; + + this.$showFoldWidgets = true; + this.setShowFoldWidgets = function(show) { + if (show) + dom.addCssClass(this.element, "ace_folding-enabled"); + else + dom.removeCssClass(this.element, "ace_folding-enabled"); + + this.$showFoldWidgets = show; + this.$padding = null; + }; + + this.getShowFoldWidgets = function() { + return this.$showFoldWidgets; + }; + + this.$computePadding = function() { + if (!this.element.firstChild) + return {left: 0, right: 0}; + var style = dom.computedStyle(this.element.firstChild); + this.$padding = {}; + this.$padding.left = parseInt(style.paddingLeft) + 1 || 0; + this.$padding.right = parseInt(style.paddingRight) || 0; + return this.$padding; + }; + + this.getRegion = function(point) { + var padding = this.$padding || this.$computePadding(); + var rect = this.element.getBoundingClientRect(); + if (point.x < padding.left + rect.left) + return "markers"; + if (this.$showFoldWidgets && point.x > rect.right - padding.right) + return "foldWidgets"; + }; + + }).call(Gutter.prototype); + + exports.Gutter = Gutter; + + }); + + ace.define("ace/layer/marker",["require","exports","module","ace/range","ace/lib/dom"], function(acequire, exports, module) { + "use strict"; + + var Range = acequire("../range").Range; + var dom = acequire("../lib/dom"); + + var Marker = function(parentEl) { + this.element = dom.createElement("div"); + this.element.className = "ace_layer ace_marker-layer"; + parentEl.appendChild(this.element); + }; + + (function() { + + this.$padding = 0; + + this.setPadding = function(padding) { + this.$padding = padding; + }; + this.setSession = function(session) { + this.session = session; + }; + + this.setMarkers = function(markers) { + this.markers = markers; + }; + + this.update = function(config) { + var config = config || this.config; + if (!config) + return; + + this.config = config; + + + var html = []; + for (var key in this.markers) { + var marker = this.markers[key]; + + if (!marker.range) { + marker.update(html, this, this.session, config); + continue; + } + + var range = marker.range.clipRows(config.firstRow, config.lastRow); + if (range.isEmpty()) continue; + + range = range.toScreenRange(this.session); + if (marker.renderer) { + var top = this.$getTop(range.start.row, config); + var left = this.$padding + range.start.column * config.characterWidth; + marker.renderer(html, range, left, top, config); + } else if (marker.type == "fullLine") { + this.drawFullLineMarker(html, range, marker.clazz, config); + } else if (marker.type == "screenLine") { + this.drawScreenLineMarker(html, range, marker.clazz, config); + } else if (range.isMultiLine()) { + if (marker.type == "text") + this.drawTextMarker(html, range, marker.clazz, config); + else + this.drawMultiLineMarker(html, range, marker.clazz, config); + } else { + this.drawSingleLineMarker(html, range, marker.clazz + " ace_start" + " ace_br15", config); + } + } + this.element.innerHTML = html.join(""); + }; + + this.$getTop = function(row, layerConfig) { + return (row - layerConfig.firstRowScreen) * layerConfig.lineHeight; + }; + + function getBorderClass(tl, tr, br, bl) { + return (tl ? 1 : 0) | (tr ? 2 : 0) | (br ? 4 : 0) | (bl ? 8 : 0); + } + this.drawTextMarker = function(stringBuilder, range, clazz, layerConfig, extraStyle) { + var session = this.session; + var start = range.start.row; + var end = range.end.row; + var row = start; + var prev = 0; + var curr = 0; + var next = session.getScreenLastRowColumn(row); + var lineRange = new Range(row, range.start.column, row, curr); + for (; row <= end; row++) { + lineRange.start.row = lineRange.end.row = row; + lineRange.start.column = row == start ? range.start.column : session.getRowWrapIndent(row); + lineRange.end.column = next; + prev = curr; + curr = next; + next = row + 1 < end ? session.getScreenLastRowColumn(row + 1) : row == end ? 0 : range.end.column; + this.drawSingleLineMarker(stringBuilder, lineRange, + clazz + (row == start ? " ace_start" : "") + " ace_br" + + getBorderClass(row == start || row == start + 1 && range.start.column, prev < curr, curr > next, row == end), + layerConfig, row == end ? 0 : 1, extraStyle); + } + }; + this.drawMultiLineMarker = function(stringBuilder, range, clazz, config, extraStyle) { + var padding = this.$padding; + var height = config.lineHeight; + var top = this.$getTop(range.start.row, config); + var left = padding + range.start.column * config.characterWidth; + extraStyle = extraStyle || ""; + + stringBuilder.push( + "
" + ); + top = this.$getTop(range.end.row, config); + var width = range.end.column * config.characterWidth; + + stringBuilder.push( + "
" + ); + height = (range.end.row - range.start.row - 1) * config.lineHeight; + if (height <= 0) + return; + top = this.$getTop(range.start.row + 1, config); + + var radiusClass = (range.start.column ? 1 : 0) | (range.end.column ? 0 : 8); + + stringBuilder.push( + "
" + ); + }; + this.drawSingleLineMarker = function(stringBuilder, range, clazz, config, extraLength, extraStyle) { + var height = config.lineHeight; + var width = (range.end.column + (extraLength || 0) - range.start.column) * config.characterWidth; + + var top = this.$getTop(range.start.row, config); + var left = this.$padding + range.start.column * config.characterWidth; + + stringBuilder.push( + "
" + ); + }; + + this.drawFullLineMarker = function(stringBuilder, range, clazz, config, extraStyle) { + var top = this.$getTop(range.start.row, config); + var height = config.lineHeight; + if (range.start.row != range.end.row) + height += this.$getTop(range.end.row, config) - top; + + stringBuilder.push( + "
" + ); + }; + + this.drawScreenLineMarker = function(stringBuilder, range, clazz, config, extraStyle) { + var top = this.$getTop(range.start.row, config); + var height = config.lineHeight; + + stringBuilder.push( + "
" + ); + }; + + }).call(Marker.prototype); + + exports.Marker = Marker; + + }); + + ace.define("ace/layer/text",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/useragent","ace/lib/event_emitter"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("../lib/oop"); + var dom = acequire("../lib/dom"); + var lang = acequire("../lib/lang"); + var useragent = acequire("../lib/useragent"); + var EventEmitter = acequire("../lib/event_emitter").EventEmitter; + + var Text = function(parentEl) { + this.element = dom.createElement("div"); + this.element.className = "ace_layer ace_text-layer"; + parentEl.appendChild(this.element); + this.$updateEolChar = this.$updateEolChar.bind(this); + }; + + (function() { + + oop.implement(this, EventEmitter); + + this.EOF_CHAR = "\xB6"; + this.EOL_CHAR_LF = "\xAC"; + this.EOL_CHAR_CRLF = "\xa4"; + this.EOL_CHAR = this.EOL_CHAR_LF; + this.TAB_CHAR = "\u2014"; //"\u21E5"; + this.SPACE_CHAR = "\xB7"; + this.$padding = 0; + + this.$updateEolChar = function() { + var EOL_CHAR = this.session.doc.getNewLineCharacter() == "\n" + ? this.EOL_CHAR_LF + : this.EOL_CHAR_CRLF; + if (this.EOL_CHAR != EOL_CHAR) { + this.EOL_CHAR = EOL_CHAR; + return true; + } + } + + this.setPadding = function(padding) { + this.$padding = padding; + this.element.style.padding = "0 " + padding + "px"; + }; + + this.getLineHeight = function() { + return this.$fontMetrics.$characterSize.height || 0; + }; + + this.getCharacterWidth = function() { + return this.$fontMetrics.$characterSize.width || 0; + }; + + this.$setFontMetrics = function(measure) { + this.$fontMetrics = measure; + this.$fontMetrics.on("changeCharacterSize", function(e) { + this._signal("changeCharacterSize", e); + }.bind(this)); + this.$pollSizeChanges(); + } + + this.checkForSizeChanges = function() { + this.$fontMetrics.checkForSizeChanges(); + }; + this.$pollSizeChanges = function() { + return this.$pollSizeChangesTimer = this.$fontMetrics.$pollSizeChanges(); + }; + this.setSession = function(session) { + this.session = session; + if (session) + this.$computeTabString(); + }; + + this.showInvisibles = false; + this.setShowInvisibles = function(showInvisibles) { + if (this.showInvisibles == showInvisibles) + return false; + + this.showInvisibles = showInvisibles; + this.$computeTabString(); + return true; + }; + + this.displayIndentGuides = true; + this.setDisplayIndentGuides = function(display) { + if (this.displayIndentGuides == display) + return false; + + this.displayIndentGuides = display; + this.$computeTabString(); + return true; + }; + + this.$tabStrings = []; + this.onChangeTabSize = + this.$computeTabString = function() { + var tabSize = this.session.getTabSize(); + this.tabSize = tabSize; + var tabStr = this.$tabStrings = [0]; + for (var i = 1; i < tabSize + 1; i++) { + if (this.showInvisibles) { + tabStr.push("" + + lang.stringRepeat(this.TAB_CHAR, i) + + ""); + } else { + tabStr.push(lang.stringRepeat(" ", i)); + } + } + if (this.displayIndentGuides) { + this.$indentGuideRe = /\s\S| \t|\t |\s$/; + var className = "ace_indent-guide"; + var spaceClass = ""; + var tabClass = ""; + if (this.showInvisibles) { + className += " ace_invisible"; + spaceClass = " ace_invisible_space"; + tabClass = " ace_invisible_tab"; + var spaceContent = lang.stringRepeat(this.SPACE_CHAR, this.tabSize); + var tabContent = lang.stringRepeat(this.TAB_CHAR, this.tabSize); + } else{ + var spaceContent = lang.stringRepeat(" ", this.tabSize); + var tabContent = spaceContent; + } + + this.$tabStrings[" "] = "" + spaceContent + ""; + this.$tabStrings["\t"] = "" + tabContent + ""; + } + }; + + this.updateLines = function(config, firstRow, lastRow) { + if (this.config.lastRow != config.lastRow || + this.config.firstRow != config.firstRow) { + this.scrollLines(config); + } + this.config = config; + + var first = Math.max(firstRow, config.firstRow); + var last = Math.min(lastRow, config.lastRow); + + var lineElements = this.element.childNodes; + var lineElementsIdx = 0; + + for (var row = config.firstRow; row < first; row++) { + var foldLine = this.session.getFoldLine(row); + if (foldLine) { + if (foldLine.containsRow(first)) { + first = foldLine.start.row; + break; + } else { + row = foldLine.end.row; + } + } + lineElementsIdx ++; + } + + var row = first; + var foldLine = this.session.getNextFoldLine(row); + var foldStart = foldLine ? foldLine.start.row : Infinity; + + while (true) { + if (row > foldStart) { + row = foldLine.end.row+1; + foldLine = this.session.getNextFoldLine(row, foldLine); + foldStart = foldLine ? foldLine.start.row :Infinity; + } + if (row > last) + break; + + var lineElement = lineElements[lineElementsIdx++]; + if (lineElement) { + var html = []; + this.$renderLine( + html, row, !this.$useLineGroups(), row == foldStart ? foldLine : false + ); + lineElement.style.height = config.lineHeight * this.session.getRowLength(row) + "px"; + lineElement.innerHTML = html.join(""); + } + row++; + } + }; + + this.scrollLines = function(config) { + var oldConfig = this.config; + this.config = config; + + if (!oldConfig || oldConfig.lastRow < config.firstRow) + return this.update(config); + + if (config.lastRow < oldConfig.firstRow) + return this.update(config); + + var el = this.element; + if (oldConfig.firstRow < config.firstRow) + for (var row=this.session.getFoldedRowCount(oldConfig.firstRow, config.firstRow - 1); row>0; row--) + el.removeChild(el.firstChild); + + if (oldConfig.lastRow > config.lastRow) + for (var row=this.session.getFoldedRowCount(config.lastRow + 1, oldConfig.lastRow); row>0; row--) + el.removeChild(el.lastChild); + + if (config.firstRow < oldConfig.firstRow) { + var fragment = this.$renderLinesFragment(config, config.firstRow, oldConfig.firstRow - 1); + if (el.firstChild) + el.insertBefore(fragment, el.firstChild); + else + el.appendChild(fragment); + } + + if (config.lastRow > oldConfig.lastRow) { + var fragment = this.$renderLinesFragment(config, oldConfig.lastRow + 1, config.lastRow); + el.appendChild(fragment); + } + }; + + this.$renderLinesFragment = function(config, firstRow, lastRow) { + var fragment = this.element.ownerDocument.createDocumentFragment(); + var row = firstRow; + var foldLine = this.session.getNextFoldLine(row); + var foldStart = foldLine ? foldLine.start.row : Infinity; + + while (true) { + if (row > foldStart) { + row = foldLine.end.row+1; + foldLine = this.session.getNextFoldLine(row, foldLine); + foldStart = foldLine ? foldLine.start.row : Infinity; + } + if (row > lastRow) + break; + + var container = dom.createElement("div"); + + var html = []; + this.$renderLine(html, row, false, row == foldStart ? foldLine : false); + container.innerHTML = html.join(""); + if (this.$useLineGroups()) { + container.className = 'ace_line_group'; + fragment.appendChild(container); + container.style.height = config.lineHeight * this.session.getRowLength(row) + "px"; + + } else { + while(container.firstChild) + fragment.appendChild(container.firstChild); + } + + row++; + } + return fragment; + }; + + this.update = function(config) { + this.config = config; + + var html = []; + var firstRow = config.firstRow, lastRow = config.lastRow; + + var row = firstRow; + var foldLine = this.session.getNextFoldLine(row); + var foldStart = foldLine ? foldLine.start.row : Infinity; + + while (true) { + if (row > foldStart) { + row = foldLine.end.row+1; + foldLine = this.session.getNextFoldLine(row, foldLine); + foldStart = foldLine ? foldLine.start.row :Infinity; + } + if (row > lastRow) + break; + + if (this.$useLineGroups()) + html.push("
") + + this.$renderLine(html, row, false, row == foldStart ? foldLine : false); + + if (this.$useLineGroups()) + html.push("
"); // end the line group + + row++; + } + this.element.innerHTML = html.join(""); + }; + + this.$textToken = { + "text": true, + "rparen": true, + "lparen": true + }; + + this.$renderToken = function(stringBuilder, screenColumn, token, value) { + var self = this; + var replaceReg = /\t|&|<|>|( +)|([\x00-\x1f\x80-\xa0\xad\u1680\u180E\u2000-\u200f\u2028\u2029\u202F\u205F\u3000\uFEFF\uFFF9-\uFFFC])|[\u1100-\u115F\u11A3-\u11A7\u11FA-\u11FF\u2329-\u232A\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3000-\u303E\u3041-\u3096\u3099-\u30FF\u3105-\u312D\u3131-\u318E\u3190-\u31BA\u31C0-\u31E3\u31F0-\u321E\u3220-\u3247\u3250-\u32FE\u3300-\u4DBF\u4E00-\uA48C\uA490-\uA4C6\uA960-\uA97C\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE66\uFE68-\uFE6B\uFF01-\uFF60\uFFE0-\uFFE6]/g; + var replaceFunc = function(c, a, b, tabIdx, idx4) { + if (a) { + return self.showInvisibles + ? "" + lang.stringRepeat(self.SPACE_CHAR, c.length) + "" + : c; + } else if (c == "&") { + return "&"; + } else if (c == "<") { + return "<"; + } else if (c == ">") { + return ">"; + } else if (c == "\t") { + var tabSize = self.session.getScreenTabSize(screenColumn + tabIdx); + screenColumn += tabSize - 1; + return self.$tabStrings[tabSize]; + } else if (c == "\u3000") { + var classToUse = self.showInvisibles ? "ace_cjk ace_invisible ace_invisible_space" : "ace_cjk"; + var space = self.showInvisibles ? self.SPACE_CHAR : ""; + screenColumn += 1; + return "" + space + ""; + } else if (b) { + return "" + self.SPACE_CHAR + ""; + } else { + screenColumn += 1; + return "" + c + ""; + } + }; + + var output = value.replace(replaceReg, replaceFunc); + + if (!this.$textToken[token.type]) { + var classes = "ace_" + token.type.replace(/\./g, " ace_"); + var style = ""; + if (token.type == "fold") + style = " style='width:" + (token.value.length * this.config.characterWidth) + "px;' "; + stringBuilder.push("", output, ""); + } + else { + stringBuilder.push(output); + } + return screenColumn + value.length; + }; + + this.renderIndentGuide = function(stringBuilder, value, max) { + var cols = value.search(this.$indentGuideRe); + if (cols <= 0 || cols >= max) + return value; + if (value[0] == " ") { + cols -= cols % this.tabSize; + stringBuilder.push(lang.stringRepeat(this.$tabStrings[" "], cols/this.tabSize)); + return value.substr(cols); + } else if (value[0] == "\t") { + stringBuilder.push(lang.stringRepeat(this.$tabStrings["\t"], cols)); + return value.substr(cols); + } + return value; + }; + + this.$renderWrappedLine = function(stringBuilder, tokens, splits, onlyContents) { + var chars = 0; + var split = 0; + var splitChars = splits[0]; + var screenColumn = 0; + + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i]; + var value = token.value; + if (i == 0 && this.displayIndentGuides) { + chars = value.length; + value = this.renderIndentGuide(stringBuilder, value, splitChars); + if (!value) + continue; + chars -= value.length; + } + + if (chars + value.length < splitChars) { + screenColumn = this.$renderToken(stringBuilder, screenColumn, token, value); + chars += value.length; + } else { + while (chars + value.length >= splitChars) { + screenColumn = this.$renderToken( + stringBuilder, screenColumn, + token, value.substring(0, splitChars - chars) + ); + value = value.substring(splitChars - chars); + chars = splitChars; + + if (!onlyContents) { + stringBuilder.push("
", + "
" + ); + } + + stringBuilder.push(lang.stringRepeat("\xa0", splits.indent)); + + split ++; + screenColumn = 0; + splitChars = splits[split] || Number.MAX_VALUE; + } + if (value.length != 0) { + chars += value.length; + screenColumn = this.$renderToken( + stringBuilder, screenColumn, token, value + ); + } + } + } + }; + + this.$renderSimpleLine = function(stringBuilder, tokens) { + var screenColumn = 0; + var token = tokens[0]; + var value = token.value; + if (this.displayIndentGuides) + value = this.renderIndentGuide(stringBuilder, value); + if (value) + screenColumn = this.$renderToken(stringBuilder, screenColumn, token, value); + for (var i = 1; i < tokens.length; i++) { + token = tokens[i]; + value = token.value; + screenColumn = this.$renderToken(stringBuilder, screenColumn, token, value); + } + }; + this.$renderLine = function(stringBuilder, row, onlyContents, foldLine) { + if (!foldLine && foldLine != false) + foldLine = this.session.getFoldLine(row); + + if (foldLine) + var tokens = this.$getFoldLineTokens(row, foldLine); + else + var tokens = this.session.getTokens(row); + + + if (!onlyContents) { + stringBuilder.push( + "
" + ); + } + + if (tokens.length) { + var splits = this.session.getRowSplitData(row); + if (splits && splits.length) + this.$renderWrappedLine(stringBuilder, tokens, splits, onlyContents); + else + this.$renderSimpleLine(stringBuilder, tokens); + } + + if (this.showInvisibles) { + if (foldLine) + row = foldLine.end.row + + stringBuilder.push( + "", + row == this.session.getLength() - 1 ? this.EOF_CHAR : this.EOL_CHAR, + "" + ); + } + if (!onlyContents) + stringBuilder.push("
"); + }; + + this.$getFoldLineTokens = function(row, foldLine) { + var session = this.session; + var renderTokens = []; + + function addTokens(tokens, from, to) { + var idx = 0, col = 0; + while ((col + tokens[idx].value.length) < from) { + col += tokens[idx].value.length; + idx++; + + if (idx == tokens.length) + return; + } + if (col != from) { + var value = tokens[idx].value.substring(from - col); + if (value.length > (to - from)) + value = value.substring(0, to - from); + + renderTokens.push({ + type: tokens[idx].type, + value: value + }); + + col = from + value.length; + idx += 1; + } + + while (col < to && idx < tokens.length) { + var value = tokens[idx].value; + if (value.length + col > to) { + renderTokens.push({ + type: tokens[idx].type, + value: value.substring(0, to - col) + }); + } else + renderTokens.push(tokens[idx]); + col += value.length; + idx += 1; + } + } + + var tokens = session.getTokens(row); + foldLine.walk(function(placeholder, row, column, lastColumn, isNewRow) { + if (placeholder != null) { + renderTokens.push({ + type: "fold", + value: placeholder + }); + } else { + if (isNewRow) + tokens = session.getTokens(row); + + if (tokens.length) + addTokens(tokens, lastColumn, column); + } + }, foldLine.end.row, this.session.getLine(foldLine.end.row).length); + + return renderTokens; + }; + + this.$useLineGroups = function() { + return this.session.getUseWrapMode(); + }; + + this.destroy = function() { + clearInterval(this.$pollSizeChangesTimer); + if (this.$measureNode) + this.$measureNode.parentNode.removeChild(this.$measureNode); + delete this.$measureNode; + }; + + }).call(Text.prototype); + + exports.Text = Text; + + }); + + ace.define("ace/layer/cursor",["require","exports","module","ace/lib/dom"], function(acequire, exports, module) { + "use strict"; + + var dom = acequire("../lib/dom"); + var isIE8; + + var Cursor = function(parentEl) { + this.element = dom.createElement("div"); + this.element.className = "ace_layer ace_cursor-layer"; + parentEl.appendChild(this.element); + + if (isIE8 === undefined) + isIE8 = !("opacity" in this.element.style); + + this.isVisible = false; + this.isBlinking = true; + this.blinkInterval = 1000; + this.smoothBlinking = false; + + this.cursors = []; + this.cursor = this.addCursor(); + dom.addCssClass(this.element, "ace_hidden-cursors"); + this.$updateCursors = (isIE8 + ? this.$updateVisibility + : this.$updateOpacity).bind(this); + }; + + (function() { + + this.$updateVisibility = function(val) { + var cursors = this.cursors; + for (var i = cursors.length; i--; ) + cursors[i].style.visibility = val ? "" : "hidden"; + }; + this.$updateOpacity = function(val) { + var cursors = this.cursors; + for (var i = cursors.length; i--; ) + cursors[i].style.opacity = val ? "" : "0"; + }; + + + this.$padding = 0; + this.setPadding = function(padding) { + this.$padding = padding; + }; + + this.setSession = function(session) { + this.session = session; + }; + + this.setBlinking = function(blinking) { + if (blinking != this.isBlinking){ + this.isBlinking = blinking; + this.restartTimer(); + } + }; + + this.setBlinkInterval = function(blinkInterval) { + if (blinkInterval != this.blinkInterval){ + this.blinkInterval = blinkInterval; + this.restartTimer(); + } + }; + + this.setSmoothBlinking = function(smoothBlinking) { + if (smoothBlinking != this.smoothBlinking && !isIE8) { + this.smoothBlinking = smoothBlinking; + dom.setCssClass(this.element, "ace_smooth-blinking", smoothBlinking); + this.$updateCursors(true); + this.$updateCursors = (this.$updateOpacity).bind(this); + this.restartTimer(); + } + }; + + this.addCursor = function() { + var el = dom.createElement("div"); + el.className = "ace_cursor"; + this.element.appendChild(el); + this.cursors.push(el); + return el; + }; + + this.removeCursor = function() { + if (this.cursors.length > 1) { + var el = this.cursors.pop(); + el.parentNode.removeChild(el); + return el; + } + }; + + this.hideCursor = function() { + this.isVisible = false; + dom.addCssClass(this.element, "ace_hidden-cursors"); + this.restartTimer(); + }; + + this.showCursor = function() { + this.isVisible = true; + dom.removeCssClass(this.element, "ace_hidden-cursors"); + this.restartTimer(); + }; + + this.restartTimer = function() { + var update = this.$updateCursors; + clearInterval(this.intervalId); + clearTimeout(this.timeoutId); + if (this.smoothBlinking) { + dom.removeCssClass(this.element, "ace_smooth-blinking"); + } + + update(true); + + if (!this.isBlinking || !this.blinkInterval || !this.isVisible) + return; + + if (this.smoothBlinking) { + setTimeout(function(){ + dom.addCssClass(this.element, "ace_smooth-blinking"); + }.bind(this)); + } + + var blink = function(){ + this.timeoutId = setTimeout(function() { + update(false); + }, 0.6 * this.blinkInterval); + }.bind(this); + + this.intervalId = setInterval(function() { + update(true); + blink(); + }, this.blinkInterval); + + blink(); + }; + + this.getPixelPosition = function(position, onScreen) { + if (!this.config || !this.session) + return {left : 0, top : 0}; + + if (!position) + position = this.session.selection.getCursor(); + var pos = this.session.documentToScreenPosition(position); + var cursorLeft = this.$padding + pos.column * this.config.characterWidth; + var cursorTop = (pos.row - (onScreen ? this.config.firstRowScreen : 0)) * + this.config.lineHeight; + + return {left : cursorLeft, top : cursorTop}; + }; + + this.update = function(config) { + this.config = config; + + var selections = this.session.$selectionMarkers; + var i = 0, cursorIndex = 0; + + if (selections === undefined || selections.length === 0){ + selections = [{cursor: null}]; + } + + for (var i = 0, n = selections.length; i < n; i++) { + var pixelPos = this.getPixelPosition(selections[i].cursor, true); + if ((pixelPos.top > config.height + config.offset || + pixelPos.top < 0) && i > 1) { + continue; + } + + var style = (this.cursors[cursorIndex++] || this.addCursor()).style; + + if (!this.drawCursor) { + style.left = pixelPos.left + "px"; + style.top = pixelPos.top + "px"; + style.width = config.characterWidth + "px"; + style.height = config.lineHeight + "px"; + } else { + this.drawCursor(style, pixelPos, config, selections[i], this.session); + } + } + while (this.cursors.length > cursorIndex) + this.removeCursor(); + + var overwrite = this.session.getOverwrite(); + this.$setOverwrite(overwrite); + this.$pixelPos = pixelPos; + this.restartTimer(); + }; + + this.drawCursor = null; + + this.$setOverwrite = function(overwrite) { + if (overwrite != this.overwrite) { + this.overwrite = overwrite; + if (overwrite) + dom.addCssClass(this.element, "ace_overwrite-cursors"); + else + dom.removeCssClass(this.element, "ace_overwrite-cursors"); + } + }; + + this.destroy = function() { + clearInterval(this.intervalId); + clearTimeout(this.timeoutId); + }; + + }).call(Cursor.prototype); + + exports.Cursor = Cursor; + + }); + + ace.define("ace/scrollbar",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/event","ace/lib/event_emitter"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("./lib/oop"); + var dom = acequire("./lib/dom"); + var event = acequire("./lib/event"); + var EventEmitter = acequire("./lib/event_emitter").EventEmitter; + var ScrollBar = function(parent) { + this.element = dom.createElement("div"); + this.element.className = "ace_scrollbar ace_scrollbar" + this.classSuffix; + + this.inner = dom.createElement("div"); + this.inner.className = "ace_scrollbar-inner"; + this.element.appendChild(this.inner); + + parent.appendChild(this.element); + + this.setVisible(false); + this.skipEvent = false; + + event.addListener(this.element, "scroll", this.onScroll.bind(this)); + event.addListener(this.element, "mousedown", event.preventDefault); + }; + + (function() { + oop.implement(this, EventEmitter); + + this.setVisible = function(isVisible) { + this.element.style.display = isVisible ? "" : "none"; + this.isVisible = isVisible; + }; + }).call(ScrollBar.prototype); + var VScrollBar = function(parent, renderer) { + ScrollBar.call(this, parent); + this.scrollTop = 0; + renderer.$scrollbarWidth = + this.width = dom.scrollbarWidth(parent.ownerDocument); + this.inner.style.width = + this.element.style.width = (this.width || 15) + 5 + "px"; + }; + + oop.inherits(VScrollBar, ScrollBar); + + (function() { + + this.classSuffix = '-v'; + this.onScroll = function() { + if (!this.skipEvent) { + this.scrollTop = this.element.scrollTop; + this._emit("scroll", {data: this.scrollTop}); + } + this.skipEvent = false; + }; + this.getWidth = function() { + return this.isVisible ? this.width : 0; + }; + this.setHeight = function(height) { + this.element.style.height = height + "px"; + }; + this.setInnerHeight = function(height) { + this.inner.style.height = height + "px"; + }; + this.setScrollHeight = function(height) { + this.inner.style.height = height + "px"; + }; + this.setScrollTop = function(scrollTop) { + if (this.scrollTop != scrollTop) { + this.skipEvent = true; + this.scrollTop = this.element.scrollTop = scrollTop; + } + }; + + }).call(VScrollBar.prototype); + var HScrollBar = function(parent, renderer) { + ScrollBar.call(this, parent); + this.scrollLeft = 0; + this.height = renderer.$scrollbarWidth; + this.inner.style.height = + this.element.style.height = (this.height || 15) + 5 + "px"; + }; + + oop.inherits(HScrollBar, ScrollBar); + + (function() { + + this.classSuffix = '-h'; + this.onScroll = function() { + if (!this.skipEvent) { + this.scrollLeft = this.element.scrollLeft; + this._emit("scroll", {data: this.scrollLeft}); + } + this.skipEvent = false; + }; + this.getHeight = function() { + return this.isVisible ? this.height : 0; + }; + this.setWidth = function(width) { + this.element.style.width = width + "px"; + }; + this.setInnerWidth = function(width) { + this.inner.style.width = width + "px"; + }; + this.setScrollWidth = function(width) { + this.inner.style.width = width + "px"; + }; + this.setScrollLeft = function(scrollLeft) { + if (this.scrollLeft != scrollLeft) { + this.skipEvent = true; + this.scrollLeft = this.element.scrollLeft = scrollLeft; + } + }; + + }).call(HScrollBar.prototype); + + + exports.ScrollBar = VScrollBar; // backward compatibility + exports.ScrollBarV = VScrollBar; // backward compatibility + exports.ScrollBarH = HScrollBar; // backward compatibility + + exports.VScrollBar = VScrollBar; + exports.HScrollBar = HScrollBar; + }); + + ace.define("ace/renderloop",["require","exports","module","ace/lib/event"], function(acequire, exports, module) { + "use strict"; + + var event = acequire("./lib/event"); + + + var RenderLoop = function(onRender, win) { + this.onRender = onRender; + this.pending = false; + this.changes = 0; + this.window = win || window; + }; + + (function() { + + + this.schedule = function(change) { + this.changes = this.changes | change; + if (!this.pending && this.changes) { + this.pending = true; + var _self = this; + event.nextFrame(function() { + _self.pending = false; + var changes; + while (changes = _self.changes) { + _self.changes = 0; + _self.onRender(changes); + } + }, this.window); + } + }; + + }).call(RenderLoop.prototype); + + exports.RenderLoop = RenderLoop; + }); + + ace.define("ace/layer/font_metrics",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/useragent","ace/lib/event_emitter"], function(acequire, exports, module) { + + var oop = acequire("../lib/oop"); + var dom = acequire("../lib/dom"); + var lang = acequire("../lib/lang"); + var useragent = acequire("../lib/useragent"); + var EventEmitter = acequire("../lib/event_emitter").EventEmitter; + + var CHAR_COUNT = 0; + + var FontMetrics = exports.FontMetrics = function(parentEl) { + this.el = dom.createElement("div"); + this.$setMeasureNodeStyles(this.el.style, true); + + this.$main = dom.createElement("div"); + this.$setMeasureNodeStyles(this.$main.style); + + this.$measureNode = dom.createElement("div"); + this.$setMeasureNodeStyles(this.$measureNode.style); + + + this.el.appendChild(this.$main); + this.el.appendChild(this.$measureNode); + parentEl.appendChild(this.el); + + if (!CHAR_COUNT) + this.$testFractionalRect(); + this.$measureNode.innerHTML = lang.stringRepeat("X", CHAR_COUNT); + + this.$characterSize = {width: 0, height: 0}; + this.checkForSizeChanges(); + }; + + (function() { + + oop.implement(this, EventEmitter); + + this.$characterSize = {width: 0, height: 0}; + + this.$testFractionalRect = function() { + var el = dom.createElement("div"); + this.$setMeasureNodeStyles(el.style); + el.style.width = "0.2px"; + document.documentElement.appendChild(el); + var w = el.getBoundingClientRect().width; + if (w > 0 && w < 1) + CHAR_COUNT = 50; + else + CHAR_COUNT = 100; + el.parentNode.removeChild(el); + }; + + this.$setMeasureNodeStyles = function(style, isRoot) { + style.width = style.height = "auto"; + style.left = style.top = "0px"; + style.visibility = "hidden"; + style.position = "absolute"; + style.whiteSpace = "pre"; + + if (useragent.isIE < 8) { + style["font-family"] = "inherit"; + } else { + style.font = "inherit"; + } + style.overflow = isRoot ? "hidden" : "visible"; + }; + + this.checkForSizeChanges = function() { + var size = this.$measureSizes(); + if (size && (this.$characterSize.width !== size.width || this.$characterSize.height !== size.height)) { + this.$measureNode.style.fontWeight = "bold"; + var boldSize = this.$measureSizes(); + this.$measureNode.style.fontWeight = ""; + this.$characterSize = size; + this.charSizes = Object.create(null); + this.allowBoldFonts = boldSize && boldSize.width === size.width && boldSize.height === size.height; + this._emit("changeCharacterSize", {data: size}); + } + }; + + this.$pollSizeChanges = function() { + if (this.$pollSizeChangesTimer) + return this.$pollSizeChangesTimer; + var self = this; + return this.$pollSizeChangesTimer = setInterval(function() { + self.checkForSizeChanges(); + }, 500); + }; + + this.setPolling = function(val) { + if (val) { + this.$pollSizeChanges(); + } else if (this.$pollSizeChangesTimer) { + clearInterval(this.$pollSizeChangesTimer); + this.$pollSizeChangesTimer = 0; + } + }; + + this.$measureSizes = function() { + if (CHAR_COUNT === 50) { + var rect = null; + try { + rect = this.$measureNode.getBoundingClientRect(); + } catch(e) { + rect = {width: 0, height:0 }; + } + var size = { + height: rect.height, + width: rect.width / CHAR_COUNT + }; + } else { + var size = { + height: this.$measureNode.clientHeight, + width: this.$measureNode.clientWidth / CHAR_COUNT + }; + } + if (size.width === 0 || size.height === 0) + return null; + return size; + }; + + this.$measureCharWidth = function(ch) { + this.$main.innerHTML = lang.stringRepeat(ch, CHAR_COUNT); + var rect = this.$main.getBoundingClientRect(); + return rect.width / CHAR_COUNT; + }; + + this.getCharacterWidth = function(ch) { + var w = this.charSizes[ch]; + if (w === undefined) { + w = this.charSizes[ch] = this.$measureCharWidth(ch) / this.$characterSize.width; + } + return w; + }; + + this.destroy = function() { + clearInterval(this.$pollSizeChangesTimer); + if (this.el && this.el.parentNode) + this.el.parentNode.removeChild(this.el); + }; + + }).call(FontMetrics.prototype); + + }); + + ace.define("ace/virtual_renderer",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/config","ace/lib/useragent","ace/layer/gutter","ace/layer/marker","ace/layer/text","ace/layer/cursor","ace/scrollbar","ace/scrollbar","ace/renderloop","ace/layer/font_metrics","ace/lib/event_emitter"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("./lib/oop"); + var dom = acequire("./lib/dom"); + var config = acequire("./config"); + var useragent = acequire("./lib/useragent"); + var GutterLayer = acequire("./layer/gutter").Gutter; + var MarkerLayer = acequire("./layer/marker").Marker; + var TextLayer = acequire("./layer/text").Text; + var CursorLayer = acequire("./layer/cursor").Cursor; + var HScrollBar = acequire("./scrollbar").HScrollBar; + var VScrollBar = acequire("./scrollbar").VScrollBar; + var RenderLoop = acequire("./renderloop").RenderLoop; + var FontMetrics = acequire("./layer/font_metrics").FontMetrics; + var EventEmitter = acequire("./lib/event_emitter").EventEmitter; + var editorCss = ".ace_editor {\ + position: relative;\ + overflow: hidden;\ + font: 12px/normal 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace;\ + direction: ltr;\ + }\ + .ace_scroller {\ + position: absolute;\ + overflow: hidden;\ + top: 0;\ + bottom: 0;\ + background-color: inherit;\ + -ms-user-select: none;\ + -moz-user-select: none;\ + -webkit-user-select: none;\ + user-select: none;\ + cursor: text;\ + }\ + .ace_content {\ + position: absolute;\ + -moz-box-sizing: border-box;\ + -webkit-box-sizing: border-box;\ + box-sizing: border-box;\ + min-width: 100%;\ + }\ + .ace_dragging .ace_scroller:before{\ + position: absolute;\ + top: 0;\ + left: 0;\ + right: 0;\ + bottom: 0;\ + content: '';\ + background: rgba(250, 250, 250, 0.01);\ + z-index: 1000;\ + }\ + .ace_dragging.ace_dark .ace_scroller:before{\ + background: rgba(0, 0, 0, 0.01);\ + }\ + .ace_selecting, .ace_selecting * {\ + cursor: text !important;\ + }\ + .ace_gutter {\ + position: absolute;\ + overflow : hidden;\ + width: auto;\ + top: 0;\ + bottom: 0;\ + left: 0;\ + cursor: default;\ + z-index: 4;\ + -ms-user-select: none;\ + -moz-user-select: none;\ + -webkit-user-select: none;\ + user-select: none;\ + }\ + .ace_gutter-active-line {\ + position: absolute;\ + left: 0;\ + right: 0;\ + }\ + .ace_scroller.ace_scroll-left {\ + box-shadow: 17px 0 16px -16px rgba(0, 0, 0, 0.4) inset;\ + }\ + .ace_gutter-cell {\ + padding-left: 19px;\ + padding-right: 6px;\ + background-repeat: no-repeat;\ + }\ + .ace_gutter-cell.ace_error {\ + background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABOFBMVEX/////////QRswFAb/Ui4wFAYwFAYwFAaWGAfDRymzOSH/PxswFAb/SiUwFAYwFAbUPRvjQiDllog5HhHdRybsTi3/Tyv9Tir+Syj/UC3////XurebMBIwFAb/RSHbPx/gUzfdwL3kzMivKBAwFAbbvbnhPx66NhowFAYwFAaZJg8wFAaxKBDZurf/RB6mMxb/SCMwFAYwFAbxQB3+RB4wFAb/Qhy4Oh+4QifbNRcwFAYwFAYwFAb/QRzdNhgwFAYwFAbav7v/Uy7oaE68MBK5LxLewr/r2NXewLswFAaxJw4wFAbkPRy2PyYwFAaxKhLm1tMwFAazPiQwFAaUGAb/QBrfOx3bvrv/VC/maE4wFAbRPBq6MRO8Qynew8Dp2tjfwb0wFAbx6eju5+by6uns4uH9/f36+vr/GkHjAAAAYnRSTlMAGt+64rnWu/bo8eAA4InH3+DwoN7j4eLi4xP99Nfg4+b+/u9B/eDs1MD1mO7+4PHg2MXa347g7vDizMLN4eG+Pv7i5evs/v79yu7S3/DV7/498Yv24eH+4ufQ3Ozu/v7+y13sRqwAAADLSURBVHjaZc/XDsFgGIBhtDrshlitmk2IrbHFqL2pvXf/+78DPokj7+Fz9qpU/9UXJIlhmPaTaQ6QPaz0mm+5gwkgovcV6GZzd5JtCQwgsxoHOvJO15kleRLAnMgHFIESUEPmawB9ngmelTtipwwfASilxOLyiV5UVUyVAfbG0cCPHig+GBkzAENHS0AstVF6bacZIOzgLmxsHbt2OecNgJC83JERmePUYq8ARGkJx6XtFsdddBQgZE2nPR6CICZhawjA4Fb/chv+399kfR+MMMDGOQAAAABJRU5ErkJggg==\");\ + background-repeat: no-repeat;\ + background-position: 2px center;\ + }\ + .ace_gutter-cell.ace_warning {\ + background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAmVBMVEX///8AAAD///8AAAAAAABPSzb/5sAAAAB/blH/73z/ulkAAAAAAAD85pkAAAAAAAACAgP/vGz/rkDerGbGrV7/pkQICAf////e0IsAAAD/oED/qTvhrnUAAAD/yHD/njcAAADuv2r/nz//oTj/p064oGf/zHAAAAA9Nir/tFIAAAD/tlTiuWf/tkIAAACynXEAAAAAAAAtIRW7zBpBAAAAM3RSTlMAABR1m7RXO8Ln31Z36zT+neXe5OzooRDfn+TZ4p3h2hTf4t3k3ucyrN1K5+Xaks52Sfs9CXgrAAAAjklEQVR42o3PbQ+CIBQFYEwboPhSYgoYunIqqLn6/z8uYdH8Vmdnu9vz4WwXgN/xTPRD2+sgOcZjsge/whXZgUaYYvT8QnuJaUrjrHUQreGczuEafQCO/SJTufTbroWsPgsllVhq3wJEk2jUSzX3CUEDJC84707djRc5MTAQxoLgupWRwW6UB5fS++NV8AbOZgnsC7BpEAAAAABJRU5ErkJggg==\");\ + background-position: 2px center;\ + }\ + .ace_gutter-cell.ace_info {\ + background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAJ0Uk5TAAB2k804AAAAPklEQVQY02NgIB68QuO3tiLznjAwpKTgNyDbMegwisCHZUETUZV0ZqOquBpXj2rtnpSJT1AEnnRmL2OgGgAAIKkRQap2htgAAAAASUVORK5CYII=\");\ + background-position: 2px center;\ + }\ + .ace_dark .ace_gutter-cell.ace_info {\ + background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAJFBMVEUAAAChoaGAgIAqKiq+vr6tra1ZWVmUlJSbm5s8PDxubm56enrdgzg3AAAAAXRSTlMAQObYZgAAAClJREFUeNpjYMAPdsMYHegyJZFQBlsUlMFVCWUYKkAZMxZAGdxlDMQBAG+TBP4B6RyJAAAAAElFTkSuQmCC\");\ + }\ + .ace_scrollbar {\ + position: absolute;\ + right: 0;\ + bottom: 0;\ + z-index: 6;\ + }\ + .ace_scrollbar-inner {\ + position: absolute;\ + cursor: text;\ + left: 0;\ + top: 0;\ + }\ + .ace_scrollbar-v{\ + overflow-x: hidden;\ + overflow-y: scroll;\ + top: 0;\ + }\ + .ace_scrollbar-h {\ + overflow-x: scroll;\ + overflow-y: hidden;\ + left: 0;\ + }\ + .ace_print-margin {\ + position: absolute;\ + height: 100%;\ + }\ + .ace_text-input {\ + position: absolute;\ + z-index: 0;\ + width: 0.5em;\ + height: 1em;\ + opacity: 0;\ + background: transparent;\ + -moz-appearance: none;\ + appearance: none;\ + border: none;\ + resize: none;\ + outline: none;\ + overflow: hidden;\ + font: inherit;\ + padding: 0 1px;\ + margin: 0 -1px;\ + text-indent: -1em;\ + -ms-user-select: text;\ + -moz-user-select: text;\ + -webkit-user-select: text;\ + user-select: text;\ + white-space: pre!important;\ + }\ + .ace_text-input.ace_composition {\ + background: inherit;\ + color: inherit;\ + z-index: 1000;\ + opacity: 1;\ + text-indent: 0;\ + }\ + .ace_layer {\ + z-index: 1;\ + position: absolute;\ + overflow: hidden;\ + word-wrap: normal;\ + white-space: pre;\ + height: 100%;\ + width: 100%;\ + -moz-box-sizing: border-box;\ + -webkit-box-sizing: border-box;\ + box-sizing: border-box;\ + pointer-events: none;\ + }\ + .ace_gutter-layer {\ + position: relative;\ + width: auto;\ + text-align: right;\ + pointer-events: auto;\ + }\ + .ace_text-layer {\ + font: inherit !important;\ + }\ + .ace_cjk {\ + display: inline-block;\ + text-align: center;\ + }\ + .ace_cursor-layer {\ + z-index: 4;\ + }\ + .ace_cursor {\ + z-index: 4;\ + position: absolute;\ + -moz-box-sizing: border-box;\ + -webkit-box-sizing: border-box;\ + box-sizing: border-box;\ + border-left: 2px solid;\ + transform: translatez(0);\ + }\ + .ace_slim-cursors .ace_cursor {\ + border-left-width: 1px;\ + }\ + .ace_overwrite-cursors .ace_cursor {\ + border-left-width: 0;\ + border-bottom: 1px solid;\ + }\ + .ace_hidden-cursors .ace_cursor {\ + opacity: 0.2;\ + }\ + .ace_smooth-blinking .ace_cursor {\ + -webkit-transition: opacity 0.18s;\ + transition: opacity 0.18s;\ + }\ + .ace_editor.ace_multiselect .ace_cursor {\ + border-left-width: 1px;\ + }\ + .ace_marker-layer .ace_step, .ace_marker-layer .ace_stack {\ + position: absolute;\ + z-index: 3;\ + }\ + .ace_marker-layer .ace_selection {\ + position: absolute;\ + z-index: 5;\ + }\ + .ace_marker-layer .ace_bracket {\ + position: absolute;\ + z-index: 6;\ + }\ + .ace_marker-layer .ace_active-line {\ + position: absolute;\ + z-index: 2;\ + }\ + .ace_marker-layer .ace_selected-word {\ + position: absolute;\ + z-index: 4;\ + -moz-box-sizing: border-box;\ + -webkit-box-sizing: border-box;\ + box-sizing: border-box;\ + }\ + .ace_line .ace_fold {\ + -moz-box-sizing: border-box;\ + -webkit-box-sizing: border-box;\ + box-sizing: border-box;\ + display: inline-block;\ + height: 11px;\ + margin-top: -2px;\ + vertical-align: middle;\ + background-image:\ + url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII=\"),\ + url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACJJREFUeNpi+P//fxgTAwPDBxDxD078RSX+YeEyDFMCIMAAI3INmXiwf2YAAAAASUVORK5CYII=\");\ + background-repeat: no-repeat, repeat-x;\ + background-position: center center, top left;\ + color: transparent;\ + border: 1px solid black;\ + border-radius: 2px;\ + cursor: pointer;\ + pointer-events: auto;\ + }\ + .ace_dark .ace_fold {\ + }\ + .ace_fold:hover{\ + background-image:\ + url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII=\"),\ + url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACBJREFUeNpi+P//fz4TAwPDZxDxD5X4i5fLMEwJgAADAEPVDbjNw87ZAAAAAElFTkSuQmCC\");\ + }\ + .ace_tooltip {\ + background-color: #FFF;\ + background-image: -webkit-linear-gradient(top, transparent, rgba(0, 0, 0, 0.1));\ + background-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1));\ + border: 1px solid gray;\ + border-radius: 1px;\ + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);\ + color: black;\ + max-width: 100%;\ + padding: 3px 4px;\ + position: fixed;\ + z-index: 999999;\ + -moz-box-sizing: border-box;\ + -webkit-box-sizing: border-box;\ + box-sizing: border-box;\ + cursor: default;\ + white-space: pre;\ + word-wrap: break-word;\ + line-height: normal;\ + font-style: normal;\ + font-weight: normal;\ + letter-spacing: normal;\ + pointer-events: none;\ + }\ + .ace_folding-enabled > .ace_gutter-cell {\ + padding-right: 13px;\ + }\ + .ace_fold-widget {\ + -moz-box-sizing: border-box;\ + -webkit-box-sizing: border-box;\ + box-sizing: border-box;\ + margin: 0 -12px 0 1px;\ + display: none;\ + width: 11px;\ + vertical-align: top;\ + background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42mWKsQ0AMAzC8ixLlrzQjzmBiEjp0A6WwBCSPgKAXoLkqSot7nN3yMwR7pZ32NzpKkVoDBUxKAAAAABJRU5ErkJggg==\");\ + background-repeat: no-repeat;\ + background-position: center;\ + border-radius: 3px;\ + border: 1px solid transparent;\ + cursor: pointer;\ + }\ + .ace_folding-enabled .ace_fold-widget {\ + display: inline-block; \ + }\ + .ace_fold-widget.ace_end {\ + background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42m3HwQkAMAhD0YzsRchFKI7sAikeWkrxwScEB0nh5e7KTPWimZki4tYfVbX+MNl4pyZXejUO1QAAAABJRU5ErkJggg==\");\ + }\ + .ace_fold-widget.ace_closed {\ + background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAGCAYAAAAG5SQMAAAAOUlEQVR42jXKwQkAMAgDwKwqKD4EwQ26sSOkVWjgIIHAzPiCgaqiqnJHZnKICBERHN194O5b9vbLuAVRL+l0YWnZAAAAAElFTkSuQmCCXA==\");\ + }\ + .ace_fold-widget:hover {\ + border: 1px solid rgba(0, 0, 0, 0.3);\ + background-color: rgba(255, 255, 255, 0.2);\ + box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);\ + }\ + .ace_fold-widget:active {\ + border: 1px solid rgba(0, 0, 0, 0.4);\ + background-color: rgba(0, 0, 0, 0.05);\ + box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);\ + }\ + .ace_dark .ace_fold-widget {\ + background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHklEQVQIW2P4//8/AzoGEQ7oGCaLLAhWiSwB146BAQCSTPYocqT0AAAAAElFTkSuQmCC\");\ + }\ + .ace_dark .ace_fold-widget.ace_end {\ + background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAH0lEQVQIW2P4//8/AxQ7wNjIAjDMgC4AxjCVKBirIAAF0kz2rlhxpAAAAABJRU5ErkJggg==\");\ + }\ + .ace_dark .ace_fold-widget.ace_closed {\ + background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAHElEQVQIW2P4//+/AxAzgDADlOOAznHAKgPWAwARji8UIDTfQQAAAABJRU5ErkJggg==\");\ + }\ + .ace_dark .ace_fold-widget:hover {\ + box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);\ + background-color: rgba(255, 255, 255, 0.1);\ + }\ + .ace_dark .ace_fold-widget:active {\ + box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);\ + }\ + .ace_fold-widget.ace_invalid {\ + background-color: #FFB4B4;\ + border-color: #DE5555;\ + }\ + .ace_fade-fold-widgets .ace_fold-widget {\ + -webkit-transition: opacity 0.4s ease 0.05s;\ + transition: opacity 0.4s ease 0.05s;\ + opacity: 0;\ + }\ + .ace_fade-fold-widgets:hover .ace_fold-widget {\ + -webkit-transition: opacity 0.05s ease 0.05s;\ + transition: opacity 0.05s ease 0.05s;\ + opacity:1;\ + }\ + .ace_underline {\ + text-decoration: underline;\ + }\ + .ace_bold {\ + font-weight: bold;\ + }\ + .ace_nobold .ace_bold {\ + font-weight: normal;\ + }\ + .ace_italic {\ + font-style: italic;\ + }\ + .ace_error-marker {\ + background-color: rgba(255, 0, 0,0.2);\ + position: absolute;\ + z-index: 9;\ + }\ + .ace_highlight-marker {\ + background-color: rgba(255, 255, 0,0.2);\ + position: absolute;\ + z-index: 8;\ + }\ + .ace_br1 {border-top-left-radius : 3px;}\ + .ace_br2 {border-top-right-radius : 3px;}\ + .ace_br3 {border-top-left-radius : 3px; border-top-right-radius: 3px;}\ + .ace_br4 {border-bottom-right-radius: 3px;}\ + .ace_br5 {border-top-left-radius : 3px; border-bottom-right-radius: 3px;}\ + .ace_br6 {border-top-right-radius : 3px; border-bottom-right-radius: 3px;}\ + .ace_br7 {border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px;}\ + .ace_br8 {border-bottom-left-radius : 3px;}\ + .ace_br9 {border-top-left-radius : 3px; border-bottom-left-radius: 3px;}\ + .ace_br10{border-top-right-radius : 3px; border-bottom-left-radius: 3px;}\ + .ace_br11{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-left-radius: 3px;}\ + .ace_br12{border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}\ + .ace_br13{border-top-left-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}\ + .ace_br14{border-top-right-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}\ + .ace_br15{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}\ + "; + + dom.importCssString(editorCss, "ace_editor.css"); + + var VirtualRenderer = function(container, theme) { + var _self = this; + + this.container = container || dom.createElement("div"); + this.$keepTextAreaAtCursor = !useragent.isOldIE; + + dom.addCssClass(this.container, "ace_editor"); + + this.setTheme(theme); + + this.$gutter = dom.createElement("div"); + this.$gutter.className = "ace_gutter"; + this.container.appendChild(this.$gutter); + + this.scroller = dom.createElement("div"); + this.scroller.className = "ace_scroller"; + this.container.appendChild(this.scroller); + + this.content = dom.createElement("div"); + this.content.className = "ace_content"; + this.scroller.appendChild(this.content); + + this.$gutterLayer = new GutterLayer(this.$gutter); + this.$gutterLayer.on("changeGutterWidth", this.onGutterResize.bind(this)); + + this.$markerBack = new MarkerLayer(this.content); + + var textLayer = this.$textLayer = new TextLayer(this.content); + this.canvas = textLayer.element; + + this.$markerFront = new MarkerLayer(this.content); + + this.$cursorLayer = new CursorLayer(this.content); + this.$horizScroll = false; + this.$vScroll = false; + + this.scrollBar = + this.scrollBarV = new VScrollBar(this.container, this); + this.scrollBarH = new HScrollBar(this.container, this); + this.scrollBarV.addEventListener("scroll", function(e) { + if (!_self.$scrollAnimation) + _self.session.setScrollTop(e.data - _self.scrollMargin.top); + }); + this.scrollBarH.addEventListener("scroll", function(e) { + if (!_self.$scrollAnimation) + _self.session.setScrollLeft(e.data - _self.scrollMargin.left); + }); + + this.scrollTop = 0; + this.scrollLeft = 0; + + this.cursorPos = { + row : 0, + column : 0 + }; + + this.$fontMetrics = new FontMetrics(this.container); + this.$textLayer.$setFontMetrics(this.$fontMetrics); + this.$textLayer.addEventListener("changeCharacterSize", function(e) { + _self.updateCharacterSize(); + _self.onResize(true, _self.gutterWidth, _self.$size.width, _self.$size.height); + _self._signal("changeCharacterSize", e); + }); + + this.$size = { + width: 0, + height: 0, + scrollerHeight: 0, + scrollerWidth: 0, + $dirty: true + }; + + this.layerConfig = { + width : 1, + padding : 0, + firstRow : 0, + firstRowScreen: 0, + lastRow : 0, + lineHeight : 0, + characterWidth : 0, + minHeight : 1, + maxHeight : 1, + offset : 0, + height : 1, + gutterOffset: 1 + }; + + this.scrollMargin = { + left: 0, + right: 0, + top: 0, + bottom: 0, + v: 0, + h: 0 + }; + + this.$loop = new RenderLoop( + this.$renderChanges.bind(this), + this.container.ownerDocument.defaultView + ); + this.$loop.schedule(this.CHANGE_FULL); + + this.updateCharacterSize(); + this.setPadding(4); + config.resetOptions(this); + config._emit("renderer", this); + }; + + (function() { + + this.CHANGE_CURSOR = 1; + this.CHANGE_MARKER = 2; + this.CHANGE_GUTTER = 4; + this.CHANGE_SCROLL = 8; + this.CHANGE_LINES = 16; + this.CHANGE_TEXT = 32; + this.CHANGE_SIZE = 64; + this.CHANGE_MARKER_BACK = 128; + this.CHANGE_MARKER_FRONT = 256; + this.CHANGE_FULL = 512; + this.CHANGE_H_SCROLL = 1024; + + oop.implement(this, EventEmitter); + + this.updateCharacterSize = function() { + if (this.$textLayer.allowBoldFonts != this.$allowBoldFonts) { + this.$allowBoldFonts = this.$textLayer.allowBoldFonts; + this.setStyle("ace_nobold", !this.$allowBoldFonts); + } + + this.layerConfig.characterWidth = + this.characterWidth = this.$textLayer.getCharacterWidth(); + this.layerConfig.lineHeight = + this.lineHeight = this.$textLayer.getLineHeight(); + this.$updatePrintMargin(); + }; + this.setSession = function(session) { + if (this.session) + this.session.doc.off("changeNewLineMode", this.onChangeNewLineMode); + + this.session = session; + if (session && this.scrollMargin.top && session.getScrollTop() <= 0) + session.setScrollTop(-this.scrollMargin.top); + + this.$cursorLayer.setSession(session); + this.$markerBack.setSession(session); + this.$markerFront.setSession(session); + this.$gutterLayer.setSession(session); + this.$textLayer.setSession(session); + if (!session) + return; + + this.$loop.schedule(this.CHANGE_FULL); + this.session.$setFontMetrics(this.$fontMetrics); + + this.onChangeNewLineMode = this.onChangeNewLineMode.bind(this); + this.onChangeNewLineMode() + this.session.doc.on("changeNewLineMode", this.onChangeNewLineMode); + }; + this.updateLines = function(firstRow, lastRow, force) { + if (lastRow === undefined) + lastRow = Infinity; + + if (!this.$changedLines) { + this.$changedLines = { + firstRow: firstRow, + lastRow: lastRow + }; + } + else { + if (this.$changedLines.firstRow > firstRow) + this.$changedLines.firstRow = firstRow; + + if (this.$changedLines.lastRow < lastRow) + this.$changedLines.lastRow = lastRow; + } + if (this.$changedLines.lastRow < this.layerConfig.firstRow) { + if (force) + this.$changedLines.lastRow = this.layerConfig.lastRow; + else + return; + } + if (this.$changedLines.firstRow > this.layerConfig.lastRow) + return; + this.$loop.schedule(this.CHANGE_LINES); + }; + + this.onChangeNewLineMode = function() { + this.$loop.schedule(this.CHANGE_TEXT); + this.$textLayer.$updateEolChar(); + }; + + this.onChangeTabSize = function() { + this.$loop.schedule(this.CHANGE_TEXT | this.CHANGE_MARKER); + this.$textLayer.onChangeTabSize(); + }; + this.updateText = function() { + this.$loop.schedule(this.CHANGE_TEXT); + }; + this.updateFull = function(force) { + if (force) + this.$renderChanges(this.CHANGE_FULL, true); + else + this.$loop.schedule(this.CHANGE_FULL); + }; + this.updateFontSize = function() { + this.$textLayer.checkForSizeChanges(); + }; + + this.$changes = 0; + this.$updateSizeAsync = function() { + if (this.$loop.pending) + this.$size.$dirty = true; + else + this.onResize(); + }; + this.onResize = function(force, gutterWidth, width, height) { + if (this.resizing > 2) + return; + else if (this.resizing > 0) + this.resizing++; + else + this.resizing = force ? 1 : 0; + var el = this.container; + if (!height) + height = el.clientHeight || el.scrollHeight; + if (!width) + width = el.clientWidth || el.scrollWidth; + var changes = this.$updateCachedSize(force, gutterWidth, width, height); + + + if (!this.$size.scrollerHeight || (!width && !height)) + return this.resizing = 0; + + if (force) + this.$gutterLayer.$padding = null; + + if (force) + this.$renderChanges(changes | this.$changes, true); + else + this.$loop.schedule(changes | this.$changes); + + if (this.resizing) + this.resizing = 0; + this.scrollBarV.scrollLeft = this.scrollBarV.scrollTop = null; + }; + + this.$updateCachedSize = function(force, gutterWidth, width, height) { + height -= (this.$extraHeight || 0); + var changes = 0; + var size = this.$size; + var oldSize = { + width: size.width, + height: size.height, + scrollerHeight: size.scrollerHeight, + scrollerWidth: size.scrollerWidth + }; + if (height && (force || size.height != height)) { + size.height = height; + changes |= this.CHANGE_SIZE; + + size.scrollerHeight = size.height; + if (this.$horizScroll) + size.scrollerHeight -= this.scrollBarH.getHeight(); + this.scrollBarV.element.style.bottom = this.scrollBarH.getHeight() + "px"; + + changes = changes | this.CHANGE_SCROLL; + } + + if (width && (force || size.width != width)) { + changes |= this.CHANGE_SIZE; + size.width = width; + + if (gutterWidth == null) + gutterWidth = this.$showGutter ? this.$gutter.offsetWidth : 0; + + this.gutterWidth = gutterWidth; + + this.scrollBarH.element.style.left = + this.scroller.style.left = gutterWidth + "px"; + size.scrollerWidth = Math.max(0, width - gutterWidth - this.scrollBarV.getWidth()); + + this.scrollBarH.element.style.right = + this.scroller.style.right = this.scrollBarV.getWidth() + "px"; + this.scroller.style.bottom = this.scrollBarH.getHeight() + "px"; + + if (this.session && this.session.getUseWrapMode() && this.adjustWrapLimit() || force) + changes |= this.CHANGE_FULL; + } + + size.$dirty = !width || !height; + + if (changes) + this._signal("resize", oldSize); + + return changes; + }; + + this.onGutterResize = function() { + var gutterWidth = this.$showGutter ? this.$gutter.offsetWidth : 0; + if (gutterWidth != this.gutterWidth) + this.$changes |= this.$updateCachedSize(true, gutterWidth, this.$size.width, this.$size.height); + + if (this.session.getUseWrapMode() && this.adjustWrapLimit()) { + this.$loop.schedule(this.CHANGE_FULL); + } else if (this.$size.$dirty) { + this.$loop.schedule(this.CHANGE_FULL); + } else { + this.$computeLayerConfig(); + this.$loop.schedule(this.CHANGE_MARKER); + } + }; + this.adjustWrapLimit = function() { + var availableWidth = this.$size.scrollerWidth - this.$padding * 2; + var limit = Math.floor(availableWidth / this.characterWidth); + return this.session.adjustWrapLimit(limit, this.$showPrintMargin && this.$printMarginColumn); + }; + this.setAnimatedScroll = function(shouldAnimate){ + this.setOption("animatedScroll", shouldAnimate); + }; + this.getAnimatedScroll = function() { + return this.$animatedScroll; + }; + this.setShowInvisibles = function(showInvisibles) { + this.setOption("showInvisibles", showInvisibles); + }; + this.getShowInvisibles = function() { + return this.getOption("showInvisibles"); + }; + this.getDisplayIndentGuides = function() { + return this.getOption("displayIndentGuides"); + }; + + this.setDisplayIndentGuides = function(display) { + this.setOption("displayIndentGuides", display); + }; + this.setShowPrintMargin = function(showPrintMargin) { + this.setOption("showPrintMargin", showPrintMargin); + }; + this.getShowPrintMargin = function() { + return this.getOption("showPrintMargin"); + }; + this.setPrintMarginColumn = function(showPrintMargin) { + this.setOption("printMarginColumn", showPrintMargin); + }; + this.getPrintMarginColumn = function() { + return this.getOption("printMarginColumn"); + }; + this.getShowGutter = function(){ + return this.getOption("showGutter"); + }; + this.setShowGutter = function(show){ + return this.setOption("showGutter", show); + }; + + this.getFadeFoldWidgets = function(){ + return this.getOption("fadeFoldWidgets") + }; + + this.setFadeFoldWidgets = function(show) { + this.setOption("fadeFoldWidgets", show); + }; + + this.setHighlightGutterLine = function(shouldHighlight) { + this.setOption("highlightGutterLine", shouldHighlight); + }; + + this.getHighlightGutterLine = function() { + return this.getOption("highlightGutterLine"); + }; + + this.$updateGutterLineHighlight = function() { + var pos = this.$cursorLayer.$pixelPos; + var height = this.layerConfig.lineHeight; + if (this.session.getUseWrapMode()) { + var cursor = this.session.selection.getCursor(); + cursor.column = 0; + pos = this.$cursorLayer.getPixelPosition(cursor, true); + height *= this.session.getRowLength(cursor.row); + } + this.$gutterLineHighlight.style.top = pos.top - this.layerConfig.offset + "px"; + this.$gutterLineHighlight.style.height = height + "px"; + }; + + this.$updatePrintMargin = function() { + if (!this.$showPrintMargin && !this.$printMarginEl) + return; + + if (!this.$printMarginEl) { + var containerEl = dom.createElement("div"); + containerEl.className = "ace_layer ace_print-margin-layer"; + this.$printMarginEl = dom.createElement("div"); + this.$printMarginEl.className = "ace_print-margin"; + containerEl.appendChild(this.$printMarginEl); + this.content.insertBefore(containerEl, this.content.firstChild); + } + + var style = this.$printMarginEl.style; + style.left = ((this.characterWidth * this.$printMarginColumn) + this.$padding) + "px"; + style.visibility = this.$showPrintMargin ? "visible" : "hidden"; + + if (this.session && this.session.$wrap == -1) + this.adjustWrapLimit(); + }; + this.getContainerElement = function() { + return this.container; + }; + this.getMouseEventTarget = function() { + return this.scroller; + }; + this.getTextAreaContainer = function() { + return this.container; + }; + this.$moveTextAreaToCursor = function() { + if (!this.$keepTextAreaAtCursor) + return; + var config = this.layerConfig; + var posTop = this.$cursorLayer.$pixelPos.top; + var posLeft = this.$cursorLayer.$pixelPos.left; + posTop -= config.offset; + + var style = this.textarea.style; + var h = this.lineHeight; + if (posTop < 0 || posTop > config.height - h) { + style.top = style.left = "0"; + return; + } + + var w = this.characterWidth; + if (this.$composition) { + var val = this.textarea.value.replace(/^\x01+/, ""); + w *= (this.session.$getStringScreenWidth(val)[0]+2); + h += 2; + } + posLeft -= this.scrollLeft; + if (posLeft > this.$size.scrollerWidth - w) + posLeft = this.$size.scrollerWidth - w; + + posLeft += this.gutterWidth; + style.height = h + "px"; + style.width = w + "px"; + style.left = Math.min(posLeft, this.$size.scrollerWidth - w) + "px"; + style.top = Math.min(posTop, this.$size.height - h) + "px"; + }; + this.getFirstVisibleRow = function() { + return this.layerConfig.firstRow; + }; + this.getFirstFullyVisibleRow = function() { + return this.layerConfig.firstRow + (this.layerConfig.offset === 0 ? 0 : 1); + }; + this.getLastFullyVisibleRow = function() { + var config = this.layerConfig; + var lastRow = config.lastRow + var top = this.session.documentToScreenRow(lastRow, 0) * config.lineHeight; + if (top - this.session.getScrollTop() > config.height - config.lineHeight) + return lastRow - 1; + return lastRow; + }; + this.getLastVisibleRow = function() { + return this.layerConfig.lastRow; + }; + + this.$padding = null; + this.setPadding = function(padding) { + this.$padding = padding; + this.$textLayer.setPadding(padding); + this.$cursorLayer.setPadding(padding); + this.$markerFront.setPadding(padding); + this.$markerBack.setPadding(padding); + this.$loop.schedule(this.CHANGE_FULL); + this.$updatePrintMargin(); + }; + + this.setScrollMargin = function(top, bottom, left, right) { + var sm = this.scrollMargin; + sm.top = top|0; + sm.bottom = bottom|0; + sm.right = right|0; + sm.left = left|0; + sm.v = sm.top + sm.bottom; + sm.h = sm.left + sm.right; + if (sm.top && this.scrollTop <= 0 && this.session) + this.session.setScrollTop(-sm.top); + this.updateFull(); + }; + this.getHScrollBarAlwaysVisible = function() { + return this.$hScrollBarAlwaysVisible; + }; + this.setHScrollBarAlwaysVisible = function(alwaysVisible) { + this.setOption("hScrollBarAlwaysVisible", alwaysVisible); + }; + this.getVScrollBarAlwaysVisible = function() { + return this.$vScrollBarAlwaysVisible; + }; + this.setVScrollBarAlwaysVisible = function(alwaysVisible) { + this.setOption("vScrollBarAlwaysVisible", alwaysVisible); + }; + + this.$updateScrollBarV = function() { + var scrollHeight = this.layerConfig.maxHeight; + var scrollerHeight = this.$size.scrollerHeight; + if (!this.$maxLines && this.$scrollPastEnd) { + scrollHeight -= (scrollerHeight - this.lineHeight) * this.$scrollPastEnd; + if (this.scrollTop > scrollHeight - scrollerHeight) { + scrollHeight = this.scrollTop + scrollerHeight; + this.scrollBarV.scrollTop = null; + } + } + this.scrollBarV.setScrollHeight(scrollHeight + this.scrollMargin.v); + this.scrollBarV.setScrollTop(this.scrollTop + this.scrollMargin.top); + }; + this.$updateScrollBarH = function() { + this.scrollBarH.setScrollWidth(this.layerConfig.width + 2 * this.$padding + this.scrollMargin.h); + this.scrollBarH.setScrollLeft(this.scrollLeft + this.scrollMargin.left); + }; + + this.$frozen = false; + this.freeze = function() { + this.$frozen = true; + }; + + this.unfreeze = function() { + this.$frozen = false; + }; + + this.$renderChanges = function(changes, force) { + if (this.$changes) { + changes |= this.$changes; + this.$changes = 0; + } + if ((!this.session || !this.container.offsetWidth || this.$frozen) || (!changes && !force)) { + this.$changes |= changes; + return; + } + if (this.$size.$dirty) { + this.$changes |= changes; + return this.onResize(true); + } + if (!this.lineHeight) { + this.$textLayer.checkForSizeChanges(); + } + + this._signal("beforeRender"); + var config = this.layerConfig; + if (changes & this.CHANGE_FULL || + changes & this.CHANGE_SIZE || + changes & this.CHANGE_TEXT || + changes & this.CHANGE_LINES || + changes & this.CHANGE_SCROLL || + changes & this.CHANGE_H_SCROLL + ) { + changes |= this.$computeLayerConfig(); + if (config.firstRow != this.layerConfig.firstRow && config.firstRowScreen == this.layerConfig.firstRowScreen) { + var st = this.scrollTop + (config.firstRow - this.layerConfig.firstRow) * this.lineHeight; + if (st > 0) { + this.scrollTop = st; + changes = changes | this.CHANGE_SCROLL; + changes |= this.$computeLayerConfig(); + } + } + config = this.layerConfig; + this.$updateScrollBarV(); + if (changes & this.CHANGE_H_SCROLL) + this.$updateScrollBarH(); + this.$gutterLayer.element.style.marginTop = (-config.offset) + "px"; + this.content.style.marginTop = (-config.offset) + "px"; + this.content.style.width = config.width + 2 * this.$padding + "px"; + this.content.style.height = config.minHeight + "px"; + } + if (changes & this.CHANGE_H_SCROLL) { + this.content.style.marginLeft = -this.scrollLeft + "px"; + this.scroller.className = this.scrollLeft <= 0 ? "ace_scroller" : "ace_scroller ace_scroll-left"; + } + if (changes & this.CHANGE_FULL) { + this.$textLayer.update(config); + if (this.$showGutter) + this.$gutterLayer.update(config); + this.$markerBack.update(config); + this.$markerFront.update(config); + this.$cursorLayer.update(config); + this.$moveTextAreaToCursor(); + this.$highlightGutterLine && this.$updateGutterLineHighlight(); + this._signal("afterRender"); + return; + } + if (changes & this.CHANGE_SCROLL) { + if (changes & this.CHANGE_TEXT || changes & this.CHANGE_LINES) + this.$textLayer.update(config); + else + this.$textLayer.scrollLines(config); + + if (this.$showGutter) + this.$gutterLayer.update(config); + this.$markerBack.update(config); + this.$markerFront.update(config); + this.$cursorLayer.update(config); + this.$highlightGutterLine && this.$updateGutterLineHighlight(); + this.$moveTextAreaToCursor(); + this._signal("afterRender"); + return; + } + + if (changes & this.CHANGE_TEXT) { + this.$textLayer.update(config); + if (this.$showGutter) + this.$gutterLayer.update(config); + } + else if (changes & this.CHANGE_LINES) { + if (this.$updateLines() || (changes & this.CHANGE_GUTTER) && this.$showGutter) + this.$gutterLayer.update(config); + } + else if (changes & this.CHANGE_TEXT || changes & this.CHANGE_GUTTER) { + if (this.$showGutter) + this.$gutterLayer.update(config); + } + + if (changes & this.CHANGE_CURSOR) { + this.$cursorLayer.update(config); + this.$moveTextAreaToCursor(); + this.$highlightGutterLine && this.$updateGutterLineHighlight(); + } + + if (changes & (this.CHANGE_MARKER | this.CHANGE_MARKER_FRONT)) { + this.$markerFront.update(config); + } + + if (changes & (this.CHANGE_MARKER | this.CHANGE_MARKER_BACK)) { + this.$markerBack.update(config); + } + + this._signal("afterRender"); + }; + + + this.$autosize = function() { + var height = this.session.getScreenLength() * this.lineHeight; + var maxHeight = this.$maxLines * this.lineHeight; + var desiredHeight = Math.max( + (this.$minLines||1) * this.lineHeight, + Math.min(maxHeight, height) + ) + this.scrollMargin.v + (this.$extraHeight || 0); + if (this.$horizScroll) + desiredHeight += this.scrollBarH.getHeight(); + var vScroll = height > maxHeight; + + if (desiredHeight != this.desiredHeight || + this.$size.height != this.desiredHeight || vScroll != this.$vScroll) { + if (vScroll != this.$vScroll) { + this.$vScroll = vScroll; + this.scrollBarV.setVisible(vScroll); + } + + var w = this.container.clientWidth; + this.container.style.height = desiredHeight + "px"; + this.$updateCachedSize(true, this.$gutterWidth, w, desiredHeight); + this.desiredHeight = desiredHeight; + + this._signal("autosize"); + } + }; + + this.$computeLayerConfig = function() { + var session = this.session; + var size = this.$size; + + var hideScrollbars = size.height <= 2 * this.lineHeight; + var screenLines = this.session.getScreenLength(); + var maxHeight = screenLines * this.lineHeight; + + var longestLine = this.$getLongestLine(); + + var horizScroll = !hideScrollbars && (this.$hScrollBarAlwaysVisible || + size.scrollerWidth - longestLine - 2 * this.$padding < 0); + + var hScrollChanged = this.$horizScroll !== horizScroll; + if (hScrollChanged) { + this.$horizScroll = horizScroll; + this.scrollBarH.setVisible(horizScroll); + } + var vScrollBefore = this.$vScroll; // autosize can change vscroll value in which case we need to update longestLine + if (this.$maxLines && this.lineHeight > 1) + this.$autosize(); + + var offset = this.scrollTop % this.lineHeight; + var minHeight = size.scrollerHeight + this.lineHeight; + + var scrollPastEnd = !this.$maxLines && this.$scrollPastEnd + ? (size.scrollerHeight - this.lineHeight) * this.$scrollPastEnd + : 0; + maxHeight += scrollPastEnd; + + var sm = this.scrollMargin; + this.session.setScrollTop(Math.max(-sm.top, + Math.min(this.scrollTop, maxHeight - size.scrollerHeight + sm.bottom))); + + this.session.setScrollLeft(Math.max(-sm.left, Math.min(this.scrollLeft, + longestLine + 2 * this.$padding - size.scrollerWidth + sm.right))); + + var vScroll = !hideScrollbars && (this.$vScrollBarAlwaysVisible || + size.scrollerHeight - maxHeight + scrollPastEnd < 0 || this.scrollTop > sm.top); + var vScrollChanged = vScrollBefore !== vScroll; + if (vScrollChanged) { + this.$vScroll = vScroll; + this.scrollBarV.setVisible(vScroll); + } + + var lineCount = Math.ceil(minHeight / this.lineHeight) - 1; + var firstRow = Math.max(0, Math.round((this.scrollTop - offset) / this.lineHeight)); + var lastRow = firstRow + lineCount; + var firstRowScreen, firstRowHeight; + var lineHeight = this.lineHeight; + firstRow = session.screenToDocumentRow(firstRow, 0); + var foldLine = session.getFoldLine(firstRow); + if (foldLine) { + firstRow = foldLine.start.row; + } + + firstRowScreen = session.documentToScreenRow(firstRow, 0); + firstRowHeight = session.getRowLength(firstRow) * lineHeight; + + lastRow = Math.min(session.screenToDocumentRow(lastRow, 0), session.getLength() - 1); + minHeight = size.scrollerHeight + session.getRowLength(lastRow) * lineHeight + + firstRowHeight; + + offset = this.scrollTop - firstRowScreen * lineHeight; + + var changes = 0; + if (this.layerConfig.width != longestLine) + changes = this.CHANGE_H_SCROLL; + if (hScrollChanged || vScrollChanged) { + changes = this.$updateCachedSize(true, this.gutterWidth, size.width, size.height); + this._signal("scrollbarVisibilityChanged"); + if (vScrollChanged) + longestLine = this.$getLongestLine(); + } + + this.layerConfig = { + width : longestLine, + padding : this.$padding, + firstRow : firstRow, + firstRowScreen: firstRowScreen, + lastRow : lastRow, + lineHeight : lineHeight, + characterWidth : this.characterWidth, + minHeight : minHeight, + maxHeight : maxHeight, + offset : offset, + gutterOffset : Math.max(0, Math.ceil((offset + size.height - size.scrollerHeight) / lineHeight)), + height : this.$size.scrollerHeight + }; + + return changes; + }; + + this.$updateLines = function() { + var firstRow = this.$changedLines.firstRow; + var lastRow = this.$changedLines.lastRow; + this.$changedLines = null; + + var layerConfig = this.layerConfig; + + if (firstRow > layerConfig.lastRow + 1) { return; } + if (lastRow < layerConfig.firstRow) { return; } + if (lastRow === Infinity) { + if (this.$showGutter) + this.$gutterLayer.update(layerConfig); + this.$textLayer.update(layerConfig); + return; + } + this.$textLayer.updateLines(layerConfig, firstRow, lastRow); + return true; + }; + + this.$getLongestLine = function() { + var charCount = this.session.getScreenWidth(); + if (this.showInvisibles && !this.session.$useWrapMode) + charCount += 1; + + return Math.max(this.$size.scrollerWidth - 2 * this.$padding, Math.round(charCount * this.characterWidth)); + }; + this.updateFrontMarkers = function() { + this.$markerFront.setMarkers(this.session.getMarkers(true)); + this.$loop.schedule(this.CHANGE_MARKER_FRONT); + }; + this.updateBackMarkers = function() { + this.$markerBack.setMarkers(this.session.getMarkers()); + this.$loop.schedule(this.CHANGE_MARKER_BACK); + }; + this.addGutterDecoration = function(row, className){ + this.$gutterLayer.addGutterDecoration(row, className); + }; + this.removeGutterDecoration = function(row, className){ + this.$gutterLayer.removeGutterDecoration(row, className); + }; + this.updateBreakpoints = function(rows) { + this.$loop.schedule(this.CHANGE_GUTTER); + }; + this.setAnnotations = function(annotations) { + this.$gutterLayer.setAnnotations(annotations); + this.$loop.schedule(this.CHANGE_GUTTER); + }; + this.updateCursor = function() { + this.$loop.schedule(this.CHANGE_CURSOR); + }; + this.hideCursor = function() { + this.$cursorLayer.hideCursor(); + }; + this.showCursor = function() { + this.$cursorLayer.showCursor(); + }; + + this.scrollSelectionIntoView = function(anchor, lead, offset) { + this.scrollCursorIntoView(anchor, offset); + this.scrollCursorIntoView(lead, offset); + }; + this.scrollCursorIntoView = function(cursor, offset, $viewMargin) { + if (this.$size.scrollerHeight === 0) + return; + + var pos = this.$cursorLayer.getPixelPosition(cursor); + + var left = pos.left; + var top = pos.top; + + var topMargin = $viewMargin && $viewMargin.top || 0; + var bottomMargin = $viewMargin && $viewMargin.bottom || 0; + + var scrollTop = this.$scrollAnimation ? this.session.getScrollTop() : this.scrollTop; + + if (scrollTop + topMargin > top) { + if (offset && scrollTop + topMargin > top + this.lineHeight) + top -= offset * this.$size.scrollerHeight; + if (top === 0) + top = -this.scrollMargin.top; + this.session.setScrollTop(top); + } else if (scrollTop + this.$size.scrollerHeight - bottomMargin < top + this.lineHeight) { + if (offset && scrollTop + this.$size.scrollerHeight - bottomMargin < top - this.lineHeight) + top += offset * this.$size.scrollerHeight; + this.session.setScrollTop(top + this.lineHeight - this.$size.scrollerHeight); + } + + var scrollLeft = this.scrollLeft; + + if (scrollLeft > left) { + if (left < this.$padding + 2 * this.layerConfig.characterWidth) + left = -this.scrollMargin.left; + this.session.setScrollLeft(left); + } else if (scrollLeft + this.$size.scrollerWidth < left + this.characterWidth) { + this.session.setScrollLeft(Math.round(left + this.characterWidth - this.$size.scrollerWidth)); + } else if (scrollLeft <= this.$padding && left - scrollLeft < this.characterWidth) { + this.session.setScrollLeft(0); + } + }; + this.getScrollTop = function() { + return this.session.getScrollTop(); + }; + this.getScrollLeft = function() { + return this.session.getScrollLeft(); + }; + this.getScrollTopRow = function() { + return this.scrollTop / this.lineHeight; + }; + this.getScrollBottomRow = function() { + return Math.max(0, Math.floor((this.scrollTop + this.$size.scrollerHeight) / this.lineHeight) - 1); + }; + this.scrollToRow = function(row) { + this.session.setScrollTop(row * this.lineHeight); + }; + + this.alignCursor = function(cursor, alignment) { + if (typeof cursor == "number") + cursor = {row: cursor, column: 0}; + + var pos = this.$cursorLayer.getPixelPosition(cursor); + var h = this.$size.scrollerHeight - this.lineHeight; + var offset = pos.top - h * (alignment || 0); + + this.session.setScrollTop(offset); + return offset; + }; + + this.STEPS = 8; + this.$calcSteps = function(fromValue, toValue){ + var i = 0; + var l = this.STEPS; + var steps = []; + + var func = function(t, x_min, dx) { + return dx * (Math.pow(t - 1, 3) + 1) + x_min; + }; + + for (i = 0; i < l; ++i) + steps.push(func(i / this.STEPS, fromValue, toValue - fromValue)); + + return steps; + }; + this.scrollToLine = function(line, center, animate, callback) { + var pos = this.$cursorLayer.getPixelPosition({row: line, column: 0}); + var offset = pos.top; + if (center) + offset -= this.$size.scrollerHeight / 2; + + var initialScroll = this.scrollTop; + this.session.setScrollTop(offset); + if (animate !== false) + this.animateScrolling(initialScroll, callback); + }; + + this.animateScrolling = function(fromValue, callback) { + var toValue = this.scrollTop; + if (!this.$animatedScroll) + return; + var _self = this; + + if (fromValue == toValue) + return; + + if (this.$scrollAnimation) { + var oldSteps = this.$scrollAnimation.steps; + if (oldSteps.length) { + fromValue = oldSteps[0]; + if (fromValue == toValue) + return; + } + } + + var steps = _self.$calcSteps(fromValue, toValue); + this.$scrollAnimation = {from: fromValue, to: toValue, steps: steps}; + + clearInterval(this.$timer); + + _self.session.setScrollTop(steps.shift()); + _self.session.$scrollTop = toValue; + this.$timer = setInterval(function() { + if (steps.length) { + _self.session.setScrollTop(steps.shift()); + _self.session.$scrollTop = toValue; + } else if (toValue != null) { + _self.session.$scrollTop = -1; + _self.session.setScrollTop(toValue); + toValue = null; + } else { + _self.$timer = clearInterval(_self.$timer); + _self.$scrollAnimation = null; + callback && callback(); + } + }, 10); + }; + this.scrollToY = function(scrollTop) { + if (this.scrollTop !== scrollTop) { + this.$loop.schedule(this.CHANGE_SCROLL); + this.scrollTop = scrollTop; + } + }; + this.scrollToX = function(scrollLeft) { + if (this.scrollLeft !== scrollLeft) + this.scrollLeft = scrollLeft; + this.$loop.schedule(this.CHANGE_H_SCROLL); + }; + this.scrollTo = function(x, y) { + this.session.setScrollTop(y); + this.session.setScrollLeft(y); + }; + this.scrollBy = function(deltaX, deltaY) { + deltaY && this.session.setScrollTop(this.session.getScrollTop() + deltaY); + deltaX && this.session.setScrollLeft(this.session.getScrollLeft() + deltaX); + }; + this.isScrollableBy = function(deltaX, deltaY) { + if (deltaY < 0 && this.session.getScrollTop() >= 1 - this.scrollMargin.top) + return true; + if (deltaY > 0 && this.session.getScrollTop() + this.$size.scrollerHeight + - this.layerConfig.maxHeight < -1 + this.scrollMargin.bottom) + return true; + if (deltaX < 0 && this.session.getScrollLeft() >= 1 - this.scrollMargin.left) + return true; + if (deltaX > 0 && this.session.getScrollLeft() + this.$size.scrollerWidth + - this.layerConfig.width < -1 + this.scrollMargin.right) + return true; + }; + + this.pixelToScreenCoordinates = function(x, y) { + var canvasPos = this.scroller.getBoundingClientRect(); + + var offset = (x + this.scrollLeft - canvasPos.left - this.$padding) / this.characterWidth; + var row = Math.floor((y + this.scrollTop - canvasPos.top) / this.lineHeight); + var col = Math.round(offset); + + return {row: row, column: col, side: offset - col > 0 ? 1 : -1}; + }; + + this.screenToTextCoordinates = function(x, y) { + var canvasPos = this.scroller.getBoundingClientRect(); + + var col = Math.round( + (x + this.scrollLeft - canvasPos.left - this.$padding) / this.characterWidth + ); + + var row = (y + this.scrollTop - canvasPos.top) / this.lineHeight; + + return this.session.screenToDocumentPosition(row, Math.max(col, 0)); + }; + this.textToScreenCoordinates = function(row, column) { + var canvasPos = this.scroller.getBoundingClientRect(); + var pos = this.session.documentToScreenPosition(row, column); + + var x = this.$padding + Math.round(pos.column * this.characterWidth); + var y = pos.row * this.lineHeight; + + return { + pageX: canvasPos.left + x - this.scrollLeft, + pageY: canvasPos.top + y - this.scrollTop + }; + }; + this.visualizeFocus = function() { + dom.addCssClass(this.container, "ace_focus"); + }; + this.visualizeBlur = function() { + dom.removeCssClass(this.container, "ace_focus"); + }; + this.showComposition = function(position) { + if (!this.$composition) + this.$composition = { + keepTextAreaAtCursor: this.$keepTextAreaAtCursor, + cssText: this.textarea.style.cssText + }; + + this.$keepTextAreaAtCursor = true; + dom.addCssClass(this.textarea, "ace_composition"); + this.textarea.style.cssText = ""; + this.$moveTextAreaToCursor(); + }; + this.setCompositionText = function(text) { + this.$moveTextAreaToCursor(); + }; + this.hideComposition = function() { + if (!this.$composition) + return; + + dom.removeCssClass(this.textarea, "ace_composition"); + this.$keepTextAreaAtCursor = this.$composition.keepTextAreaAtCursor; + this.textarea.style.cssText = this.$composition.cssText; + this.$composition = null; + }; + this.setTheme = function(theme, cb) { + var _self = this; + this.$themeId = theme; + _self._dispatchEvent('themeChange',{theme:theme}); + + if (!theme || typeof theme == "string") { + var moduleName = theme || this.$options.theme.initialValue; + config.loadModule(["theme", moduleName], afterLoad); + } else { + afterLoad(theme); + } + + function afterLoad(module) { + if (_self.$themeId != theme) + return cb && cb(); + if (!module.cssClass) + return; + dom.importCssString( + module.cssText, + module.cssClass, + _self.container.ownerDocument + ); + + if (_self.theme) + dom.removeCssClass(_self.container, _self.theme.cssClass); + + var padding = "padding" in module ? module.padding + : "padding" in (_self.theme || {}) ? 4 : _self.$padding; + if (_self.$padding && padding != _self.$padding) + _self.setPadding(padding); + _self.$theme = module.cssClass; + + _self.theme = module; + dom.addCssClass(_self.container, module.cssClass); + dom.setCssClass(_self.container, "ace_dark", module.isDark); + if (_self.$size) { + _self.$size.width = 0; + _self.$updateSizeAsync(); + } + + _self._dispatchEvent('themeLoaded', {theme:module}); + cb && cb(); + } + }; + this.getTheme = function() { + return this.$themeId; + }; + this.setStyle = function(style, include) { + dom.setCssClass(this.container, style, include !== false); + }; + this.unsetStyle = function(style) { + dom.removeCssClass(this.container, style); + }; + + this.setCursorStyle = function(style) { + if (this.scroller.style.cursor != style) + this.scroller.style.cursor = style; + }; + this.setMouseCursor = function(cursorStyle) { + this.scroller.style.cursor = cursorStyle; + }; + this.destroy = function() { + this.$textLayer.destroy(); + this.$cursorLayer.destroy(); + }; + + }).call(VirtualRenderer.prototype); + + + config.defineOptions(VirtualRenderer.prototype, "renderer", { + animatedScroll: {initialValue: false}, + showInvisibles: { + set: function(value) { + if (this.$textLayer.setShowInvisibles(value)) + this.$loop.schedule(this.CHANGE_TEXT); + }, + initialValue: false + }, + showPrintMargin: { + set: function() { this.$updatePrintMargin(); }, + initialValue: true + }, + printMarginColumn: { + set: function() { this.$updatePrintMargin(); }, + initialValue: 80 + }, + printMargin: { + set: function(val) { + if (typeof val == "number") + this.$printMarginColumn = val; + this.$showPrintMargin = !!val; + this.$updatePrintMargin(); + }, + get: function() { + return this.$showPrintMargin && this.$printMarginColumn; + } + }, + showGutter: { + set: function(show){ + this.$gutter.style.display = show ? "block" : "none"; + this.$loop.schedule(this.CHANGE_FULL); + this.onGutterResize(); + }, + initialValue: true + }, + fadeFoldWidgets: { + set: function(show) { + dom.setCssClass(this.$gutter, "ace_fade-fold-widgets", show); + }, + initialValue: false + }, + showFoldWidgets: { + set: function(show) {this.$gutterLayer.setShowFoldWidgets(show)}, + initialValue: true + }, + showLineNumbers: { + set: function(show) { + this.$gutterLayer.setShowLineNumbers(show); + this.$loop.schedule(this.CHANGE_GUTTER); + }, + initialValue: true + }, + displayIndentGuides: { + set: function(show) { + if (this.$textLayer.setDisplayIndentGuides(show)) + this.$loop.schedule(this.CHANGE_TEXT); + }, + initialValue: true + }, + highlightGutterLine: { + set: function(shouldHighlight) { + if (!this.$gutterLineHighlight) { + this.$gutterLineHighlight = dom.createElement("div"); + this.$gutterLineHighlight.className = "ace_gutter-active-line"; + this.$gutter.appendChild(this.$gutterLineHighlight); + return; + } + + this.$gutterLineHighlight.style.display = shouldHighlight ? "" : "none"; + if (this.$cursorLayer.$pixelPos) + this.$updateGutterLineHighlight(); + }, + initialValue: false, + value: true + }, + hScrollBarAlwaysVisible: { + set: function(val) { + if (!this.$hScrollBarAlwaysVisible || !this.$horizScroll) + this.$loop.schedule(this.CHANGE_SCROLL); + }, + initialValue: false + }, + vScrollBarAlwaysVisible: { + set: function(val) { + if (!this.$vScrollBarAlwaysVisible || !this.$vScroll) + this.$loop.schedule(this.CHANGE_SCROLL); + }, + initialValue: false + }, + fontSize: { + set: function(size) { + if (typeof size == "number") + size = size + "px"; + this.container.style.fontSize = size; + this.updateFontSize(); + }, + initialValue: 12 + }, + fontFamily: { + set: function(name) { + this.container.style.fontFamily = name; + this.updateFontSize(); + } + }, + maxLines: { + set: function(val) { + this.updateFull(); + } + }, + minLines: { + set: function(val) { + this.updateFull(); + } + }, + scrollPastEnd: { + set: function(val) { + val = +val || 0; + if (this.$scrollPastEnd == val) + return; + this.$scrollPastEnd = val; + this.$loop.schedule(this.CHANGE_SCROLL); + }, + initialValue: 0, + handlesSet: true + }, + fixedWidthGutter: { + set: function(val) { + this.$gutterLayer.$fixedWidth = !!val; + this.$loop.schedule(this.CHANGE_GUTTER); + } + }, + theme: { + set: function(val) { this.setTheme(val) }, + get: function() { return this.$themeId || this.theme; }, + initialValue: "./theme/textmate", + handlesSet: true + } + }); + + exports.VirtualRenderer = VirtualRenderer; + }); + + ace.define("ace/worker/worker_client",["require","exports","module","ace/lib/oop","ace/lib/net","ace/lib/event_emitter","ace/config"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("../lib/oop"); + var net = acequire("../lib/net"); + var EventEmitter = acequire("../lib/event_emitter").EventEmitter; + var config = acequire("../config"); + + var WorkerClient = function(topLevelNamespaces, mod, classname, workerUrl) { + this.$sendDeltaQueue = this.$sendDeltaQueue.bind(this); + this.changeListener = this.changeListener.bind(this); + this.onMessage = this.onMessage.bind(this); + if (acequire.nameToUrl && !acequire.toUrl) + acequire.toUrl = acequire.nameToUrl; + + if (config.get("packaged") || !acequire.toUrl) { + workerUrl = workerUrl || config.moduleUrl(mod.id, "worker") + } else { + var normalizePath = this.$normalizePath; + workerUrl = workerUrl || normalizePath(acequire.toUrl("ace/worker/worker.js", null, "_")); + + var tlns = {}; + topLevelNamespaces.forEach(function(ns) { + tlns[ns] = normalizePath(acequire.toUrl(ns, null, "_").replace(/(\.js)?(\?.*)?$/, "")); + }); + } + + try { + var workerSrc = mod.src; + var Blob = __webpack_require__(66); + var blob = new Blob([ workerSrc ], { type: 'application/javascript' }); + var blobUrl = (window.URL || window.webkitURL).createObjectURL(blob); + + this.$worker = new Worker(blobUrl); + + } catch(e) { + if (e instanceof window.DOMException) { + var blob = this.$workerBlob(workerUrl); + var URL = window.URL || window.webkitURL; + var blobURL = URL.createObjectURL(blob); + + this.$worker = new Worker(blobURL); + URL.revokeObjectURL(blobURL); + } else { + throw e; + } + } + this.$worker.postMessage({ + init : true, + tlns : tlns, + module : mod.id, + classname : classname + }); + + this.callbackId = 1; + this.callbacks = {}; + + this.$worker.onmessage = this.onMessage; + }; + + (function(){ + + oop.implement(this, EventEmitter); + + this.onMessage = function(e) { + var msg = e.data; + switch(msg.type) { + case "event": + this._signal(msg.name, {data: msg.data}); + break; + case "call": + var callback = this.callbacks[msg.id]; + if (callback) { + callback(msg.data); + delete this.callbacks[msg.id]; + } + break; + case "error": + this.reportError(msg.data); + break; + case "log": + window.console && console.log && console.log.apply(console, msg.data); + break; + } + }; + + this.reportError = function(err) { + window.console && console.error && console.error(err); + }; + + this.$normalizePath = function(path) { + return net.qualifyURL(path); + }; + + this.terminate = function() { + this._signal("terminate", {}); + this.deltaQueue = null; + this.$worker.terminate(); + this.$worker = null; + if (this.$doc) + this.$doc.off("change", this.changeListener); + this.$doc = null; + }; + + this.send = function(cmd, args) { + this.$worker.postMessage({command: cmd, args: args}); + }; + + this.call = function(cmd, args, callback) { + if (callback) { + var id = this.callbackId++; + this.callbacks[id] = callback; + args.push(id); + } + this.send(cmd, args); + }; + + this.emit = function(event, data) { + try { + this.$worker.postMessage({event: event, data: {data: data.data}}); + } + catch(ex) { + console.error(ex.stack); + } + }; + + this.attachToDocument = function(doc) { + if(this.$doc) + this.terminate(); + + this.$doc = doc; + this.call("setValue", [doc.getValue()]); + doc.on("change", this.changeListener); + }; + + this.changeListener = function(delta) { + if (!this.deltaQueue) { + this.deltaQueue = []; + setTimeout(this.$sendDeltaQueue, 0); + } + if (delta.action == "insert") + this.deltaQueue.push(delta.start, delta.lines); + else + this.deltaQueue.push(delta.start, delta.end); + }; + + this.$sendDeltaQueue = function() { + var q = this.deltaQueue; + if (!q) return; + this.deltaQueue = null; + if (q.length > 50 && q.length > this.$doc.getLength() >> 1) { + this.call("setValue", [this.$doc.getValue()]); + } else + this.emit("change", {data: q}); + }; + + this.$workerBlob = function(workerUrl) { + var script = "importScripts('" + net.qualifyURL(workerUrl) + "');"; + try { + return new Blob([script], {"type": "application/javascript"}); + } catch (e) { // Backwards-compatibility + var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder; + var blobBuilder = new BlobBuilder(); + blobBuilder.append(script); + return blobBuilder.getBlob("application/javascript"); + } + }; + + }).call(WorkerClient.prototype); + + + var UIWorkerClient = function(topLevelNamespaces, mod, classname) { + this.$sendDeltaQueue = this.$sendDeltaQueue.bind(this); + this.changeListener = this.changeListener.bind(this); + this.callbackId = 1; + this.callbacks = {}; + this.messageBuffer = []; + + var main = null; + var emitSync = false; + var sender = Object.create(EventEmitter); + var _self = this; + + this.$worker = {}; + this.$worker.terminate = function() {}; + this.$worker.postMessage = function(e) { + _self.messageBuffer.push(e); + if (main) { + if (emitSync) + setTimeout(processNext); + else + processNext(); + } + }; + this.setEmitSync = function(val) { emitSync = val }; + + var processNext = function() { + var msg = _self.messageBuffer.shift(); + if (msg.command) + main[msg.command].apply(main, msg.args); + else if (msg.event) + sender._signal(msg.event, msg.data); + }; + + sender.postMessage = function(msg) { + _self.onMessage({data: msg}); + }; + sender.callback = function(data, callbackId) { + this.postMessage({type: "call", id: callbackId, data: data}); + }; + sender.emit = function(name, data) { + this.postMessage({type: "event", name: name, data: data}); + }; + + config.loadModule(["worker", mod], function(Main) { + main = new Main[classname](sender); + while (_self.messageBuffer.length) + processNext(); + }); + }; + + UIWorkerClient.prototype = WorkerClient.prototype; + + exports.UIWorkerClient = UIWorkerClient; + exports.WorkerClient = WorkerClient; + + }); + + ace.define("ace/placeholder",["require","exports","module","ace/range","ace/lib/event_emitter","ace/lib/oop"], function(acequire, exports, module) { + "use strict"; + + var Range = acequire("./range").Range; + var EventEmitter = acequire("./lib/event_emitter").EventEmitter; + var oop = acequire("./lib/oop"); + + var PlaceHolder = function(session, length, pos, others, mainClass, othersClass) { + var _self = this; + this.length = length; + this.session = session; + this.doc = session.getDocument(); + this.mainClass = mainClass; + this.othersClass = othersClass; + this.$onUpdate = this.onUpdate.bind(this); + this.doc.on("change", this.$onUpdate); + this.$others = others; + + this.$onCursorChange = function() { + setTimeout(function() { + _self.onCursorChange(); + }); + }; + + this.$pos = pos; + var undoStack = session.getUndoManager().$undoStack || session.getUndoManager().$undostack || {length: -1}; + this.$undoStackDepth = undoStack.length; + this.setup(); + + session.selection.on("changeCursor", this.$onCursorChange); + }; + + (function() { + + oop.implement(this, EventEmitter); + this.setup = function() { + var _self = this; + var doc = this.doc; + var session = this.session; + + this.selectionBefore = session.selection.toJSON(); + if (session.selection.inMultiSelectMode) + session.selection.toSingleRange(); + + this.pos = doc.createAnchor(this.$pos.row, this.$pos.column); + var pos = this.pos; + pos.$insertRight = true; + pos.detach(); + pos.markerId = session.addMarker(new Range(pos.row, pos.column, pos.row, pos.column + this.length), this.mainClass, null, false); + this.others = []; + this.$others.forEach(function(other) { + var anchor = doc.createAnchor(other.row, other.column); + anchor.$insertRight = true; + anchor.detach(); + _self.others.push(anchor); + }); + session.setUndoSelect(false); + }; + this.showOtherMarkers = function() { + if (this.othersActive) return; + var session = this.session; + var _self = this; + this.othersActive = true; + this.others.forEach(function(anchor) { + anchor.markerId = session.addMarker(new Range(anchor.row, anchor.column, anchor.row, anchor.column+_self.length), _self.othersClass, null, false); + }); + }; + this.hideOtherMarkers = function() { + if (!this.othersActive) return; + this.othersActive = false; + for (var i = 0; i < this.others.length; i++) { + this.session.removeMarker(this.others[i].markerId); + } + }; + this.onUpdate = function(delta) { + if (this.$updating) + return this.updateAnchors(delta); + + var range = delta; + if (range.start.row !== range.end.row) return; + if (range.start.row !== this.pos.row) return; + this.$updating = true; + var lengthDiff = delta.action === "insert" ? range.end.column - range.start.column : range.start.column - range.end.column; + var inMainRange = range.start.column >= this.pos.column && range.start.column <= this.pos.column + this.length + 1; + var distanceFromStart = range.start.column - this.pos.column; + + this.updateAnchors(delta); + + if (inMainRange) + this.length += lengthDiff; + + if (inMainRange && !this.session.$fromUndo) { + if (delta.action === 'insert') { + for (var i = this.others.length - 1; i >= 0; i--) { + var otherPos = this.others[i]; + var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart}; + this.doc.insertMergedLines(newPos, delta.lines); + } + } else if (delta.action === 'remove') { + for (var i = this.others.length - 1; i >= 0; i--) { + var otherPos = this.others[i]; + var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart}; + this.doc.remove(new Range(newPos.row, newPos.column, newPos.row, newPos.column - lengthDiff)); + } + } + } + + this.$updating = false; + this.updateMarkers(); + }; + + this.updateAnchors = function(delta) { + this.pos.onChange(delta); + for (var i = this.others.length; i--;) + this.others[i].onChange(delta); + this.updateMarkers(); + }; + + this.updateMarkers = function() { + if (this.$updating) + return; + var _self = this; + var session = this.session; + var updateMarker = function(pos, className) { + session.removeMarker(pos.markerId); + pos.markerId = session.addMarker(new Range(pos.row, pos.column, pos.row, pos.column+_self.length), className, null, false); + }; + updateMarker(this.pos, this.mainClass); + for (var i = this.others.length; i--;) + updateMarker(this.others[i], this.othersClass); + }; + + this.onCursorChange = function(event) { + if (this.$updating || !this.session) return; + var pos = this.session.selection.getCursor(); + if (pos.row === this.pos.row && pos.column >= this.pos.column && pos.column <= this.pos.column + this.length) { + this.showOtherMarkers(); + this._emit("cursorEnter", event); + } else { + this.hideOtherMarkers(); + this._emit("cursorLeave", event); + } + }; + this.detach = function() { + this.session.removeMarker(this.pos && this.pos.markerId); + this.hideOtherMarkers(); + this.doc.removeEventListener("change", this.$onUpdate); + this.session.selection.removeEventListener("changeCursor", this.$onCursorChange); + this.session.setUndoSelect(true); + this.session = null; + }; + this.cancel = function() { + if (this.$undoStackDepth === -1) + return; + var undoManager = this.session.getUndoManager(); + var undosRequired = (undoManager.$undoStack || undoManager.$undostack).length - this.$undoStackDepth; + for (var i = 0; i < undosRequired; i++) { + undoManager.undo(true); + } + if (this.selectionBefore) + this.session.selection.fromJSON(this.selectionBefore); + }; + }).call(PlaceHolder.prototype); + + + exports.PlaceHolder = PlaceHolder; + }); + + ace.define("ace/mouse/multi_select_handler",["require","exports","module","ace/lib/event","ace/lib/useragent"], function(acequire, exports, module) { + + var event = acequire("../lib/event"); + var useragent = acequire("../lib/useragent"); + function isSamePoint(p1, p2) { + return p1.row == p2.row && p1.column == p2.column; + } + + function onMouseDown(e) { + var ev = e.domEvent; + var alt = ev.altKey; + var shift = ev.shiftKey; + var ctrl = ev.ctrlKey; + var accel = e.getAccelKey(); + var button = e.getButton(); + + if (ctrl && useragent.isMac) + button = ev.button; + + if (e.editor.inMultiSelectMode && button == 2) { + e.editor.textInput.onContextMenu(e.domEvent); + return; + } + + if (!ctrl && !alt && !accel) { + if (button === 0 && e.editor.inMultiSelectMode) + e.editor.exitMultiSelectMode(); + return; + } + + if (button !== 0) + return; + + var editor = e.editor; + var selection = editor.selection; + var isMultiSelect = editor.inMultiSelectMode; + var pos = e.getDocumentPosition(); + var cursor = selection.getCursor(); + var inSelection = e.inSelection() || (selection.isEmpty() && isSamePoint(pos, cursor)); + + var mouseX = e.x, mouseY = e.y; + var onMouseSelection = function(e) { + mouseX = e.clientX; + mouseY = e.clientY; + }; + + var session = editor.session; + var screenAnchor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY); + var screenCursor = screenAnchor; + + var selectionMode; + if (editor.$mouseHandler.$enableJumpToDef) { + if (ctrl && alt || accel && alt) + selectionMode = shift ? "block" : "add"; + else if (alt && editor.$blockSelectEnabled) + selectionMode = "block"; + } else { + if (accel && !alt) { + selectionMode = "add"; + if (!isMultiSelect && shift) + return; + } else if (alt && editor.$blockSelectEnabled) { + selectionMode = "block"; + } + } + + if (selectionMode && useragent.isMac && ev.ctrlKey) { + editor.$mouseHandler.cancelContextMenu(); + } + + if (selectionMode == "add") { + if (!isMultiSelect && inSelection) + return; // dragging + + if (!isMultiSelect) { + var range = selection.toOrientedRange(); + editor.addSelectionMarker(range); + } + + var oldRange = selection.rangeList.rangeAtPoint(pos); + + + editor.$blockScrolling++; + editor.inVirtualSelectionMode = true; + + if (shift) { + oldRange = null; + range = selection.ranges[0] || range; + editor.removeSelectionMarker(range); + } + editor.once("mouseup", function() { + var tmpSel = selection.toOrientedRange(); + + if (oldRange && tmpSel.isEmpty() && isSamePoint(oldRange.cursor, tmpSel.cursor)) + selection.substractPoint(tmpSel.cursor); + else { + if (shift) { + selection.substractPoint(range.cursor); + } else if (range) { + editor.removeSelectionMarker(range); + selection.addRange(range); + } + selection.addRange(tmpSel); + } + editor.$blockScrolling--; + editor.inVirtualSelectionMode = false; + }); + + } else if (selectionMode == "block") { + e.stop(); + editor.inVirtualSelectionMode = true; + var initialRange; + var rectSel = []; + var blockSelect = function() { + var newCursor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY); + var cursor = session.screenToDocumentPosition(newCursor.row, newCursor.column); + + if (isSamePoint(screenCursor, newCursor) && isSamePoint(cursor, selection.lead)) + return; + screenCursor = newCursor; + + editor.$blockScrolling++; + editor.selection.moveToPosition(cursor); + editor.renderer.scrollCursorIntoView(); + + editor.removeSelectionMarkers(rectSel); + rectSel = selection.rectangularRangeBlock(screenCursor, screenAnchor); + if (editor.$mouseHandler.$clickSelection && rectSel.length == 1 && rectSel[0].isEmpty()) + rectSel[0] = editor.$mouseHandler.$clickSelection.clone(); + rectSel.forEach(editor.addSelectionMarker, editor); + editor.updateSelectionMarkers(); + editor.$blockScrolling--; + }; + editor.$blockScrolling++; + if (isMultiSelect && !accel) { + selection.toSingleRange(); + } else if (!isMultiSelect && accel) { + initialRange = selection.toOrientedRange(); + editor.addSelectionMarker(initialRange); + } + + if (shift) + screenAnchor = session.documentToScreenPosition(selection.lead); + else + selection.moveToPosition(pos); + editor.$blockScrolling--; + + screenCursor = {row: -1, column: -1}; + + var onMouseSelectionEnd = function(e) { + clearInterval(timerId); + editor.removeSelectionMarkers(rectSel); + if (!rectSel.length) + rectSel = [selection.toOrientedRange()]; + editor.$blockScrolling++; + if (initialRange) { + editor.removeSelectionMarker(initialRange); + selection.toSingleRange(initialRange); + } + for (var i = 0; i < rectSel.length; i++) + selection.addRange(rectSel[i]); + editor.inVirtualSelectionMode = false; + editor.$mouseHandler.$clickSelection = null; + editor.$blockScrolling--; + }; + + var onSelectionInterval = blockSelect; + + event.capture(editor.container, onMouseSelection, onMouseSelectionEnd); + var timerId = setInterval(function() {onSelectionInterval();}, 20); + + return e.preventDefault(); + } + } + + + exports.onMouseDown = onMouseDown; + + }); + + ace.define("ace/commands/multi_select_commands",["require","exports","module","ace/keyboard/hash_handler"], function(acequire, exports, module) { + exports.defaultCommands = [{ + name: "addCursorAbove", + exec: function(editor) { editor.selectMoreLines(-1); }, + bindKey: {win: "Ctrl-Alt-Up", mac: "Ctrl-Alt-Up"}, + scrollIntoView: "cursor", + readOnly: true + }, { + name: "addCursorBelow", + exec: function(editor) { editor.selectMoreLines(1); }, + bindKey: {win: "Ctrl-Alt-Down", mac: "Ctrl-Alt-Down"}, + scrollIntoView: "cursor", + readOnly: true + }, { + name: "addCursorAboveSkipCurrent", + exec: function(editor) { editor.selectMoreLines(-1, true); }, + bindKey: {win: "Ctrl-Alt-Shift-Up", mac: "Ctrl-Alt-Shift-Up"}, + scrollIntoView: "cursor", + readOnly: true + }, { + name: "addCursorBelowSkipCurrent", + exec: function(editor) { editor.selectMoreLines(1, true); }, + bindKey: {win: "Ctrl-Alt-Shift-Down", mac: "Ctrl-Alt-Shift-Down"}, + scrollIntoView: "cursor", + readOnly: true + }, { + name: "selectMoreBefore", + exec: function(editor) { editor.selectMore(-1); }, + bindKey: {win: "Ctrl-Alt-Left", mac: "Ctrl-Alt-Left"}, + scrollIntoView: "cursor", + readOnly: true + }, { + name: "selectMoreAfter", + exec: function(editor) { editor.selectMore(1); }, + bindKey: {win: "Ctrl-Alt-Right", mac: "Ctrl-Alt-Right"}, + scrollIntoView: "cursor", + readOnly: true + }, { + name: "selectNextBefore", + exec: function(editor) { editor.selectMore(-1, true); }, + bindKey: {win: "Ctrl-Alt-Shift-Left", mac: "Ctrl-Alt-Shift-Left"}, + scrollIntoView: "cursor", + readOnly: true + }, { + name: "selectNextAfter", + exec: function(editor) { editor.selectMore(1, true); }, + bindKey: {win: "Ctrl-Alt-Shift-Right", mac: "Ctrl-Alt-Shift-Right"}, + scrollIntoView: "cursor", + readOnly: true + }, { + name: "splitIntoLines", + exec: function(editor) { editor.multiSelect.splitIntoLines(); }, + bindKey: {win: "Ctrl-Alt-L", mac: "Ctrl-Alt-L"}, + readOnly: true + }, { + name: "alignCursors", + exec: function(editor) { editor.alignCursors(); }, + bindKey: {win: "Ctrl-Alt-A", mac: "Ctrl-Alt-A"}, + scrollIntoView: "cursor" + }, { + name: "findAll", + exec: function(editor) { editor.findAll(); }, + bindKey: {win: "Ctrl-Alt-K", mac: "Ctrl-Alt-G"}, + scrollIntoView: "cursor", + readOnly: true + }]; + exports.multiSelectCommands = [{ + name: "singleSelection", + bindKey: "esc", + exec: function(editor) { editor.exitMultiSelectMode(); }, + scrollIntoView: "cursor", + readOnly: true, + isAvailable: function(editor) {return editor && editor.inMultiSelectMode} + }]; + + var HashHandler = acequire("../keyboard/hash_handler").HashHandler; + exports.keyboardHandler = new HashHandler(exports.multiSelectCommands); + + }); + + ace.define("ace/multi_select",["require","exports","module","ace/range_list","ace/range","ace/selection","ace/mouse/multi_select_handler","ace/lib/event","ace/lib/lang","ace/commands/multi_select_commands","ace/search","ace/edit_session","ace/editor","ace/config"], function(acequire, exports, module) { + + var RangeList = acequire("./range_list").RangeList; + var Range = acequire("./range").Range; + var Selection = acequire("./selection").Selection; + var onMouseDown = acequire("./mouse/multi_select_handler").onMouseDown; + var event = acequire("./lib/event"); + var lang = acequire("./lib/lang"); + var commands = acequire("./commands/multi_select_commands"); + exports.commands = commands.defaultCommands.concat(commands.multiSelectCommands); + var Search = acequire("./search").Search; + var search = new Search(); + + function find(session, needle, dir) { + search.$options.wrap = true; + search.$options.needle = needle; + search.$options.backwards = dir == -1; + return search.find(session); + } + var EditSession = acequire("./edit_session").EditSession; + (function() { + this.getSelectionMarkers = function() { + return this.$selectionMarkers; + }; + }).call(EditSession.prototype); + (function() { + this.ranges = null; + this.rangeList = null; + this.addRange = function(range, $blockChangeEvents) { + if (!range) + return; + + if (!this.inMultiSelectMode && this.rangeCount === 0) { + var oldRange = this.toOrientedRange(); + this.rangeList.add(oldRange); + this.rangeList.add(range); + if (this.rangeList.ranges.length != 2) { + this.rangeList.removeAll(); + return $blockChangeEvents || this.fromOrientedRange(range); + } + this.rangeList.removeAll(); + this.rangeList.add(oldRange); + this.$onAddRange(oldRange); + } + + if (!range.cursor) + range.cursor = range.end; + + var removed = this.rangeList.add(range); + + this.$onAddRange(range); + + if (removed.length) + this.$onRemoveRange(removed); + + if (this.rangeCount > 1 && !this.inMultiSelectMode) { + this._signal("multiSelect"); + this.inMultiSelectMode = true; + this.session.$undoSelect = false; + this.rangeList.attach(this.session); + } + + return $blockChangeEvents || this.fromOrientedRange(range); + }; + + this.toSingleRange = function(range) { + range = range || this.ranges[0]; + var removed = this.rangeList.removeAll(); + if (removed.length) + this.$onRemoveRange(removed); + + range && this.fromOrientedRange(range); + }; + this.substractPoint = function(pos) { + var removed = this.rangeList.substractPoint(pos); + if (removed) { + this.$onRemoveRange(removed); + return removed[0]; + } + }; + this.mergeOverlappingRanges = function() { + var removed = this.rangeList.merge(); + if (removed.length) + this.$onRemoveRange(removed); + else if(this.ranges[0]) + this.fromOrientedRange(this.ranges[0]); + }; + + this.$onAddRange = function(range) { + this.rangeCount = this.rangeList.ranges.length; + this.ranges.unshift(range); + this._signal("addRange", {range: range}); + }; + + this.$onRemoveRange = function(removed) { + this.rangeCount = this.rangeList.ranges.length; + if (this.rangeCount == 1 && this.inMultiSelectMode) { + var lastRange = this.rangeList.ranges.pop(); + removed.push(lastRange); + this.rangeCount = 0; + } + + for (var i = removed.length; i--; ) { + var index = this.ranges.indexOf(removed[i]); + this.ranges.splice(index, 1); + } + + this._signal("removeRange", {ranges: removed}); + + if (this.rangeCount === 0 && this.inMultiSelectMode) { + this.inMultiSelectMode = false; + this._signal("singleSelect"); + this.session.$undoSelect = true; + this.rangeList.detach(this.session); + } + + lastRange = lastRange || this.ranges[0]; + if (lastRange && !lastRange.isEqual(this.getRange())) + this.fromOrientedRange(lastRange); + }; + this.$initRangeList = function() { + if (this.rangeList) + return; + + this.rangeList = new RangeList(); + this.ranges = []; + this.rangeCount = 0; + }; + this.getAllRanges = function() { + return this.rangeCount ? this.rangeList.ranges.concat() : [this.getRange()]; + }; + + this.splitIntoLines = function () { + if (this.rangeCount > 1) { + var ranges = this.rangeList.ranges; + var lastRange = ranges[ranges.length - 1]; + var range = Range.fromPoints(ranges[0].start, lastRange.end); + + this.toSingleRange(); + this.setSelectionRange(range, lastRange.cursor == lastRange.start); + } else { + var range = this.getRange(); + var isBackwards = this.isBackwards(); + var startRow = range.start.row; + var endRow = range.end.row; + if (startRow == endRow) { + if (isBackwards) + var start = range.end, end = range.start; + else + var start = range.start, end = range.end; + + this.addRange(Range.fromPoints(end, end)); + this.addRange(Range.fromPoints(start, start)); + return; + } + + var rectSel = []; + var r = this.getLineRange(startRow, true); + r.start.column = range.start.column; + rectSel.push(r); + + for (var i = startRow + 1; i < endRow; i++) + rectSel.push(this.getLineRange(i, true)); + + r = this.getLineRange(endRow, true); + r.end.column = range.end.column; + rectSel.push(r); + + rectSel.forEach(this.addRange, this); + } + }; + this.toggleBlockSelection = function () { + if (this.rangeCount > 1) { + var ranges = this.rangeList.ranges; + var lastRange = ranges[ranges.length - 1]; + var range = Range.fromPoints(ranges[0].start, lastRange.end); + + this.toSingleRange(); + this.setSelectionRange(range, lastRange.cursor == lastRange.start); + } else { + var cursor = this.session.documentToScreenPosition(this.selectionLead); + var anchor = this.session.documentToScreenPosition(this.selectionAnchor); + + var rectSel = this.rectangularRangeBlock(cursor, anchor); + rectSel.forEach(this.addRange, this); + } + }; + this.rectangularRangeBlock = function(screenCursor, screenAnchor, includeEmptyLines) { + var rectSel = []; + + var xBackwards = screenCursor.column < screenAnchor.column; + if (xBackwards) { + var startColumn = screenCursor.column; + var endColumn = screenAnchor.column; + } else { + var startColumn = screenAnchor.column; + var endColumn = screenCursor.column; + } + + var yBackwards = screenCursor.row < screenAnchor.row; + if (yBackwards) { + var startRow = screenCursor.row; + var endRow = screenAnchor.row; + } else { + var startRow = screenAnchor.row; + var endRow = screenCursor.row; + } + + if (startColumn < 0) + startColumn = 0; + if (startRow < 0) + startRow = 0; + + if (startRow == endRow) + includeEmptyLines = true; + + for (var row = startRow; row <= endRow; row++) { + var range = Range.fromPoints( + this.session.screenToDocumentPosition(row, startColumn), + this.session.screenToDocumentPosition(row, endColumn) + ); + if (range.isEmpty()) { + if (docEnd && isSamePoint(range.end, docEnd)) + break; + var docEnd = range.end; + } + range.cursor = xBackwards ? range.start : range.end; + rectSel.push(range); + } + + if (yBackwards) + rectSel.reverse(); + + if (!includeEmptyLines) { + var end = rectSel.length - 1; + while (rectSel[end].isEmpty() && end > 0) + end--; + if (end > 0) { + var start = 0; + while (rectSel[start].isEmpty()) + start++; + } + for (var i = end; i >= start; i--) { + if (rectSel[i].isEmpty()) + rectSel.splice(i, 1); + } + } + + return rectSel; + }; + }).call(Selection.prototype); + var Editor = acequire("./editor").Editor; + (function() { + this.updateSelectionMarkers = function() { + this.renderer.updateCursor(); + this.renderer.updateBackMarkers(); + }; + this.addSelectionMarker = function(orientedRange) { + if (!orientedRange.cursor) + orientedRange.cursor = orientedRange.end; + + var style = this.getSelectionStyle(); + orientedRange.marker = this.session.addMarker(orientedRange, "ace_selection", style); + + this.session.$selectionMarkers.push(orientedRange); + this.session.selectionMarkerCount = this.session.$selectionMarkers.length; + return orientedRange; + }; + this.removeSelectionMarker = function(range) { + if (!range.marker) + return; + this.session.removeMarker(range.marker); + var index = this.session.$selectionMarkers.indexOf(range); + if (index != -1) + this.session.$selectionMarkers.splice(index, 1); + this.session.selectionMarkerCount = this.session.$selectionMarkers.length; + }; + + this.removeSelectionMarkers = function(ranges) { + var markerList = this.session.$selectionMarkers; + for (var i = ranges.length; i--; ) { + var range = ranges[i]; + if (!range.marker) + continue; + this.session.removeMarker(range.marker); + var index = markerList.indexOf(range); + if (index != -1) + markerList.splice(index, 1); + } + this.session.selectionMarkerCount = markerList.length; + }; + + this.$onAddRange = function(e) { + this.addSelectionMarker(e.range); + this.renderer.updateCursor(); + this.renderer.updateBackMarkers(); + }; + + this.$onRemoveRange = function(e) { + this.removeSelectionMarkers(e.ranges); + this.renderer.updateCursor(); + this.renderer.updateBackMarkers(); + }; + + this.$onMultiSelect = function(e) { + if (this.inMultiSelectMode) + return; + this.inMultiSelectMode = true; + + this.setStyle("ace_multiselect"); + this.keyBinding.addKeyboardHandler(commands.keyboardHandler); + this.commands.setDefaultHandler("exec", this.$onMultiSelectExec); + + this.renderer.updateCursor(); + this.renderer.updateBackMarkers(); + }; + + this.$onSingleSelect = function(e) { + if (this.session.multiSelect.inVirtualMode) + return; + this.inMultiSelectMode = false; + + this.unsetStyle("ace_multiselect"); + this.keyBinding.removeKeyboardHandler(commands.keyboardHandler); + + this.commands.removeDefaultHandler("exec", this.$onMultiSelectExec); + this.renderer.updateCursor(); + this.renderer.updateBackMarkers(); + this._emit("changeSelection"); + }; + + this.$onMultiSelectExec = function(e) { + var command = e.command; + var editor = e.editor; + if (!editor.multiSelect) + return; + if (!command.multiSelectAction) { + var result = command.exec(editor, e.args || {}); + editor.multiSelect.addRange(editor.multiSelect.toOrientedRange()); + editor.multiSelect.mergeOverlappingRanges(); + } else if (command.multiSelectAction == "forEach") { + result = editor.forEachSelection(command, e.args); + } else if (command.multiSelectAction == "forEachLine") { + result = editor.forEachSelection(command, e.args, true); + } else if (command.multiSelectAction == "single") { + editor.exitMultiSelectMode(); + result = command.exec(editor, e.args || {}); + } else { + result = command.multiSelectAction(editor, e.args || {}); + } + return result; + }; + this.forEachSelection = function(cmd, args, options) { + if (this.inVirtualSelectionMode) + return; + var keepOrder = options && options.keepOrder; + var $byLines = options == true || options && options.$byLines + var session = this.session; + var selection = this.selection; + var rangeList = selection.rangeList; + var ranges = (keepOrder ? selection : rangeList).ranges; + var result; + + if (!ranges.length) + return cmd.exec ? cmd.exec(this, args || {}) : cmd(this, args || {}); + + var reg = selection._eventRegistry; + selection._eventRegistry = {}; + + var tmpSel = new Selection(session); + this.inVirtualSelectionMode = true; + for (var i = ranges.length; i--;) { + if ($byLines) { + while (i > 0 && ranges[i].start.row == ranges[i - 1].end.row) + i--; + } + tmpSel.fromOrientedRange(ranges[i]); + tmpSel.index = i; + this.selection = session.selection = tmpSel; + var cmdResult = cmd.exec ? cmd.exec(this, args || {}) : cmd(this, args || {}); + if (!result && cmdResult !== undefined) + result = cmdResult; + tmpSel.toOrientedRange(ranges[i]); + } + tmpSel.detach(); + + this.selection = session.selection = selection; + this.inVirtualSelectionMode = false; + selection._eventRegistry = reg; + selection.mergeOverlappingRanges(); + + var anim = this.renderer.$scrollAnimation; + this.onCursorChange(); + this.onSelectionChange(); + if (anim && anim.from == anim.to) + this.renderer.animateScrolling(anim.from); + + return result; + }; + this.exitMultiSelectMode = function() { + if (!this.inMultiSelectMode || this.inVirtualSelectionMode) + return; + this.multiSelect.toSingleRange(); + }; + + this.getSelectedText = function() { + var text = ""; + if (this.inMultiSelectMode && !this.inVirtualSelectionMode) { + var ranges = this.multiSelect.rangeList.ranges; + var buf = []; + for (var i = 0; i < ranges.length; i++) { + buf.push(this.session.getTextRange(ranges[i])); + } + var nl = this.session.getDocument().getNewLineCharacter(); + text = buf.join(nl); + if (text.length == (buf.length - 1) * nl.length) + text = ""; + } else if (!this.selection.isEmpty()) { + text = this.session.getTextRange(this.getSelectionRange()); + } + return text; + }; + + this.$checkMultiselectChange = function(e, anchor) { + if (this.inMultiSelectMode && !this.inVirtualSelectionMode) { + var range = this.multiSelect.ranges[0]; + if (this.multiSelect.isEmpty() && anchor == this.multiSelect.anchor) + return; + var pos = anchor == this.multiSelect.anchor + ? range.cursor == range.start ? range.end : range.start + : range.cursor; + if (pos.row != anchor.row + || this.session.$clipPositionToDocument(pos.row, pos.column).column != anchor.column) + this.multiSelect.toSingleRange(this.multiSelect.toOrientedRange()); + } + }; + this.findAll = function(needle, options, additive) { + options = options || {}; + options.needle = needle || options.needle; + if (options.needle == undefined) { + var range = this.selection.isEmpty() + ? this.selection.getWordRange() + : this.selection.getRange(); + options.needle = this.session.getTextRange(range); + } + this.$search.set(options); + + var ranges = this.$search.findAll(this.session); + if (!ranges.length) + return 0; + + this.$blockScrolling += 1; + var selection = this.multiSelect; + + if (!additive) + selection.toSingleRange(ranges[0]); + + for (var i = ranges.length; i--; ) + selection.addRange(ranges[i], true); + if (range && selection.rangeList.rangeAtPoint(range.start)) + selection.addRange(range, true); + + this.$blockScrolling -= 1; + + return ranges.length; + }; + this.selectMoreLines = function(dir, skip) { + var range = this.selection.toOrientedRange(); + var isBackwards = range.cursor == range.end; + + var screenLead = this.session.documentToScreenPosition(range.cursor); + if (this.selection.$desiredColumn) + screenLead.column = this.selection.$desiredColumn; + + var lead = this.session.screenToDocumentPosition(screenLead.row + dir, screenLead.column); + + if (!range.isEmpty()) { + var screenAnchor = this.session.documentToScreenPosition(isBackwards ? range.end : range.start); + var anchor = this.session.screenToDocumentPosition(screenAnchor.row + dir, screenAnchor.column); + } else { + var anchor = lead; + } + + if (isBackwards) { + var newRange = Range.fromPoints(lead, anchor); + newRange.cursor = newRange.start; + } else { + var newRange = Range.fromPoints(anchor, lead); + newRange.cursor = newRange.end; + } + + newRange.desiredColumn = screenLead.column; + if (!this.selection.inMultiSelectMode) { + this.selection.addRange(range); + } else { + if (skip) + var toRemove = range.cursor; + } + + this.selection.addRange(newRange); + if (toRemove) + this.selection.substractPoint(toRemove); + }; + this.transposeSelections = function(dir) { + var session = this.session; + var sel = session.multiSelect; + var all = sel.ranges; + + for (var i = all.length; i--; ) { + var range = all[i]; + if (range.isEmpty()) { + var tmp = session.getWordRange(range.start.row, range.start.column); + range.start.row = tmp.start.row; + range.start.column = tmp.start.column; + range.end.row = tmp.end.row; + range.end.column = tmp.end.column; + } + } + sel.mergeOverlappingRanges(); + + var words = []; + for (var i = all.length; i--; ) { + var range = all[i]; + words.unshift(session.getTextRange(range)); + } + + if (dir < 0) + words.unshift(words.pop()); + else + words.push(words.shift()); + + for (var i = all.length; i--; ) { + var range = all[i]; + var tmp = range.clone(); + session.replace(range, words[i]); + range.start.row = tmp.start.row; + range.start.column = tmp.start.column; + } + }; + this.selectMore = function(dir, skip, stopAtFirst) { + var session = this.session; + var sel = session.multiSelect; + + var range = sel.toOrientedRange(); + if (range.isEmpty()) { + range = session.getWordRange(range.start.row, range.start.column); + range.cursor = dir == -1 ? range.start : range.end; + this.multiSelect.addRange(range); + if (stopAtFirst) + return; + } + var needle = session.getTextRange(range); + + var newRange = find(session, needle, dir); + if (newRange) { + newRange.cursor = dir == -1 ? newRange.start : newRange.end; + this.$blockScrolling += 1; + this.session.unfold(newRange); + this.multiSelect.addRange(newRange); + this.$blockScrolling -= 1; + this.renderer.scrollCursorIntoView(null, 0.5); + } + if (skip) + this.multiSelect.substractPoint(range.cursor); + }; + this.alignCursors = function() { + var session = this.session; + var sel = session.multiSelect; + var ranges = sel.ranges; + var row = -1; + var sameRowRanges = ranges.filter(function(r) { + if (r.cursor.row == row) + return true; + row = r.cursor.row; + }); + + if (!ranges.length || sameRowRanges.length == ranges.length - 1) { + var range = this.selection.getRange(); + var fr = range.start.row, lr = range.end.row; + var guessRange = fr == lr; + if (guessRange) { + var max = this.session.getLength(); + var line; + do { + line = this.session.getLine(lr); + } while (/[=:]/.test(line) && ++lr < max); + do { + line = this.session.getLine(fr); + } while (/[=:]/.test(line) && --fr > 0); + + if (fr < 0) fr = 0; + if (lr >= max) lr = max - 1; + } + var lines = this.session.removeFullLines(fr, lr); + lines = this.$reAlignText(lines, guessRange); + this.session.insert({row: fr, column: 0}, lines.join("\n") + "\n"); + if (!guessRange) { + range.start.column = 0; + range.end.column = lines[lines.length - 1].length; + } + this.selection.setRange(range); + } else { + sameRowRanges.forEach(function(r) { + sel.substractPoint(r.cursor); + }); + + var maxCol = 0; + var minSpace = Infinity; + var spaceOffsets = ranges.map(function(r) { + var p = r.cursor; + var line = session.getLine(p.row); + var spaceOffset = line.substr(p.column).search(/\S/g); + if (spaceOffset == -1) + spaceOffset = 0; + + if (p.column > maxCol) + maxCol = p.column; + if (spaceOffset < minSpace) + minSpace = spaceOffset; + return spaceOffset; + }); + ranges.forEach(function(r, i) { + var p = r.cursor; + var l = maxCol - p.column; + var d = spaceOffsets[i] - minSpace; + if (l > d) + session.insert(p, lang.stringRepeat(" ", l - d)); + else + session.remove(new Range(p.row, p.column, p.row, p.column - l + d)); + + r.start.column = r.end.column = maxCol; + r.start.row = r.end.row = p.row; + r.cursor = r.end; + }); + sel.fromOrientedRange(ranges[0]); + this.renderer.updateCursor(); + this.renderer.updateBackMarkers(); + } + }; + + this.$reAlignText = function(lines, forceLeft) { + var isLeftAligned = true, isRightAligned = true; + var startW, textW, endW; + + return lines.map(function(line) { + var m = line.match(/(\s*)(.*?)(\s*)([=:].*)/); + if (!m) + return [line]; + + if (startW == null) { + startW = m[1].length; + textW = m[2].length; + endW = m[3].length; + return m; + } + + if (startW + textW + endW != m[1].length + m[2].length + m[3].length) + isRightAligned = false; + if (startW != m[1].length) + isLeftAligned = false; + + if (startW > m[1].length) + startW = m[1].length; + if (textW < m[2].length) + textW = m[2].length; + if (endW > m[3].length) + endW = m[3].length; + + return m; + }).map(forceLeft ? alignLeft : + isLeftAligned ? isRightAligned ? alignRight : alignLeft : unAlign); + + function spaces(n) { + return lang.stringRepeat(" ", n); + } + + function alignLeft(m) { + return !m[2] ? m[0] : spaces(startW) + m[2] + + spaces(textW - m[2].length + endW) + + m[4].replace(/^([=:])\s+/, "$1 "); + } + function alignRight(m) { + return !m[2] ? m[0] : spaces(startW + textW - m[2].length) + m[2] + + spaces(endW, " ") + + m[4].replace(/^([=:])\s+/, "$1 "); + } + function unAlign(m) { + return !m[2] ? m[0] : spaces(startW) + m[2] + + spaces(endW) + + m[4].replace(/^([=:])\s+/, "$1 "); + } + }; + }).call(Editor.prototype); + + + function isSamePoint(p1, p2) { + return p1.row == p2.row && p1.column == p2.column; + } + exports.onSessionChange = function(e) { + var session = e.session; + if (session && !session.multiSelect) { + session.$selectionMarkers = []; + session.selection.$initRangeList(); + session.multiSelect = session.selection; + } + this.multiSelect = session && session.multiSelect; + + var oldSession = e.oldSession; + if (oldSession) { + oldSession.multiSelect.off("addRange", this.$onAddRange); + oldSession.multiSelect.off("removeRange", this.$onRemoveRange); + oldSession.multiSelect.off("multiSelect", this.$onMultiSelect); + oldSession.multiSelect.off("singleSelect", this.$onSingleSelect); + oldSession.multiSelect.lead.off("change", this.$checkMultiselectChange); + oldSession.multiSelect.anchor.off("change", this.$checkMultiselectChange); + } + + if (session) { + session.multiSelect.on("addRange", this.$onAddRange); + session.multiSelect.on("removeRange", this.$onRemoveRange); + session.multiSelect.on("multiSelect", this.$onMultiSelect); + session.multiSelect.on("singleSelect", this.$onSingleSelect); + session.multiSelect.lead.on("change", this.$checkMultiselectChange); + session.multiSelect.anchor.on("change", this.$checkMultiselectChange); + } + + if (session && this.inMultiSelectMode != session.selection.inMultiSelectMode) { + if (session.selection.inMultiSelectMode) + this.$onMultiSelect(); + else + this.$onSingleSelect(); + } + }; + function MultiSelect(editor) { + if (editor.$multiselectOnSessionChange) + return; + editor.$onAddRange = editor.$onAddRange.bind(editor); + editor.$onRemoveRange = editor.$onRemoveRange.bind(editor); + editor.$onMultiSelect = editor.$onMultiSelect.bind(editor); + editor.$onSingleSelect = editor.$onSingleSelect.bind(editor); + editor.$multiselectOnSessionChange = exports.onSessionChange.bind(editor); + editor.$checkMultiselectChange = editor.$checkMultiselectChange.bind(editor); + + editor.$multiselectOnSessionChange(editor); + editor.on("changeSession", editor.$multiselectOnSessionChange); + + editor.on("mousedown", onMouseDown); + editor.commands.addCommands(commands.defaultCommands); + + addAltCursorListeners(editor); + } + + function addAltCursorListeners(editor){ + var el = editor.textInput.getElement(); + var altCursor = false; + event.addListener(el, "keydown", function(e) { + var altDown = e.keyCode == 18 && !(e.ctrlKey || e.shiftKey || e.metaKey); + if (editor.$blockSelectEnabled && altDown) { + if (!altCursor) { + editor.renderer.setMouseCursor("crosshair"); + altCursor = true; + } + } else if (altCursor) { + reset(); + } + }); + + event.addListener(el, "keyup", reset); + event.addListener(el, "blur", reset); + function reset(e) { + if (altCursor) { + editor.renderer.setMouseCursor(""); + altCursor = false; + } + } + } + + exports.MultiSelect = MultiSelect; + + + acequire("./config").defineOptions(Editor.prototype, "editor", { + enableMultiselect: { + set: function(val) { + MultiSelect(this); + if (val) { + this.on("changeSession", this.$multiselectOnSessionChange); + this.on("mousedown", onMouseDown); + } else { + this.off("changeSession", this.$multiselectOnSessionChange); + this.off("mousedown", onMouseDown); + } + }, + value: true + }, + enableBlockSelect: { + set: function(val) { + this.$blockSelectEnabled = val; + }, + value: true + } + }); + + + + }); + + ace.define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"], function(acequire, exports, module) { + "use strict"; + + var Range = acequire("../../range").Range; + + var FoldMode = exports.FoldMode = function() {}; + + (function() { + + this.foldingStartMarker = null; + this.foldingStopMarker = null; + this.getFoldWidget = function(session, foldStyle, row) { + var line = session.getLine(row); + if (this.foldingStartMarker.test(line)) + return "start"; + if (foldStyle == "markbeginend" + && this.foldingStopMarker + && this.foldingStopMarker.test(line)) + return "end"; + return ""; + }; + + this.getFoldWidgetRange = function(session, foldStyle, row) { + return null; + }; + + this.indentationBlock = function(session, row, column) { + var re = /\S/; + var line = session.getLine(row); + var startLevel = line.search(re); + if (startLevel == -1) + return; + + var startColumn = column || line.length; + var maxRow = session.getLength(); + var startRow = row; + var endRow = row; + + while (++row < maxRow) { + var level = session.getLine(row).search(re); + + if (level == -1) + continue; + + if (level <= startLevel) + break; + + endRow = row; + } + + if (endRow > startRow) { + var endColumn = session.getLine(endRow).length; + return new Range(startRow, startColumn, endRow, endColumn); + } + }; + + this.openingBracketBlock = function(session, bracket, row, column, typeRe) { + var start = {row: row, column: column + 1}; + var end = session.$findClosingBracket(bracket, start, typeRe); + if (!end) + return; + + var fw = session.foldWidgets[end.row]; + if (fw == null) + fw = session.getFoldWidget(end.row); + + if (fw == "start" && end.row > start.row) { + end.row --; + end.column = session.getLine(end.row).length; + } + return Range.fromPoints(start, end); + }; + + this.closingBracketBlock = function(session, bracket, row, column, typeRe) { + var end = {row: row, column: column}; + var start = session.$findOpeningBracket(bracket, end); + + if (!start) + return; + + start.column++; + end.column--; + + return Range.fromPoints(start, end); + }; + }).call(FoldMode.prototype); + + }); + + ace.define("ace/theme/textmate",["require","exports","module","ace/lib/dom"], function(acequire, exports, module) { + "use strict"; + + exports.isDark = false; + exports.cssClass = "ace-tm"; + exports.cssText = ".ace-tm .ace_gutter {\ + background: #f0f0f0;\ + color: #333;\ + }\ + .ace-tm .ace_print-margin {\ + width: 1px;\ + background: #e8e8e8;\ + }\ + .ace-tm .ace_fold {\ + background-color: #6B72E6;\ + }\ + .ace-tm {\ + background-color: #FFFFFF;\ + color: black;\ + }\ + .ace-tm .ace_cursor {\ + color: black;\ + }\ + .ace-tm .ace_invisible {\ + color: rgb(191, 191, 191);\ + }\ + .ace-tm .ace_storage,\ + .ace-tm .ace_keyword {\ + color: blue;\ + }\ + .ace-tm .ace_constant {\ + color: rgb(197, 6, 11);\ + }\ + .ace-tm .ace_constant.ace_buildin {\ + color: rgb(88, 72, 246);\ + }\ + .ace-tm .ace_constant.ace_language {\ + color: rgb(88, 92, 246);\ + }\ + .ace-tm .ace_constant.ace_library {\ + color: rgb(6, 150, 14);\ + }\ + .ace-tm .ace_invalid {\ + background-color: rgba(255, 0, 0, 0.1);\ + color: red;\ + }\ + .ace-tm .ace_support.ace_function {\ + color: rgb(60, 76, 114);\ + }\ + .ace-tm .ace_support.ace_constant {\ + color: rgb(6, 150, 14);\ + }\ + .ace-tm .ace_support.ace_type,\ + .ace-tm .ace_support.ace_class {\ + color: rgb(109, 121, 222);\ + }\ + .ace-tm .ace_keyword.ace_operator {\ + color: rgb(104, 118, 135);\ + }\ + .ace-tm .ace_string {\ + color: rgb(3, 106, 7);\ + }\ + .ace-tm .ace_comment {\ + color: rgb(76, 136, 107);\ + }\ + .ace-tm .ace_comment.ace_doc {\ + color: rgb(0, 102, 255);\ + }\ + .ace-tm .ace_comment.ace_doc.ace_tag {\ + color: rgb(128, 159, 191);\ + }\ + .ace-tm .ace_constant.ace_numeric {\ + color: rgb(0, 0, 205);\ + }\ + .ace-tm .ace_variable {\ + color: rgb(49, 132, 149);\ + }\ + .ace-tm .ace_xml-pe {\ + color: rgb(104, 104, 91);\ + }\ + .ace-tm .ace_entity.ace_name.ace_function {\ + color: #0000A2;\ + }\ + .ace-tm .ace_heading {\ + color: rgb(12, 7, 255);\ + }\ + .ace-tm .ace_list {\ + color:rgb(185, 6, 144);\ + }\ + .ace-tm .ace_meta.ace_tag {\ + color:rgb(0, 22, 142);\ + }\ + .ace-tm .ace_string.ace_regex {\ + color: rgb(255, 0, 0)\ + }\ + .ace-tm .ace_marker-layer .ace_selection {\ + background: rgb(181, 213, 255);\ + }\ + .ace-tm.ace_multiselect .ace_selection.ace_start {\ + box-shadow: 0 0 3px 0px white;\ + }\ + .ace-tm .ace_marker-layer .ace_step {\ + background: rgb(252, 255, 0);\ + }\ + .ace-tm .ace_marker-layer .ace_stack {\ + background: rgb(164, 229, 101);\ + }\ + .ace-tm .ace_marker-layer .ace_bracket {\ + margin: -1px 0 0 -1px;\ + border: 1px solid rgb(192, 192, 192);\ + }\ + .ace-tm .ace_marker-layer .ace_active-line {\ + background: rgba(0, 0, 0, 0.07);\ + }\ + .ace-tm .ace_gutter-active-line {\ + background-color : #dcdcdc;\ + }\ + .ace-tm .ace_marker-layer .ace_selected-word {\ + background: rgb(250, 250, 255);\ + border: 1px solid rgb(200, 200, 250);\ + }\ + .ace-tm .ace_indent-guide {\ + background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y;\ + }\ + "; + + var dom = acequire("../lib/dom"); + dom.importCssString(exports.cssText, exports.cssClass); + }); + + ace.define("ace/line_widgets",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/range"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("./lib/oop"); + var dom = acequire("./lib/dom"); + var Range = acequire("./range").Range; + + + function LineWidgets(session) { + this.session = session; + this.session.widgetManager = this; + this.session.getRowLength = this.getRowLength; + this.session.$getWidgetScreenLength = this.$getWidgetScreenLength; + this.updateOnChange = this.updateOnChange.bind(this); + this.renderWidgets = this.renderWidgets.bind(this); + this.measureWidgets = this.measureWidgets.bind(this); + this.session._changedWidgets = []; + this.$onChangeEditor = this.$onChangeEditor.bind(this); + + this.session.on("change", this.updateOnChange); + this.session.on("changeFold", this.updateOnFold); + this.session.on("changeEditor", this.$onChangeEditor); + } + + (function() { + this.getRowLength = function(row) { + var h; + if (this.lineWidgets) + h = this.lineWidgets[row] && this.lineWidgets[row].rowCount || 0; + else + h = 0; + if (!this.$useWrapMode || !this.$wrapData[row]) { + return 1 + h; + } else { + return this.$wrapData[row].length + 1 + h; + } + }; + + this.$getWidgetScreenLength = function() { + var screenRows = 0; + this.lineWidgets.forEach(function(w){ + if (w && w.rowCount && !w.hidden) + screenRows += w.rowCount; + }); + return screenRows; + }; + + this.$onChangeEditor = function(e) { + this.attach(e.editor); + }; + + this.attach = function(editor) { + if (editor && editor.widgetManager && editor.widgetManager != this) + editor.widgetManager.detach(); + + if (this.editor == editor) + return; + + this.detach(); + this.editor = editor; + + if (editor) { + editor.widgetManager = this; + editor.renderer.on("beforeRender", this.measureWidgets); + editor.renderer.on("afterRender", this.renderWidgets); + } + }; + this.detach = function(e) { + var editor = this.editor; + if (!editor) + return; + + this.editor = null; + editor.widgetManager = null; + + editor.renderer.off("beforeRender", this.measureWidgets); + editor.renderer.off("afterRender", this.renderWidgets); + var lineWidgets = this.session.lineWidgets; + lineWidgets && lineWidgets.forEach(function(w) { + if (w && w.el && w.el.parentNode) { + w._inDocument = false; + w.el.parentNode.removeChild(w.el); + } + }); + }; + + this.updateOnFold = function(e, session) { + var lineWidgets = session.lineWidgets; + if (!lineWidgets || !e.action) + return; + var fold = e.data; + var start = fold.start.row; + var end = fold.end.row; + var hide = e.action == "add"; + for (var i = start + 1; i < end; i++) { + if (lineWidgets[i]) + lineWidgets[i].hidden = hide; + } + if (lineWidgets[end]) { + if (hide) { + if (!lineWidgets[start]) + lineWidgets[start] = lineWidgets[end]; + else + lineWidgets[end].hidden = hide; + } else { + if (lineWidgets[start] == lineWidgets[end]) + lineWidgets[start] = undefined; + lineWidgets[end].hidden = hide; + } + } + }; + + this.updateOnChange = function(delta) { + var lineWidgets = this.session.lineWidgets; + if (!lineWidgets) return; + + var startRow = delta.start.row; + var len = delta.end.row - startRow; + + if (len === 0) { + } else if (delta.action == 'remove') { + var removed = lineWidgets.splice(startRow + 1, len); + removed.forEach(function(w) { + w && this.removeLineWidget(w); + }, this); + this.$updateRows(); + } else { + var args = new Array(len); + args.unshift(startRow, 0); + lineWidgets.splice.apply(lineWidgets, args); + this.$updateRows(); + } + }; + + this.$updateRows = function() { + var lineWidgets = this.session.lineWidgets; + if (!lineWidgets) return; + var noWidgets = true; + lineWidgets.forEach(function(w, i) { + if (w) { + noWidgets = false; + w.row = i; + while (w.$oldWidget) { + w.$oldWidget.row = i; + w = w.$oldWidget; + } + } + }); + if (noWidgets) + this.session.lineWidgets = null; + }; + + this.addLineWidget = function(w) { + if (!this.session.lineWidgets) + this.session.lineWidgets = new Array(this.session.getLength()); + + var old = this.session.lineWidgets[w.row]; + if (old) { + w.$oldWidget = old; + if (old.el && old.el.parentNode) { + old.el.parentNode.removeChild(old.el); + old._inDocument = false; + } + } + + this.session.lineWidgets[w.row] = w; + + w.session = this.session; + + var renderer = this.editor.renderer; + if (w.html && !w.el) { + w.el = dom.createElement("div"); + w.el.innerHTML = w.html; + } + if (w.el) { + dom.addCssClass(w.el, "ace_lineWidgetContainer"); + w.el.style.position = "absolute"; + w.el.style.zIndex = 5; + renderer.container.appendChild(w.el); + w._inDocument = true; + } + + if (!w.coverGutter) { + w.el.style.zIndex = 3; + } + if (!w.pixelHeight) { + w.pixelHeight = w.el.offsetHeight; + } + if (w.rowCount == null) { + w.rowCount = w.pixelHeight / renderer.layerConfig.lineHeight; + } + + var fold = this.session.getFoldAt(w.row, 0); + w.$fold = fold; + if (fold) { + var lineWidgets = this.session.lineWidgets; + if (w.row == fold.end.row && !lineWidgets[fold.start.row]) + lineWidgets[fold.start.row] = w; + else + w.hidden = true; + } + + this.session._emit("changeFold", {data:{start:{row: w.row}}}); + + this.$updateRows(); + this.renderWidgets(null, renderer); + this.onWidgetChanged(w); + return w; + }; + + this.removeLineWidget = function(w) { + w._inDocument = false; + w.session = null; + if (w.el && w.el.parentNode) + w.el.parentNode.removeChild(w.el); + if (w.editor && w.editor.destroy) try { + w.editor.destroy(); + } catch(e){} + if (this.session.lineWidgets) { + var w1 = this.session.lineWidgets[w.row] + if (w1 == w) { + this.session.lineWidgets[w.row] = w.$oldWidget; + if (w.$oldWidget) + this.onWidgetChanged(w.$oldWidget); + } else { + while (w1) { + if (w1.$oldWidget == w) { + w1.$oldWidget = w.$oldWidget; + break; + } + w1 = w1.$oldWidget; + } + } + } + this.session._emit("changeFold", {data:{start:{row: w.row}}}); + this.$updateRows(); + }; + + this.getWidgetsAtRow = function(row) { + var lineWidgets = this.session.lineWidgets; + var w = lineWidgets && lineWidgets[row]; + var list = []; + while (w) { + list.push(w); + w = w.$oldWidget; + } + return list; + }; + + this.onWidgetChanged = function(w) { + this.session._changedWidgets.push(w); + this.editor && this.editor.renderer.updateFull(); + }; + + this.measureWidgets = function(e, renderer) { + var changedWidgets = this.session._changedWidgets; + var config = renderer.layerConfig; + + if (!changedWidgets || !changedWidgets.length) return; + var min = Infinity; + for (var i = 0; i < changedWidgets.length; i++) { + var w = changedWidgets[i]; + if (!w || !w.el) continue; + if (w.session != this.session) continue; + if (!w._inDocument) { + if (this.session.lineWidgets[w.row] != w) + continue; + w._inDocument = true; + renderer.container.appendChild(w.el); + } + + w.h = w.el.offsetHeight; + + if (!w.fixedWidth) { + w.w = w.el.offsetWidth; + w.screenWidth = Math.ceil(w.w / config.characterWidth); + } + + var rowCount = w.h / config.lineHeight; + if (w.coverLine) { + rowCount -= this.session.getRowLineCount(w.row); + if (rowCount < 0) + rowCount = 0; + } + if (w.rowCount != rowCount) { + w.rowCount = rowCount; + if (w.row < min) + min = w.row; + } + } + if (min != Infinity) { + this.session._emit("changeFold", {data:{start:{row: min}}}); + this.session.lineWidgetWidth = null; + } + this.session._changedWidgets = []; + }; + + this.renderWidgets = function(e, renderer) { + var config = renderer.layerConfig; + var lineWidgets = this.session.lineWidgets; + if (!lineWidgets) + return; + var first = Math.min(this.firstRow, config.firstRow); + var last = Math.max(this.lastRow, config.lastRow, lineWidgets.length); + + while (first > 0 && !lineWidgets[first]) + first--; + + this.firstRow = config.firstRow; + this.lastRow = config.lastRow; + + renderer.$cursorLayer.config = config; + for (var i = first; i <= last; i++) { + var w = lineWidgets[i]; + if (!w || !w.el) continue; + if (w.hidden) { + w.el.style.top = -100 - (w.pixelHeight || 0) + "px"; + continue; + } + if (!w._inDocument) { + w._inDocument = true; + renderer.container.appendChild(w.el); + } + var top = renderer.$cursorLayer.getPixelPosition({row: i, column:0}, true).top; + if (!w.coverLine) + top += config.lineHeight * this.session.getRowLineCount(w.row); + w.el.style.top = top - config.offset + "px"; + + var left = w.coverGutter ? 0 : renderer.gutterWidth; + if (!w.fixedWidth) + left -= renderer.scrollLeft; + w.el.style.left = left + "px"; + + if (w.fullWidth && w.screenWidth) { + w.el.style.minWidth = config.width + 2 * config.padding + "px"; + } + + if (w.fixedWidth) { + w.el.style.right = renderer.scrollBar.getWidth() + "px"; + } else { + w.el.style.right = ""; + } + } + }; + + }).call(LineWidgets.prototype); + + + exports.LineWidgets = LineWidgets; + + }); + + ace.define("ace/ext/error_marker",["require","exports","module","ace/line_widgets","ace/lib/dom","ace/range"], function(acequire, exports, module) { + "use strict"; + var LineWidgets = acequire("../line_widgets").LineWidgets; + var dom = acequire("../lib/dom"); + var Range = acequire("../range").Range; + + function binarySearch(array, needle, comparator) { + var first = 0; + var last = array.length - 1; + + while (first <= last) { + var mid = (first + last) >> 1; + var c = comparator(needle, array[mid]); + if (c > 0) + first = mid + 1; + else if (c < 0) + last = mid - 1; + else + return mid; + } + return -(first + 1); + } + + function findAnnotations(session, row, dir) { + var annotations = session.getAnnotations().sort(Range.comparePoints); + if (!annotations.length) + return; + + var i = binarySearch(annotations, {row: row, column: -1}, Range.comparePoints); + if (i < 0) + i = -i - 1; + + if (i >= annotations.length) + i = dir > 0 ? 0 : annotations.length - 1; + else if (i === 0 && dir < 0) + i = annotations.length - 1; + + var annotation = annotations[i]; + if (!annotation || !dir) + return; + + if (annotation.row === row) { + do { + annotation = annotations[i += dir]; + } while (annotation && annotation.row === row); + if (!annotation) + return annotations.slice(); + } + + + var matched = []; + row = annotation.row; + do { + matched[dir < 0 ? "unshift" : "push"](annotation); + annotation = annotations[i += dir]; + } while (annotation && annotation.row == row); + return matched.length && matched; + } + + exports.showErrorMarker = function(editor, dir) { + var session = editor.session; + if (!session.widgetManager) { + session.widgetManager = new LineWidgets(session); + session.widgetManager.attach(editor); + } + + var pos = editor.getCursorPosition(); + var row = pos.row; + var oldWidget = session.widgetManager.getWidgetsAtRow(row).filter(function(w) { + return w.type == "errorMarker"; + })[0]; + if (oldWidget) { + oldWidget.destroy(); + } else { + row -= dir; + } + var annotations = findAnnotations(session, row, dir); + var gutterAnno; + if (annotations) { + var annotation = annotations[0]; + pos.column = (annotation.pos && typeof annotation.column != "number" + ? annotation.pos.sc + : annotation.column) || 0; + pos.row = annotation.row; + gutterAnno = editor.renderer.$gutterLayer.$annotations[pos.row]; + } else if (oldWidget) { + return; + } else { + gutterAnno = { + text: ["Looks good!"], + className: "ace_ok" + }; + } + editor.session.unfold(pos.row); + editor.selection.moveToPosition(pos); + + var w = { + row: pos.row, + fixedWidth: true, + coverGutter: true, + el: dom.createElement("div"), + type: "errorMarker" + }; + var el = w.el.appendChild(dom.createElement("div")); + var arrow = w.el.appendChild(dom.createElement("div")); + arrow.className = "error_widget_arrow " + gutterAnno.className; + + var left = editor.renderer.$cursorLayer + .getPixelPosition(pos).left; + arrow.style.left = left + editor.renderer.gutterWidth - 5 + "px"; + + w.el.className = "error_widget_wrapper"; + el.className = "error_widget " + gutterAnno.className; + el.innerHTML = gutterAnno.text.join("
"); + + el.appendChild(dom.createElement("div")); + + var kb = function(_, hashId, keyString) { + if (hashId === 0 && (keyString === "esc" || keyString === "return")) { + w.destroy(); + return {command: "null"}; + } + }; + + w.destroy = function() { + if (editor.$mouseHandler.isMousePressed) + return; + editor.keyBinding.removeKeyboardHandler(kb); + session.widgetManager.removeLineWidget(w); + editor.off("changeSelection", w.destroy); + editor.off("changeSession", w.destroy); + editor.off("mouseup", w.destroy); + editor.off("change", w.destroy); + }; + + editor.keyBinding.addKeyboardHandler(kb); + editor.on("changeSelection", w.destroy); + editor.on("changeSession", w.destroy); + editor.on("mouseup", w.destroy); + editor.on("change", w.destroy); + + editor.session.widgetManager.addLineWidget(w); + + w.el.onmousedown = editor.focus.bind(editor); + + editor.renderer.scrollCursorIntoView(null, 0.5, {bottom: w.el.offsetHeight}); + }; + + + dom.importCssString("\ + .error_widget_wrapper {\ + background: inherit;\ + color: inherit;\ + border:none\ + }\ + .error_widget {\ + border-top: solid 2px;\ + border-bottom: solid 2px;\ + margin: 5px 0;\ + padding: 10px 40px;\ + white-space: pre-wrap;\ + }\ + .error_widget.ace_error, .error_widget_arrow.ace_error{\ + border-color: #ff5a5a\ + }\ + .error_widget.ace_warning, .error_widget_arrow.ace_warning{\ + border-color: #F1D817\ + }\ + .error_widget.ace_info, .error_widget_arrow.ace_info{\ + border-color: #5a5a5a\ + }\ + .error_widget.ace_ok, .error_widget_arrow.ace_ok{\ + border-color: #5aaa5a\ + }\ + .error_widget_arrow {\ + position: absolute;\ + border: solid 5px;\ + border-top-color: transparent!important;\ + border-right-color: transparent!important;\ + border-left-color: transparent!important;\ + top: -5px;\ + }\ + ", ""); + + }); + + ace.define("ace/ace",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/dom","ace/lib/event","ace/editor","ace/edit_session","ace/undomanager","ace/virtual_renderer","ace/worker/worker_client","ace/keyboard/hash_handler","ace/placeholder","ace/multi_select","ace/mode/folding/fold_mode","ace/theme/textmate","ace/ext/error_marker","ace/config"], function(acequire, exports, module) { + "use strict"; + + acequire("./lib/fixoldbrowsers"); + + var dom = acequire("./lib/dom"); + var event = acequire("./lib/event"); + + var Editor = acequire("./editor").Editor; + var EditSession = acequire("./edit_session").EditSession; + var UndoManager = acequire("./undomanager").UndoManager; + var Renderer = acequire("./virtual_renderer").VirtualRenderer; + acequire("./worker/worker_client"); + acequire("./keyboard/hash_handler"); + acequire("./placeholder"); + acequire("./multi_select"); + acequire("./mode/folding/fold_mode"); + acequire("./theme/textmate"); + acequire("./ext/error_marker"); + + exports.config = acequire("./config"); + exports.acequire = acequire; + exports.edit = function(el) { + if (typeof el == "string") { + var _id = el; + el = document.getElementById(_id); + if (!el) + throw new Error("ace.edit can't find div #" + _id); + } + + if (el && el.env && el.env.editor instanceof Editor) + return el.env.editor; + + var value = ""; + if (el && /input|textarea/i.test(el.tagName)) { + var oldNode = el; + value = oldNode.value; + el = dom.createElement("pre"); + oldNode.parentNode.replaceChild(el, oldNode); + } else if (el) { + value = dom.getInnerText(el); + el.innerHTML = ""; + } + + var doc = exports.createEditSession(value); + + var editor = new Editor(new Renderer(el)); + editor.setSession(doc); + + var env = { + document: doc, + editor: editor, + onResize: editor.resize.bind(editor, null) + }; + if (oldNode) env.textarea = oldNode; + event.addListener(window, "resize", env.onResize); + editor.on("destroy", function() { + event.removeListener(window, "resize", env.onResize); + env.editor.container.env = null; // prevent memory leak on old ie + }); + editor.container.env = editor.env = env; + return editor; + }; + exports.createEditSession = function(text, mode) { + var doc = new EditSession(text, mode); + doc.setUndoManager(new UndoManager()); + return doc; + } + exports.EditSession = EditSession; + exports.UndoManager = UndoManager; + exports.version = "1.2.3"; + }); + (function() { + ace.acequire(["ace/ace"], function(a) { + a && a.config.init(true); + if (!window.ace) + window.ace = a; + for (var key in a) if (a.hasOwnProperty(key)) + window.ace[key] = a[key]; + }); + })(); + + module.exports = window.ace.acequire("ace/ace"); + +/***/ }, +/* 65 */ +/***/ function(module, exports) { + + module.exports = function() { throw new Error("define cannot be used indirect"); }; + + +/***/ }, +/* 66 */ +/***/ function(module, exports) { + + /* WEBPACK VAR INJECTION */(function(global) {module.exports = get_blob() + + function get_blob() { + if(global.Blob) { + try { + new Blob(['asdf'], {type: 'text/plain'}) + return Blob + } catch(err) {} + } + + var Builder = global.WebKitBlobBuilder || + global.MozBlobBuilder || + global.MSBlobBuilder + + return function(parts, bag) { + var builder = new Builder + , endings = bag.endings + , type = bag.type + + if(endings) for(var i = 0, len = parts.length; i < len; ++i) { + builder.append(parts[i], endings) + } else for(var i = 0, len = parts.length; i < len; ++i) { + builder.append(parts[i]) + } + + return type ? builder.getBlob(type) : builder.getBlob() + } + } + + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ }, +/* 67 */ +/***/ function(module, exports, __webpack_require__) { + + ace.define("ace/mode/json_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("../lib/oop"); + var TextHighlightRules = acequire("./text_highlight_rules").TextHighlightRules; + + var JsonHighlightRules = function() { + this.$rules = { + "start" : [ + { + token : "variable", // single line + regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]\\s*(?=:)' + }, { + token : "string", // single line + regex : '"', + next : "string" + }, { + token : "constant.numeric", // hex + regex : "0[xX][0-9a-fA-F]+\\b" + }, { + token : "constant.numeric", // float + regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b" + }, { + token : "constant.language.boolean", + regex : "(?:true|false)\\b" + }, { + token : "invalid.illegal", // single quoted strings are not allowed + regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']" + }, { + token : "invalid.illegal", // comments are not allowed + regex : "\\/\\/.*$" + }, { + token : "paren.lparen", + regex : "[[({]" + }, { + token : "paren.rparen", + regex : "[\\])}]" + }, { + token : "text", + regex : "\\s+" + } + ], + "string" : [ + { + token : "constant.language.escape", + regex : /\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|["\\\/bfnrt])/ + }, { + token : "string", + regex : '[^"\\\\]+' + }, { + token : "string", + regex : '"', + next : "start" + }, { + token : "string", + regex : "", + next : "start" + } + ] + }; + + }; + + oop.inherits(JsonHighlightRules, TextHighlightRules); + + exports.JsonHighlightRules = JsonHighlightRules; + }); + + ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"], function(acequire, exports, module) { + "use strict"; + + var Range = acequire("../range").Range; + + var MatchingBraceOutdent = function() {}; + + (function() { + + this.checkOutdent = function(line, input) { + if (! /^\s+$/.test(line)) + return false; + + return /^\s*\}/.test(input); + }; + + this.autoOutdent = function(doc, row) { + var line = doc.getLine(row); + var match = line.match(/^(\s*\})/); + + if (!match) return 0; + + var column = match[1].length; + var openBracePos = doc.findMatchingBracket({row: row, column: column}); + + if (!openBracePos || openBracePos.row == row) return 0; + + var indent = this.$getIndent(doc.getLine(openBracePos.row)); + doc.replace(new Range(row, 0, row, column-1), indent); + }; + + this.$getIndent = function(line) { + return line.match(/^\s*/)[0]; + }; + + }).call(MatchingBraceOutdent.prototype); + + exports.MatchingBraceOutdent = MatchingBraceOutdent; + }); + + ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("../../lib/oop"); + var Behaviour = acequire("../behaviour").Behaviour; + var TokenIterator = acequire("../../token_iterator").TokenIterator; + var lang = acequire("../../lib/lang"); + + var SAFE_INSERT_IN_TOKENS = + ["text", "paren.rparen", "punctuation.operator"]; + var SAFE_INSERT_BEFORE_TOKENS = + ["text", "paren.rparen", "punctuation.operator", "comment"]; + + var context; + var contextCache = {}; + var initContext = function(editor) { + var id = -1; + if (editor.multiSelect) { + id = editor.selection.index; + if (contextCache.rangeCount != editor.multiSelect.rangeCount) + contextCache = {rangeCount: editor.multiSelect.rangeCount}; + } + if (contextCache[id]) + return context = contextCache[id]; + context = contextCache[id] = { + autoInsertedBrackets: 0, + autoInsertedRow: -1, + autoInsertedLineEnd: "", + maybeInsertedBrackets: 0, + maybeInsertedRow: -1, + maybeInsertedLineStart: "", + maybeInsertedLineEnd: "" + }; + }; + + var getWrapped = function(selection, selected, opening, closing) { + var rowDiff = selection.end.row - selection.start.row; + return { + text: opening + selected + closing, + selection: [ + 0, + selection.start.column + 1, + rowDiff, + selection.end.column + (rowDiff ? 0 : 1) + ] + }; + }; + + var CstyleBehaviour = function() { + this.add("braces", "insertion", function(state, action, editor, session, text) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + if (text == '{') { + initContext(editor); + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && selected !== "{" && editor.getWrapBehavioursEnabled()) { + return getWrapped(selection, selected, '{', '}'); + } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { + if (/[\]\}\)]/.test(line[cursor.column]) || editor.inMultiSelectMode) { + CstyleBehaviour.recordAutoInsert(editor, session, "}"); + return { + text: '{}', + selection: [1, 1] + }; + } else { + CstyleBehaviour.recordMaybeInsert(editor, session, "{"); + return { + text: '{', + selection: [1, 1] + }; + } + } + } else if (text == '}') { + initContext(editor); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == '}') { + var matching = session.$findOpeningBracket('}', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) { + CstyleBehaviour.popAutoInsertedClosing(); + return { + text: '', + selection: [1, 1] + }; + } + } + } else if (text == "\n" || text == "\r\n") { + initContext(editor); + var closing = ""; + if (CstyleBehaviour.isMaybeInsertedClosing(cursor, line)) { + closing = lang.stringRepeat("}", context.maybeInsertedBrackets); + CstyleBehaviour.clearMaybeInsertedClosing(); + } + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar === '}') { + var openBracePos = session.findMatchingBracket({row: cursor.row, column: cursor.column+1}, '}'); + if (!openBracePos) + return null; + var next_indent = this.$getIndent(session.getLine(openBracePos.row)); + } else if (closing) { + var next_indent = this.$getIndent(line); + } else { + CstyleBehaviour.clearMaybeInsertedClosing(); + return; + } + var indent = next_indent + session.getTabString(); + + return { + text: '\n' + indent + '\n' + next_indent + closing, + selection: [1, indent.length, 1, indent.length] + }; + } else { + CstyleBehaviour.clearMaybeInsertedClosing(); + } + }); + + this.add("braces", "deletion", function(state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '{') { + initContext(editor); + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.end.column, range.end.column + 1); + if (rightChar == '}') { + range.end.column++; + return range; + } else { + context.maybeInsertedBrackets--; + } + } + }); + + this.add("parens", "insertion", function(state, action, editor, session, text) { + if (text == '(') { + initContext(editor); + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && editor.getWrapBehavioursEnabled()) { + return getWrapped(selection, selected, '(', ')'); + } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { + CstyleBehaviour.recordAutoInsert(editor, session, ")"); + return { + text: '()', + selection: [1, 1] + }; + } + } else if (text == ')') { + initContext(editor); + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == ')') { + var matching = session.$findOpeningBracket(')', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) { + CstyleBehaviour.popAutoInsertedClosing(); + return { + text: '', + selection: [1, 1] + }; + } + } + } + }); + + this.add("parens", "deletion", function(state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '(') { + initContext(editor); + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == ')') { + range.end.column++; + return range; + } + } + }); + + this.add("brackets", "insertion", function(state, action, editor, session, text) { + if (text == '[') { + initContext(editor); + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && editor.getWrapBehavioursEnabled()) { + return getWrapped(selection, selected, '[', ']'); + } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { + CstyleBehaviour.recordAutoInsert(editor, session, "]"); + return { + text: '[]', + selection: [1, 1] + }; + } + } else if (text == ']') { + initContext(editor); + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == ']') { + var matching = session.$findOpeningBracket(']', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) { + CstyleBehaviour.popAutoInsertedClosing(); + return { + text: '', + selection: [1, 1] + }; + } + } + } + }); + + this.add("brackets", "deletion", function(state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '[') { + initContext(editor); + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == ']') { + range.end.column++; + return range; + } + } + }); + + this.add("string_dquotes", "insertion", function(state, action, editor, session, text) { + if (text == '"' || text == "'") { + initContext(editor); + var quote = text; + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && selected !== "'" && selected != '"' && editor.getWrapBehavioursEnabled()) { + return getWrapped(selection, selected, quote, quote); + } else if (!selected) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var leftChar = line.substring(cursor.column-1, cursor.column); + var rightChar = line.substring(cursor.column, cursor.column + 1); + + var token = session.getTokenAt(cursor.row, cursor.column); + var rightToken = session.getTokenAt(cursor.row, cursor.column + 1); + if (leftChar == "\\" && token && /escape/.test(token.type)) + return null; + + var stringBefore = token && /string|escape/.test(token.type); + var stringAfter = !rightToken || /string|escape/.test(rightToken.type); + + var pair; + if (rightChar == quote) { + pair = stringBefore !== stringAfter; + } else { + if (stringBefore && !stringAfter) + return null; // wrap string with different quote + if (stringBefore && stringAfter) + return null; // do not pair quotes inside strings + var wordRe = session.$mode.tokenRe; + wordRe.lastIndex = 0; + var isWordBefore = wordRe.test(leftChar); + wordRe.lastIndex = 0; + var isWordAfter = wordRe.test(leftChar); + if (isWordBefore || isWordAfter) + return null; // before or after alphanumeric + if (rightChar && !/[\s;,.})\]\\]/.test(rightChar)) + return null; // there is rightChar and it isn't closing + pair = true; + } + return { + text: pair ? quote + quote : "", + selection: [1,1] + }; + } + } + }); + + this.add("string_dquotes", "deletion", function(state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && (selected == '"' || selected == "'")) { + initContext(editor); + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == selected) { + range.end.column++; + return range; + } + } + }); + + }; + + + CstyleBehaviour.isSaneInsertion = function(editor, session) { + var cursor = editor.getCursorPosition(); + var iterator = new TokenIterator(session, cursor.row, cursor.column); + if (!this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) { + var iterator2 = new TokenIterator(session, cursor.row, cursor.column + 1); + if (!this.$matchTokenType(iterator2.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) + return false; + } + iterator.stepForward(); + return iterator.getCurrentTokenRow() !== cursor.row || + this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_BEFORE_TOKENS); + }; + + CstyleBehaviour.$matchTokenType = function(token, types) { + return types.indexOf(token.type || token) > -1; + }; + + CstyleBehaviour.recordAutoInsert = function(editor, session, bracket) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + if (!this.isAutoInsertedClosing(cursor, line, context.autoInsertedLineEnd[0])) + context.autoInsertedBrackets = 0; + context.autoInsertedRow = cursor.row; + context.autoInsertedLineEnd = bracket + line.substr(cursor.column); + context.autoInsertedBrackets++; + }; + + CstyleBehaviour.recordMaybeInsert = function(editor, session, bracket) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + if (!this.isMaybeInsertedClosing(cursor, line)) + context.maybeInsertedBrackets = 0; + context.maybeInsertedRow = cursor.row; + context.maybeInsertedLineStart = line.substr(0, cursor.column) + bracket; + context.maybeInsertedLineEnd = line.substr(cursor.column); + context.maybeInsertedBrackets++; + }; + + CstyleBehaviour.isAutoInsertedClosing = function(cursor, line, bracket) { + return context.autoInsertedBrackets > 0 && + cursor.row === context.autoInsertedRow && + bracket === context.autoInsertedLineEnd[0] && + line.substr(cursor.column) === context.autoInsertedLineEnd; + }; + + CstyleBehaviour.isMaybeInsertedClosing = function(cursor, line) { + return context.maybeInsertedBrackets > 0 && + cursor.row === context.maybeInsertedRow && + line.substr(cursor.column) === context.maybeInsertedLineEnd && + line.substr(0, cursor.column) == context.maybeInsertedLineStart; + }; + + CstyleBehaviour.popAutoInsertedClosing = function() { + context.autoInsertedLineEnd = context.autoInsertedLineEnd.substr(1); + context.autoInsertedBrackets--; + }; + + CstyleBehaviour.clearMaybeInsertedClosing = function() { + if (context) { + context.maybeInsertedBrackets = 0; + context.maybeInsertedRow = -1; + } + }; + + + + oop.inherits(CstyleBehaviour, Behaviour); + + exports.CstyleBehaviour = CstyleBehaviour; + }); + + ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("../../lib/oop"); + var Range = acequire("../../range").Range; + var BaseFoldMode = acequire("./fold_mode").FoldMode; + + var FoldMode = exports.FoldMode = function(commentRegex) { + if (commentRegex) { + this.foldingStartMarker = new RegExp( + this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start) + ); + this.foldingStopMarker = new RegExp( + this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end) + ); + } + }; + oop.inherits(FoldMode, BaseFoldMode); + + (function() { + + this.foldingStartMarker = /(\{|\[)[^\}\]]*$|^\s*(\/\*)/; + this.foldingStopMarker = /^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/; + this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/; + this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/; + this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/; + this._getFoldWidgetBase = this.getFoldWidget; + this.getFoldWidget = function(session, foldStyle, row) { + var line = session.getLine(row); + + if (this.singleLineBlockCommentRe.test(line)) { + if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line)) + return ""; + } + + var fw = this._getFoldWidgetBase(session, foldStyle, row); + + if (!fw && this.startRegionRe.test(line)) + return "start"; // lineCommentRegionStart + + return fw; + }; + + this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) { + var line = session.getLine(row); + + if (this.startRegionRe.test(line)) + return this.getCommentRegionBlock(session, line, row); + + var match = line.match(this.foldingStartMarker); + if (match) { + var i = match.index; + + if (match[1]) + return this.openingBracketBlock(session, match[1], row, i); + + var range = session.getCommentFoldRange(row, i + match[0].length, 1); + + if (range && !range.isMultiLine()) { + if (forceMultiline) { + range = this.getSectionRange(session, row); + } else if (foldStyle != "all") + range = null; + } + + return range; + } + + if (foldStyle === "markbegin") + return; + + var match = line.match(this.foldingStopMarker); + if (match) { + var i = match.index + match[0].length; + + if (match[1]) + return this.closingBracketBlock(session, match[1], row, i); + + return session.getCommentFoldRange(row, i, -1); + } + }; + + this.getSectionRange = function(session, row) { + var line = session.getLine(row); + var startIndent = line.search(/\S/); + var startRow = row; + var startColumn = line.length; + row = row + 1; + var endRow = row; + var maxRow = session.getLength(); + while (++row < maxRow) { + line = session.getLine(row); + var indent = line.search(/\S/); + if (indent === -1) + continue; + if (startIndent > indent) + break; + var subRange = this.getFoldWidgetRange(session, "all", row); + + if (subRange) { + if (subRange.start.row <= startRow) { + break; + } else if (subRange.isMultiLine()) { + row = subRange.end.row; + } else if (startIndent == indent) { + break; + } + } + endRow = row; + } + + return new Range(startRow, startColumn, endRow, session.getLine(endRow).length); + }; + this.getCommentRegionBlock = function(session, line, row) { + var startColumn = line.search(/\s*$/); + var maxRow = session.getLength(); + var startRow = row; + + var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/; + var depth = 1; + while (++row < maxRow) { + line = session.getLine(row); + var m = re.exec(line); + if (!m) continue; + if (m[1]) depth--; + else depth++; + + if (!depth) break; + } + + var endRow = row; + if (endRow > startRow) { + return new Range(startRow, startColumn, endRow, line.length); + } + }; + + }).call(FoldMode.prototype); + + }); + + ace.define("ace/mode/json",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/json_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle","ace/worker/worker_client"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("../lib/oop"); + var TextMode = acequire("./text").Mode; + var HighlightRules = acequire("./json_highlight_rules").JsonHighlightRules; + var MatchingBraceOutdent = acequire("./matching_brace_outdent").MatchingBraceOutdent; + var CstyleBehaviour = acequire("./behaviour/cstyle").CstyleBehaviour; + var CStyleFoldMode = acequire("./folding/cstyle").FoldMode; + var WorkerClient = acequire("../worker/worker_client").WorkerClient; + + var Mode = function() { + this.HighlightRules = HighlightRules; + this.$outdent = new MatchingBraceOutdent(); + this.$behaviour = new CstyleBehaviour(); + this.foldingRules = new CStyleFoldMode(); + }; + oop.inherits(Mode, TextMode); + + (function() { + + this.getNextLineIndent = function(state, line, tab) { + var indent = this.$getIndent(line); + + if (state == "start") { + var match = line.match(/^.*[\{\(\[]\s*$/); + if (match) { + indent += tab; + } + } + + return indent; + }; + + this.checkOutdent = function(state, line, input) { + return this.$outdent.checkOutdent(line, input); + }; + + this.autoOutdent = function(state, doc, row) { + this.$outdent.autoOutdent(doc, row); + }; + + this.createWorker = function(session) { + var worker = new WorkerClient(["ace"], __webpack_require__(68), "JsonWorker"); + worker.attachToDocument(session.getDocument()); + + worker.on("annotate", function(e) { + session.setAnnotations(e.data); + }); + + worker.on("terminate", function() { + session.clearAnnotations(); + }); + + return worker; + }; + + + this.$id = "ace/mode/json"; + }).call(Mode.prototype); + + exports.Mode = Mode; + }); + + +/***/ }, +/* 68 */ +/***/ function(module, exports) { + + module.exports.id = 'ace/mode/json_worker'; + module.exports.src = "\"no use strict\";(function(window){function resolveModuleId(id,paths){for(var testPath=id,tail=\"\";testPath;){var alias=paths[testPath];if(\"string\"==typeof alias)return alias+tail;if(alias)return alias.location.replace(/\\/*$/,\"/\")+(tail||alias.main||alias.name);if(alias===!1)return\"\";var i=testPath.lastIndexOf(\"/\");if(-1===i)break;tail=testPath.substr(i)+tail,testPath=testPath.slice(0,i)}return id}if(!(void 0!==window.window&&window.document||window.acequire&&window.define)){window.console||(window.console=function(){var msgs=Array.prototype.slice.call(arguments,0);postMessage({type:\"log\",data:msgs})},window.console.error=window.console.warn=window.console.log=window.console.trace=window.console),window.window=window,window.ace=window,window.onerror=function(message,file,line,col,err){postMessage({type:\"error\",data:{message:message,data:err.data,file:file,line:line,col:col,stack:err.stack}})},window.normalizeModule=function(parentId,moduleName){if(-1!==moduleName.indexOf(\"!\")){var chunks=moduleName.split(\"!\");return window.normalizeModule(parentId,chunks[0])+\"!\"+window.normalizeModule(parentId,chunks[1])}if(\".\"==moduleName.charAt(0)){var base=parentId.split(\"/\").slice(0,-1).join(\"/\");for(moduleName=(base?base+\"/\":\"\")+moduleName;-1!==moduleName.indexOf(\".\")&&previous!=moduleName;){var previous=moduleName;moduleName=moduleName.replace(/^\\.\\//,\"\").replace(/\\/\\.\\//,\"/\").replace(/[^\\/]+\\/\\.\\.\\//,\"\")}}return moduleName},window.acequire=function acequire(parentId,id){if(id||(id=parentId,parentId=null),!id.charAt)throw Error(\"worker.js acequire() accepts only (parentId, id) as arguments\");id=window.normalizeModule(parentId,id);var module=window.acequire.modules[id];if(module)return module.initialized||(module.initialized=!0,module.exports=module.factory().exports),module.exports;if(!window.acequire.tlns)return console.log(\"unable to load \"+id);var path=resolveModuleId(id,window.acequire.tlns);return\".js\"!=path.slice(-3)&&(path+=\".js\"),window.acequire.id=id,window.acequire.modules[id]={},importScripts(path),window.acequire(parentId,id)},window.acequire.modules={},window.acequire.tlns={},window.define=function(id,deps,factory){if(2==arguments.length?(factory=deps,\"string\"!=typeof id&&(deps=id,id=window.acequire.id)):1==arguments.length&&(factory=id,deps=[],id=window.acequire.id),\"function\"!=typeof factory)return window.acequire.modules[id]={exports:factory,initialized:!0},void 0;deps.length||(deps=[\"require\",\"exports\",\"module\"]);var req=function(childId){return window.acequire(id,childId)};window.acequire.modules[id]={exports:{},factory:function(){var module=this,returnExports=factory.apply(this,deps.map(function(dep){switch(dep){case\"require\":return req;case\"exports\":return module.exports;case\"module\":return module;default:return req(dep)}}));return returnExports&&(module.exports=returnExports),module}}},window.define.amd={},acequire.tlns={},window.initBaseUrls=function(topLevelNamespaces){for(var i in topLevelNamespaces)acequire.tlns[i]=topLevelNamespaces[i]},window.initSender=function(){var EventEmitter=window.acequire(\"ace/lib/event_emitter\").EventEmitter,oop=window.acequire(\"ace/lib/oop\"),Sender=function(){};return function(){oop.implement(this,EventEmitter),this.callback=function(data,callbackId){postMessage({type:\"call\",id:callbackId,data:data})},this.emit=function(name,data){postMessage({type:\"event\",name:name,data:data})}}.call(Sender.prototype),new Sender};var main=window.main=null,sender=window.sender=null;window.onmessage=function(e){var msg=e.data;if(msg.event&&sender)sender._signal(msg.event,msg.data);else if(msg.command)if(main[msg.command])main[msg.command].apply(main,msg.args);else{if(!window[msg.command])throw Error(\"Unknown command:\"+msg.command);window[msg.command].apply(window,msg.args)}else if(msg.init){window.initBaseUrls(msg.tlns),acequire(\"ace/lib/es5-shim\"),sender=window.sender=window.initSender();var clazz=acequire(msg.module)[msg.classname];main=window.main=new clazz(sender)}}}})(this),ace.define(\"ace/lib/oop\",[\"require\",\"exports\",\"module\"],function(acequire,exports){\"use strict\";exports.inherits=function(ctor,superCtor){ctor.super_=superCtor,ctor.prototype=Object.create(superCtor.prototype,{constructor:{value:ctor,enumerable:!1,writable:!0,configurable:!0}})},exports.mixin=function(obj,mixin){for(var key in mixin)obj[key]=mixin[key];return obj},exports.implement=function(proto,mixin){exports.mixin(proto,mixin)}}),ace.define(\"ace/range\",[\"require\",\"exports\",\"module\"],function(acequire,exports){\"use strict\";var comparePoints=function(p1,p2){return p1.row-p2.row||p1.column-p2.column},Range=function(startRow,startColumn,endRow,endColumn){this.start={row:startRow,column:startColumn},this.end={row:endRow,column:endColumn}};(function(){this.isEqual=function(range){return this.start.row===range.start.row&&this.end.row===range.end.row&&this.start.column===range.start.column&&this.end.column===range.end.column},this.toString=function(){return\"Range: [\"+this.start.row+\"/\"+this.start.column+\"] -> [\"+this.end.row+\"/\"+this.end.column+\"]\"},this.contains=function(row,column){return 0==this.compare(row,column)},this.compareRange=function(range){var cmp,end=range.end,start=range.start;return cmp=this.compare(end.row,end.column),1==cmp?(cmp=this.compare(start.row,start.column),1==cmp?2:0==cmp?1:0):-1==cmp?-2:(cmp=this.compare(start.row,start.column),-1==cmp?-1:1==cmp?42:0)},this.comparePoint=function(p){return this.compare(p.row,p.column)},this.containsRange=function(range){return 0==this.comparePoint(range.start)&&0==this.comparePoint(range.end)},this.intersects=function(range){var cmp=this.compareRange(range);return-1==cmp||0==cmp||1==cmp},this.isEnd=function(row,column){return this.end.row==row&&this.end.column==column},this.isStart=function(row,column){return this.start.row==row&&this.start.column==column},this.setStart=function(row,column){\"object\"==typeof row?(this.start.column=row.column,this.start.row=row.row):(this.start.row=row,this.start.column=column)},this.setEnd=function(row,column){\"object\"==typeof row?(this.end.column=row.column,this.end.row=row.row):(this.end.row=row,this.end.column=column)},this.inside=function(row,column){return 0==this.compare(row,column)?this.isEnd(row,column)||this.isStart(row,column)?!1:!0:!1},this.insideStart=function(row,column){return 0==this.compare(row,column)?this.isEnd(row,column)?!1:!0:!1},this.insideEnd=function(row,column){return 0==this.compare(row,column)?this.isStart(row,column)?!1:!0:!1},this.compare=function(row,column){return this.isMultiLine()||row!==this.start.row?this.start.row>row?-1:row>this.end.row?1:this.start.row===row?column>=this.start.column?0:-1:this.end.row===row?this.end.column>=column?0:1:0:this.start.column>column?-1:column>this.end.column?1:0},this.compareStart=function(row,column){return this.start.row==row&&this.start.column==column?-1:this.compare(row,column)},this.compareEnd=function(row,column){return this.end.row==row&&this.end.column==column?1:this.compare(row,column)},this.compareInside=function(row,column){return this.end.row==row&&this.end.column==column?1:this.start.row==row&&this.start.column==column?-1:this.compare(row,column)},this.clipRows=function(firstRow,lastRow){if(this.end.row>lastRow)var end={row:lastRow+1,column:0};else if(firstRow>this.end.row)var end={row:firstRow,column:0};if(this.start.row>lastRow)var start={row:lastRow+1,column:0};else if(firstRow>this.start.row)var start={row:firstRow,column:0};return Range.fromPoints(start||this.start,end||this.end)},this.extend=function(row,column){var cmp=this.compare(row,column);if(0==cmp)return this;if(-1==cmp)var start={row:row,column:column};else var end={row:row,column:column};return Range.fromPoints(start||this.start,end||this.end)},this.isEmpty=function(){return this.start.row===this.end.row&&this.start.column===this.end.column},this.isMultiLine=function(){return this.start.row!==this.end.row},this.clone=function(){return Range.fromPoints(this.start,this.end)},this.collapseRows=function(){return 0==this.end.column?new Range(this.start.row,0,Math.max(this.start.row,this.end.row-1),0):new Range(this.start.row,0,this.end.row,0)},this.toScreenRange=function(session){var screenPosStart=session.documentToScreenPosition(this.start),screenPosEnd=session.documentToScreenPosition(this.end);return new Range(screenPosStart.row,screenPosStart.column,screenPosEnd.row,screenPosEnd.column)},this.moveBy=function(row,column){this.start.row+=row,this.start.column+=column,this.end.row+=row,this.end.column+=column}}).call(Range.prototype),Range.fromPoints=function(start,end){return new Range(start.row,start.column,end.row,end.column)},Range.comparePoints=comparePoints,Range.comparePoints=function(p1,p2){return p1.row-p2.row||p1.column-p2.column},exports.Range=Range}),ace.define(\"ace/apply_delta\",[\"require\",\"exports\",\"module\"],function(acequire,exports){\"use strict\";exports.applyDelta=function(docLines,delta){var row=delta.start.row,startColumn=delta.start.column,line=docLines[row]||\"\";switch(delta.action){case\"insert\":var lines=delta.lines;if(1===lines.length)docLines[row]=line.substring(0,startColumn)+delta.lines[0]+line.substring(startColumn);else{var args=[row,1].concat(delta.lines);docLines.splice.apply(docLines,args),docLines[row]=line.substring(0,startColumn)+docLines[row],docLines[row+delta.lines.length-1]+=line.substring(startColumn)}break;case\"remove\":var endColumn=delta.end.column,endRow=delta.end.row;row===endRow?docLines[row]=line.substring(0,startColumn)+line.substring(endColumn):docLines.splice(row,endRow-row+1,line.substring(0,startColumn)+docLines[endRow].substring(endColumn))}}}),ace.define(\"ace/lib/event_emitter\",[\"require\",\"exports\",\"module\"],function(acequire,exports){\"use strict\";var EventEmitter={},stopPropagation=function(){this.propagationStopped=!0},preventDefault=function(){this.defaultPrevented=!0};EventEmitter._emit=EventEmitter._dispatchEvent=function(eventName,e){this._eventRegistry||(this._eventRegistry={}),this._defaultHandlers||(this._defaultHandlers={});var listeners=this._eventRegistry[eventName]||[],defaultHandler=this._defaultHandlers[eventName];if(listeners.length||defaultHandler){\"object\"==typeof e&&e||(e={}),e.type||(e.type=eventName),e.stopPropagation||(e.stopPropagation=stopPropagation),e.preventDefault||(e.preventDefault=preventDefault),listeners=listeners.slice();for(var i=0;listeners.length>i&&(listeners[i](e,this),!e.propagationStopped);i++);return defaultHandler&&!e.defaultPrevented?defaultHandler(e,this):void 0}},EventEmitter._signal=function(eventName,e){var listeners=(this._eventRegistry||{})[eventName];if(listeners){listeners=listeners.slice();for(var i=0;listeners.length>i;i++)listeners[i](e,this)}},EventEmitter.once=function(eventName,callback){var _self=this;callback&&this.addEventListener(eventName,function newCallback(){_self.removeEventListener(eventName,newCallback),callback.apply(null,arguments)})},EventEmitter.setDefaultHandler=function(eventName,callback){var handlers=this._defaultHandlers;if(handlers||(handlers=this._defaultHandlers={_disabled_:{}}),handlers[eventName]){var old=handlers[eventName],disabled=handlers._disabled_[eventName];disabled||(handlers._disabled_[eventName]=disabled=[]),disabled.push(old);var i=disabled.indexOf(callback);-1!=i&&disabled.splice(i,1)}handlers[eventName]=callback},EventEmitter.removeDefaultHandler=function(eventName,callback){var handlers=this._defaultHandlers;if(handlers){var disabled=handlers._disabled_[eventName];if(handlers[eventName]==callback)handlers[eventName],disabled&&this.setDefaultHandler(eventName,disabled.pop());else if(disabled){var i=disabled.indexOf(callback);-1!=i&&disabled.splice(i,1)}}},EventEmitter.on=EventEmitter.addEventListener=function(eventName,callback,capturing){this._eventRegistry=this._eventRegistry||{};var listeners=this._eventRegistry[eventName];return listeners||(listeners=this._eventRegistry[eventName]=[]),-1==listeners.indexOf(callback)&&listeners[capturing?\"unshift\":\"push\"](callback),callback},EventEmitter.off=EventEmitter.removeListener=EventEmitter.removeEventListener=function(eventName,callback){this._eventRegistry=this._eventRegistry||{};var listeners=this._eventRegistry[eventName];if(listeners){var index=listeners.indexOf(callback);-1!==index&&listeners.splice(index,1)}},EventEmitter.removeAllListeners=function(eventName){this._eventRegistry&&(this._eventRegistry[eventName]=[])},exports.EventEmitter=EventEmitter}),ace.define(\"ace/anchor\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/event_emitter\"],function(acequire,exports){\"use strict\";var oop=acequire(\"./lib/oop\"),EventEmitter=acequire(\"./lib/event_emitter\").EventEmitter,Anchor=exports.Anchor=function(doc,row,column){this.$onChange=this.onChange.bind(this),this.attach(doc),column===void 0?this.setPosition(row.row,row.column):this.setPosition(row,column)};(function(){function $pointsInOrder(point1,point2,equalPointsInOrder){var bColIsAfter=equalPointsInOrder?point1.column<=point2.column:point1.columnthis.row)){var point=$getTransformedPoint(delta,{row:this.row,column:this.column},this.$insertRight);this.setPosition(point.row,point.column,!0)}},this.setPosition=function(row,column,noClip){var pos;if(pos=noClip?{row:row,column:column}:this.$clipPositionToDocument(row,column),this.row!=pos.row||this.column!=pos.column){var old={row:this.row,column:this.column};this.row=pos.row,this.column=pos.column,this._signal(\"change\",{old:old,value:pos})}},this.detach=function(){this.document.removeEventListener(\"change\",this.$onChange)},this.attach=function(doc){this.document=doc||this.document,this.document.on(\"change\",this.$onChange)},this.$clipPositionToDocument=function(row,column){var pos={};return row>=this.document.getLength()?(pos.row=Math.max(0,this.document.getLength()-1),pos.column=this.document.getLine(pos.row).length):0>row?(pos.row=0,pos.column=0):(pos.row=row,pos.column=Math.min(this.document.getLine(pos.row).length,Math.max(0,column))),0>column&&(pos.column=0),pos}}).call(Anchor.prototype)}),ace.define(\"ace/document\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/apply_delta\",\"ace/lib/event_emitter\",\"ace/range\",\"ace/anchor\"],function(acequire,exports){\"use strict\";var oop=acequire(\"./lib/oop\"),applyDelta=acequire(\"./apply_delta\").applyDelta,EventEmitter=acequire(\"./lib/event_emitter\").EventEmitter,Range=acequire(\"./range\").Range,Anchor=acequire(\"./anchor\").Anchor,Document=function(textOrLines){this.$lines=[\"\"],0===textOrLines.length?this.$lines=[\"\"]:Array.isArray(textOrLines)?this.insertMergedLines({row:0,column:0},textOrLines):this.insert({row:0,column:0},textOrLines)};(function(){oop.implement(this,EventEmitter),this.setValue=function(text){var len=this.getLength()-1;this.remove(new Range(0,0,len,this.getLine(len).length)),this.insert({row:0,column:0},text)},this.getValue=function(){return this.getAllLines().join(this.getNewLineCharacter())},this.createAnchor=function(row,column){return new Anchor(this,row,column)},this.$split=0===\"aaa\".split(/a/).length?function(text){return text.replace(/\\r\\n|\\r/g,\"\\n\").split(\"\\n\")}:function(text){return text.split(/\\r\\n|\\r|\\n/)},this.$detectNewLine=function(text){var match=text.match(/^.*?(\\r\\n|\\r|\\n)/m);this.$autoNewLine=match?match[1]:\"\\n\",this._signal(\"changeNewLineMode\")},this.getNewLineCharacter=function(){switch(this.$newLineMode){case\"windows\":return\"\\r\\n\";case\"unix\":return\"\\n\";default:return this.$autoNewLine||\"\\n\"}},this.$autoNewLine=\"\",this.$newLineMode=\"auto\",this.setNewLineMode=function(newLineMode){this.$newLineMode!==newLineMode&&(this.$newLineMode=newLineMode,this._signal(\"changeNewLineMode\"))},this.getNewLineMode=function(){return this.$newLineMode},this.isNewLine=function(text){return\"\\r\\n\"==text||\"\\r\"==text||\"\\n\"==text},this.getLine=function(row){return this.$lines[row]||\"\"},this.getLines=function(firstRow,lastRow){return this.$lines.slice(firstRow,lastRow+1)},this.getAllLines=function(){return this.getLines(0,this.getLength())},this.getLength=function(){return this.$lines.length},this.getTextRange=function(range){return this.getLinesForRange(range).join(this.getNewLineCharacter())},this.getLinesForRange=function(range){var lines;if(range.start.row===range.end.row)lines=[this.getLine(range.start.row).substring(range.start.column,range.end.column)];else{lines=this.getLines(range.start.row,range.end.row),lines[0]=(lines[0]||\"\").substring(range.start.column);var l=lines.length-1;range.end.row-range.start.row==l&&(lines[l]=lines[l].substring(0,range.end.column))}return lines},this.insertLines=function(row,lines){return console.warn(\"Use of document.insertLines is deprecated. Use the insertFullLines method instead.\"),this.insertFullLines(row,lines)},this.removeLines=function(firstRow,lastRow){return console.warn(\"Use of document.removeLines is deprecated. Use the removeFullLines method instead.\"),this.removeFullLines(firstRow,lastRow)},this.insertNewLine=function(position){return console.warn(\"Use of document.insertNewLine is deprecated. Use insertMergedLines(position, ['', '']) instead.\"),this.insertMergedLines(position,[\"\",\"\"])},this.insert=function(position,text){return 1>=this.getLength()&&this.$detectNewLine(text),this.insertMergedLines(position,this.$split(text))},this.insertInLine=function(position,text){var start=this.clippedPos(position.row,position.column),end=this.pos(position.row,position.column+text.length);return this.applyDelta({start:start,end:end,action:\"insert\",lines:[text]},!0),this.clonePos(end)},this.clippedPos=function(row,column){var length=this.getLength();void 0===row?row=length:0>row?row=0:row>=length&&(row=length-1,column=void 0);var line=this.getLine(row);return void 0==column&&(column=line.length),column=Math.min(Math.max(column,0),line.length),{row:row,column:column}},this.clonePos=function(pos){return{row:pos.row,column:pos.column}},this.pos=function(row,column){return{row:row,column:column}},this.$clipPosition=function(position){var length=this.getLength();return position.row>=length?(position.row=Math.max(0,length-1),position.column=this.getLine(length-1).length):(position.row=Math.max(0,position.row),position.column=Math.min(Math.max(position.column,0),this.getLine(position.row).length)),position},this.insertFullLines=function(row,lines){row=Math.min(Math.max(row,0),this.getLength());var column=0;this.getLength()>row?(lines=lines.concat([\"\"]),column=0):(lines=[\"\"].concat(lines),row--,column=this.$lines[row].length),this.insertMergedLines({row:row,column:column},lines)},this.insertMergedLines=function(position,lines){var start=this.clippedPos(position.row,position.column),end={row:start.row+lines.length-1,column:(1==lines.length?start.column:0)+lines[lines.length-1].length};return this.applyDelta({start:start,end:end,action:\"insert\",lines:lines}),this.clonePos(end)},this.remove=function(range){var start=this.clippedPos(range.start.row,range.start.column),end=this.clippedPos(range.end.row,range.end.column);return this.applyDelta({start:start,end:end,action:\"remove\",lines:this.getLinesForRange({start:start,end:end})}),this.clonePos(start)},this.removeInLine=function(row,startColumn,endColumn){var start=this.clippedPos(row,startColumn),end=this.clippedPos(row,endColumn);return this.applyDelta({start:start,end:end,action:\"remove\",lines:this.getLinesForRange({start:start,end:end})},!0),this.clonePos(start)},this.removeFullLines=function(firstRow,lastRow){firstRow=Math.min(Math.max(0,firstRow),this.getLength()-1),lastRow=Math.min(Math.max(0,lastRow),this.getLength()-1);var deleteFirstNewLine=lastRow==this.getLength()-1&&firstRow>0,deleteLastNewLine=this.getLength()-1>lastRow,startRow=deleteFirstNewLine?firstRow-1:firstRow,startCol=deleteFirstNewLine?this.getLine(startRow).length:0,endRow=deleteLastNewLine?lastRow+1:lastRow,endCol=deleteLastNewLine?0:this.getLine(endRow).length,range=new Range(startRow,startCol,endRow,endCol),deletedLines=this.$lines.slice(firstRow,lastRow+1);return this.applyDelta({start:range.start,end:range.end,action:\"remove\",lines:this.getLinesForRange(range)}),deletedLines},this.removeNewLine=function(row){this.getLength()-1>row&&row>=0&&this.applyDelta({start:this.pos(row,this.getLine(row).length),end:this.pos(row+1,0),action:\"remove\",lines:[\"\",\"\"]})},this.replace=function(range,text){if(range instanceof Range||(range=Range.fromPoints(range.start,range.end)),0===text.length&&range.isEmpty())return range.start;if(text==this.getTextRange(range))return range.end;this.remove(range);var end;return end=text?this.insert(range.start,text):range.start},this.applyDeltas=function(deltas){for(var i=0;deltas.length>i;i++)this.applyDelta(deltas[i])},this.revertDeltas=function(deltas){for(var i=deltas.length-1;i>=0;i--)this.revertDelta(deltas[i])},this.applyDelta=function(delta,doNotValidate){var isInsert=\"insert\"==delta.action;(isInsert?1>=delta.lines.length&&!delta.lines[0]:!Range.comparePoints(delta.start,delta.end))||(isInsert&&delta.lines.length>2e4&&this.$splitAndapplyLargeDelta(delta,2e4),applyDelta(this.$lines,delta,doNotValidate),this._signal(\"change\",delta))},this.$splitAndapplyLargeDelta=function(delta,MAX){for(var lines=delta.lines,l=lines.length,row=delta.start.row,column=delta.start.column,from=0,to=0;;){from=to,to+=MAX-1;var chunk=lines.slice(from,to);if(to>l){delta.lines=chunk,delta.start.row=row+from,delta.start.column=column;break}chunk.push(\"\"),this.applyDelta({start:this.pos(row+from,column),end:this.pos(row+to,column=0),action:delta.action,lines:chunk},!0)}},this.revertDelta=function(delta){this.applyDelta({start:this.clonePos(delta.start),end:this.clonePos(delta.end),action:\"insert\"==delta.action?\"remove\":\"insert\",lines:delta.lines.slice()})},this.indexToPosition=function(index,startRow){for(var lines=this.$lines||this.getAllLines(),newlineLength=this.getNewLineCharacter().length,i=startRow||0,l=lines.length;l>i;i++)if(index-=lines[i].length+newlineLength,0>index)return{row:i,column:index+lines[i].length+newlineLength};return{row:l-1,column:lines[l-1].length}},this.positionToIndex=function(pos,startRow){for(var lines=this.$lines||this.getAllLines(),newlineLength=this.getNewLineCharacter().length,index=0,row=Math.min(pos.row,lines.length),i=startRow||0;row>i;++i)index+=lines[i].length+newlineLength;return index+pos.column}}).call(Document.prototype),exports.Document=Document}),ace.define(\"ace/lib/lang\",[\"require\",\"exports\",\"module\"],function(acequire,exports){\"use strict\";exports.last=function(a){return a[a.length-1]},exports.stringReverse=function(string){return string.split(\"\").reverse().join(\"\")},exports.stringRepeat=function(string,count){for(var result=\"\";count>0;)1&count&&(result+=string),(count>>=1)&&(string+=string);return result};var trimBeginRegexp=/^\\s\\s*/,trimEndRegexp=/\\s\\s*$/;exports.stringTrimLeft=function(string){return string.replace(trimBeginRegexp,\"\")},exports.stringTrimRight=function(string){return string.replace(trimEndRegexp,\"\")},exports.copyObject=function(obj){var copy={};for(var key in obj)copy[key]=obj[key];return copy},exports.copyArray=function(array){for(var copy=[],i=0,l=array.length;l>i;i++)copy[i]=array[i]&&\"object\"==typeof array[i]?this.copyObject(array[i]):array[i];return copy},exports.deepCopy=function deepCopy(obj){if(\"object\"!=typeof obj||!obj)return obj;var copy;if(Array.isArray(obj)){copy=[];for(var key=0;obj.length>key;key++)copy[key]=deepCopy(obj[key]);return copy}var cons=obj.constructor;if(cons===RegExp)return obj;copy=cons();for(var key in obj)copy[key]=deepCopy(obj[key]);return copy},exports.arrayToMap=function(arr){for(var map={},i=0;arr.length>i;i++)map[arr[i]]=1;return map},exports.createMap=function(props){var map=Object.create(null);for(var i in props)map[i]=props[i];return map},exports.arrayRemove=function(array,value){for(var i=0;array.length>=i;i++)value===array[i]&&array.splice(i,1)},exports.escapeRegExp=function(str){return str.replace(/([.*+?^${}()|[\\]\\/\\\\])/g,\"\\\\$1\")},exports.escapeHTML=function(str){return str.replace(/&/g,\"&\").replace(/\"/g,\""\").replace(/'/g,\"'\").replace(/i;i+=2){if(Array.isArray(data[i+1]))var d={action:\"insert\",start:data[i],lines:data[i+1]};else var d={action:\"remove\",start:data[i],end:data[i+1]};doc.applyDelta(d,!0)}return _self.$timeout?deferredUpdate.schedule(_self.$timeout):(_self.onUpdate(),void 0)})};(function(){this.$timeout=500,this.setTimeout=function(timeout){this.$timeout=timeout},this.setValue=function(value){this.doc.setValue(value),this.deferredUpdate.schedule(this.$timeout)},this.getValue=function(callbackId){this.sender.callback(this.doc.getValue(),callbackId)},this.onUpdate=function(){},this.isPending=function(){return this.deferredUpdate.isPending()}}).call(Mirror.prototype)}),ace.define(\"ace/mode/json/json_parse\",[\"require\",\"exports\",\"module\"],function(){\"use strict\";var at,ch,text,value,escapee={'\"':'\"',\"\\\\\":\"\\\\\",\"/\":\"/\",b:\"\\b\",f:\"\\f\",n:\"\\n\",r:\"\\r\",t:\"\t\"},error=function(m){throw{name:\"SyntaxError\",message:m,at:at,text:text}},next=function(c){return c&&c!==ch&&error(\"Expected '\"+c+\"' instead of '\"+ch+\"'\"),ch=text.charAt(at),at+=1,ch},number=function(){var number,string=\"\";for(\"-\"===ch&&(string=\"-\",next(\"-\"));ch>=\"0\"&&\"9\">=ch;)string+=ch,next();if(\".\"===ch)for(string+=\".\";next()&&ch>=\"0\"&&\"9\">=ch;)string+=ch;if(\"e\"===ch||\"E\"===ch)for(string+=ch,next(),(\"-\"===ch||\"+\"===ch)&&(string+=ch,next());ch>=\"0\"&&\"9\">=ch;)string+=ch,next();return number=+string,isNaN(number)?(error(\"Bad number\"),void 0):number},string=function(){var hex,i,uffff,string=\"\";if('\"'===ch)for(;next();){if('\"'===ch)return next(),string;if(\"\\\\\"===ch)if(next(),\"u\"===ch){for(uffff=0,i=0;4>i&&(hex=parseInt(next(),16),isFinite(hex));i+=1)uffff=16*uffff+hex;string+=String.fromCharCode(uffff)}else{if(\"string\"!=typeof escapee[ch])break;string+=escapee[ch]}else string+=ch}error(\"Bad string\")},white=function(){for(;ch&&\" \">=ch;)next()},word=function(){switch(ch){case\"t\":return next(\"t\"),next(\"r\"),next(\"u\"),next(\"e\"),!0;case\"f\":return next(\"f\"),next(\"a\"),next(\"l\"),next(\"s\"),next(\"e\"),!1;case\"n\":return next(\"n\"),next(\"u\"),next(\"l\"),next(\"l\"),null}error(\"Unexpected '\"+ch+\"'\")},array=function(){var array=[];if(\"[\"===ch){if(next(\"[\"),white(),\"]\"===ch)return next(\"]\"),array;for(;ch;){if(array.push(value()),white(),\"]\"===ch)return next(\"]\"),array;next(\",\"),white()}}error(\"Bad array\")},object=function(){var key,object={};if(\"{\"===ch){if(next(\"{\"),white(),\"}\"===ch)return next(\"}\"),object;for(;ch;){if(key=string(),white(),next(\":\"),Object.hasOwnProperty.call(object,key)&&error('Duplicate key \"'+key+'\"'),object[key]=value(),white(),\"}\"===ch)return next(\"}\"),object;next(\",\"),white()}}error(\"Bad object\")};return value=function(){switch(white(),ch){case\"{\":return object();case\"[\":return array();case'\"':return string();case\"-\":return number();default:return ch>=\"0\"&&\"9\">=ch?number():word()}},function(source,reviver){var result;return text=source,at=0,ch=\" \",result=value(),white(),ch&&error(\"Syntax error\"),\"function\"==typeof reviver?function walk(holder,key){var k,v,value=holder[key];if(value&&\"object\"==typeof value)for(k in value)Object.hasOwnProperty.call(value,k)&&(v=walk(value,k),void 0!==v?value[k]=v:delete value[k]);return reviver.call(holder,key,value)}({\"\":result},\"\"):result}}),ace.define(\"ace/mode/json_worker\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/worker/mirror\",\"ace/mode/json/json_parse\"],function(acequire,exports){\"use strict\";var oop=acequire(\"../lib/oop\"),Mirror=acequire(\"../worker/mirror\").Mirror,parse=acequire(\"./json/json_parse\"),JsonWorker=exports.JsonWorker=function(sender){Mirror.call(this,sender),this.setTimeout(200)};oop.inherits(JsonWorker,Mirror),function(){this.onUpdate=function(){var value=this.doc.getValue(),errors=[];try{value&&parse(value)}catch(e){var pos=this.doc.indexToPosition(e.at-1);errors.push({row:pos.row,column:pos.column,text:e.message,type:\"error\"})}this.sender.emit(\"annotate\",errors)}}.call(JsonWorker.prototype)}),ace.define(\"ace/lib/es5-shim\",[\"require\",\"exports\",\"module\"],function(){function Empty(){}function doesDefinePropertyWork(object){try{return Object.defineProperty(object,\"sentinel\",{}),\"sentinel\"in object}catch(exception){}}function toInteger(n){return n=+n,n!==n?n=0:0!==n&&n!==1/0&&n!==-(1/0)&&(n=(n>0||-1)*Math.floor(Math.abs(n))),n}Function.prototype.bind||(Function.prototype.bind=function(that){var target=this;if(\"function\"!=typeof target)throw new TypeError(\"Function.prototype.bind called on incompatible \"+target);var args=slice.call(arguments,1),bound=function(){if(this instanceof bound){var result=target.apply(this,args.concat(slice.call(arguments)));return Object(result)===result?result:this}return target.apply(that,args.concat(slice.call(arguments)))};return target.prototype&&(Empty.prototype=target.prototype,bound.prototype=new Empty,Empty.prototype=null),bound});var defineGetter,defineSetter,lookupGetter,lookupSetter,supportsAccessors,call=Function.prototype.call,prototypeOfArray=Array.prototype,prototypeOfObject=Object.prototype,slice=prototypeOfArray.slice,_toString=call.bind(prototypeOfObject.toString),owns=call.bind(prototypeOfObject.hasOwnProperty);if((supportsAccessors=owns(prototypeOfObject,\"__defineGetter__\"))&&(defineGetter=call.bind(prototypeOfObject.__defineGetter__),defineSetter=call.bind(prototypeOfObject.__defineSetter__),lookupGetter=call.bind(prototypeOfObject.__lookupGetter__),lookupSetter=call.bind(prototypeOfObject.__lookupSetter__)),2!=[1,2].splice(0).length)if(function(){function makeArray(l){var a=Array(l+2);return a[0]=a[1]=0,a}var lengthBefore,array=[];return array.splice.apply(array,makeArray(20)),array.splice.apply(array,makeArray(26)),lengthBefore=array.length,array.splice(5,0,\"XXX\"),lengthBefore+1==array.length,lengthBefore+1==array.length?!0:void 0\n}()){var array_splice=Array.prototype.splice;Array.prototype.splice=function(start,deleteCount){return arguments.length?array_splice.apply(this,[void 0===start?0:start,void 0===deleteCount?this.length-start:deleteCount].concat(slice.call(arguments,2))):[]}}else Array.prototype.splice=function(pos,removeCount){var length=this.length;pos>0?pos>length&&(pos=length):void 0==pos?pos=0:0>pos&&(pos=Math.max(length+pos,0)),length>pos+removeCount||(removeCount=length-pos);var removed=this.slice(pos,pos+removeCount),insert=slice.call(arguments,2),add=insert.length;if(pos===length)add&&this.push.apply(this,insert);else{var remove=Math.min(removeCount,length-pos),tailOldPos=pos+remove,tailNewPos=tailOldPos+add-remove,tailCount=length-tailOldPos,lengthAfterRemove=length-remove;if(tailOldPos>tailNewPos)for(var i=0;tailCount>i;++i)this[tailNewPos+i]=this[tailOldPos+i];else if(tailNewPos>tailOldPos)for(i=tailCount;i--;)this[tailNewPos+i]=this[tailOldPos+i];if(add&&pos===lengthAfterRemove)this.length=lengthAfterRemove,this.push.apply(this,insert);else for(this.length=lengthAfterRemove+add,i=0;add>i;++i)this[pos+i]=insert[i]}return removed};Array.isArray||(Array.isArray=function(obj){return\"[object Array]\"==_toString(obj)});var boxedString=Object(\"a\"),splitString=\"a\"!=boxedString[0]||!(0 in boxedString);if(Array.prototype.forEach||(Array.prototype.forEach=function(fun){var object=toObject(this),self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):object,thisp=arguments[1],i=-1,length=self.length>>>0;if(\"[object Function]\"!=_toString(fun))throw new TypeError;for(;length>++i;)i in self&&fun.call(thisp,self[i],i,object)}),Array.prototype.map||(Array.prototype.map=function(fun){var object=toObject(this),self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):object,length=self.length>>>0,result=Array(length),thisp=arguments[1];if(\"[object Function]\"!=_toString(fun))throw new TypeError(fun+\" is not a function\");for(var i=0;length>i;i++)i in self&&(result[i]=fun.call(thisp,self[i],i,object));return result}),Array.prototype.filter||(Array.prototype.filter=function(fun){var value,object=toObject(this),self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):object,length=self.length>>>0,result=[],thisp=arguments[1];if(\"[object Function]\"!=_toString(fun))throw new TypeError(fun+\" is not a function\");for(var i=0;length>i;i++)i in self&&(value=self[i],fun.call(thisp,value,i,object)&&result.push(value));return result}),Array.prototype.every||(Array.prototype.every=function(fun){var object=toObject(this),self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):object,length=self.length>>>0,thisp=arguments[1];if(\"[object Function]\"!=_toString(fun))throw new TypeError(fun+\" is not a function\");for(var i=0;length>i;i++)if(i in self&&!fun.call(thisp,self[i],i,object))return!1;return!0}),Array.prototype.some||(Array.prototype.some=function(fun){var object=toObject(this),self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):object,length=self.length>>>0,thisp=arguments[1];if(\"[object Function]\"!=_toString(fun))throw new TypeError(fun+\" is not a function\");for(var i=0;length>i;i++)if(i in self&&fun.call(thisp,self[i],i,object))return!0;return!1}),Array.prototype.reduce||(Array.prototype.reduce=function(fun){var object=toObject(this),self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):object,length=self.length>>>0;if(\"[object Function]\"!=_toString(fun))throw new TypeError(fun+\" is not a function\");if(!length&&1==arguments.length)throw new TypeError(\"reduce of empty array with no initial value\");var result,i=0;if(arguments.length>=2)result=arguments[1];else for(;;){if(i in self){result=self[i++];break}if(++i>=length)throw new TypeError(\"reduce of empty array with no initial value\")}for(;length>i;i++)i in self&&(result=fun.call(void 0,result,self[i],i,object));return result}),Array.prototype.reduceRight||(Array.prototype.reduceRight=function(fun){var object=toObject(this),self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):object,length=self.length>>>0;if(\"[object Function]\"!=_toString(fun))throw new TypeError(fun+\" is not a function\");if(!length&&1==arguments.length)throw new TypeError(\"reduceRight of empty array with no initial value\");var result,i=length-1;if(arguments.length>=2)result=arguments[1];else for(;;){if(i in self){result=self[i--];break}if(0>--i)throw new TypeError(\"reduceRight of empty array with no initial value\")}do i in this&&(result=fun.call(void 0,result,self[i],i,object));while(i--);return result}),Array.prototype.indexOf&&-1==[0,1].indexOf(1,2)||(Array.prototype.indexOf=function(sought){var self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):toObject(this),length=self.length>>>0;if(!length)return-1;var i=0;for(arguments.length>1&&(i=toInteger(arguments[1])),i=i>=0?i:Math.max(0,length+i);length>i;i++)if(i in self&&self[i]===sought)return i;return-1}),Array.prototype.lastIndexOf&&-1==[0,1].lastIndexOf(0,-3)||(Array.prototype.lastIndexOf=function(sought){var self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):toObject(this),length=self.length>>>0;if(!length)return-1;var i=length-1;for(arguments.length>1&&(i=Math.min(i,toInteger(arguments[1]))),i=i>=0?i:length-Math.abs(i);i>=0;i--)if(i in self&&sought===self[i])return i;return-1}),Object.getPrototypeOf||(Object.getPrototypeOf=function(object){return object.__proto__||(object.constructor?object.constructor.prototype:prototypeOfObject)}),!Object.getOwnPropertyDescriptor){var ERR_NON_OBJECT=\"Object.getOwnPropertyDescriptor called on a non-object: \";Object.getOwnPropertyDescriptor=function(object,property){if(\"object\"!=typeof object&&\"function\"!=typeof object||null===object)throw new TypeError(ERR_NON_OBJECT+object);if(owns(object,property)){var descriptor,getter,setter;if(descriptor={enumerable:!0,configurable:!0},supportsAccessors){var prototype=object.__proto__;object.__proto__=prototypeOfObject;var getter=lookupGetter(object,property),setter=lookupSetter(object,property);if(object.__proto__=prototype,getter||setter)return getter&&(descriptor.get=getter),setter&&(descriptor.set=setter),descriptor}return descriptor.value=object[property],descriptor}}}if(Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(object){return Object.keys(object)}),!Object.create){var createEmpty;createEmpty=null===Object.prototype.__proto__?function(){return{__proto__:null}}:function(){var empty={};for(var i in empty)empty[i]=null;return empty.constructor=empty.hasOwnProperty=empty.propertyIsEnumerable=empty.isPrototypeOf=empty.toLocaleString=empty.toString=empty.valueOf=empty.__proto__=null,empty},Object.create=function(prototype,properties){var object;if(null===prototype)object=createEmpty();else{if(\"object\"!=typeof prototype)throw new TypeError(\"typeof prototype[\"+typeof prototype+\"] != 'object'\");var Type=function(){};Type.prototype=prototype,object=new Type,object.__proto__=prototype}return void 0!==properties&&Object.defineProperties(object,properties),object}}if(Object.defineProperty){var definePropertyWorksOnObject=doesDefinePropertyWork({}),definePropertyWorksOnDom=\"undefined\"==typeof document||doesDefinePropertyWork(document.createElement(\"div\"));if(!definePropertyWorksOnObject||!definePropertyWorksOnDom)var definePropertyFallback=Object.defineProperty}if(!Object.defineProperty||definePropertyFallback){var ERR_NON_OBJECT_DESCRIPTOR=\"Property description must be an object: \",ERR_NON_OBJECT_TARGET=\"Object.defineProperty called on non-object: \",ERR_ACCESSORS_NOT_SUPPORTED=\"getters & setters can not be defined on this javascript engine\";Object.defineProperty=function(object,property,descriptor){if(\"object\"!=typeof object&&\"function\"!=typeof object||null===object)throw new TypeError(ERR_NON_OBJECT_TARGET+object);if(\"object\"!=typeof descriptor&&\"function\"!=typeof descriptor||null===descriptor)throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR+descriptor);if(definePropertyFallback)try{return definePropertyFallback.call(Object,object,property,descriptor)}catch(exception){}if(owns(descriptor,\"value\"))if(supportsAccessors&&(lookupGetter(object,property)||lookupSetter(object,property))){var prototype=object.__proto__;object.__proto__=prototypeOfObject,delete object[property],object[property]=descriptor.value,object.__proto__=prototype}else object[property]=descriptor.value;else{if(!supportsAccessors)throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);owns(descriptor,\"get\")&&defineGetter(object,property,descriptor.get),owns(descriptor,\"set\")&&defineSetter(object,property,descriptor.set)}return object}}Object.defineProperties||(Object.defineProperties=function(object,properties){for(var property in properties)owns(properties,property)&&Object.defineProperty(object,property,properties[property]);return object}),Object.seal||(Object.seal=function(object){return object}),Object.freeze||(Object.freeze=function(object){return object});try{Object.freeze(function(){})}catch(exception){Object.freeze=function(freezeObject){return function(object){return\"function\"==typeof object?object:freezeObject(object)}}(Object.freeze)}if(Object.preventExtensions||(Object.preventExtensions=function(object){return object}),Object.isSealed||(Object.isSealed=function(){return!1}),Object.isFrozen||(Object.isFrozen=function(){return!1}),Object.isExtensible||(Object.isExtensible=function(object){if(Object(object)===object)throw new TypeError;for(var name=\"\";owns(object,name);)name+=\"?\";object[name]=!0;var returnValue=owns(object,name);return delete object[name],returnValue}),!Object.keys){var hasDontEnumBug=!0,dontEnums=[\"toString\",\"toLocaleString\",\"valueOf\",\"hasOwnProperty\",\"isPrototypeOf\",\"propertyIsEnumerable\",\"constructor\"],dontEnumsLength=dontEnums.length;for(var key in{toString:null})hasDontEnumBug=!1;Object.keys=function(object){if(\"object\"!=typeof object&&\"function\"!=typeof object||null===object)throw new TypeError(\"Object.keys called on a non-object\");var keys=[];for(var name in object)owns(object,name)&&keys.push(name);if(hasDontEnumBug)for(var i=0,ii=dontEnumsLength;ii>i;i++){var dontEnum=dontEnums[i];owns(object,dontEnum)&&keys.push(dontEnum)}return keys}}Date.now||(Date.now=function(){return(new Date).getTime()});var ws=\"\t\\n\u000b\\f\\r   ᠎              \\u2028\\u2029\";if(!String.prototype.trim||ws.trim()){ws=\"[\"+ws+\"]\";var trimBeginRegexp=RegExp(\"^\"+ws+ws+\"*\"),trimEndRegexp=RegExp(ws+ws+\"*$\");String.prototype.trim=function(){return(this+\"\").replace(trimBeginRegexp,\"\").replace(trimEndRegexp,\"\")}}var toObject=function(o){if(null==o)throw new TypeError(\"can't convert \"+o+\" to object\");return Object(o)}});"; + +/***/ }, +/* 69 */ +/***/ function(module, exports) { + + ace.define("ace/ext/searchbox",["require","exports","module","ace/lib/dom","ace/lib/lang","ace/lib/event","ace/keyboard/hash_handler","ace/lib/keys"], function(acequire, exports, module) { + "use strict"; + + var dom = acequire("../lib/dom"); + var lang = acequire("../lib/lang"); + var event = acequire("../lib/event"); + var searchboxCss = "\ + .ace_search {\ + background-color: #ddd;\ + border: 1px solid #cbcbcb;\ + border-top: 0 none;\ + max-width: 325px;\ + overflow: hidden;\ + margin: 0;\ + padding: 4px;\ + padding-right: 6px;\ + padding-bottom: 0;\ + position: absolute;\ + top: 0px;\ + z-index: 99;\ + white-space: normal;\ + }\ + .ace_search.left {\ + border-left: 0 none;\ + border-radius: 0px 0px 5px 0px;\ + left: 0;\ + }\ + .ace_search.right {\ + border-radius: 0px 0px 0px 5px;\ + border-right: 0 none;\ + right: 0;\ + }\ + .ace_search_form, .ace_replace_form {\ + border-radius: 3px;\ + border: 1px solid #cbcbcb;\ + float: left;\ + margin-bottom: 4px;\ + overflow: hidden;\ + }\ + .ace_search_form.ace_nomatch {\ + outline: 1px solid red;\ + }\ + .ace_search_field {\ + background-color: white;\ + border-right: 1px solid #cbcbcb;\ + border: 0 none;\ + -webkit-box-sizing: border-box;\ + -moz-box-sizing: border-box;\ + box-sizing: border-box;\ + float: left;\ + height: 22px;\ + outline: 0;\ + padding: 0 7px;\ + width: 214px;\ + margin: 0;\ + }\ + .ace_searchbtn,\ + .ace_replacebtn {\ + background: #fff;\ + border: 0 none;\ + border-left: 1px solid #dcdcdc;\ + cursor: pointer;\ + float: left;\ + height: 22px;\ + margin: 0;\ + position: relative;\ + }\ + .ace_searchbtn:last-child,\ + .ace_replacebtn:last-child {\ + border-top-right-radius: 3px;\ + border-bottom-right-radius: 3px;\ + }\ + .ace_searchbtn:disabled {\ + background: none;\ + cursor: default;\ + }\ + .ace_searchbtn {\ + background-position: 50% 50%;\ + background-repeat: no-repeat;\ + width: 27px;\ + }\ + .ace_searchbtn.prev {\ + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADFJREFUeNpiSU1NZUAC/6E0I0yACYskCpsJiySKIiY0SUZk40FyTEgCjGgKwTRAgAEAQJUIPCE+qfkAAAAASUVORK5CYII=); \ + }\ + .ace_searchbtn.next {\ + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADRJREFUeNpiTE1NZQCC/0DMyIAKwGJMUAYDEo3M/s+EpvM/mkKwCQxYjIeLMaELoLMBAgwAU7UJObTKsvAAAAAASUVORK5CYII=); \ + }\ + .ace_searchbtn_close {\ + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAcCAYAAABRVo5BAAAAZ0lEQVR42u2SUQrAMAhDvazn8OjZBilCkYVVxiis8H4CT0VrAJb4WHT3C5xU2a2IQZXJjiQIRMdkEoJ5Q2yMqpfDIo+XY4k6h+YXOyKqTIj5REaxloNAd0xiKmAtsTHqW8sR2W5f7gCu5nWFUpVjZwAAAABJRU5ErkJggg==) no-repeat 50% 0;\ + border-radius: 50%;\ + border: 0 none;\ + color: #656565;\ + cursor: pointer;\ + float: right;\ + font: 16px/16px Arial;\ + height: 14px;\ + margin: 5px 1px 9px 5px;\ + padding: 0;\ + text-align: center;\ + width: 14px;\ + }\ + .ace_searchbtn_close:hover {\ + background-color: #656565;\ + background-position: 50% 100%;\ + color: white;\ + }\ + .ace_replacebtn.prev {\ + width: 54px\ + }\ + .ace_replacebtn.next {\ + width: 27px\ + }\ + .ace_button {\ + margin-left: 2px;\ + cursor: pointer;\ + -webkit-user-select: none;\ + -moz-user-select: none;\ + -o-user-select: none;\ + -ms-user-select: none;\ + user-select: none;\ + overflow: hidden;\ + opacity: 0.7;\ + border: 1px solid rgba(100,100,100,0.23);\ + padding: 1px;\ + -moz-box-sizing: border-box;\ + box-sizing: border-box;\ + color: black;\ + }\ + .ace_button:hover {\ + background-color: #eee;\ + opacity:1;\ + }\ + .ace_button:active {\ + background-color: #ddd;\ + }\ + .ace_button.checked {\ + border-color: #3399ff;\ + opacity:1;\ + }\ + .ace_search_options{\ + margin-bottom: 3px;\ + text-align: right;\ + -webkit-user-select: none;\ + -moz-user-select: none;\ + -o-user-select: none;\ + -ms-user-select: none;\ + user-select: none;\ + }"; + var HashHandler = acequire("../keyboard/hash_handler").HashHandler; + var keyUtil = acequire("../lib/keys"); + + dom.importCssString(searchboxCss, "ace_searchbox"); + + var html = ''.replace(/>\s+/g, ">"); + + var SearchBox = function(editor, range, showReplaceForm) { + var div = dom.createElement("div"); + div.innerHTML = html; + this.element = div.firstChild; + + this.$init(); + this.setEditor(editor); + }; + + (function() { + this.setEditor = function(editor) { + editor.searchBox = this; + editor.container.appendChild(this.element); + this.editor = editor; + }; + + this.$initElements = function(sb) { + this.searchBox = sb.querySelector(".ace_search_form"); + this.replaceBox = sb.querySelector(".ace_replace_form"); + this.searchOptions = sb.querySelector(".ace_search_options"); + this.regExpOption = sb.querySelector("[action=toggleRegexpMode]"); + this.caseSensitiveOption = sb.querySelector("[action=toggleCaseSensitive]"); + this.wholeWordOption = sb.querySelector("[action=toggleWholeWords]"); + this.searchInput = this.searchBox.querySelector(".ace_search_field"); + this.replaceInput = this.replaceBox.querySelector(".ace_search_field"); + }; + + this.$init = function() { + var sb = this.element; + + this.$initElements(sb); + + var _this = this; + event.addListener(sb, "mousedown", function(e) { + setTimeout(function(){ + _this.activeInput.focus(); + }, 0); + event.stopPropagation(e); + }); + event.addListener(sb, "click", function(e) { + var t = e.target || e.srcElement; + var action = t.getAttribute("action"); + if (action && _this[action]) + _this[action](); + else if (_this.$searchBarKb.commands[action]) + _this.$searchBarKb.commands[action].exec(_this); + event.stopPropagation(e); + }); + + event.addCommandKeyListener(sb, function(e, hashId, keyCode) { + var keyString = keyUtil.keyCodeToString(keyCode); + var command = _this.$searchBarKb.findKeyCommand(hashId, keyString); + if (command && command.exec) { + command.exec(_this); + event.stopEvent(e); + } + }); + + this.$onChange = lang.delayedCall(function() { + _this.find(false, false); + }); + + event.addListener(this.searchInput, "input", function() { + _this.$onChange.schedule(20); + }); + event.addListener(this.searchInput, "focus", function() { + _this.activeInput = _this.searchInput; + _this.searchInput.value && _this.highlight(); + }); + event.addListener(this.replaceInput, "focus", function() { + _this.activeInput = _this.replaceInput; + _this.searchInput.value && _this.highlight(); + }); + }; + this.$closeSearchBarKb = new HashHandler([{ + bindKey: "Esc", + name: "closeSearchBar", + exec: function(editor) { + editor.searchBox.hide(); + } + }]); + this.$searchBarKb = new HashHandler(); + this.$searchBarKb.bindKeys({ + "Ctrl-f|Command-f": function(sb) { + var isReplace = sb.isReplace = !sb.isReplace; + sb.replaceBox.style.display = isReplace ? "" : "none"; + sb.searchInput.focus(); + }, + "Ctrl-H|Command-Option-F": function(sb) { + sb.replaceBox.style.display = ""; + sb.replaceInput.focus(); + }, + "Ctrl-G|Command-G": function(sb) { + sb.findNext(); + }, + "Ctrl-Shift-G|Command-Shift-G": function(sb) { + sb.findPrev(); + }, + "esc": function(sb) { + setTimeout(function() { sb.hide();}); + }, + "Return": function(sb) { + if (sb.activeInput == sb.replaceInput) + sb.replace(); + sb.findNext(); + }, + "Shift-Return": function(sb) { + if (sb.activeInput == sb.replaceInput) + sb.replace(); + sb.findPrev(); + }, + "Alt-Return": function(sb) { + if (sb.activeInput == sb.replaceInput) + sb.replaceAll(); + sb.findAll(); + }, + "Tab": function(sb) { + (sb.activeInput == sb.replaceInput ? sb.searchInput : sb.replaceInput).focus(); + } + }); + + this.$searchBarKb.addCommands([{ + name: "toggleRegexpMode", + bindKey: {win: "Alt-R|Alt-/", mac: "Ctrl-Alt-R|Ctrl-Alt-/"}, + exec: function(sb) { + sb.regExpOption.checked = !sb.regExpOption.checked; + sb.$syncOptions(); + } + }, { + name: "toggleCaseSensitive", + bindKey: {win: "Alt-C|Alt-I", mac: "Ctrl-Alt-R|Ctrl-Alt-I"}, + exec: function(sb) { + sb.caseSensitiveOption.checked = !sb.caseSensitiveOption.checked; + sb.$syncOptions(); + } + }, { + name: "toggleWholeWords", + bindKey: {win: "Alt-B|Alt-W", mac: "Ctrl-Alt-B|Ctrl-Alt-W"}, + exec: function(sb) { + sb.wholeWordOption.checked = !sb.wholeWordOption.checked; + sb.$syncOptions(); + } + }]); + + this.$syncOptions = function() { + dom.setCssClass(this.regExpOption, "checked", this.regExpOption.checked); + dom.setCssClass(this.wholeWordOption, "checked", this.wholeWordOption.checked); + dom.setCssClass(this.caseSensitiveOption, "checked", this.caseSensitiveOption.checked); + this.find(false, false); + }; + + this.highlight = function(re) { + this.editor.session.highlight(re || this.editor.$search.$options.re); + this.editor.renderer.updateBackMarkers() + }; + this.find = function(skipCurrent, backwards, preventScroll) { + var range = this.editor.find(this.searchInput.value, { + skipCurrent: skipCurrent, + backwards: backwards, + wrap: true, + regExp: this.regExpOption.checked, + caseSensitive: this.caseSensitiveOption.checked, + wholeWord: this.wholeWordOption.checked, + preventScroll: preventScroll + }); + var noMatch = !range && this.searchInput.value; + dom.setCssClass(this.searchBox, "ace_nomatch", noMatch); + this.editor._emit("findSearchBox", { match: !noMatch }); + this.highlight(); + }; + this.findNext = function() { + this.find(true, false); + }; + this.findPrev = function() { + this.find(true, true); + }; + this.findAll = function(){ + var range = this.editor.findAll(this.searchInput.value, { + regExp: this.regExpOption.checked, + caseSensitive: this.caseSensitiveOption.checked, + wholeWord: this.wholeWordOption.checked + }); + var noMatch = !range && this.searchInput.value; + dom.setCssClass(this.searchBox, "ace_nomatch", noMatch); + this.editor._emit("findSearchBox", { match: !noMatch }); + this.highlight(); + this.hide(); + }; + this.replace = function() { + if (!this.editor.getReadOnly()) + this.editor.replace(this.replaceInput.value); + }; + this.replaceAndFindNext = function() { + if (!this.editor.getReadOnly()) { + this.editor.replace(this.replaceInput.value); + this.findNext() + } + }; + this.replaceAll = function() { + if (!this.editor.getReadOnly()) + this.editor.replaceAll(this.replaceInput.value); + }; + + this.hide = function() { + this.element.style.display = "none"; + this.editor.keyBinding.removeKeyboardHandler(this.$closeSearchBarKb); + this.editor.focus(); + }; + this.show = function(value, isReplace) { + this.element.style.display = ""; + this.replaceBox.style.display = isReplace ? "" : "none"; + + this.isReplace = isReplace; + + if (value) + this.searchInput.value = value; + + this.find(false, false, true); + + this.searchInput.focus(); + this.searchInput.select(); + + this.editor.keyBinding.addKeyboardHandler(this.$closeSearchBarKb); + }; + + this.isFocused = function() { + var el = document.activeElement; + return el == this.searchInput || el == this.replaceInput; + } + }).call(SearchBox.prototype); + + exports.SearchBox = SearchBox; + + exports.Search = function(editor, isReplace) { + var sb = editor.searchBox || new SearchBox(editor); + sb.show(editor.session.getTextRange(), isReplace); + }; + + }); + (function() { + ace.acequire(["ace/ext/searchbox"], function() {}); + })(); + + +/***/ }, +/* 70 */ +/***/ function(module, exports) { + + /* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + + ace.define('ace/theme/jsoneditor', ['require', 'exports', 'module', 'ace/lib/dom'], function(acequire, exports, module) { + + exports.isDark = false; + exports.cssClass = "ace-jsoneditor"; + exports.cssText = ".ace-jsoneditor .ace_gutter {\ + background: #ebebeb;\ + color: #333\ + }\ + \ + .ace-jsoneditor.ace_editor {\ + font-family: droid sans mono, consolas, monospace, courier new, courier, sans-serif;\ + line-height: 1.3;\ + }\ + .ace-jsoneditor .ace_print-margin {\ + width: 1px;\ + background: #e8e8e8\ + }\ + .ace-jsoneditor .ace_scroller {\ + background-color: #FFFFFF\ + }\ + .ace-jsoneditor .ace_text-layer {\ + color: gray\ + }\ + .ace-jsoneditor .ace_variable {\ + color: #1a1a1a\ + }\ + .ace-jsoneditor .ace_cursor {\ + border-left: 2px solid #000000\ + }\ + .ace-jsoneditor .ace_overwrite-cursors .ace_cursor {\ + border-left: 0px;\ + border-bottom: 1px solid #000000\ + }\ + .ace-jsoneditor .ace_marker-layer .ace_selection {\ + background: lightgray\ + }\ + .ace-jsoneditor.ace_multiselect .ace_selection.ace_start {\ + box-shadow: 0 0 3px 0px #FFFFFF;\ + border-radius: 2px\ + }\ + .ace-jsoneditor .ace_marker-layer .ace_step {\ + background: rgb(255, 255, 0)\ + }\ + .ace-jsoneditor .ace_marker-layer .ace_bracket {\ + margin: -1px 0 0 -1px;\ + border: 1px solid #BFBFBF\ + }\ + .ace-jsoneditor .ace_marker-layer .ace_active-line {\ + background: #FFFBD1\ + }\ + .ace-jsoneditor .ace_gutter-active-line {\ + background-color : #dcdcdc\ + }\ + .ace-jsoneditor .ace_marker-layer .ace_selected-word {\ + border: 1px solid lightgray\ + }\ + .ace-jsoneditor .ace_invisible {\ + color: #BFBFBF\ + }\ + .ace-jsoneditor .ace_keyword,\ + .ace-jsoneditor .ace_meta,\ + .ace-jsoneditor .ace_support.ace_constant.ace_property-value {\ + color: #AF956F\ + }\ + .ace-jsoneditor .ace_keyword.ace_operator {\ + color: #484848\ + }\ + .ace-jsoneditor .ace_keyword.ace_other.ace_unit {\ + color: #96DC5F\ + }\ + .ace-jsoneditor .ace_constant.ace_language {\ + color: darkorange\ + }\ + .ace-jsoneditor .ace_constant.ace_numeric {\ + color: red\ + }\ + .ace-jsoneditor .ace_constant.ace_character.ace_entity {\ + color: #BF78CC\ + }\ + .ace-jsoneditor .ace_invalid {\ + color: #FFFFFF;\ + background-color: #FF002A;\ + }\ + .ace-jsoneditor .ace_fold {\ + background-color: #AF956F;\ + border-color: #000000\ + }\ + .ace-jsoneditor .ace_storage,\ + .ace-jsoneditor .ace_support.ace_class,\ + .ace-jsoneditor .ace_support.ace_function,\ + .ace-jsoneditor .ace_support.ace_other,\ + .ace-jsoneditor .ace_support.ace_type {\ + color: #C52727\ + }\ + .ace-jsoneditor .ace_string {\ + color: green\ + }\ + .ace-jsoneditor .ace_comment {\ + color: #BCC8BA\ + }\ + .ace-jsoneditor .ace_entity.ace_name.ace_tag,\ + .ace-jsoneditor .ace_entity.ace_other.ace_attribute-name {\ + color: #606060\ + }\ + .ace-jsoneditor .ace_markup.ace_underline {\ + text-decoration: underline\ + }\ + .ace-jsoneditor .ace_indent-guide {\ + background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y\ + }"; + + var dom = acequire("../lib/dom"); + dom.importCssString(exports.cssText, exports.cssClass); + }); + + +/***/ } +/******/ ]) +}); +; \ No newline at end of file diff --git a/ui/app/bower_components/jsoneditor/dist/jsoneditor.js.map b/ui/app/bower_components/jsoneditor/dist/jsoneditor.js.map new file mode 100644 index 0000000..38bfd9c --- /dev/null +++ b/ui/app/bower_components/jsoneditor/dist/jsoneditor.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///webpack/bootstrap 5d44b740c714db823b48","webpack:///./src/index.js","webpack:///./~/preact/dist/preact.js","webpack:///./src/CodeMode.js","webpack:///./src/TextMode.js","webpack:///./src/utils/jsonUtils.js","webpack:///./src/assets/jsonlint/jsonlint.js","webpack:///./src/jsonData.js","webpack:///./src/utils/immutabilityHelpers.js","webpack:///./~/lodash/clone.js","webpack:///./~/lodash/_baseClone.js","webpack:///./~/lodash/_Stack.js","webpack:///./~/lodash/_ListCache.js","webpack:///./~/lodash/_listCacheClear.js","webpack:///./~/lodash/_listCacheDelete.js","webpack:///./~/lodash/_assocIndexOf.js","webpack:///./~/lodash/eq.js","webpack:///./~/lodash/_listCacheGet.js","webpack:///./~/lodash/_listCacheHas.js","webpack:///./~/lodash/_listCacheSet.js","webpack:///./~/lodash/_stackClear.js","webpack:///./~/lodash/_stackDelete.js","webpack:///./~/lodash/_stackGet.js","webpack:///./~/lodash/_stackHas.js","webpack:///./~/lodash/_stackSet.js","webpack:///./~/lodash/_Map.js","webpack:///./~/lodash/_getNative.js","webpack:///./~/lodash/_baseIsNative.js","webpack:///./~/lodash/isFunction.js","webpack:///./~/lodash/isObject.js","webpack:///./~/lodash/_isMasked.js","webpack:///./~/lodash/_coreJsData.js","webpack:///./~/lodash/_root.js","webpack:///./~/lodash/_freeGlobal.js","webpack:///./~/lodash/_toSource.js","webpack:///./~/lodash/_getValue.js","webpack:///./~/lodash/_MapCache.js","webpack:///./~/lodash/_mapCacheClear.js","webpack:///./~/lodash/_Hash.js","webpack:///./~/lodash/_hashClear.js","webpack:///./~/lodash/_nativeCreate.js","webpack:///./~/lodash/_hashDelete.js","webpack:///./~/lodash/_hashGet.js","webpack:///./~/lodash/_hashHas.js","webpack:///./~/lodash/_hashSet.js","webpack:///./~/lodash/_mapCacheDelete.js","webpack:///./~/lodash/_getMapData.js","webpack:///./~/lodash/_isKeyable.js","webpack:///./~/lodash/_mapCacheGet.js","webpack:///./~/lodash/_mapCacheHas.js","webpack:///./~/lodash/_mapCacheSet.js","webpack:///./~/lodash/_arrayEach.js","webpack:///./~/lodash/_assignValue.js","webpack:///./~/lodash/_baseAssignValue.js","webpack:///./~/lodash/_defineProperty.js","webpack:///./~/lodash/_baseAssign.js","webpack:///./~/lodash/_copyObject.js","webpack:///./~/lodash/keys.js","webpack:///./~/lodash/_arrayLikeKeys.js","webpack:///./~/lodash/_baseTimes.js","webpack:///./~/lodash/isArguments.js","webpack:///./~/lodash/_baseIsArguments.js","webpack:///./~/lodash/isObjectLike.js","webpack:///./~/lodash/isArray.js","webpack:///./~/lodash/isBuffer.js","webpack:///(webpack)/buildin/module.js","webpack:///./~/lodash/stubFalse.js","webpack:///./~/lodash/_isIndex.js","webpack:///./~/lodash/isTypedArray.js","webpack:///./~/lodash/_baseIsTypedArray.js","webpack:///./~/lodash/isLength.js","webpack:///./~/lodash/_baseUnary.js","webpack:///./~/lodash/_nodeUtil.js","webpack:///./~/lodash/_baseKeys.js","webpack:///./~/lodash/_isPrototype.js","webpack:///./~/lodash/_nativeKeys.js","webpack:///./~/lodash/_overArg.js","webpack:///./~/lodash/isArrayLike.js","webpack:///./~/lodash/_cloneBuffer.js","webpack:///./~/lodash/_copyArray.js","webpack:///./~/lodash/_copySymbols.js","webpack:///./~/lodash/_getSymbols.js","webpack:///./~/lodash/stubArray.js","webpack:///./~/lodash/_getAllKeys.js","webpack:///./~/lodash/_baseGetAllKeys.js","webpack:///./~/lodash/_arrayPush.js","webpack:///./~/lodash/_getTag.js","webpack:///./~/lodash/_DataView.js","webpack:///./~/lodash/_Promise.js","webpack:///./~/lodash/_Set.js","webpack:///./~/lodash/_WeakMap.js","webpack:///./~/lodash/_baseGetTag.js","webpack:///./~/lodash/_initCloneArray.js","webpack:///./~/lodash/_initCloneByTag.js","webpack:///./~/lodash/_cloneArrayBuffer.js","webpack:///./~/lodash/_Uint8Array.js","webpack:///./~/lodash/_cloneDataView.js","webpack:///./~/lodash/_cloneMap.js","webpack:///./~/lodash/_addMapEntry.js","webpack:///./~/lodash/_arrayReduce.js","webpack:///./~/lodash/_mapToArray.js","webpack:///./~/lodash/_cloneRegExp.js","webpack:///./~/lodash/_cloneSet.js","webpack:///./~/lodash/_addSetEntry.js","webpack:///./~/lodash/_setToArray.js","webpack:///./~/lodash/_cloneSymbol.js","webpack:///./~/lodash/_Symbol.js","webpack:///./~/lodash/_cloneTypedArray.js","webpack:///./~/lodash/_initCloneObject.js","webpack:///./~/lodash/_baseCreate.js","webpack:///./~/lodash/_getPrototype.js","webpack:///./src/utils/typeUtils.js","webpack:///./~/lodash/isEqual.js","webpack:///./~/lodash/_baseIsEqual.js","webpack:///./~/lodash/_baseIsEqualDeep.js","webpack:///./~/lodash/_equalArrays.js","webpack:///./~/lodash/_SetCache.js","webpack:///./~/lodash/_setCacheAdd.js","webpack:///./~/lodash/_setCacheHas.js","webpack:///./~/lodash/_arraySome.js","webpack:///./~/lodash/_cacheHas.js","webpack:///./~/lodash/_equalByTag.js","webpack:///./~/lodash/_equalObjects.js","webpack:///./src/menu/ModeButton.js","webpack:///./src/menu/ModeMenu.js","webpack:///./src/utils/stringUtils.js","webpack:///./src/utils/domUtils.js","webpack:///./src/assets/ace/index.js","webpack:///./~/brace/index.js","webpack:///(webpack)/buildin/amd-define.js","webpack:///./~/w3c-blob/browser.js","webpack:///./~/brace/mode/json.js","webpack:///./~/brace/worker/json.js","webpack:///./~/brace/ext/searchbox.js","webpack:///./src/assets/ace/theme-jsoneditor.js","webpack:///./src/TreeMode.js","webpack:///./src/actions.js","webpack:///./src/utils/arrayUtils.js","webpack:///./src/JSONNode.js","webpack:///./src/menu/ActionButton.js","webpack:///./src/menu/ActionMenu.js","webpack:///./src/menu/Menu.js","webpack:///./src/menu/entries.js","webpack:///./src/menu/AppendActionButton.js","webpack:///./src/menu/AppendActionMenu.js","webpack:///./src/JSONNodeView.js","webpack:///./src/JSONNodeForm.js","webpack:///./src/jsoneditor.less?e043","webpack:///./src/jsoneditor.less","webpack:///./~/css-loader/lib/css-base.js","webpack:///./src/img/jsoneditor-icons.svg","webpack:///./~/style-loader/addStyles.js"],"names":["modes","code","form","text","tree","view","jsoneditor","container","options","editor","isJSONEditor","_container","_options","_modes","_mode","_element","_component","set","json","get","setText","getText","expand","callback","collapse","patch","actions","setMode","mode","success","initialChildCount","children","length","element","handleChangeMode","prevMode","onChangeMode","constructor","Error","Object","keys","join","destroy","parentNode","removeChild","childCount","lastChild","module","exports","CodeMode","props","handleChange","onChangeText","state","id","Math","round","random","aceEditor","class","renderMenu","base","querySelector","_ace","window","edit","require","$blockScrolling","Infinity","setTheme","setShowPrintMargin","setFontSize","getSession","setTabSize","indentation","setUseSoftTabs","setUseWrapMode","commands","bindKey","onLoadAce","on","setValue","getValue","TextMode","event","target","value","handleFormat","format","err","handleError","handleCompact","compact","onError","console","error","onInput","title","onClick","JSON","stringify","getIndentation","data","result","revert","setState","parseJSON","validate","jsonString","parse","jsonlint","parser","trace","yy","symbols_","terminals_","productions_","performAction","anonymous","yytext","yyleng","yylineno","yystate","$$","_$","$0","$","replace","Number","push","table","defaultActions","parseError","str","hash","input","self","stack","vstack","lstack","recovering","TERROR","EOF","lexer","setInput","yylloc","yyloc","popStack","n","lex","token","symbol","preErrorSymbol","action","a","r","yyval","p","len","newState","expected","_handle_error","errStr","showPosition","match","line","loc","toString","Array","first_line","last_line","first_column","last_column","call","slice","_input","_more","_less","done","matched","conditionStack","ch","lines","unput","more","less","pastInput","past","substr","upcomingInput","next","pre","c","tempMatch","index","col","rules","_currentRules","i","flex","begin","condition","popState","pop","conditions","topState","pushState","yy_","$avoiding_name_collisions","YY_START","YYSTATE","bind","jsonToData","dataToJson","toDataPath","patchData","remove","simplifyPatch","add","copy","move","test","pathExists","resolvePathIndex","findNextProp","findPropertyIndex","parseJSONPointer","compileJSONPointer","expandAll","path","isArray","type","expanded","items","map","child","concat","name","object","forEach","prop","item","updatedData","op","newValue","from","dataPath","oldValue","pathArray","parentPath","parent","dataValue","before","simplifiedPatch","paths","unshift","undefined","resolvedPath","newProp","fromArray","result1","result2","beforeNeeded","actualValue","expandRecursive","updatedItems","updatedProps","findIndex","pointer","split","shift","String","getIn","setIn","updateIn","deleteIn","insertAt","key","updatedValue","updatedObject","splice","TypeError","isObject","isObjectOrArray","valueType","isUrl","stringConvert","RegExp","isUrlRegex","num","numFloat","parseFloat","isNaN","ModeButton","handleOpen","open","handleRequestClose","onRequestClose","ModeMenu","nodemenu","updateRequestCloseListener","removeRequestCloseListener","addRequestCloseListener","setTimeout","addEventListener","removeEventListener","escapeHTML","unescapeHTML","escapeJSON","findUniqueName","toCapital","escapeUnicode","htmlEscaped","html","substring","escapeUnicodeChars","charCodeAt","escapedText","escaped","charAt","indexOf","invalidNames","validName","includes","toUpperCase","toLowerCase","getInnerText","findParentNode","getInternetExplorerVersion","buffer","first","nodeValue","flush","hasChildNodes","childNodes","innerText","iMax","nodeName","prevChild","prevName","elem","attr","getAttribute","_ieVersion","rv","navigator","appName","ua","userAgent","re","exec","$1","ace","define","acequire","isDark","cssClass","cssText","dom","importCssString","MAX_HISTORY_ITEMS","TreeMode","nodeOptions","history","historyIndex","events","onChangeProperty","handleChangeProperty","onChangeValue","handleChangeValue","onChangeType","handleChangeType","onInsert","handleInsert","onAppend","handleAppend","onDuplicate","handleDuplicate","onRemove","handleRemove","onSort","handleSort","onExpand","handleExpand","search","Node","handleHideMenus","handleExpandAll","handleCollapseAll","style","disabled","canUndo","undo","canRedo","redo","onChange","historyItem","hideActionMenu","handlePatch","oldProp","order","recurse","emitOnChange","changeValue","changeProperty","changeType","duplicate","insert","append","sort","createEntry","convertType","oldDataValue","uniqueNewProp","parseInt","compare","orderedItems","b","reverse","orderedProps","array","last","compareAsc","compareDesc","strictShallowEqual","activeContextMenu","JSONNode","updateValueStyling","getValueFromEvent","itsAnUrl","isEmpty","contentEditable","className","getValueClass","URL_TITLE","removeChildClasses","getPath","handleClickValue","ctrlKey","button","openLinkIfUrl","handleKeyDownValue","which","handleContextMenu","stopPropagation","menu","anchor","root","findRootElement","handleAppendContextMenu","appendMenu","renderJSONArray","renderJSONObject","renderJSONValue","contents","renderExpandButton","renderActionMenuButton","renderProperty","renderReadonly","renderAppend","renderPlaceholder","renderSeparator","renderValue","renderAppendMenuButton","isIndex","spellCheck","escapedProp","onBlur","content","getRootName","escapedValue","onKeyDown","nextProps","nextState","hasOwnProperty","preventDefault","stringValue","isEditorElement","ActionButton","ActionMenu","hasParent","CONTEXT_MENU_HEIGHT","Menu","renderMenuItem","click","submenu","createExpandHandler","renderSubMenu","expanding","collapsing","anchorRect","getBoundingClientRect","rootRect","orientation","bottom","top","prev","createChangeType","createSort","createInsert","createAppend","createDuplicate","createRemove","createSeparator","TYPE_TITLES","string","direction","submenuTitle","AppendActionButton","AppendActionMenu","JSONNodeView","href","JSONNodeForm"],"mappings":"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A2B0B,OAA3B;AACAjC,kBAAOM,QAAP,CAAgB4B,UAAhB,CAA2BC,WAA3B,CAAuCnC,OAAOM,QAA9C;AACD;;AAEDN,gBAAOK,KAAP,GAAec,IAAf;AACAnB,gBAAOM,QAAP,GAAkBkB,OAAlB;AACAxB,gBAAOO,UAAP,GAAoBiB,QAAQjB,UAA5B;AACD,QAVD,MAWK;AACH;;AAEA;AACA,aAAM6B,aAAapC,OAAOE,UAAP,CAAkBoB,QAAlB,CAA2BC,MAA9C;AACA,aAAIa,eAAef,iBAAnB,EAAsC;AACpCrB,kBAAOE,UAAP,CAAkBiC,WAAlB,CAA8BnC,OAAOE,UAAP,CAAkBmC,SAAhD;AACD;AACF;AACF;AACF,IAjED;;AAmEA;;AAEArC,UAAOkB,OAAP,CAAenB,WAAWA,QAAQoB,IAAnB,IAA2B,MAA1C;;AAEA,UAAOnB,MAAP;AACD;;AAEDsC,QAAOC,OAAP,GAAiB1C,UAAjB,C;;;;;;ACjMA;AACA,wJAA4M;AAC5M,EAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mCAAkC,SAAS;AAC3C;AACA;AACA;AACA;AACA,gGAA+F,KAAK,wBAAwB;AAC5H;AACA;AACA,8EAA6E;AAC7E;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,yBAAwB;AACxB;AACA;AACA,4CAA2C,qBAAqB;AAChE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,4BAA2B,qBAAqB,8CAA8C;AAC9F;AACA;AACA;AACA,yDAAwD;AACxD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,8HAA6H;AAC7H;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,8BAA6B,mEAAmE;AAChG;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA,UAAS;AACT,6DAA4D;AAC5D;AACA;AACA;AACA,cAAa;AACb;AACA,UAAS;AACT;AACA;AACA,UAAS;AACT;AACA,mIAAkI,iCAAiC,iJAAiJ;AACpT;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,yDAAwD;AACxD;AACA;AACA;AACA;AACA,kNAAiN;AACjN;AACA;AACA;AACA,uDAAsD,KAAK;AAC3D;AACA;AACA;AACA;AACA;AACA;AACA;AACA,8FAA6F;AAC7F,iCAAgC,SAAS;AACzC;AACA;AACA;AACA;AACA,cAAa;AACb;AACA,kCAAiC,UAAU;AAC3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb,8BAA6B,iBAAiB;AAC9C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sCAAqC,KAAK;AAC1C;AACA;AACA;AACA,kEAAiE;AACjE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,wCAAuC;AACvC;AACA;AACA;AACA;AACA,4CAA2C,KAAK;AAChD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+IAA8I;AAC9I;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+IAA8I;AAC9I;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sHAAqH;AACrH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAiB;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kEAAiE;AACjE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oDAAmD;AACnD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qCAAoC;AACpC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mEAAkE;AAClE;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA,UAAS;AACT;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;AACD,mC;;;;;;;;;;;;;;ACpdA;;AACA;;;;AACA;;;;;;;;;;;;AAEA;;;;;;;;;;;;;;;;;;;;;;;;KAwBqB2C,Q;;;AACnB,qBAAaC,KAAb,EAAoB;AAAA;;AAAA,qHACZA,KADY;;AAAA,WA6EpBC,YA7EoB,GA6EL,YAAM;AACnB,WAAI,MAAKD,KAAL,CAAW1C,OAAX,IAAsB,MAAK0C,KAAL,CAAW1C,OAAX,CAAmB4C,YAA7C,EAA2D;AACzD;AACA,eAAKF,KAAL,CAAW1C,OAAX,CAAmB4C,YAAnB;AACD;AACF,M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CAA5B,CAAnB;AACA,OAAMkK,QAAQmC,KAAKA,KAAKrM,MAAL,GAAc,CAAnB,CAAd;;AAEA,UAAOkP,SAASpC,MAAT,EAAiBW,UAAjB,EAA6B,UAAChB,KAAD,EAAW;AAC7C,SAAI,CAACjE,MAAM8D,OAAN,CAAcG,KAAd,CAAL,EAA2B;AACzB,aAAM,IAAIgD,SAAJ,CAAc,4BAA4BtL,KAAKC,SAAL,CAAeqJ,UAAf,CAA1C,CAAN;AACD;;AAED,SAAMgB,eAAehC,MAAM3D,KAAN,CAAY,CAAZ,CAArB;;AAEA2F,kBAAae,MAAb,CAAoBtF,KAApB,EAA2B,CAA3B,EAA8B5G,KAA9B;;AAEA,YAAOmL,YAAP;AACD,IAVM,CAAP;AAWD,E;;;;;;ACnLD;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,EAAE;AACb,cAAa,EAAE;AACf;AACA;AACA;AACA,oBAAmB,SAAS,GAAG,SAAS;AACxC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;AChCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,YAAW,EAAE;AACb,YAAW,QAAQ;AACnB,YAAW,QAAQ;AACnB,YAAW,SAAS;AACpB,YAAW,OAAO;AAClB,YAAW,OAAO;AAClB,YAAW,OAAO;AAClB,cAAa,EAAE;AACf;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;;AAEA;AACA;AACA;AACA;AACA,2CAA0C;AAC1C;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;;AAEA;;;;;;;ACpIA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,YAAW,MAAM;AACjB;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;AC1BA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,YAAW,MAAM;AACjB;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;AC/BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACZA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,cAAa,QAAQ;AACrB;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;;AAEA;;;;;;;AClCA;;AAEA;AACA;AACA;AACA;AACA,YAAW,MAAM;AACjB,YAAW,EAAE;AACb,cAAa,OAAO;AACpB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACpBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,EAAE;AACb,YAAW,EAAE;AACb,cAAa,QAAQ;AACrB;AACA;AACA,kBAAiB;AACjB,iBAAgB;AAChB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACpCA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,cAAa,EAAE;AACf;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;;;;;;AClBA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,cAAa,QAAQ;AACrB;AACA;AACA;AACA;;AAEA;;;;;;;ACfA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,YAAW,EAAE;AACb,cAAa,OAAO;AACpB;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;;AAEA;;;;;;;ACzBA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACdA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,cAAa,QAAQ;AACrB;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;;;;;;ACjBA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,cAAa,EAAE;AACf;AACA;AACA;AACA;;AAEA;;;;;;;ACbA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,cAAa,QAAQ;AACrB;AACA;AACA;AACA;;AAEA;;;;;;;ACbA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,YAAW,EAAE;AACb,cAAa,OAAO;AACpB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACjCA;AACA;;AAEA;AACA;;AAEA;;;;;;;ACNA;AACA;;AAEA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,YAAW,OAAO;AAClB,cAAa,EAAE;AACf;AACA;AACA;AACA;AACA;;AAEA;;;;;;;AChBA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,qCAAoC;;AAEpC;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,YAAW,EAAE;AACb,cAAa,QAAQ;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;AC9CA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,EAAE;AACb,cAAa,QAAQ;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACzCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,EAAE;AACb,cAAa,QAAQ;AACrB;AACA;AACA,iBAAgB;AAChB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;AC9BA;;AAEA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;AACA;AACA;AACA,YAAW,SAAS;AACpB,cAAa,QAAQ;AACrB;AACA;AACA;AACA;;AAEA;;;;;;;ACnBA;;AAEA;AACA;;AAEA;;;;;;;ACLA;;AAEA;AACA;;AAEA;AACA;;AAEA;;;;;;;ACRA;AACA;;AAEA;;;;;;;;ACHA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,YAAW,SAAS;AACpB,cAAa,OAAO;AACpB;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA,MAAK;AACL;AACA;AACA;;AAEA;;;;;;;ACzBA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,YAAW,OAAO;AAClB,cAAa,EAAE;AACf;AACA;AACA;AACA;;AAEA;;;;;;;ACZA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,YAAW,MAAM;AACjB;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;AC/BA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACpBA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,YAAW,MAAM;AACjB;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;AC/BA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACdA;;AAEA;AACA;;AAEA;;;;;;;ACLA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,YAAW,OAAO;AAClB,cAAa,QAAQ;AACrB;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;AChBA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,cAAa,EAAE;AACf;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;AC7BA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,cAAa,QAAQ;AACrB;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACtBA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,YAAW,EAAE;AACb,cAAa,OAAO;AACpB;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACtBA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,cAAa,QAAQ;AACrB;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACjBA;;AAEA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,YAAW,OAAO;AAClB,cAAa,EAAE;AACf;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACjBA;AACA;AACA;AACA;AACA,YAAW,EAAE;AACb,cAAa,QAAQ;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACdA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,cAAa,EAAE;AACf;AACA;AACA;AACA;;AAEA;;;;;;;ACfA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,cAAa,QAAQ;AACrB;AACA;AACA;AACA;;AAEA;;;;;;;ACfA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,YAAW,EAAE;AACb,cAAa,OAAO;AACpB;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;;;;;;ACrBA;AACA;AACA;AACA;AACA;AACA,YAAW,MAAM;AACjB,YAAW,SAAS;AACpB,cAAa,MAAM;AACnB;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACrBA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,YAAW,OAAO;AAClB,YAAW,EAAE;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;AC3BA;;AAEA;AACA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,YAAW,OAAO;AAClB,YAAW,EAAE;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL,IAAG;AACH;AACA;AACA;;AAEA;;;;;;;ACxBA;;AAEA;AACA;AACA;AACA,YAAW,QAAQ;AACnB;AACA,IAAG;AACH,EAAC;;AAED;;;;;;;ACVA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,YAAW,OAAO;AAClB,cAAa,OAAO;AACpB;AACA;AACA;AACA;;AAEA;;;;;;;AChBA;AACA;;AAEA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,YAAW,MAAM;AACjB,YAAW,OAAO,WAAW;AAC7B,YAAW,SAAS;AACpB,cAAa,OAAO;AACpB;AACA;AACA;AACA,yBAAwB;;AAExB;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACvCA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,cAAa,MAAM;AACnB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACpCA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,YAAW,EAAE;AACb,YAAW,QAAQ;AACnB,cAAa,MAAM;AACnB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;AChDA;AACA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,YAAW,SAAS;AACpB,cAAa,MAAM;AACnB;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACnBA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,EAAE;AACb,cAAa,QAAQ;AACrB;AACA;AACA;AACA,8BAA6B,kBAAkB,EAAE;AACjD;AACA;AACA;AACA;AACA;AACA,+CAA8C,kBAAkB,EAAE;AAClE;AACA;AACA;;AAEA;;;;;;;ACnCA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,YAAW,EAAE;AACb,cAAa,QAAQ;AACrB;AACA;AACA;AACA;;AAEA;;;;;;;AC1BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,EAAE;AACb,cAAa,QAAQ;AACrB;AACA;AACA,qBAAoB;AACpB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;AC5BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,EAAE;AACb,cAAa,QAAQ;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACzBA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,EAAE;AACb,cAAa,QAAQ;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;;ACrCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;ACTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa,QAAQ;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACjBA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,YAAW,EAAE;AACb,YAAW,OAAO;AAClB,cAAa,QAAQ;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACrBA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,EAAE;AACb,cAAa,QAAQ;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;AC1BA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,YAAW,EAAE;AACb,cAAa,QAAQ;AACrB;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACpEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,EAAE;AACb,cAAa,QAAQ;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;AClCA;AACA;AACA;AACA;AACA,YAAW,SAAS;AACpB,cAAa,SAAS;AACtB;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACbA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,IAAG;AACH,EAAC;;AAED;;;;;;;;ACrBA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,cAAa,MAAM;AACnB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;AC7BA;AACA;;AAEA;AACA;AACA;AACA;AACA,YAAW,EAAE;AACb,cAAa,QAAQ;AACrB;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;;;;;;ACjBA;;AAEA;AACA;;AAEA;;;;;;;ACLA;AACA;AACA;AACA;AACA,YAAW,SAAS;AACpB,YAAW,SAAS;AACpB,cAAa,SAAS;AACtB;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACdA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,EAAE;AACb,cAAa,QAAQ;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;AChCA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,YAAW,QAAQ;AACnB,cAAa,OAAO;AACpB;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;;;;;;;AClCA;AACA;AACA;AACA;AACA,YAAW,MAAM;AACjB,YAAW,MAAM;AACjB,cAAa,MAAM;AACnB;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACnBA;AACA;;AAEA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,YAAW,OAAO,WAAW;AAC7B,cAAa,OAAO;AACpB;AACA;AACA;AACA;;AAEA;;;;;;;ACfA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,cAAa,MAAM;AACnB;AACA;;AAEA;;;;;;;ACfA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa,MAAM;AACnB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACtBA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,cAAa,MAAM;AACnB;AACA;AACA;AACA;;AAEA;;;;;;;ACfA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,YAAW,SAAS;AACpB,YAAW,SAAS;AACpB,cAAa,MAAM;AACnB;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACnBA;AACA;AACA;AACA;AACA,YAAW,MAAM;AACjB,YAAW,MAAM;AACjB,cAAa,MAAM;AACnB;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACnBA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,YAAW,EAAE;AACb,cAAa,OAAO;AACpB;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACnEA;AACA;;AAEA;AACA;;AAEA;;;;;;;ACNA;AACA;;AAEA;AACA;;AAEA;;;;;;;ACNA;AACA;;AAEA;AACA;;AAEA;;;;;;;ACNA;AACA;;AAEA;AACA;;AAEA;;;;;;;ACNA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,YAAW,EAAE;AACb,cAAa,OAAO;AACpB;AACA;AACA;AACA;;AAEA;;;;;;;ACrBA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,YAAW,MAAM;AACjB,cAAa,MAAM;AACnB;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACzBA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,YAAW,OAAO;AAClB,YAAW,SAAS;AACpB,YAAW,QAAQ;AACnB,cAAa,OAAO;AACpB;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;;;;;;AC/EA;;AAEA;AACA;AACA;AACA;AACA,YAAW,YAAY;AACvB,cAAa,YAAY;AACzB;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACfA;;AAEA;AACA;;AAEA;;;;;;;ACLA;;AAEA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,YAAW,QAAQ;AACnB,cAAa,OAAO;AACpB;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACfA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,YAAW,SAAS;AACpB,YAAW,QAAQ;AACnB,cAAa,OAAO;AACpB;AACA;AACA;AACA;AACA;;AAEA;;;;;;;AClBA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,YAAW,MAAM;AACjB,cAAa,OAAO;AACpB;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACdA;AACA;AACA;AACA;AACA;AACA,YAAW,MAAM;AACjB,YAAW,SAAS;AACpB,YAAW,EAAE;AACb,YAAW,QAAQ;AACnB;AACA,cAAa,EAAE;AACf;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACzBA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,cAAa,MAAM;AACnB;AACA;AACA;AACA;;AAEA;AACA;AACA,IAAG;AACH;AACA;;AAEA;;;;;;;ACjBA;AACA;;AAEA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,cAAa,OAAO;AACpB;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;AChBA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,YAAW,SAAS;AACpB,YAAW,QAAQ;AACnB,cAAa,OAAO;AACpB;AACA;AACA;AACA;AACA;;AAEA;;;;;;;AClBA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,YAAW,EAAE;AACb,cAAa,OAAO;AACpB;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACdA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,cAAa,MAAM;AACnB;AACA;AACA;AACA;;AAEA;AACA;AACA,IAAG;AACH;AACA;;AAEA;;;;;;;ACjBA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,cAAa,OAAO;AACpB;AACA;AACA;AACA;;AAEA;;;;;;;ACjBA;;AAEA;AACA;;AAEA;;;;;;;ACLA;;AAEA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,YAAW,QAAQ;AACnB,cAAa,OAAO;AACpB;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACfA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,cAAa,OAAO;AACpB;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACjBA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,cAAa,OAAO;AACpB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED;;;;;;;AC7BA;;AAEA;AACA;;AAEA;;;;;;;;;;;;;;;SCIgBiB,Q,GAAAA,Q;SAYAC,e,GAAAA,e;SASAC,S,GAAAA,S;SAgCAC,K,GAAAA,K;SAWAC,a,GAAAA,a;;AAxEhB;;AAEA;;;;;;AAMO,UAASJ,QAAT,CAAmBpM,KAAnB,EAA0B;AAC/B,UAAO,QAAOA,KAAP,yCAAOA,KAAP,OAAiB,QAAjB,IACHA,UAAU,IADP,IAEH,CAACkF,MAAM8D,OAAN,CAAchJ,KAAd,CAFL;AAGD;;AAED;;;;;;AAMO,UAASqM,eAAT,CAA0BrM,KAA1B,EAAiC;AACtC,UAAO,QAAOA,KAAP,yCAAOA,KAAP,OAAiB,QAAjB,IAA6BA,UAAU,IAA9C;AACD;;AAED;;;;;AAKO,UAASsM,SAAT,CAAmBtM,KAAnB,EAA0B;AAC/B,OAAIA,UAAU,IAAd,EAAoB;AAClB,YAAO,MAAP;AACD;AACD,OAAIA,UAAU0K,SAAd,EAAyB;AACvB,YAAO,WAAP;AACD;AACD,OAAI,OAAO1K,KAAP,KAAiB,QAArB,EAA+B;AAC7B,YAAO,QAAP;AACD;AACD,OAAI,OAAOA,KAAP,KAAiB,QAArB,EAA+B;AAC7B,YAAO,QAAP;AACD;AACD,OAAI,OAAOA,KAAP,KAAiB,SAArB,EAAgC;AAC9B,YAAO,SAAP;AACD;AACD,OAAIA,iBAAiByM,MAArB,EAA6B;AAC3B,YAAO,QAAP;AACD;AACD,OAAIvH,MAAM8D,OAAN,CAAchJ,KAAd,CAAJ,EAA0B;AACxB,YAAO,OAAP;AACD;;AAED,UAAO,QAAP;AACD;;AAED;;;;;AAKA,KAAI0M,aAAa,kBAAjB;AACO,UAASH,KAAT,CAAgB1R,IAAhB,EAAsB;AAC3B,UAAQ,OAAOA,IAAP,KAAgB,QAAjB,IAA8B6R,WAAWnE,IAAX,CAAgB1N,IAAhB,CAArC;AACD;;AAED;;;;;;;AAOO,UAAS2R,aAAT,CAAwBzJ,GAAxB,EAA6B;AAClC,OAAM4J,MAAMjK,OAAOK,GAAP,CAAZ,CADkC,CACA;AAClC,OAAM6J,WAAWC,WAAW9J,GAAX,CAAjB,CAFkC,CAEA;;AAElC,OAAIA,OAAO,EAAX,EAAe;AACb,YAAO,EAAP;AACD,IAFD,MAGK,IAAIA,OAAO,MAAX,EAAmB;AACtB,YAAO,IAAP;AACD,IAFI,MAGA,IAAIA,OAAO,MAAX,EAAmB;AACtB,YAAO,IAAP;AACD,IAFI,MAGA,IAAIA,OAAO,OAAX,EAAoB;AACvB,YAAO,KAAP;AACD,IAFI,MAGA,IAAI,CAAC+J,MAAMH,GAAN,CAAD,IAAe,CAACG,MAAMF,QAAN,CAApB,EAAqC;AACxC,YAAOD,GAAP;AACD,IAFI,MAGA;AACH,YAAO5J,GAAP;AACD;AACF,E;;;;;;AC/FD;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,EAAE;AACb,YAAW,EAAE;AACb,cAAa,QAAQ;AACrB;AACA;AACA,kBAAiB;AACjB,iBAAgB;AAChB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;AClCA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,YAAW,EAAE;AACb,YAAW,EAAE;AACb,YAAW,SAAS;AACpB,YAAW,QAAQ;AACnB;AACA;AACA;AACA,YAAW,OAAO;AAClB,cAAa,QAAQ;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;AC7BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,YAAW,OAAO;AAClB,YAAW,SAAS;AACpB,YAAW,SAAS;AACpB,YAAW,OAAO;AAClB;AACA,YAAW,OAAO;AAClB,cAAa,QAAQ;AACrB;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACxFA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,YAAW,MAAM;AACjB,YAAW,MAAM;AACjB,YAAW,SAAS;AACpB,YAAW,SAAS;AACpB,YAAW,OAAO;AAClB;AACA,YAAW,OAAO;AAClB,cAAa,QAAQ;AACrB;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW;AACX;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACnFA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,MAAM;AACjB;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;;;;;;AC1BA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,EAAE;AACb,cAAa,OAAO;AACpB;AACA;AACA;AACA;AACA;;AAEA;;;;;;;AClBA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,EAAE;AACb,cAAa,OAAO;AACpB;AACA;AACA;AACA;;AAEA;;;;;;;ACbA;AACA;AACA;AACA;AACA;AACA,YAAW,MAAM;AACjB,YAAW,SAAS;AACpB,cAAa,QAAQ;AACrB;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACtBA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,YAAW,OAAO;AAClB,cAAa,QAAQ;AACrB;AACA;AACA;AACA;;AAEA;;;;;;;ACZA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,YAAW,OAAO;AAClB,YAAW,OAAO;AAClB,YAAW,SAAS;AACpB,YAAW,SAAS;AACpB,YAAW,OAAO;AAClB;AACA,YAAW,OAAO;AAClB,cAAa,QAAQ;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;AChHA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,YAAW,OAAO;AAClB,YAAW,OAAO;AAClB,YAAW,SAAS;AACpB,YAAW,SAAS;AACpB,YAAW,OAAO;AAClB;AACA,YAAW,OAAO;AAClB,cAAa,QAAQ;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;;;;;;;;;;;ACzFA;;AACA;;;;AACA;;;;;;;;;;KAEqBgK,U;;;AACnB,uBAAanP,KAAb,EAAoB;AAAA;;AAAA,yHACXA,KADW;;AAAA,WA4BpBoP,UA5BoB,GA4BP,YAAM;AACjB,aAAK7L,QAAL,CAAc,EAAC8L,MAAM,IAAP,EAAd;AACD,MA9BmB;;AAAA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A,aAAa,CAAC,CAAlB,C;;;;;;;;;;;;AC5HA;;;;AAGA;;AACA;;;;AAFA;oCAHA,a;;;;;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kCAAiC;AACjC;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA,2BAA0B,aAAa,EAAE;AACzC,8DAA6D;;;AAG7D;AACA;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA,2CAA0C,OAAO;AACjD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA,UAAS;;AAET;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oCAAmC,0BAA0B;AAC7D;AACA;AACA;AACA,kBAAiB;AACjB;AACA;AACA,gCAA+B,kBAAkB;AACjD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,oEAAmE;AACnE;AACA;;AAEA;AACA;AACA;AACA,gCAA+B,kBAAkB;AACjD;AACA;AACA;AACA;AACA;;AAEA,EAAC;;AAED;;AAEA;;AAEA;AACA,oDAAmD;AACnD;AACA;AACA;AACA;AACA,6CAA4C;AAC5C;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,cAAa;AACb;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB;AACnB;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA,qCAAoC;AACpC,mCAAkC;;AAElC;;AAEA;AACA,yBAAwB;AACxB;AACA,MAAK,KAAK;AACV;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA,MAAK,OAAO;AACZ;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA,cAAa;AACb;AACA;;AAEA;AACA;;AAEA;AACA;AACA,qC;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;;AAEA,+CAA8C;AAC9C,oCAAmC,eAAe;AAClD;AACA;AACA,kBAAiB,oCAAoC;AACrD,wCAAuC,KAAK;AAC5C;AACA;AACA,kBAAiB;;AAEjB;AACA,qDAAoD;AACpD;AACA,kBAAiB;AACjB,2DAA0D;AAC1D,gCAA+B,SAAS;AACxC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mCAAkC;AAClC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,wBAAuB,YAAY;AACnC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,wBAAuB,YAAY;AACnC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,wBAAuB,YAAY;AACnC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,wBAAuB,YAAY;AACnC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;;AAEA,eAAc,YAAY;AAC1B;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;;AAEA;AACA;AACA;AACA;AACA,UAAS;;AAET;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,eAAc,YAAY;AAC1B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAc,QAAQ;AACtB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,wBAAuB;AACvB;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qBAAoB;AACpB;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,qDAAoD;AACpD;AACA,MAAK;AACL;AACA;AACA;AACA,gEAA+D;AAC/D;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iCAAgC;AAChC,EAAC;AACD;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mCAAkC;AAClC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,sBAAqB,iBAAiB;AACtC;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,kDAAiD,QAAQ;AACzD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,mBAAkB;AAClB;AACA,MAAK;AACL;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qBAAoB;AACpB;AACA;AACA;AACA;;AAEA,EAAC;;AAED;AACA;;AAEA;AACA;;AAEA,EAAC;;AAED;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,+DAA8D;AAC9D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uCAAsC;AACtC;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA,EAAC;;AAED;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA,UAAS;;AAET;AACA;AACA;AACA,UAAS;;AAET;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;;AAET;AACA;AACA,0DAAyD;AACzD;AACA;AACA;AACA;AACA,kBAAiB;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,+CAA8C,KAAK,G;AACnD;AACA;AACA,cAAa;AACb;AACA,MAAK;;AAEL;AACA;;AAEA;AACA,EAAC;AACD;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA,EAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,8DAA6D;AAC7D,wDAAuD,kCAAkC;;AAEzF;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA,EAAC;;AAED;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAgB,cAAc;AAC9B;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA,UAAS;AACT,M;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA,UAAS;AACT,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,UAAS;AACT,MAAK;AACL;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;;AAEA;AACA;AACA,+B;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,4CAA2C,aAAa;;AAExD;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,wCAAuC,aAAa;AACpD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA,UAAS;AACT,MAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;;AAET;AACA;AACA;AACA;AACA;AACA,UAAS;;AAET;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;;AAET;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;;;AAGA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,kCAAiC,KAAK;AACtC;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,0BAAyB,kBAAkB;AAC3C;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,kBAAiB,cAAc;AAC/B;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAiB,mBAAmB;AACpC;AACA;AACA;AACA;AACA;;AAEA;AACA,mCAAkC;AAClC;;AAEA;AACA,oCAAmC,uBAAuB,uBAAuB,uBAAuB;AACxG;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,UAAS;AACT,MAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;;AAGA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA,UAAS,iDAAiD,EAAE;;AAE5D;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA,MAAK;;AAEL;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA,UAAS;;AAET;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,MAAK;;AAEL;AACA;AACA;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,yBAAwB;AACxB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA,UAAS;AACT;;AAEA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA,UAAS;AACT;AACA;AACA;;AAEA;AACA,0CAAyC;AACzC,wCAAuC;AACvC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA,0CAAyC,cAAc;AACvD;AACA,gDAA+C,cAAc;AAC7D,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AAIA;;AAEA;AACA;AACA,oDAAmD,2BAA2B;AAC9E,MAAK;AACL,qDAAoD,2BAA2B;AAC/E,uDAAsD,2BAA2B;AACjF;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,0CAAyC,0BAA0B;AACnE;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,8DAA6D;AAC7D,iDAAgD;AAChD,8CAA6C;;AAE7C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,W;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;;AAEA;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;;AAEA,qBAAoB;;AAEpB;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,MAAK;;AAEL;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB;AACnB;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,cAAa;AACb;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA,cAAa;AACb;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,EAAC;;AAED;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,iBAAgB;AAChB;AACA,iBAAgB;AAChB;;AAEA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,EAAC;;AAED;AACA,EAAC;;AAED;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;;;AAGL;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT,MAAK;;AAEL;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,UAAS;AACT,MAAK;;AAEL;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,EAAC;;;;AAID;;AAEA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA,c;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,uBAAsB,8BAA8B;AACpD,uBAAsB,8BAA8B;;AAEpD,EAAC;;AAED,EAAC;;AAED;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA,sCAAqC;AACrC;AACA,+CAA8C,WAAW,eAAe,MAAM,OAAO,mBAAmB,UAAU;;AAElH;;AAEA;AACA;AACA,MAAK;AACL;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sBAAqB;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,wCAAuC;AACvC,UAAS;AACT;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAY;AACZ;AACA;AACA;AACA;AACA;AACA;AACA;AACA,6BAA4B;AAC5B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;;AAEA;AACA;AACA;AACA;AACA,UAAS;AACT;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,UAAS;AACT;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;;AAEA,EAAC;;;AAGD;AACA;AACA;;AAEA;;AAEA,EAAC;;AAED;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,EAAC;;AAED;AACA;;AAEA;AACA,mCAAkC,gCAAgC;AAClE,kCAAiC,8BAA8B;;AAE/D;AACA;AACA,qDAAoD;AACpD,yDAAwD;;AAExD;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,kBAAiB,oBAAoB;AACrC;AACA;AACA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA,+CAA8C;AAC9C;AACA;AACA;AACA,kBAAiB,oBAAoB;AACrC;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;;;AAGA;AACA;AACA;AACA,6CAA4C;;AAE5C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA,EAAC;;AAED;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,UAAS;AACT,MAAK;AACL;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,4BAA2B,SAAS,EAAE;AACtC;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,wBAAuB;;AAEvB;AACA;AACA;AACA;AACA,UAAS;AACT;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;;AAEA;AACA,kFAAiF;AACjF;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,UAAS;AACT;;AAEA;AACA;;AAEA,EAAC;;AAED;;AAEA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA,EAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,MAAK;AACL;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA,2CAA0C,iCAAiC;AAC3E;AACA;AACA;AACA;AACA,cAAa;AACb,UAAS;AACT;;AAEA;AACA;AACA;AACA;AACA,YAAW;;AAEX;AACA;;AAEA;;AAEA;AACA;AACA,8EAA6E;AAC7E;;AAEA;AACA,kBAAiB,kBAAkB;AACnC;;AAEA;AACA;AACA;;AAEA;AACA,2CAA0C,OAAO;AACjD;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA,kDAAiD,yBAAyB,EAAE;AAC5E;;AAEA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,UAAS;AACT;AACA;AACA,MAAK;AACL;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,8BAA6B;AAC7B;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA,2CAA0C,kBAAkB;AAC5D;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA,EAAC;;AAED;AACA,mBAAkB,gBAAgB;AAClC,iBAAgB,0CAA0C;AAC1D,mBAAkB,mBAAmB;AACrC,mBAAkB,gBAAgB;AAClC,2BAA0B;AAC1B,EAAC;;;AAGD;AACA,EAAC;;AAED;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,MAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,kBAAiB;AACjB;AACA,2DAA0D,gCAAgC;AAC1F;AACA;AACA;AACA;AACA,MAAK;AACL;;AAEA;;AAEA,EAAC;;AAED;AACA;;AAEA;AACA;;AAEA;AACA;AACA,mBAAkB;AAClB;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;;AAEA;AACA;AACA;AACA;;AAEA,4CAA2C,KAAK;AAChD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,0BAAyB;AACzB;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA,EAAC;;AAED;AACA,EAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA,cAAa;AACb;AACA;AACA,UAAS;AACT;AACA,UAAS;AACT;AACA;AACA;AACA,cAAa;AACb;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA,wBAAuB;AACvB;AACA,wBAAuB;;AAEvB;AACA,0BAAyB;AACzB;AACA,0BAAyB;;AAEzB;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,0BAAyB;AACzB;AACA,wBAAuB;;AAEvB;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,EAAC;AACD;AACA;AACA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;;AAEL;AACA;AACA;AACA,MAAK;AACL;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,UAAS;AACT;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,0BAAyB;AACzB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,cAAa;;AAEb;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,cAAa;;AAEb;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA,UAAS;AACT;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb,UAAS;AACT;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,0CAAyC,KAAK;AAC9C;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA,yCAAwC,KAAK;AAC7C;AACA;AACA;AACA;AACA;;AAEA,EAAC;;AAED;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,kDAAiD;AACjD;;AAEA;AACA,wBAAuB,kBAAkB;AACzC;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAiB;AACjB,4F;AACA;AACA;AACA,sBAAqB;AACrB;AACA,kBAAiB;AACjB;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,sBAAqB;AACrB,kBAAiB;AACjB;AACA;AACA;AACA;AACA,+CAA8C;AAC9C;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,UAAS;;AAET;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,sBAAqB,wBAAwB;;AAE7C;AACA,0CAAyC,OAAO;AAChD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,0CAAyC,OAAO;AAChD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,6BAA4B;AAC5B;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAiB;AACjB;AACA,kBAAiB;AACjB;AACA;AACA;AACA;AACA;AACA,kBAAiB;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;;AAEb;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA,sBAAqB;;AAErB;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,kBAAiB;AACjB;AACA;AACA,8BAA6B;AAC7B;AACA;;AAEA,4BAA2B,oBAAoB;AAC/C;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,sBAAqB;AACrB;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,sBAAqB;AACrB;AACA;AACA,kCAAiC;AACjC;AACA,kBAAiB;AACjB;AACA;AACA,8BAA6B;AAC7B,oCAAmC,iBAAiB;AACpD;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA,sBAAqB;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA,EAAC;;AAED;AACA,EAAC;;AAED;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA,UAAS;AACT;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,4BAA2B,kBAAkB;AAC7C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,4BAA2B,mBAAmB;AAC9C;AACA,UAAS;AACT;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA,4BAA2B,mBAAmB;AAC9C;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,4BAA2B,kBAAkB;AAC7C;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sBAAqB;AACrB;AACA;AACA;AACA,sBAAqB;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAiB;AACjB;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,0BAAyB;AACzB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAiB;AACjB;;AAEA;AACA;AACA;AACA,yDAAwD,gBAAgB;AACxE;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sCAAqC,KAAK;AAC1C;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA,gCAA+B;AAC/B,gCAA+B;AAC/B;;AAEA;AACA;AACA;;AAEA,EAAC;;AAED;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,UAAS;AACT;AACA,4BAA2B,mBAAmB;AAC9C;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,EAAC;;AAED;AACA,EAAC;;AAED;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA,yBAAwB,EAAE;AAC1B;AACA;AACA;;AAEA,EAAC;;AAED;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA,c;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA,O;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA,O;AACA;AACA;AACA,O;AACA;AACA;AACA,O;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA,uB;AACA;AACA;AACA,iBAAgB;AAChB;;AAEA,EAAC;;AAED;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,uCAAsC,4BAA4B;AAClE,uCAAsC,0BAA0B;AAChE;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,gCAA+B,mBAAmB;AAClD;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,2CAA0C,0BAA0B;AACpE;AACA,2CAA0C,0BAA0B;AACpE;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,mCAAkC,aAAa;AAC/C;AACA;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA,UAAS;;AAET;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA,wBAAuB,wBAAwB;AAC/C;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;;AAEA;AACA;AACA;AACA;AACA,wBAAuB,yBAAyB;AAChD;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,oDAAmD,OAAO;AAC1D;AACA;AACA;AACA;AACA;AACA,2EAA0E,aAAa,O;AACvF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;;AAEA;AACA,EAAC;;AAED;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA,kDAAiD,mCAAmC;AACpF;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,+DAA8D;AAC9D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA,EAAC;;AAED,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,MAAK;AACL,iCAAgC,kBAAkB;AAClD,MAAK;AACL,sBAAqB,iBAAiB;AACtC;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA,sBAAqB,kBAAkB;AACvC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,UAAS;;AAET;AACA;;AAEA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAgB;AAChB;;AAEA;AACA,iBAAgB;AAChB;;AAEA;AACA,iBAAgB;AAChB;;AAEA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA,iCAAgC,yBAAyB;AACzD,O;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,UAAS;;AAET;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,2CAA0C,uBAAuB;AACjE,UAAS;AACT;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,2CAA0C,uBAAuB;AACjE,UAAS;;AAET;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,6G;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,sBAAqB,iBAAiB;AACtC;AACA;AACA;AACA;AACA,oCAAmC,MAAM;AACzC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,mC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA,sDAAqD,OAAO;AAC5D;AACA;AACA,yBAAwB;AACxB;AACA,iBAAgB;AAChB;AACA;AACA;AACA;AACA;AACA;AACA,oCAAmC,SAAS;AAC5C;;AAEA;AACA;;AAEA,EAAC;;AAED;AACA,EAAC;;AAED;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA,6BAA4B,QAAQ;;AAEpC;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA,iF;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iCAAgC,WAAW;AAC3C;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,UAAS;AACT;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;;AAEA;AACA;;AAEA,EAAC;;AAED;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA,4BAA2B,UAAU;AACrC;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAiB;AACjB;AACA;;AAEA,wCAAuC,MAAM;AAC7C;AACA;AACA;AACA;AACA;;AAEA,EAAC;;AAED;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,MAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA,wBAAuB,kBAAkB;AACzC;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,wBAAuB,uBAAuB;AAC9C;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA,wBAAuB,kBAAkB;AACzC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,wBAAuB,kBAAkB;AACzC;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,UAAS;AACT;AACA;AACA;;AAEA;AACA;;AAEA,wBAAuB,uBAAuB;AAC9C;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA,EAAC;;AAED;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA,sCAAqC,iBAAiB;AACtD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,kCAAiC,KAAK;AACtC;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,UAAS;;AAET;AACA,wBAAuB,iBAAiB;AACxC;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA,iCAAgC,yBAAyB;AACzD;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;;AAGA;AACA;AACA;AACA;;AAEA,2CAA0C,yBAAyB;AACnE;AACA;AACA,yCAAwC,uBAAuB;AAC/D;AACA;;AAEA;AACA,iCAAgC,cAAc;AAC9C;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA,2CAA0C,OAAO;AACjD;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,kBAAiB;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,mBAAkB,OAAO;AACzB;AACA;AACA;AACA;AACA;AACA;;AAEA,EAAC;;AAED;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,UAAS;AACT;;AAEA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA,kCAAiC,0BAA0B;AAC3D;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,kCAAiC,0BAA0B;AAC3D;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA,EAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA,wBAAuB,kBAAkB;AACzC;AACA;AACA;AACA;AACA,kBAAiB;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA,wBAAuB,sBAAsB;AAC7C;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,4BAA2B,kBAAkB;AAC7C;AACA;AACA;AACA;AACA,kBAAiB;AACjB;AACA,kBAAiB;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,wBAAuB,sBAAsB;AAC7C,4BAA2B,+BAA+B;AAC1D;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,mBAAkB;AAClB;AACA;AACA,wBAAuB,2BAA2B;AAClD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAe,qBAAqB;AACpC;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAe,qBAAqB;AACpC;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,wBAAuB,qBAAqB;AAC5C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sCAAqC;AACrC;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;;AAEA,wBAAuB,qBAAqB;AAC5C;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,qCAAoC,4BAA4B;;AAEhE;AACA;;AAEA;AACA;AACA;AACA,UAAS;AACT;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qCAAoC,+BAA+B;AACnE;;AAEA;AACA;AACA,wBAAuB,kBAAkB;AACzC;AACA;;AAEA;AACA;AACA,UAAS;AACT;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,UAAS;AACT;;AAEA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,cAAa;AACb;AACA;AACA,UAAS;AACT;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA,UAAS;;AAET;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA,kBAAiB;AACjB;AACA;AACA;AACA;AACA,cAAa,iDAAiD,2CAA2C;AACzG;AACA;AACA;AACA;;AAEA;AACA,cAAa;AACb;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAiB;AACjB;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA,kBAAiB;AACjB;AACA,cAAa;AACb;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,4BAA2B;AAC3B;AACA;AACA,oBAAmB;AACnB;AACA;AACA,iCAAgC,cAAc;AAC9C;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAiB;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;;AAEA;AACA;;;;AAIA;AACA;AACA;AACA,mDAAkD;;AAElD;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,UAAS;AACT;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA,EAAC;;AAED;AACA;;AAEA;AACA;;;AAGA;;AAEA;AACA;;AAEA;AACA;;AAEA,qDAAoD,WAAW;AAC/D;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA,+CAA8C,WAAW;AACzD;AACA;AACA,oBAAmB;AACnB,+CAA8C,WAAW;AACzD;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,WAAU,KAAK;AACf,WAAU,KAAK;AACf;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA,iCAAgC;AAChC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;;AAEb;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iCAAgC;AAChC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;;AAEb;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;;AAGA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAiB;AACjB;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT,4BAA2B,mBAAmB;AAC9C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,sBAAqB;AACrB;AACA;;AAEA;AACA;AACA;AACA;AACA,sBAAqB;AACrB;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,sBAAqB;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,4BAA2B;AAC3B,4BAA2B;AAC3B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,4CAA2C;AAC3C;AACA;AACA;AACA,4CAA2C;AAC3C;AACA;AACA;AACA;AACA;AACA;AACA,sBAAqB,eAAe;AACpC;AACA;AACA,4CAA2C;AAC3C;AACA;AACA;AACA,4CAA2C;AAC3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,4CAA2C;AAC3C;AACA;AACA;AACA,4CAA2C;AAC3C;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,4CAA2C;AAC3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,8CAA6C,wCAAwC;AACrF,qCAAoC,wBAAwB;AAC5D;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb,UAAS;AACT;AACA;;AAEA;;AAEA;AACA;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,4BAA2B,SAAS;AACpC;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,wCAAuC,SAAS;AAChD;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA,kBAAiB;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,wBAAuB,mBAAmB;AAC1C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;;AAEA,wBAAuB,mBAAmB;AAC1C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;;AAEA;AACA;AACA;AACA;AACA,+BAA8B,aAAa;AAC3C,oCAAmC,oBAAoB;AACvD;AACA;AACA;AACA;AACA;;AAEA,yCAAwC,uBAAuB;AAC/D;;AAEA;AACA;AACA,4BAA2B,UAAU;AACrC;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;;AAET;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAGA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qCAAoC;AACpC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uBAAsB;AACtB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,0BAAyB,wBAAwB;AACjD;AACA;AACA;AACA;AACA;;AAEA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sBAAqB;AACrB;AACA;AACA;AACA;AACA;AACA;;AAEA,0BAAyB,wBAAwB;AACjD;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA,4CAA2C,uBAAuB;AAClE;AACA;AACA,0BAAyB;AACzB;AACA;AACA;AACA;AACA;AACA,sBAAqB;AACrB;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAGA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,gCAA+B,mBAAmB;AAClD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAiB;AACjB;AACA;AACA,kBAAiB;;AAEjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,4BAA2B,wBAAwB;AACnD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,4BAA2B,uBAAuB;AAClD;AACA;AACA;AACA;AACA;AACA,2BAA0B;AAC1B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,wBAAuB,gBAAgB;AACvC;AACA;AACA;AACA;AACA,gCAA+B,aAAa;AAC5C;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,yBAAwB,qBAAqB;AAC7C;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;;;AAGA;AACA;AACA;;;AAGA;AACA;AACA;AACA;AACA;AACA,qBAAoB;;AAEpB;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA,iBAAgB;AAChB;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,4BAA2B,qBAAqB;AAChD;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,6BAA4B,qBAAqB;AACjD;AACA;AACA;AACA,kBAAiB;AACjB;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,EAAC;;AAED;AACA;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA,MAAK;AACL,wBAAuB,qBAAqB;AAC5C;AACA,0BAAyB,kCAAkC;AAC3D;AACA,MAAK;AACL;AACA;AACA;;AAEA;AACA;AACA;AACA,UAAS;AACT;AACA,MAAK;AACL,mBAAkB,mBAAmB;AACrC;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA,MAAK;AACL;AACA,6BAA4B,iCAAiC;AAC7D;AACA,MAAK;AACL;AACA,6BAA4B,6BAA6B;AACzD,0BAAyB,iCAAiC;AAC1D;AACA,MAAK;AACL;AACA,6BAA4B,oBAAoB;AAChD,0BAAyB;AACzB;AACA,EAAC;;AAED;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA,UAAS;;AAET;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,kDAAiD,eAAe;AAChE,gCAA+B,SAAS;AACxC;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT,4BAA2B,kBAAkB;AAC7C;AACA,gCAA+B,oBAAoB;AACnD;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA,2CAA0C,OAAO;AACjD;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,+DAA8D,KAAK;AACnE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gCAA+B,SAAS;AACxC;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA,kBAAiB;AACjB;;AAEA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA,+CAA8C,QAAQ;AACtD;AACA;AACA;AACA,UAAS;AACT;AACA;AACA,gCAA+B,oBAAoB;AACnD;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,wBAAuB,kBAAkB;AACzC;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA,4BAA2B,iBAAiB;AAC5C;AACA;;AAEA;AACA;;AAEA,0DAAyD,iBAAiB;AAC1E;AACA;AACA,cAAa;AACb;;AAEA;AACA;AACA;;AAEA,kCAAiC,gBAAgB;AACjD;AACA;;AAEA;AACA;;AAEA,0DAAyD,gBAAgB;AACzE;AACA;AACA;;AAEA,iBAAgB;AAChB;;AAEA,EAAC;;AAED;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;;;AAGA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qCAAoC,uDAAuD;;AAE3F;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAiB;AACjB;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA,UAAS;AACT;AACA;AACA,cAAa;AACb;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,wBAAuB,qBAAqB;AAC5C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA,4BAA2B;;AAE3B;AACA;;AAEA;AACA;;AAEA;AACA,UAAS;AACT;;AAEA;AACA;AACA;AACA,UAAS;AACT;;AAEA;AACA;AACA;AACA,UAAS;AACT;;AAEA;AACA;AACA;AACA;AACA,oFAAmF,SAAS;AAC5F;;AAEA;AACA;AACA;AACA;AACA,qBAAoB;AACpB;AACA,qBAAoB;;AAEpB;AACA,mCAAkC,KAAK;AACvC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAgB;AAChB;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,yBAAwB;AACxB;AACA;;AAEA;AACA;AACA,2EAA0E;AAC1E;AACA,qCAAoC;AACpC;AACA,iBAAgB;AAChB;;AAEA;AACA;AACA;;AAEA,EAAC;;AAED;AACA;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,qDAAoD;AACpD,MAAK;AACL;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA,yCAAwC,KAAK;AAC7C;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA,kBAAiB;AACjB;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb,UAAS;AACT;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;;AAEA,EAAC;;AAED;;AAEA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;;AAEA;AACA,aAAY;AACZ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT,MAAK;AACL;AACA,EAAC;AACD;AACA;AACA;AACA;AACA;AACA,UAAS;AACT,MAAK;AACL;AACA;AACA,EAAC;AACD;AACA;AACA;AACA;AACA;AACA,UAAS;AACT,MAAK;AACL;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,oBAAoB,EAAE;AAClD;AACA,EAAC;AACD;AACA;AACA,6BAA4B,0BAA0B,EAAE;AACxD;AACA,EAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA,EAAC;AACD;AACA;AACA,6BAA4B,kCAAkC,EAAE;AAChE;AACA;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,iCAAiC,EAAE;AAC/D;AACA;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,mCAAmC,EAAE;AACjE;AACA;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,uCAAuC,EAAE;AACrE;AACA;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,0BAA0B,EAAE;AACxD;AACA;AACA,EAAC;AACD;AACA;AACA,6B;AACA;AACA;AACA,MAAK;AACL;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,yBAAyB,EAAE;AACvD;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,mBAAmB,EAAE;AACjD;AACA;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,uBAAuB,EAAE;AACrD;AACA;AACA;AACA,EAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA,+B;AACA,MAAK;AACL;AACA,EAAC;AACD;AACA;AACA,6B;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA,EAAC;AACD;AACA;AACA;AACA,6DAA4D,iBAAiB;AAC7E,MAAK;AACL;AACA,EAAC;AACD;AACA;AACA,6BAA4B,0BAA0B,EAAE;AACxD;AACA,EAAC;AACD;AACA;AACA,6BAA4B,yCAAyC,EAAE;AACvE;AACA;AACA;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,4BAA4B,EAAE;AAC1D;AACA;AACA;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,kCAAkC,EAAE;AAChE;AACA;AACA;AACA,EAAC;AACD;AACA;AACA,mCAAkC,+BAA+B,EAAE;AACnE;AACA;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,uCAAuC,EAAE;AACrE;AACA;AACA;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,0BAA0B,EAAE;AACxD;AACA;AACA;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,oCAAoC,EAAE;AAClE;AACA;AACA;AACA,EAAC;AACD;AACA;AACA,mCAAkC,iCAAiC,EAAE;AACrE;AACA;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,wCAAwC,EAAE;AACtE;AACA;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,2BAA2B,EAAE;AACzD;AACA;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,yCAAyC,EAAE;AACvE;AACA;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,4BAA4B,EAAE;AAC1D;AACA;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,oCAAoC,EAAE;AAClE;AACA;AACA;AACA,EAAC;AACD;AACA;AACA,mCAAkC,iCAAiC,EAAE;AACrE;AACA;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,yCAAyC,EAAE;AACvE;AACA;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,4BAA4B,EAAE;AAC1D;AACA;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,uCAAuC,EAAE;AACrE;AACA;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,0BAA0B,EAAE;AACxD;AACA;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,qCAAqC,EAAE;AACnE;AACA;AACA;AACA,EAAC;AACD;AACA;AACA,mCAAkC,kCAAkC,EAAE;AACtE;AACA;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,yBAAyB,EAAE;AACvD;AACA,EAAC;AACD;AACA;AACA,6BAA4B,yBAAyB,EAAE;AACvD;AACA,EAAC;AACD;AACA;AACA,6BAA4B,uBAAuB,EAAE;AACrD;AACA,EAAC;AACD;AACA;AACA,6BAA4B,uBAAuB,EAAE;AACrD;AACA,EAAC;AACD;AACA;AACA,6BAA4B,uBAAuB,EAAE;AACrD;AACA,EAAC;AACD;AACA;AACA,6BAA4B,qBAAqB,EAAE;AACnD;AACA,EAAC;AACD;AACA;AACA,wBAAuB,gEAAgE,EAAE;AACzF;AACA,EAAC;AACD;AACA;AACA,wBAAuB,+DAA+D,EAAE;AACxF;AACA,EAAC;AACD;AACA;AACA,6BAA4B,yCAAyC,EAAE;AACvE;AACA;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,uCAAuC,EAAE;AACrE;AACA;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,yCAAyC,EAAE;AACvE;AACA,EAAC;AACD;AACA;AACA,6BAA4B,gCAAgC,EAAE;AAC9D;AACA,EAAC;AACD;AACA;AACA,6BAA4B,yBAAyB,EAAE;AACvD;AACA;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,6BAA6B,EAAE;AAC3D;AACA;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,mCAAmC,EAAE;AACjE;AACA;AACA;AACA,EAAC;AACD;AACA;AACA,wBAAuB;AACvB;AACA;AACA,EAAC;AACD;AACA;AACA,MAAK;AACL;AACA,EAAC;AACD;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA,EAAC;AACD;AACA;AACA;AACA,MAAK;AACL;AACA,EAAC;AACD;AACA;AACA,6BAA4B,sBAAsB,EAAE;AACpD;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,6BAA6B,EAAE;AAC3D;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,oBAAoB,EAAE;AAClD;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,6BAA6B,EAAE;AAC3D;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,6BAA6B,EAAE;AAC3D;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,wBAAwB,EAAE;AACtD;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,yBAAyB,EAAE;AACvD;AACA;AACA,EAAC;AACD;AACA;AACA;AACA,6DAA4D,uBAAuB;AACnF;AACA,EAAC;AACD;AACA;AACA,6BAA4B,eAAe;AAC3C,EAAC;AACD;AACA;AACA,6BAA4B,eAAe;AAC3C,EAAC;AACD;AACA;AACA,6BAA4B,sBAAsB,EAAE;AACpD;AACA,EAAC;AACD;AACA;AACA,6BAA4B,sBAAsB,EAAE;AACpD;AACA,EAAC;AACD;AACA;AACA,6BAA4B,wBAAwB,EAAE;AACtD;AACA,EAAC;AACD;AACA;AACA,6BAA4B,wBAAwB,EAAE;AACtD;AACA,EAAC;AACD;AACA;AACA,6BAA4B,wBAAwB,EAAE;AACtD;AACA;AACA,EAAC;AACD;AACA;AACA;AACA;AACA;AACA,6BAA4B,uBAAuB,EAAE;AACrD;AACA;AACA,EAAC;AACD;AACA;AACA,6B;AACA;AACA;AACA,UAAS;AACT;AACA;AACA,MAAK;AACL;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,4BAA4B,EAAE;AAC1D;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,0BAA0B,EAAE;AACxD;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,yBAAyB,EAAE;AACvD;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,0BAA0B,EAAE;AACxD;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,uBAAuB,EAAE;AACrD;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,iBAAiB,EAAE;AAC/C;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,uBAAuB,EAAE;AACrD;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,sBAAsB,EAAE;AACpD;AACA;AACA,EAAC;AACD;AACA,kCAAiC,oBAAoB,EAAE;AACvD;AACA;AACA,EAAC;AACD;AACA;AACA;AACA,MAAK;AACL;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,oBAAoB,EAAE;AAClD;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,2BAA2B,EAAE;AACzD,0CAAyC,8BAA8B,EAAE;AACzE;AACA,EAAC;AACD;AACA;AACA,6BAA4B,sBAAsB,EAAE;AACpD;AACA;AACA,EAAC;AACD;AACA;AACA,6BAA4B,sBAAsB,EAAE;AACpD;AACA;AACA,EAAC;AACD;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA,EAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,6CAA4C,2BAA2B;AACvE;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA,MAAK;AACL;AACA;AACA,EAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,wBAAuB,mBAAmB;AAC1C;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;;AAEA;AACA;;AAEA,uBAAsB,sBAAsB;AAC5C;AACA;AACA,MAAK;AACL;AACA;AACA,EAAC;;AAED,EAAC;;AAED;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,MAAK;;AAEL;AACA;;AAEA;;AAEA;AACA,iCAAgC;AAChC;AACA;AACA,MAAK;;AAEL;AACA;AACA,MAAK;;AAEL;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA,2BAA0B;;AAE1B;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA,UAAS;;AAET;AACA;AACA;AACA,UAAS;AACT;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,+CAA8C;AAC9C;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,+DAA8D;;AAE9D;AACA,UAAS;AACT;AACA,qEAAoE;AACpE;;AAEA;AACA;AACA;AACA;AACA,iCAAgC;AAChC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;;AAEA;AACA;AACA;AACA,UAAS;;AAET;;AAEA,2DAA0D,gBAAgB;AAC1E,qDAAoD,aAAa;AACjE;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,0BAAyB;AACzB;AACA;AACA;;AAEA,kBAAiB;AACjB,cAAa;AACb;AACA;AACA;;AAEA;AACA;AACA;AACA,0BAAyB;AACzB;AACA;AACA;AACA,kBAAiB;AACjB;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;;AAGA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,UAAS;;AAET;AACA;;;AAGA;AACA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;AACA;AACA;;;AAGA;AACA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAiB;AACjB;AACA;;AAEA;AACA;AACA,kBAAiB;AACjB;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;;AAEA;AACA;;AAEA,wCAAuC,KAAK;AAC5C;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA,mDAAkD;AAClD;AACA;AACA;AACA,cAAa,OAAO;AACpB;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA,6BAA4B,6BAA6B;AACzD;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,6BAA4B,gBAAgB;AAC5C;;AAEA;AACA;AACA;AACA;AACA,UAAS;;AAET;AACA,iCAAgC,gBAAgB;AAChD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;;AAGA;AACA;AACA,kBAAiB;AACjB;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;;AAEA;AACA;AACA;AACA,4BAA2B,OAAO;AAClC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,cAAa;AACb,UAAS;AACT;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAc,KAAK;AACnB,eAAc,KAAK;AACnB;;AAEA;AACA,uCAAsC;AACtC,uBAAsB,kCAAkC;AACxD;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,gCAA+B;AAC/B;AACA;AACA;AACA;AACA,gCAA+B;AAC/B;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,kBAAiB;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,kBAAiB;AACjB;AACA,kBAAiB;AACjB;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA,8BAA6B,yCAAyC;;AAEtE;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA,wCAAuC,QAAQ;AAC/C;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+BAA8B,eAAe;AAC7C;;AAEA;AACA;AACA,+BAA8B,aAAa;;AAE3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB,oCAAoC;AACvD;AACA;AACA,6BAA4B,mCAAmC;AAC/D;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAiB;AACjB;AACA;AACA,kBAAiB;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,EAAC;;;;AAID;AACA;AACA;AACA;AACA,mDAAkD,YAAY;AAC9D,UAAS;AACT;AACA,MAAK;AACL;AACA,0BAAyB,mCAAmC;AAC5D;AACA,MAAK;AACL;AACA,yCAAwC,2BAA2B;AACnE;AACA,MAAK;AACL;AACA;AACA,sC;AACA,UAAS;AACT;AACA,MAAK;AACL;AACA,6BAA4B,0BAA0B,EAAE;AACxD;AACA;AACA,MAAK;AACL;AACA;AACA;AACA,MAAK;AACL,yBAAwB,mBAAmB;AAC3C,6BAA4B,mBAAmB;AAC/C;AACA,6BAA4B;AAC5B,MAAK;AACL;AACA,6BAA4B,8BAA8B,EAAE;AAC5D,0BAAyB,0BAA0B,EAAE;AACrD;AACA,MAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA,EAAC;;AAED;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,wBAAuB,0BAA0B;AACjD;AACA,iCAAgC;;AAEhC,4BAA2B,gCAAgC;AAC3D;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA,EAAC;;AAED;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,wBAAuB,wBAAwB;AAC/C;AACA;AACA;AACA;AACA,qDAAoD;;AAEpD;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,yBAAwB;AACxB;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA,mCAAkC,UAAU;AAC5C,kCAAiC;AACjC;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,qBAAoB;AACpB;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,EAAC;;AAED;;AAEA,EAAC;;AAED;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;;AAGA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA,cAAa;AACb;AACA,cAAa;AACb;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sB;AACA;AACA;AACA;AACA,eAAc,YAAY;AAC1B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,oCAAmC;AACnC,sBAAqB;AACrB,8BAA6B;AAC7B,gCAA+B;AAC/B;AACA;AACA;;AAEA;AACA;AACA,oCAAmC;AACnC,kCAAiC;AACjC,8BAA6B;AAC7B,mCAAkC;AAClC;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA,oCAAmC;AACnC,sBAAqB;AACrB,8BAA6B;AAC7B,mCAAkC;AAClC;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,oCAAmC;AACnC,kCAAiC;AACjC,8BAA6B;AAC7B,gCAA+B;AAC/B;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,oCAAmC;AACnC,8BAA6B;AAC7B,qBAAoB,QAAQ;AAC5B;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,oCAAmC;AACnC,8BAA6B;AAC7B,qBAAoB,QAAQ;AAC5B;AACA;;AAEA,EAAC;;AAED;;AAEA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA,8BAA6B;AAC7B;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,wBAAuB,iBAAiB;AACxC;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA,wCAAuC,aAAa;AACpD;AACA;AACA;AACA;AACA;AACA,kBAAiB;AACjB;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,kGAAiG,OAAO;AACxG;;AAEA;AACA,gGAA+F,OAAO;AACtG;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,cAAa;AACb;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA,qCAAoC;;AAEpC;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb,8BAA6B;AAC7B,cAAa;AACb,8BAA6B;AAC7B,cAAa;AACb,8BAA6B;AAC7B,cAAa;AACb;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA,oGAAmG;AACnG;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA,wBAAuB,mBAAmB;AAC1C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,wBAAuB,mBAAmB;AAC1C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,kBAAiB;;AAEjB;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,sBAAqB;AACrB,kBAAiB;AACjB;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAiB;AACjB,cAAa;AACb;AACA;;AAEA;AACA;AACA;AACA,UAAS;;AAET;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA,EAAC;;AAED;;AAEA,EAAC;;AAED;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA,qCAAoC,KAAK;AACzC;AACA;AACA;AACA;AACA,qCAAoC,KAAK;AACzC;AACA;;;AAGA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,cAAa;AACb;;AAEA;AACA;AACA;AACA,cAAa;AACb,UAAS;;AAET;AACA;AACA;AACA,UAAS;;AAET;AACA;;AAEA;AACA;AACA,qBAAoB;;AAEpB;AACA;AACA;AACA;AACA;AACA;;AAEA,iBAAgB;AAChB;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA,4BAA2B,aAAa;AACxC;;AAEA,+CAA8C,OAAO;AACrD;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA,EAAC;;AAED;;AAEA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,EAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA,mCAAkC,qBAAqB;AACvD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,EAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA,mCAAkC,sBAAsB;AACxD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,EAAC;;;AAGD,gCAA+B;AAC/B,iCAAgC;AAChC,iCAAgC;;AAEhC;AACA;AACA,EAAC;;AAED;AACA;;AAEA;;;AAGA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;;AAEA,EAAC;;AAED;AACA,EAAC;;AAED;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;;AAGA;AACA;AACA;;AAEA;AACA;AACA;;AAEA,4BAA2B;AAC3B;AACA;;AAEA;;AAEA;;AAEA,4BAA2B;;AAE3B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gDAA+C,WAAW;AAC1D;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;;AAEA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,kB;AACA;AACA,cAAa;AACb,wBAAuB;AACvB;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA,EAAC;;AAED,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+BAA8B;AAC9B,oBAAmB;AACnB,kBAAiB;AACjB,8FAA6F;AAC7F,gBAAe;AACf,EAAC;AACD,gBAAe;AACf,oBAAmB;AACnB,kBAAiB;AACjB,QAAO;AACP,WAAU;AACV,2BAA0B;AAC1B,uBAAsB;AACtB,wBAAuB;AACvB,2BAA0B;AAC1B,mBAAkB;AAClB,cAAa;AACb,EAAC;AACD,eAAc;AACd,oBAAmB;AACnB,6BAA4B;AAC5B,gCAA+B;AAC/B,wBAAuB;AACvB,iBAAgB;AAChB,EAAC;AACD,oCAAmC;AACnC,oBAAmB;AACnB,QAAO;AACP,SAAQ;AACR,UAAS;AACT,WAAU;AACV,aAAY;AACZ,uCAAsC;AACtC,eAAc;AACd,EAAC;AACD,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A;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA,gG;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,UAAS;AACT;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oB;AACA,U;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,2CAA0C;AAC1C;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA,kDAAiD,QAAQ;AACzD,8CAA6C,QAAQ;AACrD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,uBAAsB;;AAEtB;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA,oBAAmB,OAAO;AAC1B;;AAEA;AACA;AACA;AACA,uDAAsD,qBAAqB;AAC3E;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,kCAAiC;;AAEjC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA,iBAAgB;AAChB;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,6CAA4C,YAAY;;AAExD;AACA;AACA;AACA,UAAS;AACT;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA,kDAAiD;AACjD;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,kDAAiD,aAAa;AAC9D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,EAAC;;;AAGD;AACA,sBAAqB,oBAAoB;AACzC;AACA;AACA;AACA;AACA,UAAS;AACT;AACA,MAAK;AACL;AACA,0BAAyB,2BAA2B,EAAE;AACtD;AACA,MAAK;AACL;AACA,0BAAyB,2BAA2B,EAAE;AACtD;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA,qE;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA,MAAK;AACL;AACA;AACA;AACA,UAAS;AACT;AACA,MAAK;AACL;AACA,8BAA6B,2CAA2C;AACxE;AACA,MAAK;AACL;AACA;AACA;AACA;AACA,UAAS;AACT;AACA,MAAK;AACL;AACA;AACA;AACA;AACA,UAAS;AACT;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA,UAAS;AACT;AACA,MAAK;AACL;AACA;AACA;AACA;AACA,UAAS;AACT;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA,6BAA4B,qBAAqB;AACjD,0BAAyB,oCAAoC,EAAE;AAC/D;AACA;AACA;AACA,EAAC;;AAED;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,MAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,UAAS;AACT;;AAEA;AACA;AACA;AACA,yCAAwC,iCAAiC;AACzE;;AAEA;;AAEA,MAAK;AACL;AACA;AACA;AACA;;AAEA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;;AAEL;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA,yCAAwC,eAAe;AACvD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA,qCAAoC;AACpC;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,mCAAkC,yBAAyB;AAC3D;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,uCAAsC,qBAAqB,iBAAiB;AAC5E;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT,kCAAiC,QAAQ;AACzC;;AAEA;AACA,0EAAyE;AACzE;AACA,wCAAuC,iCAAiC;AACxE,UAAS,YAAY;AACrB;AACA;AACA;AACA;AACA;AACA;;AAEA,EAAC;;;AAGD;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uCAAsC;;AAEtC;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,0BAAyB,UAAU;AACnC;AACA;AACA,2BAA0B,yCAAyC;AACnE;AACA;AACA,2BAA0B,sCAAsC;AAChE;;AAEA;AACA;AACA;AACA;AACA,MAAK;AACL;;AAEA;;AAEA;AACA;;AAEA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,UAAS;AACT;;AAEA;AACA,oGAAmG;AACnG;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA,wBAAuB,wBAAwB;AAC/C;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA,qDAAoD,QAAQ;AAC5D;AACA,mCAAkC;AAClC;AACA;AACA,cAAa;AACb,qDAAoD,QAAQ;AAC5D;AACA,mCAAkC;AAClC;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,yCAAwC,KAAK;AAC7C;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,yCAAwC,KAAK;AAC7C;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA,O;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,wBAAuB,mBAAmB;AAC1C;AACA;AACA;AACA;AACA;AACA,EAAC;;;AAGD;AACA,EAAC;;AAED;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,oBAAmB;;AAEnB;AACA;AACA;AACA;;AAEA;;;AAGA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,kBAAiB;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;;AAET,MAAK;AACL;AACA,8C;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;;AAEA;AACA,6E;AACA;AACA;AACA;;AAEA,yBAAwB;;AAExB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,4BAA2B,oBAAoB;AAC/C;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA,+CAA8C,uBAAuB;;AAErE;AACA;AACA;;;AAGA;;AAEA,EAAC;;AAED;AACA;AACA;AACA,6BAA4B,4BAA4B,EAAE;AAC1D,eAAc,uCAAuC;AACrD;AACA;AACA,EAAC;AACD;AACA,6BAA4B,2BAA2B,EAAE;AACzD,eAAc,2CAA2C;AACzD;AACA;AACA,EAAC;AACD;AACA,6BAA4B,kCAAkC,EAAE;AAChE,eAAc,mDAAmD;AACjE;AACA;AACA,EAAC;AACD;AACA,6BAA4B,iCAAiC,EAAE;AAC/D,eAAc,uDAAuD;AACrE;AACA;AACA,EAAC;AACD;AACA,6BAA4B,uBAAuB,EAAE;AACrD,eAAc,2CAA2C;AACzD;AACA;AACA,EAAC;AACD;AACA,6BAA4B,sBAAsB,EAAE;AACpD,eAAc,6CAA6C;AAC3D;AACA;AACA,EAAC;AACD;AACA,6BAA4B,6BAA6B,EAAE;AAC3D,eAAc,uDAAuD;AACrE;AACA;AACA,EAAC;AACD;AACA,6BAA4B,4BAA4B,EAAE;AAC1D,eAAc,yDAAyD;AACvE;AACA;AACA,EAAC;AACD;AACA,6BAA4B,qCAAqC,EAAE;AACnE,eAAc,qCAAqC;AACnD;AACA,EAAC;AACD;AACA,6BAA4B,uBAAuB,EAAE;AACrD,eAAc,qCAAqC;AACnD;AACA,EAAC;AACD;AACA,6BAA4B,kBAAkB,EAAE;AAChD,eAAc,qCAAqC;AACnD;AACA;AACA,EAAC;AACD;AACA;AACA;AACA,6BAA4B,8BAA8B,EAAE;AAC5D;AACA;AACA,oCAAmC;AACnC,EAAC;;AAED;AACA;;AAEA,EAAC;;AAED;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;AACD;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,mCAAkC,aAAa;AAC/C;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,qCAAoC,KAAK;AACzC;AACA;AACA;;AAEA,sCAAqC,gBAAgB;;AAErD;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA,uCAAsC,YAAY;AAClD;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,UAAS;AACT;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA,iCAAgC,eAAe;AAC/C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,8BAA6B,YAAY;AACzC;AACA;AACA;AACA;;AAEA;AACA;AACA,EAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,oCAAmC,KAAK;AACxC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,2DAA0D;AAC1D;AACA;AACA,UAAS;AACT;AACA,UAAS;AACT;AACA,UAAS;AACT;AACA,uDAAsD;AACtD,UAAS;AACT,oEAAmE;AACnE;AACA;AACA,O;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,wDAAuD,wBAAwB;;AAE/E;AACA;;AAEA;AACA;AACA,oCAAmC,KAAK;AACxC;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iEAAgE,wBAAwB;AACxF;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,4BAA2B,mBAAmB;AAC9C;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,U;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA,oCAAmC,KAAK;AACxC;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA,UAAS;AACT;AACA;;AAEA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;;AAEA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,iCAAgC,KAAK;AACrC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,iCAAgC,KAAK;AACrC;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA,iCAAgC,KAAK;AACrC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;;AAET;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAiB;AACjB;AACA;AACA,kBAAiB;;AAEjB;AACA;AACA;AACA;AACA;AACA,kCAAiC,mBAAmB;AACpD;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA,cAAa;;AAEb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,UAAS;AACT;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;;;AAGD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA,MAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA,UAAS;AACT;AACA,MAAK;AACL;AACA;AACA;AACA,UAAS;AACT;AACA;AACA,EAAC;;;;AAID,EAAC;;AAED;AACA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA,sBAAqB;AACrB;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,oBAAmB;AACnB;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,EAAC;;AAED,EAAC;;AAED;AACA;;AAEA;AACA;AACA,yCAAwC;AACxC,qBAAoB;AACpB,aAAY;AACZ,EAAC;AACD,4BAA2B;AAC3B,YAAW;AACX,qBAAoB;AACpB,EAAC;AACD,oBAAmB;AACnB,2BAA0B;AAC1B,EAAC;AACD,UAAS;AACT,2BAA0B;AAC1B,cAAa;AACb,EAAC;AACD,sBAAqB;AACrB,cAAa;AACb,EAAC;AACD,yBAAwB;AACxB,2BAA0B;AAC1B,EAAC;AACD;AACA,uBAAsB;AACtB,aAAY;AACZ,EAAC;AACD,wBAAuB;AACvB,wBAAuB;AACvB,EAAC;AACD,oCAAmC;AACnC,yBAAwB;AACxB,EAAC;AACD,qCAAoC;AACpC,yBAAwB;AACxB,EAAC;AACD,oCAAmC;AACnC,wBAAuB;AACvB,EAAC;AACD,uBAAsB;AACtB,wCAAuC;AACvC,YAAW;AACX,EAAC;AACD,oCAAmC;AACnC,yBAAwB;AACxB,EAAC;AACD,oCAAmC;AACnC,wBAAuB;AACvB,EAAC;AACD;AACA,iCAAgC;AAChC,2BAA0B;AAC1B,EAAC;AACD,oCAAmC;AACnC,2BAA0B;AAC1B,EAAC;AACD,sBAAqB;AACrB,uBAAsB;AACtB,EAAC;AACD,uBAAsB;AACtB,0BAAyB;AACzB,EAAC;AACD,+BAA8B;AAC9B,yBAAwB;AACxB,EAAC;AACD,uCAAsC;AACtC,2BAA0B;AAC1B,EAAC;AACD,oCAAmC;AACnC,uBAAsB;AACtB,EAAC;AACD,wBAAuB;AACvB,0BAAyB;AACzB,EAAC;AACD,sBAAqB;AACrB,0BAAyB;AACzB,EAAC;AACD,4CAA2C;AAC3C,gBAAe;AACf,EAAC;AACD,uBAAsB;AACtB,wBAAuB;AACvB,EAAC;AACD,oBAAmB;AACnB,wBAAuB;AACvB,EAAC;AACD,4BAA2B;AAC3B,uBAAsB;AACtB,EAAC;AACD,gCAA+B;AAC/B;AACA,EAAC;AACD,2CAA0C;AAC1C,gCAA+B;AAC/B,EAAC;AACD,mDAAkD;AAClD,+BAA8B;AAC9B,EAAC;AACD,sCAAqC;AACrC,8BAA6B;AAC7B,EAAC;AACD,uCAAsC;AACtC,gCAA+B;AAC/B,EAAC;AACD,yCAAwC;AACxC,uBAAsB;AACtB,sCAAqC;AACrC,EAAC;AACD,6CAA4C;AAC5C,iCAAgC;AAChC,EAAC;AACD,kCAAiC;AACjC,4BAA2B;AAC3B,EAAC;AACD,+CAA8C;AAC9C,gCAA+B;AAC/B,sCAAqC;AACrC,EAAC;AACD,4BAA2B;AAC3B,kCAAiC,kIAAkI;AACnK,EAAC;AACD;;AAEA;AACA;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA,O;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gCAA+B,SAAS;AACxC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA,UAAS;AACT;AACA;AACA;AACA,cAAa;AACb;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,2CAA0C,MAAM,OAAO,aAAa;;AAEpE;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,2CAA0C,MAAM,OAAO,aAAa;AACpE;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,wBAAuB,2BAA2B;AAClD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+CAA8C,MAAM,OAAO,WAAW;AACtE;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA,4BAA2B,WAAW;AACtC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+DAA8D,iBAAiB;AAC/E;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;;AAEA,EAAC;;;AAGD;;AAEA,EAAC;;AAED;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA,wCAAuC,qBAAqB;AAC5D;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;;;AAGA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA,qBAAoB;AACpB;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA,sDAAqD,0BAA0B;AAC/E;;;AAGA;AACA,4BAA2B;AAC3B,6BAA4B;AAC5B,wBAAuB;AACvB;AACA,MAAK;AACL,oBAAmB;AACnB,+BAA8B;AAC9B,kCAAiC;AACjC,uBAAsB;AACtB,4BAA2B;AAC3B,+BAA8B;AAC9B,MAAK;AACL,4DAA2D;AAC3D;AACA,MAAK;AACL,gEAA+D;AAC/D;AACA,MAAK;AACL,0DAAyD;AACzD;AACA,MAAK;AACL,sDAAqD;AACrD;AACA,MAAK;AACL,0BAAyB;AACzB,4BAA2B;AAC3B,2BAA0B;AAC1B,iDAAgD;AAChD,mDAAkD;AAClD,kDAAiD;AACjD,mBAAkB;AAClB,MAAK;AACL;;AAEA,EAAC;;AAED;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,yCAAwC;AACxC,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAiB;AACjB,cAAa;;AAEb,iD;;;;;;ACvvkBA,8BAA6B,mDAAmD;;;;;;;ACAhF;;AAEA;AACA;AACA;AACA,2BAA0B,mBAAmB;AAC7C;AACA,MAAK;AACL;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA,mDAAkD,SAAS;AAC3D;AACA,MAAK,wCAAwC,SAAS;AACtD;AACA;;AAEA;AACA;AACA;;;;;;;;AC3BA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA,cAAa;AACb;AACA;AACA,cAAa;AACb;AACA;AACA,cAAa;AACb;AACA;AACA,cAAa;AACb;AACA;AACA,cAAa;AACb;AACA;AACA,cAAa;AACb;AACA,8BAA6B;AAC7B,cAAa;AACb;AACA,gCAA+B;AAC/B,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA,4CAA2C,EAAE,cAAc,EAAE;AAC7D,cAAa;AACb;AACA;AACA,cAAa;AACb;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA,EAAC;;AAED;AACA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA;;AAEA,uBAAsB;AACtB;;AAEA;AACA;AACA,wCAAuC;;AAEvC;;AAEA;AACA,qDAAoD,yBAAyB;;AAE7E;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA,EAAC;;AAED;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,6BAA4B;AAC5B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,uBAAsB;AACtB;AACA;AACA;AACA,mDAAkD;AAClD,0DAAyD,KAAK;AAC9D,cAAa;AACb,2BAA0B;AAC1B,yEAAwE;AACxE;AACA,kCAAiC;AACjC;AACA;AACA,kBAAiB;AACjB,0EAAyE;AACzE;AACA,iCAAgC;AAChC;AACA;AACA;AACA;AACA,UAAS,oBAAoB;AAC7B;AACA;AACA,gCAA+B;AAC/B,8DAA6D,IAAI,2CAA2C;AAC5G;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA,+CAA8C;AAC9C;AACA;AACA;AACA,iCAAgC;AAChC,iEAAgE,yCAAyC,IAAI;AAC7G;AACA;AACA;AACA,cAAa;AACb;AACA,cAAa;AACb;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA,MAAK;;AAEL;AACA;AACA,mDAAkD;AAClD;AACA;AACA;AACA,gCAA+B;AAC/B;AACA;AACA,cAAa;AACb;AACA;AACA;AACA,MAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA,kEAAiE,2CAA2C;AAC5G;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA,kEAAiE,2CAA2C;AAC5G;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,kBAAiB;AACjB;AACA,qCAAoC;AACpC;AACA,qCAAoC;AACpC;AACA;AACA;AACA;AACA;AACA;AACA,qCAAoC;AACpC,4CAA2C,GAAG;AAC9C,qCAAoC;AACpC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;;AAEL;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;;;AAIA;;AAEA;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA,mCAAkC,QAAQ;AAC1C,sCAAqC,KAAK;AAC1C;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AAC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;AACb,0CAAyC;AACzC,cAAa;AACb,6BAA4B;AAC5B,2BAA0B;AAC1B,cAAa;AACb,EAAC;AACD,oBAAmB;AACnB,wBAAuB;AACvB,WAAU;AACV,EAAC;AACD,qBAAoB;AACpB,wBAAuB;AACvB,EAAC;AACD,sBAAqB;AACrB,uBAAsB;AACtB,WAAU;AACV,EAAC;AACD,qBAAoB;AACpB,oBAAmB;AACnB,mBAAkB;AAClB,2BAA0B;AAC1B,wBAAuB;AACvB,sBAAqB;AACrB,uBAAsB;AACtB,mBAAkB;AAClB,EAAC;AACD;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;;AAET;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;;AAET;AACA;AACA,UAAS;;AAET;AACA;AACA,UAAS;AACT;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA,UAAS;AACT;AACA;AACA,UAAS;AACT;AACA;AACA,UAAS;AACT;AACA,oCAAmC,YAAY;AAC/C,UAAS;AACT;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA,MAAK;;AAEL;AACA;AACA,mBAAkB,iDAAiD;AACnE;AACA;AACA;AACA;AACA,MAAK;AACL;AACA,mBAAkB,iDAAiD;AACnE;AACA;AACA;AACA;AA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CA,kBAAiB,2BAA2B;AAC5C;AACA;AACA,SAAQ,uBAAuB;AAC/B;AACA;AACA,IAAG;AACH;AACA,kBAAiB,uBAAuB;AACxC;AACA;AACA,4BAA2B;AAC3B;AACA;AACA;;AAEA;AACA;AACA;AACA,gBAAe,iBAAiB;AAChC;AACA;AACA;AACA;AACA;AACA,eAAc;AACd;AACA,iCAAgC,sBAAsB;AACtD;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA,IAAG;AACH;AACA;AACA;AACA,GAAE;AACF;AACA,GAAE;AACF;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,wDAAuD;AACvD;;AAEA,8BAA6B,mBAAmB;;AAEhD;;AAEA;;AAEA;AACA;AACA","file":"jsoneditor.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"jsoneditor\"] = factory();\n\telse\n\t\troot[\"jsoneditor\"] = factory();\n})(this, function() {\nreturn \n\n\n/** WEBPACK FOOTER **\n ** webpack/universalModuleDefinition\n **/"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\texports: {},\n \t\t\tid: moduleId,\n \t\t\tloaded: false\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.loaded = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(0);\n\n\n\n/** WEBPACK FOOTER **\n ** webpack/bootstrap 5d44b740c714db823b48\n **/","import { h, render } from 'preact'\nimport CodeMode from './CodeMode'\nimport TextMode from './TextMode'\nimport TreeMode from './TreeMode'\n\nimport '!style!css!less!./jsoneditor.less'\n\nconst modes = {\n code: CodeMode,\n form: TreeMode,\n text: TextMode,\n tree: TreeMode,\n view: TreeMode\n}\n\n/**\n * Create a new json editor\n * @param {HTMLElement} container\n * @param {Options} options\n * @return {Object}\n * @constructor\n */\nfunction jsoneditor (container, options = {}) {\n\n const editor = {\n isJSONEditor: true,\n\n _container: container,\n _options: options,\n _modes: modes,\n _mode: null,\n _element: null,\n _component: null\n }\n\n /**\n * Set JSON object in editor\n * @param {Object | Array | string | number | boolean | null} json JSON data\n * @param {SetOptions} [options]\n */\n editor.set = function (json, options = {}) {\n editor._component.set(json, options)\n }\n\n /**\n * Get JSON from the editor\n * @returns {Object | Array | string | number | boolean | null} json\n */\n editor.get = function () {\n return editor._component.get()\n }\n\n /**\n * Set a string containing a JSON document\n * @param {string} text\n */\n editor.setText = function (text) {\n editor._component.setText(text)\n }\n\n /**\n * Get the JSON document as text\n * @return {string} text\n */\n editor.getText = function () {\n return editor._component.getText()\n }\n\n /**\n * Expand one or multiple objects or arrays.\n *\n * Example usage:\n *\n * // expand one item at a specific path\n * editor.expand(['foo', 1, 'bar'])\n *\n * // expand all items nested at a maximum depth of 2\n * editor.expand(function (path) {\n * return path.length <= 2\n * })\n *\n * @param {Path | function (path: Path) : boolean} callback\n */\n editor.expand = function (callback) {\n editor._component.expand(callback)\n }\n\n /**\n * Collapse one or multiple objects or arrays\n *\n * Example usage:\n *\n * // collapse one item at a specific path\n * editor.collapse(['foo', 1, 'bar'])\n *\n * // collapse all items nested deeper than 2\n * editor.collapse(function (path) {\n * return path.length > 2\n * })\n *\n * @param {Path | function (path: Path) : boolean} callback\n */\n editor.collapse = function (callback) {\n editor._component.collapse(callback)\n }\n\n /**\n * Apply a JSONPatch to the current JSON document\n * @param {Array} actions JSONPatch actions\n * @return {Array} Returns a JSONPatch to revert the applied patch\n */\n editor.patch = function (actions) {\n return editor._component.patch(actions)\n }\n\n /**\n * Change the mode of the editor\n * @param {'tree' | 'text'} mode\n */\n editor.setMode = function (mode) {\n if (mode === editor._mode) {\n // mode stays the same. do nothing\n return\n }\n\n let success = false\n let initialChildCount = editor._container.children.length\n let element\n try {\n // find the constructor for the selected mode\n const constructor = editor._modes[mode]\n if (!constructor) {\n throw new Error('Unknown mode \"' + mode + '\". ' +\n 'Choose from: ' + Object.keys(modes).join(', '))\n }\n\n function handleChangeMode (mode) {\n const prevMode = editor._mode\n\n editor.setMode(mode)\n\n if (editor._options.onChangeMode) {\n editor._options.onChangeMode(mode, prevMode)\n }\n }\n\n // create new component\n element = render(\n h(constructor, {\n mode,\n options: editor._options,\n onChangeMode: handleChangeMode\n }),\n editor._container)\n\n // set JSON (this can throw an error)\n const text = editor._component ? editor._component.getText() : '{}'\n element._component.setText(text)\n\n // when setText didn't fail, we will reach this point\n success = true\n }\n finally {\n if (success) {\n // destroy previous component\n if (editor._element) {\n editor._element._component.destroy()\n editor._element.parentNode.removeChild(editor._element)\n }\n\n editor._mode = mode\n editor._element = element\n editor._component = element._component\n }\n else {\n // TODO: fall back to text mode when loading code mode failed?\n\n // remove the just created component if any (where construction or setText failed)\n const childCount = editor._container.children.length\n if (childCount !== initialChildCount) {\n editor._container.removeChild(editor._container.lastChild)\n }\n }\n }\n }\n\n // TODO: implement destroy\n\n editor.setMode(options && options.mode || 'tree')\n\n return editor\n}\n\nmodule.exports = jsoneditor\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/index.js\n **/","!function(global, factory) {\n 'object' == typeof exports && 'undefined' != typeof module ? factory(exports) : 'function' == typeof define && define.amd ? define([ 'exports' ], factory) : factory(global.preact = global.preact || {});\n}(this, function(exports) {\n function VNode(nodeName, attributes, children) {\n this.nodeName = nodeName;\n this.attributes = attributes;\n this.children = children;\n this.key = attributes && attributes.key;\n }\n function h(nodeName, attributes) {\n var lastSimple, child, simple, i, children = [];\n for (i = arguments.length; i-- > 2; ) stack.push(arguments[i]);\n if (attributes && attributes.children) {\n if (!stack.length) stack.push(attributes.children);\n delete attributes.children;\n }\n while (stack.length) if ((child = stack.pop()) instanceof Array) for (i = child.length; i--; ) stack.push(child[i]); else if (null != child && child !== !1) {\n if ('number' == typeof child || child === !0) child = String(child);\n simple = 'string' == typeof child;\n if (simple && lastSimple) children[children.length - 1] += child; else {\n children.push(child);\n lastSimple = simple;\n }\n }\n var p = new VNode(nodeName, attributes || void 0, children);\n if (options.vnode) options.vnode(p);\n return p;\n }\n function extend(obj, props) {\n if (props) for (var i in props) obj[i] = props[i];\n return obj;\n }\n function clone(obj) {\n return extend({}, obj);\n }\n function delve(obj, key) {\n for (var p = key.split('.'), i = 0; i < p.length && obj; i++) obj = obj[p[i]];\n return obj;\n }\n function isFunction(obj) {\n return 'function' == typeof obj;\n }\n function isString(obj) {\n return 'string' == typeof obj;\n }\n function hashToClassName(c) {\n var str = '';\n for (var prop in c) if (c[prop]) {\n if (str) str += ' ';\n str += prop;\n }\n return str;\n }\n function cloneElement(vnode, props) {\n return h(vnode.nodeName, extend(clone(vnode.attributes), props), arguments.length > 2 ? [].slice.call(arguments, 2) : vnode.children);\n }\n function createLinkedState(component, key, eventPath) {\n var path = key.split('.'), p0 = path[0];\n return function(e) {\n var _component$setState;\n var i, t = e && e.currentTarget || this, s = component.state, obj = s, v = isString(eventPath) ? delve(e, eventPath) : t.nodeName ? (t.nodeName + t.type).match(/^input(che|rad)/i) ? t.checked : t.value : e;\n if (path.length > 1) {\n for (i = 0; i < path.length - 1; i++) obj = obj[path[i]] || (obj[path[i]] = {});\n obj[path[i]] = v;\n v = s[p0];\n }\n component.setState((_component$setState = {}, _component$setState[p0] = v, _component$setState));\n };\n }\n function enqueueRender(component) {\n if (!component._dirty && (component._dirty = !0) && 1 == items.push(component)) (options.debounceRendering || defer)(rerender);\n }\n function rerender() {\n var p, list = items;\n items = [];\n while (p = list.pop()) if (p._dirty) renderComponent(p);\n }\n function isFunctionalComponent(vnode) {\n var nodeName = vnode && vnode.nodeName;\n return nodeName && isFunction(nodeName) && !(nodeName.prototype && nodeName.prototype.render);\n }\n function buildFunctionalComponent(vnode, context) {\n return vnode.nodeName(getNodeProps(vnode), context || EMPTY);\n }\n function isSameNodeType(node, vnode) {\n if (isString(vnode)) return node instanceof Text;\n if (isString(vnode.nodeName)) return isNamedNode(node, vnode.nodeName);\n if (isFunction(vnode.nodeName)) return node._componentConstructor === vnode.nodeName || isFunctionalComponent(vnode); else ;\n }\n function isNamedNode(node, nodeName) {\n return node.normalizedNodeName === nodeName || toLowerCase(node.nodeName) === toLowerCase(nodeName);\n }\n function getNodeProps(vnode) {\n var props = clone(vnode.attributes);\n props.children = vnode.children;\n var defaultProps = vnode.nodeName.defaultProps;\n if (defaultProps) for (var i in defaultProps) if (void 0 === props[i]) props[i] = defaultProps[i];\n return props;\n }\n function removeNode(node) {\n var p = node.parentNode;\n if (p) p.removeChild(node);\n }\n function setAccessor(node, name, old, value, isSvg) {\n if ('className' === name) name = 'class';\n if ('class' === name && value && 'object' == typeof value) value = hashToClassName(value);\n if ('key' === name) ; else if ('class' === name && !isSvg) node.className = value || ''; else if ('style' === name) {\n if (!value || isString(value) || isString(old)) node.style.cssText = value || '';\n if (value && 'object' == typeof value) {\n if (!isString(old)) for (var i in old) if (!(i in value)) node.style[i] = '';\n for (var i in value) node.style[i] = 'number' == typeof value[i] && !NON_DIMENSION_PROPS[i] ? value[i] + 'px' : value[i];\n }\n } else if ('dangerouslySetInnerHTML' === name) {\n if (value) node.innerHTML = value.__html;\n } else if ('o' == name[0] && 'n' == name[1]) {\n var l = node._listeners || (node._listeners = {});\n name = toLowerCase(name.substring(2));\n if (value) {\n if (!l[name]) node.addEventListener(name, eventProxy, !!NON_BUBBLING_EVENTS[name]);\n } else if (l[name]) node.removeEventListener(name, eventProxy, !!NON_BUBBLING_EVENTS[name]);\n l[name] = value;\n } else if ('list' !== name && 'type' !== name && !isSvg && name in node) {\n setProperty(node, name, null == value ? '' : value);\n if (null == value || value === !1) node.removeAttribute(name);\n } else {\n var ns = isSvg && name.match(/^xlink\\:?(.+)/);\n if (null == value || value === !1) if (ns) node.removeAttributeNS('http://www.w3.org/1999/xlink', toLowerCase(ns[1])); else node.removeAttribute(name); else if ('object' != typeof value && !isFunction(value)) if (ns) node.setAttributeNS('http://www.w3.org/1999/xlink', toLowerCase(ns[1]), value); else node.setAttribute(name, value);\n }\n }\n function setProperty(node, name, value) {\n try {\n node[name] = value;\n } catch (e) {}\n }\n function eventProxy(e) {\n return this._listeners[e.type](options.event && options.event(e) || e);\n }\n function collectNode(node) {\n removeNode(node);\n if (node instanceof Element) {\n node._component = node._componentConstructor = null;\n var _name = node.normalizedNodeName || toLowerCase(node.nodeName);\n (nodes[_name] || (nodes[_name] = [])).push(node);\n }\n }\n function createNode(nodeName, isSvg) {\n var name = toLowerCase(nodeName), node = nodes[name] && nodes[name].pop() || (isSvg ? document.createElementNS('http://www.w3.org/2000/svg', nodeName) : document.createElement(nodeName));\n node.normalizedNodeName = name;\n return node;\n }\n function flushMounts() {\n var c;\n while (c = mounts.pop()) if (c.componentDidMount) c.componentDidMount();\n }\n function diff(dom, vnode, context, mountAll, parent, componentRoot) {\n if (!diffLevel++) isSvgMode = parent instanceof SVGElement;\n var ret = idiff(dom, vnode, context, mountAll);\n if (parent && ret.parentNode !== parent) parent.appendChild(ret);\n if (!--diffLevel && !componentRoot) flushMounts();\n return ret;\n }\n function idiff(dom, vnode, context, mountAll) {\n var originalAttributes = vnode && vnode.attributes;\n while (isFunctionalComponent(vnode)) vnode = buildFunctionalComponent(vnode, context);\n if (null == vnode) vnode = '';\n if (isString(vnode)) {\n if (dom) {\n if (dom instanceof Text && dom.parentNode) {\n dom.nodeValue = vnode;\n return dom;\n }\n recollectNodeTree(dom);\n }\n return document.createTextNode(vnode);\n }\n if (isFunction(vnode.nodeName)) return buildComponentFromVNode(dom, vnode, context, mountAll);\n var out = dom, nodeName = vnode.nodeName, prevSvgMode = isSvgMode;\n if (!isString(nodeName)) nodeName = String(nodeName);\n isSvgMode = 'svg' === nodeName ? !0 : 'foreignObject' === nodeName ? !1 : isSvgMode;\n if (!dom) out = createNode(nodeName, isSvgMode); else if (!isNamedNode(dom, nodeName)) {\n out = createNode(nodeName, isSvgMode);\n while (dom.firstChild) out.appendChild(dom.firstChild);\n recollectNodeTree(dom);\n }\n if (vnode.children && 1 === vnode.children.length && 'string' == typeof vnode.children[0] && 1 === out.childNodes.length && out.firstChild instanceof Text) out.firstChild.nodeValue = vnode.children[0]; else if (vnode.children && vnode.children.length || out.firstChild) innerDiffNode(out, vnode.children, context, mountAll);\n var props = out[ATTR_KEY];\n if (!props) {\n out[ATTR_KEY] = props = {};\n for (var a = out.attributes, i = a.length; i--; ) props[a[i].name] = a[i].value;\n }\n diffAttributes(out, vnode.attributes, props);\n if (originalAttributes && 'function' == typeof originalAttributes.ref) (props.ref = originalAttributes.ref)(out);\n isSvgMode = prevSvgMode;\n return out;\n }\n function innerDiffNode(dom, vchildren, context, mountAll) {\n var j, c, vchild, child, originalChildren = dom.childNodes, children = [], keyed = {}, keyedLen = 0, min = 0, len = originalChildren.length, childrenLen = 0, vlen = vchildren && vchildren.length;\n if (len) for (var i = 0; i < len; i++) {\n var _child = originalChildren[i], key = vlen ? (c = _child._component) ? c.__key : (c = _child[ATTR_KEY]) ? c.key : null : null;\n if (key || 0 === key) {\n keyedLen++;\n keyed[key] = _child;\n } else children[childrenLen++] = _child;\n }\n if (vlen) for (var i = 0; i < vlen; i++) {\n vchild = vchildren[i];\n child = null;\n var key = vchild.key;\n if (null != key) {\n if (keyedLen && key in keyed) {\n child = keyed[key];\n keyed[key] = void 0;\n keyedLen--;\n }\n } else if (!child && min < childrenLen) {\n for (j = min; j < childrenLen; j++) {\n c = children[j];\n if (c && isSameNodeType(c, vchild)) {\n child = c;\n children[j] = void 0;\n if (j === childrenLen - 1) childrenLen--;\n if (j === min) min++;\n break;\n }\n }\n if (!child && min < childrenLen && isFunction(vchild.nodeName) && mountAll) {\n child = children[min];\n children[min++] = void 0;\n }\n }\n child = idiff(child, vchild, context, mountAll);\n if (child && child !== dom && child !== originalChildren[i]) dom.insertBefore(child, originalChildren[i] || null);\n }\n if (keyedLen) for (var i in keyed) if (keyed[i]) recollectNodeTree(keyed[i]);\n if (min < childrenLen) removeOrphanedChildren(children);\n }\n function removeOrphanedChildren(children, unmountOnly) {\n for (var i = children.length; i--; ) if (children[i]) recollectNodeTree(children[i], unmountOnly);\n }\n function recollectNodeTree(node, unmountOnly) {\n var component = node._component;\n if (component) unmountComponent(component, !unmountOnly); else {\n if (node[ATTR_KEY] && node[ATTR_KEY].ref) node[ATTR_KEY].ref(null);\n if (!unmountOnly) collectNode(node);\n if (node.childNodes && node.childNodes.length) removeOrphanedChildren(node.childNodes, unmountOnly);\n }\n }\n function diffAttributes(dom, attrs, old) {\n for (var _name in old) if (!(attrs && _name in attrs) && null != old[_name]) setAccessor(dom, _name, old[_name], old[_name] = void 0, isSvgMode);\n if (attrs) for (var _name2 in attrs) if (!('children' === _name2 || 'innerHTML' === _name2 || _name2 in old && attrs[_name2] === ('value' === _name2 || 'checked' === _name2 ? dom[_name2] : old[_name2]))) setAccessor(dom, _name2, old[_name2], old[_name2] = attrs[_name2], isSvgMode);\n }\n function collectComponent(component) {\n var name = component.constructor.name, list = components[name];\n if (list) list.push(component); else components[name] = [ component ];\n }\n function createComponent(Ctor, props, context) {\n var inst = new Ctor(props, context), list = components[Ctor.name];\n Component.call(inst, props, context);\n if (list) for (var i = list.length; i--; ) if (list[i].constructor === Ctor) {\n inst.nextBase = list[i].nextBase;\n list.splice(i, 1);\n break;\n }\n return inst;\n }\n function setComponentProps(component, props, opts, context, mountAll) {\n if (!component._disable) {\n component._disable = !0;\n if (component.__ref = props.ref) delete props.ref;\n if (component.__key = props.key) delete props.key;\n if (!component.base || mountAll) {\n if (component.componentWillMount) component.componentWillMount();\n } else if (component.componentWillReceiveProps) component.componentWillReceiveProps(props, context);\n if (context && context !== component.context) {\n if (!component.prevContext) component.prevContext = component.context;\n component.context = context;\n }\n if (!component.prevProps) component.prevProps = component.props;\n component.props = props;\n component._disable = !1;\n if (0 !== opts) if (1 === opts || options.syncComponentUpdates !== !1 || !component.base) renderComponent(component, 1, mountAll); else enqueueRender(component);\n if (component.__ref) component.__ref(component);\n }\n }\n function renderComponent(component, opts, mountAll, isChild) {\n if (!component._disable) {\n var skip, rendered, inst, cbase, props = component.props, state = component.state, context = component.context, previousProps = component.prevProps || props, previousState = component.prevState || state, previousContext = component.prevContext || context, isUpdate = component.base, nextBase = component.nextBase, initialBase = isUpdate || nextBase, initialChildComponent = component._component;\n if (isUpdate) {\n component.props = previousProps;\n component.state = previousState;\n component.context = previousContext;\n if (2 !== opts && component.shouldComponentUpdate && component.shouldComponentUpdate(props, state, context) === !1) skip = !0; else if (component.componentWillUpdate) component.componentWillUpdate(props, state, context);\n component.props = props;\n component.state = state;\n component.context = context;\n }\n component.prevProps = component.prevState = component.prevContext = component.nextBase = null;\n component._dirty = !1;\n if (!skip) {\n if (component.render) rendered = component.render(props, state, context);\n if (component.getChildContext) context = extend(clone(context), component.getChildContext());\n while (isFunctionalComponent(rendered)) rendered = buildFunctionalComponent(rendered, context);\n var toUnmount, base, childComponent = rendered && rendered.nodeName;\n if (isFunction(childComponent)) {\n inst = initialChildComponent;\n var childProps = getNodeProps(rendered);\n if (inst && inst.constructor === childComponent) setComponentProps(inst, childProps, 1, context); else {\n toUnmount = inst;\n inst = createComponent(childComponent, childProps, context);\n inst.nextBase = inst.nextBase || nextBase;\n inst._parentComponent = component;\n component._component = inst;\n setComponentProps(inst, childProps, 0, context);\n renderComponent(inst, 1, mountAll, !0);\n }\n base = inst.base;\n } else {\n cbase = initialBase;\n toUnmount = initialChildComponent;\n if (toUnmount) cbase = component._component = null;\n if (initialBase || 1 === opts) {\n if (cbase) cbase._component = null;\n base = diff(cbase, rendered, context, mountAll || !isUpdate, initialBase && initialBase.parentNode, !0);\n }\n }\n if (initialBase && base !== initialBase && inst !== initialChildComponent) {\n var baseParent = initialBase.parentNode;\n if (baseParent && base !== baseParent) baseParent.replaceChild(base, initialBase);\n if (!cbase && !toUnmount && component._parentComponent) {\n initialBase._component = null;\n recollectNodeTree(initialBase);\n }\n }\n if (toUnmount) unmountComponent(toUnmount, base !== initialBase);\n component.base = base;\n if (base && !isChild) {\n var componentRef = component, t = component;\n while (t = t._parentComponent) componentRef = t;\n base._component = componentRef;\n base._componentConstructor = componentRef.constructor;\n }\n }\n if (!isUpdate || mountAll) mounts.unshift(component); else if (!skip && component.componentDidUpdate) component.componentDidUpdate(previousProps, previousState, previousContext);\n var fn, cb = component._renderCallbacks;\n if (cb) while (fn = cb.pop()) fn.call(component);\n if (!diffLevel && !isChild) flushMounts();\n }\n }\n function buildComponentFromVNode(dom, vnode, context, mountAll) {\n var c = dom && dom._component, oldDom = dom, isDirectOwner = c && dom._componentConstructor === vnode.nodeName, isOwner = isDirectOwner, props = getNodeProps(vnode);\n while (c && !isOwner && (c = c._parentComponent)) isOwner = c.constructor === vnode.nodeName;\n if (c && isOwner && (!mountAll || c._component)) {\n setComponentProps(c, props, 3, context, mountAll);\n dom = c.base;\n } else {\n if (c && !isDirectOwner) {\n unmountComponent(c, !0);\n dom = oldDom = null;\n }\n c = createComponent(vnode.nodeName, props, context);\n if (dom && !c.nextBase) c.nextBase = dom;\n setComponentProps(c, props, 1, context, mountAll);\n dom = c.base;\n if (oldDom && dom !== oldDom) {\n oldDom._component = null;\n recollectNodeTree(oldDom);\n }\n }\n return dom;\n }\n function unmountComponent(component, remove) {\n var base = component.base;\n component._disable = !0;\n if (component.componentWillUnmount) component.componentWillUnmount();\n component.base = null;\n var inner = component._component;\n if (inner) unmountComponent(inner, remove); else if (base) {\n if (base[ATTR_KEY] && base[ATTR_KEY].ref) base[ATTR_KEY].ref(null);\n component.nextBase = base;\n if (remove) {\n removeNode(base);\n collectComponent(component);\n }\n removeOrphanedChildren(base.childNodes, !remove);\n }\n if (component.__ref) component.__ref(null);\n if (component.componentDidUnmount) component.componentDidUnmount();\n }\n function Component(props, context) {\n this._dirty = !0;\n this.context = context;\n this.props = props;\n if (!this.state) this.state = {};\n }\n function render(vnode, parent, merge) {\n return diff(merge, vnode, {}, !1, parent);\n }\n var options = {};\n var stack = [];\n var lcCache = {};\n var toLowerCase = function(s) {\n return lcCache[s] || (lcCache[s] = s.toLowerCase());\n };\n var resolved = 'undefined' != typeof Promise && Promise.resolve();\n var defer = resolved ? function(f) {\n resolved.then(f);\n } : setTimeout;\n var EMPTY = {};\n var ATTR_KEY = 'undefined' != typeof Symbol ? Symbol.for('preactattr') : '__preactattr_';\n var NON_DIMENSION_PROPS = {\n boxFlex: 1,\n boxFlexGroup: 1,\n columnCount: 1,\n fillOpacity: 1,\n flex: 1,\n flexGrow: 1,\n flexPositive: 1,\n flexShrink: 1,\n flexNegative: 1,\n fontWeight: 1,\n lineClamp: 1,\n lineHeight: 1,\n opacity: 1,\n order: 1,\n orphans: 1,\n strokeOpacity: 1,\n widows: 1,\n zIndex: 1,\n zoom: 1\n };\n var NON_BUBBLING_EVENTS = {\n blur: 1,\n error: 1,\n focus: 1,\n load: 1,\n resize: 1,\n scroll: 1\n };\n var items = [];\n var nodes = {};\n var mounts = [];\n var diffLevel = 0;\n var isSvgMode = !1;\n var components = {};\n extend(Component.prototype, {\n linkState: function(key, eventPath) {\n var c = this._linkedStates || (this._linkedStates = {});\n return c[key + eventPath] || (c[key + eventPath] = createLinkedState(this, key, eventPath));\n },\n setState: function(state, callback) {\n var s = this.state;\n if (!this.prevState) this.prevState = clone(s);\n extend(s, isFunction(state) ? state(s, this.props) : state);\n if (callback) (this._renderCallbacks = this._renderCallbacks || []).push(callback);\n enqueueRender(this);\n },\n forceUpdate: function() {\n renderComponent(this, 2);\n },\n render: function() {}\n });\n exports.h = h;\n exports.cloneElement = cloneElement;\n exports.Component = Component;\n exports.render = render;\n exports.rerender = rerender;\n exports.options = options;\n});\n//# sourceMappingURL=preact.js.map\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/preact/dist/preact.js\n ** module id = 1\n ** module chunks = 0\n **/","import { h } from 'preact'\nimport TextMode from './TextMode'\nimport ace from './assets/ace'\n\n/**\n * CodeMode (powered by Ace editor)\n *\n * Usage:\n *\n * \n *\n * Methods:\n *\n * setText(text)\n * getText() : text\n * set(json : JSON)\n * get() : JSON\n * patch(actions: JSONPatch)\n * format()\n * compact()\n * destroy()\n *\n */\nexport default class CodeMode extends TextMode {\n constructor (props) {\n super(props)\n\n this.state = {}\n\n this.id = 'id' + Math.round(Math.random() * 1e6) // unique enough id within the JSONEditor\n this.aceEditor = null\n }\n\n render (props, state) {\n return h('div', {class: 'jsoneditor jsoneditor-mode-code'}, [\n this.renderMenu(),\n\n h('div', {class: 'jsoneditor-contents', id: this.id})\n ])\n }\n\n componentDidMount () {\n const options = this.props.options || {}\n\n const container = this.base.querySelector('#' + this.id)\n\n // use ace from bundle, and if not available try to use from global\n const _ace = ace || window['ace']\n\n let aceEditor = null\n if (_ace && _ace.edit) {\n // create ace editor\n aceEditor = _ace.edit(container)\n\n // bundle and load jsoneditor theme for ace editor\n require('./assets/ace/theme-jsoneditor')\n\n // configure ace editor\n aceEditor.$blockScrolling = Infinity\n aceEditor.setTheme('ace/theme/jsoneditor')\n aceEditor.setShowPrintMargin(false)\n aceEditor.setFontSize(13)\n aceEditor.getSession().setMode('ace/mode/json')\n aceEditor.getSession().setTabSize(options.indentation || 2)\n aceEditor.getSession().setUseSoftTabs(true)\n aceEditor.getSession().setUseWrapMode(true)\n aceEditor.commands.bindKey('Ctrl-L', null) // disable Ctrl+L (is used by the browser to select the address bar)\n aceEditor.commands.bindKey('Command-L', null) // disable Ctrl+L (is used by the browser to select the address bar)\n }\n else {\n // ace is excluded from the bundle.\n }\n\n // allow changing the config or completely replacing aceEditor\n this.aceEditor = options.onLoadAce\n ? options.onLoadAce(aceEditor, container, options) || aceEditor\n : aceEditor\n\n // register onchange event\n this.aceEditor.on('change', this.handleChange)\n\n // set initial text\n this.setText('{}')\n }\n\n componentWillUnmount () {\n this.destroy()\n }\n\n /**\n * Destroy the editor\n */\n destroy () {\n // neatly destroy ace editor\n this.aceEditor.destroy()\n }\n\n componentDidUpdate () {\n // TODO: handle changes in props\n }\n\n handleChange = () => {\n if (this.props.options && this.props.options.onChangeText) {\n // TODO: pass a diff\n this.props.options.onChangeText()\n }\n }\n\n /**\n * Set a string containing a JSON document\n * @param {string} text\n */\n setText (text) {\n this.aceEditor.setValue(text, -1)\n }\n\n /**\n * Get the JSON document as text\n * @return {string} text\n */\n getText () {\n return this.aceEditor.getValue()\n }\n}\n\n\n/** WEBPACK FOOTER **\n ** ./src/CodeMode.js\n **/","import { h, Component } from 'preact'\nimport { parseJSON } from './utils/jsonUtils'\nimport { jsonToData, dataToJson, patchData } from './jsonData'\nimport ModeButton from './menu/ModeButton'\n\n/**\n * TextMode\n *\n * Usage:\n *\n * \n *\n * Methods:\n *\n * setText(text)\n * getText() : text\n * set(json : JSON)\n * get() : JSON\n * patch(actions: JSONPatch)\n * format()\n * compact()\n * destroy()\n *\n */\nexport default class TextMode extends Component {\n\n constructor (props) {\n super(props)\n\n this.state = {\n text: '{}'\n }\n }\n\n render (props, state) {\n return h('div', {class: 'jsoneditor jsoneditor-mode-text'}, [\n this.renderMenu(),\n\n h('div', {class: 'jsoneditor-contents'}, [\n h('textarea', {\n class: 'jsoneditor-text',\n value: this.state.text,\n onInput: this.handleChange\n })\n ])\n ])\n }\n\n /** @protected */\n renderMenu () {\n return h('div', {class: 'jsoneditor-menu'}, [\n h('button', {\n class: 'jsoneditor-format',\n title: 'Format the JSON document',\n onClick: this.handleFormat\n }),\n h('button', {\n class: 'jsoneditor-compact',\n title: 'Compact the JSON document',\n onClick: this.handleCompact\n }),\n\n // TODO: implement a button \"Repair\"\n\n h('div', {class: 'jsoneditor-vertical-menu-separator'}),\n\n this.props.options.modes && h(ModeButton, {\n modes: this.props.options.modes,\n mode: this.props.mode,\n onChangeMode: this.props.onChangeMode,\n onError: this.handleError\n })\n ])\n }\n\n /**\n * Get the configured indentation\n * @return {number}\n * @protected\n */\n getIndentation () {\n return this.props.options && this.props.options.indentation || 2\n }\n\n /**\n * handle changed text input in the textarea\n * @param {Event} event\n * @protected\n */\n handleChange = (event) => {\n this.setText(event.target.value)\n\n if (this.props.options && this.props.options.onChangeText) {\n this.props.options.onChangeText()\n }\n }\n\n /** @protected */\n handleFormat = () => {\n try {\n this.format()\n }\n catch (err) {\n this.handleError(err)\n }\n }\n\n /** @protected */\n handleCompact = () => {\n try {\n this.compact()\n }\n catch (err) {\n this.handleError(err)\n }\n }\n\n /** @protected */\n handleError = (err) => {\n if (this.props.options && this.props.options.onError) {\n this.props.options.onError(err)\n }\n else {\n console.error(err)\n }\n }\n\n /**\n * Format the json\n */\n format () {\n var json = this.get()\n var text = JSON.stringify(json, null, this.getIndentation())\n this.setText(text)\n }\n\n /**\n * Compact the json\n */\n compact () {\n var json = this.get()\n var text = JSON.stringify(json)\n this.setText(text)\n }\n\n /**\n * Apply a JSONPatch to the current JSON document\n * @param {JSONPatch} actions JSONPatch actions\n * @return {JSONPatchResult} Returns a JSONPatch result containing the\n * patch, a patch to revert the action, and\n * an error object which is null when successful\n */\n patch (actions) {\n const json = this.get()\n\n const data = jsonToData(json)\n const result = patchData(data, actions)\n\n this.set(dataToJson(result.data))\n\n return {\n patch: actions,\n revert: result.revert,\n error: result.error\n }\n }\n\n /**\n * Set JSON object in editor\n * @param {Object | Array | string | number | boolean | null} json JSON data\n */\n set (json) {\n this.setText(JSON.stringify(json, null, this.getIndentation()))\n }\n\n /**\n * Get JSON from the editor\n * @returns {Object | Array | string | number | boolean | null} json\n */\n get () {\n return parseJSON(this.getText())\n }\n\n /**\n * Set a string containing a JSON document\n * @param {string} text\n */\n setText (text) {\n this.setState({ text })\n }\n\n /**\n * Get the JSON document as text\n * @return {string} text\n */\n getText () {\n return this.state.text\n }\n\n /**\n * Destroy the editor\n */\n destroy () {\n\n }\n}\n\n\n/** WEBPACK FOOTER **\n ** ./src/TextMode.js\n **/","import jsonlint from '../assets/jsonlint/jsonlint'\n\n/**\n * Parse JSON using the parser built-in in the browser.\n * On exception, the jsonString is validated and a detailed error is thrown.\n * @param {String} jsonString\n * @return {JSON} json\n */\nexport function parseJSON(jsonString) {\n try {\n return JSON.parse(jsonString)\n }\n catch (err) {\n // try to throw a more detailed error message using validate\n validate(jsonString)\n\n // rethrow the original error\n throw err\n }\n}\n\n/**\n * Validate a string containing a JSON object\n * This method uses JSONLint to validate the String. If JSONLint is not\n * available, the built-in JSON parser of the browser is used.\n * @param {String} jsonString String with an (invalid) JSON object\n * @throws Error\n */\nexport function validate(jsonString) {\n if (jsonlint) {\n // use embedded jsonlint\n jsonlint.parse(jsonString)\n }\n else if (window.jsonlint) {\n // use global jsonlint\n window.jsonlint.parse(jsonString)\n }\n else {\n // don't use jsonlint\n JSON.parse(jsonString)\n }\n}\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/utils/jsonUtils.js\n **/","/*\n * Jison generated parser\n * Refactored into an ES6 module\n **/\nvar parser = (function(){\n var parser = {trace: function trace() { },\n yy: {},\n symbols_: {\"error\":2,\"JSONString\":3,\"STRING\":4,\"JSONNumber\":5,\"NUMBER\":6,\"JSONNullLiteral\":7,\"NULL\":8,\"JSONBooleanLiteral\":9,\"TRUE\":10,\"FALSE\":11,\"JSONText\":12,\"JSONValue\":13,\"EOF\":14,\"JSONObject\":15,\"JSONArray\":16,\"{\":17,\"}\":18,\"JSONMemberList\":19,\"JSONMember\":20,\":\":21,\",\":22,\"[\":23,\"]\":24,\"JSONElementList\":25,\"$accept\":0,\"$end\":1},\n terminals_: {2:\"error\",4:\"STRING\",6:\"NUMBER\",8:\"NULL\",10:\"TRUE\",11:\"FALSE\",14:\"EOF\",17:\"{\",18:\"}\",21:\":\",22:\",\",23:\"[\",24:\"]\"},\n productions_: [0,[3,1],[5,1],[7,1],[9,1],[9,1],[12,2],[13,1],[13,1],[13,1],[13,1],[13,1],[13,1],[15,2],[15,3],[20,3],[19,1],[19,3],[16,2],[16,3],[25,1],[25,3]],\n performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {\n\n var $0 = $$.length - 1;\n switch (yystate) {\n case 1: // replace escaped characters with actual character\n this.$ = yytext.replace(/\\\\(\\\\|\")/g, \"$\"+\"1\")\n .replace(/\\\\n/g,'\\n')\n .replace(/\\\\r/g,'\\r')\n .replace(/\\\\t/g,'\\t')\n .replace(/\\\\v/g,'\\v')\n .replace(/\\\\f/g,'\\f')\n .replace(/\\\\b/g,'\\b');\n\n break;\n case 2:this.$ = Number(yytext);\n break;\n case 3:this.$ = null;\n break;\n case 4:this.$ = true;\n break;\n case 5:this.$ = false;\n break;\n case 6:return this.$ = $$[$0-1];\n break;\n case 13:this.$ = {};\n break;\n case 14:this.$ = $$[$0-1];\n break;\n case 15:this.$ = [$$[$0-2], $$[$0]];\n break;\n case 16:this.$ = {}; this.$[$$[$0][0]] = $$[$0][1];\n break;\n case 17:this.$ = $$[$0-2]; $$[$0-2][$$[$0][0]] = $$[$0][1];\n break;\n case 18:this.$ = [];\n break;\n case 19:this.$ = $$[$0-1];\n break;\n case 20:this.$ = [$$[$0]];\n break;\n case 21:this.$ = $$[$0-2]; $$[$0-2].push($$[$0]);\n break;\n }\n },\n table: [{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],12:1,13:2,15:7,16:8,17:[1,14],23:[1,15]},{1:[3]},{14:[1,16]},{14:[2,7],18:[2,7],22:[2,7],24:[2,7]},{14:[2,8],18:[2,8],22:[2,8],24:[2,8]},{14:[2,9],18:[2,9],22:[2,9],24:[2,9]},{14:[2,10],18:[2,10],22:[2,10],24:[2,10]},{14:[2,11],18:[2,11],22:[2,11],24:[2,11]},{14:[2,12],18:[2,12],22:[2,12],24:[2,12]},{14:[2,3],18:[2,3],22:[2,3],24:[2,3]},{14:[2,4],18:[2,4],22:[2,4],24:[2,4]},{14:[2,5],18:[2,5],22:[2,5],24:[2,5]},{14:[2,1],18:[2,1],21:[2,1],22:[2,1],24:[2,1]},{14:[2,2],18:[2,2],22:[2,2],24:[2,2]},{3:20,4:[1,12],18:[1,17],19:18,20:19},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:23,15:7,16:8,17:[1,14],23:[1,15],24:[1,21],25:22},{1:[2,6]},{14:[2,13],18:[2,13],22:[2,13],24:[2,13]},{18:[1,24],22:[1,25]},{18:[2,16],22:[2,16]},{21:[1,26]},{14:[2,18],18:[2,18],22:[2,18],24:[2,18]},{22:[1,28],24:[1,27]},{22:[2,20],24:[2,20]},{14:[2,14],18:[2,14],22:[2,14],24:[2,14]},{3:20,4:[1,12],20:29},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:30,15:7,16:8,17:[1,14],23:[1,15]},{14:[2,19],18:[2,19],22:[2,19],24:[2,19]},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:31,15:7,16:8,17:[1,14],23:[1,15]},{18:[2,17],22:[2,17]},{18:[2,15],22:[2,15]},{22:[2,21],24:[2,21]}],\n defaultActions: {16:[2,6]},\n parseError: function parseError(str, hash) {\n throw new Error(str);\n },\n parse: function parse(input) {\n var self = this,\n stack = [0],\n vstack = [null], // semantic value stack\n lstack = [], // location stack\n table = this.table,\n yytext = '',\n yylineno = 0,\n yyleng = 0,\n recovering = 0,\n TERROR = 2,\n EOF = 1;\n\n //this.reductionCount = this.shiftCount = 0;\n\n this.lexer.setInput(input);\n this.lexer.yy = this.yy;\n this.yy.lexer = this.lexer;\n if (typeof this.lexer.yylloc == 'undefined')\n this.lexer.yylloc = {};\n var yyloc = this.lexer.yylloc;\n lstack.push(yyloc);\n\n if (typeof this.yy.parseError === 'function')\n this.parseError = this.yy.parseError;\n\n function popStack (n) {\n stack.length = stack.length - 2*n;\n vstack.length = vstack.length - n;\n lstack.length = lstack.length - n;\n }\n\n function lex() {\n var token;\n token = self.lexer.lex() || 1; // $end = 1\n // if token isn't its numeric value, convert\n if (typeof token !== 'number') {\n token = self.symbols_[token] || token;\n }\n return token;\n }\n\n var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected;\n while (true) {\n // retreive state number from top of stack\n state = stack[stack.length-1];\n\n // use default actions if available\n if (this.defaultActions[state]) {\n action = this.defaultActions[state];\n } else {\n if (symbol == null)\n symbol = lex();\n // read action for current state and first input\n action = table[state] && table[state][symbol];\n }\n\n // handle parse error\n _handle_error:\n if (typeof action === 'undefined' || !action.length || !action[0]) {\n\n if (!recovering) {\n // Report error\n expected = [];\n for (p in table[state]) if (this.terminals_[p] && p > 2) {\n expected.push(\"'\"+this.terminals_[p]+\"'\");\n }\n var errStr = '';\n if (this.lexer.showPosition) {\n errStr = 'Parse error on line '+(yylineno+1)+\":\\n\"+this.lexer.showPosition()+\"\\nExpecting \"+expected.join(', ') + \", got '\" + this.terminals_[symbol]+ \"'\";\n } else {\n errStr = 'Parse error on line '+(yylineno+1)+\": Unexpected \" +\n (symbol == 1 /*EOF*/ ? \"end of input\" :\n (\"'\"+(this.terminals_[symbol] || symbol)+\"'\"));\n }\n this.parseError(errStr,\n {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected});\n }\n\n // just recovered from another error\n if (recovering == 3) {\n if (symbol == EOF) {\n throw new Error(errStr || 'Parsing halted.');\n }\n\n // discard current lookahead and grab another\n yyleng = this.lexer.yyleng;\n yytext = this.lexer.yytext;\n yylineno = this.lexer.yylineno;\n yyloc = this.lexer.yylloc;\n symbol = lex();\n }\n\n // try to recover from error\n while (1) {\n // check for error recovery rule in this state\n if ((TERROR.toString()) in table[state]) {\n break;\n }\n if (state == 0) {\n throw new Error(errStr || 'Parsing halted.');\n }\n popStack(1);\n state = stack[stack.length-1];\n }\n\n preErrorSymbol = symbol; // save the lookahead token\n symbol = TERROR; // insert generic error symbol as new lookahead\n state = stack[stack.length-1];\n action = table[state] && table[state][TERROR];\n recovering = 3; // allow 3 real symbols to be shifted before reporting a new error\n }\n\n // this shouldn't happen, unless resolve defaults are off\n if (action[0] instanceof Array && action.length > 1) {\n throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol);\n }\n\n switch (action[0]) {\n\n case 1: // shift\n //this.shiftCount++;\n\n stack.push(symbol);\n vstack.push(this.lexer.yytext);\n lstack.push(this.lexer.yylloc);\n stack.push(action[1]); // push state\n symbol = null;\n if (!preErrorSymbol) { // normal execution/no error\n yyleng = this.lexer.yyleng;\n yytext = this.lexer.yytext;\n yylineno = this.lexer.yylineno;\n yyloc = this.lexer.yylloc;\n if (recovering > 0)\n recovering--;\n } else { // error just occurred, resume old lookahead f/ before error\n symbol = preErrorSymbol;\n preErrorSymbol = null;\n }\n break;\n\n case 2: // reduce\n //this.reductionCount++;\n\n len = this.productions_[action[1]][1];\n\n // perform semantic action\n yyval.$ = vstack[vstack.length-len]; // default to $$ = $1\n // default location, uses first token for firsts, last for lasts\n yyval._$ = {\n first_line: lstack[lstack.length-(len||1)].first_line,\n last_line: lstack[lstack.length-1].last_line,\n first_column: lstack[lstack.length-(len||1)].first_column,\n last_column: lstack[lstack.length-1].last_column\n };\n r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);\n\n if (typeof r !== 'undefined') {\n return r;\n }\n\n // pop off stack\n if (len) {\n stack = stack.slice(0,-1*len*2);\n vstack = vstack.slice(0, -1*len);\n lstack = lstack.slice(0, -1*len);\n }\n\n stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce)\n vstack.push(yyval.$);\n lstack.push(yyval._$);\n // goto new state = table[STATE][NONTERMINAL]\n newState = table[stack[stack.length-2]][stack[stack.length-1]];\n stack.push(newState);\n break;\n\n case 3: // accept\n return true;\n }\n\n }\n\n return true;\n }};\n /* Jison generated lexer */\n var lexer = (function(){\n var lexer = ({EOF:1,\n parseError:function parseError(str, hash) {\n if (this.yy.parseError) {\n this.yy.parseError(str, hash);\n } else {\n throw new Error(str);\n }\n },\n setInput:function (input) {\n this._input = input;\n this._more = this._less = this.done = false;\n this.yylineno = this.yyleng = 0;\n this.yytext = this.matched = this.match = '';\n this.conditionStack = ['INITIAL'];\n this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0};\n return this;\n },\n input:function () {\n var ch = this._input[0];\n this.yytext+=ch;\n this.yyleng++;\n this.match+=ch;\n this.matched+=ch;\n var lines = ch.match(/\\n/);\n if (lines) this.yylineno++;\n this._input = this._input.slice(1);\n return ch;\n },\n unput:function (ch) {\n this._input = ch + this._input;\n return this;\n },\n more:function () {\n this._more = true;\n return this;\n },\n less:function (n) {\n this._input = this.match.slice(n) + this._input;\n },\n pastInput:function () {\n var past = this.matched.substr(0, this.matched.length - this.match.length);\n return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\\n/g, \"\");\n },\n upcomingInput:function () {\n var next = this.match;\n if (next.length < 20) {\n next += this._input.substr(0, 20-next.length);\n }\n return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\\n/g, \"\");\n },\n showPosition:function () {\n var pre = this.pastInput();\n var c = new Array(pre.length + 1).join(\"-\");\n return pre + this.upcomingInput() + \"\\n\" + c+\"^\";\n },\n next:function () {\n if (this.done) {\n return this.EOF;\n }\n if (!this._input) this.done = true;\n\n var token,\n match,\n tempMatch,\n index,\n col,\n lines;\n if (!this._more) {\n this.yytext = '';\n this.match = '';\n }\n var rules = this._currentRules();\n for (var i=0;i < rules.length; i++) {\n tempMatch = this._input.match(this.rules[rules[i]]);\n if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {\n match = tempMatch;\n index = i;\n if (!this.options.flex) break;\n }\n }\n if (match) {\n lines = match[0].match(/\\n.*/g);\n if (lines) this.yylineno += lines.length;\n this.yylloc = {first_line: this.yylloc.last_line,\n last_line: this.yylineno+1,\n first_column: this.yylloc.last_column,\n last_column: lines ? lines[lines.length-1].length-1 : this.yylloc.last_column + match[0].length}\n this.yytext += match[0];\n this.match += match[0];\n this.yyleng = this.yytext.length;\n this._more = false;\n this._input = this._input.slice(match[0].length);\n this.matched += match[0];\n token = this.performAction.call(this, this.yy, this, rules[index],this.conditionStack[this.conditionStack.length-1]);\n if (this.done && this._input) this.done = false;\n if (token) return token;\n else return;\n }\n if (this._input === \"\") {\n return this.EOF;\n } else {\n this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\\n'+this.showPosition(),\n {text: \"\", token: null, line: this.yylineno});\n }\n },\n lex:function lex() {\n var r = this.next();\n if (typeof r !== 'undefined') {\n return r;\n } else {\n return this.lex();\n }\n },\n begin:function begin(condition) {\n this.conditionStack.push(condition);\n },\n popState:function popState() {\n return this.conditionStack.pop();\n },\n _currentRules:function _currentRules() {\n return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules;\n },\n topState:function () {\n return this.conditionStack[this.conditionStack.length-2];\n },\n pushState:function begin(condition) {\n this.begin(condition);\n }});\n lexer.options = {};\n lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {\n\n var YYSTATE=YY_START\n switch($avoiding_name_collisions) {\n case 0:/* skip whitespace */\n break;\n case 1:return 6\n break;\n case 2:yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2); return 4\n break;\n case 3:return 17\n break;\n case 4:return 18\n break;\n case 5:return 23\n break;\n case 6:return 24\n break;\n case 7:return 22\n break;\n case 8:return 21\n break;\n case 9:return 10\n break;\n case 10:return 11\n break;\n case 11:return 8\n break;\n case 12:return 14\n break;\n case 13:return 'INVALID'\n break;\n }\n };\n lexer.rules = [/^(?:\\s+)/,/^(?:(-?([0-9]|[1-9][0-9]+))(\\.[0-9]+)?([eE][-+]?[0-9]+)?\\b)/,/^(?:\"(?:\\\\[\\\\\"bfnrt/]|\\\\u[a-fA-F0-9]{4}|[^\\\\\\0-\\x09\\x0a-\\x1f\"])*\")/,/^(?:\\{)/,/^(?:\\})/,/^(?:\\[)/,/^(?:\\])/,/^(?:,)/,/^(?::)/,/^(?:true\\b)/,/^(?:false\\b)/,/^(?:null\\b)/,/^(?:$)/,/^(?:.)/];\n lexer.conditions = {\"INITIAL\":{\"rules\":[0,1,2,3,4,5,6,7,8,9,10,11,12,13],\"inclusive\":true}};\n\n\n return lexer;\n })()\n\n parser.lexer = lexer;\n return parser;\n})();\n\n\nexport default {\n parse: parser.parse.bind(parser),\n parser\n}\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/assets/jsonlint/jsonlint.js\n **/","/**\n * This file contains functions to act on a JSONData object.\n * All functions are pure and don't mutate the JSONData.\n */\n\nimport { setIn, updateIn, getIn, deleteIn, insertAt } from './utils/immutabilityHelpers'\nimport { isObject } from './utils/typeUtils'\nimport isEqual from 'lodash/isEqual'\n\nconst expandAll = function (path) {\n return true\n}\n\n// TODO: double check whether all patch functions handle each of the\n// extra properties in .jsoneditor: `before`, `type`, `order`\n\n/**\n * Convert a JSON object into the internally used data model\n * @param {Object | Array | string | number | boolean | null} json\n * @param {function(path: Path)} [expand]\n * @param {Path} [path=[]]\n * @return {JSONData}\n */\nexport function jsonToData (json, expand = expandAll, path = []) {\n if (Array.isArray(json)) {\n return {\n type: 'Array',\n expanded: expand(path),\n items: json.map((child, index) => jsonToData(child, expand, path.concat(index)))\n }\n }\n else if (isObject(json)) {\n return {\n type: 'Object',\n expanded: expand(path),\n props: Object.keys(json).map(name => {\n return {\n name,\n value: jsonToData(json[name], expand, path.concat(name))\n }\n })\n }\n }\n else {\n return {\n type: 'value',\n value: json\n }\n }\n}\n\n/**\n * Convert the internal data model to a regular JSON object\n * @param {JSONData} data\n * @return {Object | Array | string | number | boolean | null} json\n */\nexport function dataToJson (data) {\n switch (data.type) {\n case 'Array':\n return data.items.map(dataToJson)\n\n case 'Object':\n const object = {}\n\n data.props.forEach(prop => {\n object[prop.name] = dataToJson(prop.value)\n })\n\n return object\n\n default: // type 'string' or 'value'\n return data.value\n }\n}\n\n/**\n * Convert a path of a JSON object into a path in the corresponding data model\n * @param {JSONData} data\n * @param {Path} path\n * @return {Path} dataPath\n * @private\n */\nexport function toDataPath (data, path) {\n if (path.length === 0) {\n return []\n }\n\n if (data.type === 'Array') {\n // index of an array\n const index = path[0]\n const item = data.items[index]\n if (!item) {\n throw new Error('Array item \"' + index + '\" not found')\n }\n\n return ['items', index].concat(toDataPath(item, path.slice(1)))\n }\n else {\n // object property. find the index of this property\n const index = findPropertyIndex(data, path[0])\n const prop = data.props[index]\n if (!prop) {\n throw new Error('Object property \"' + path[0] + '\" not found')\n }\n\n return ['props', index, 'value']\n .concat(toDataPath(prop && prop.value, path.slice(1)))\n }\n}\n\n/**\n * Apply a patch to a JSONData object\n * @param {JSONData} data\n * @param {Array} patch A JSON patch\n * @return {{data: JSONData, revert: Array., error: Error | null}}\n */\nexport function patchData (data, patch) {\n const expand = expandAll // TODO: customizable expand function\n\n try {\n let updatedData = data\n let revert = []\n\n patch.forEach(function (action) {\n const options = action.jsoneditor\n\n switch (action.op) {\n case 'add': {\n const path = parseJSONPointer(action.path)\n const newValue = jsonToData(action.value, expand, path)\n\n // TODO: move setting type to jsonToData\n if (options && options.type) {\n // insert with type 'string' or 'value'\n newValue.type = options.type\n }\n // TODO: handle options.order\n\n const result = add(updatedData, action.path, newValue, options)\n updatedData = result.data\n revert = result.revert.concat(revert)\n\n break\n }\n\n case 'remove': {\n const result = remove(updatedData, action.path)\n updatedData = result.data\n revert = result.revert.concat(revert)\n\n break\n }\n\n case 'replace': {\n const path = parseJSONPointer(action.path)\n let newValue = jsonToData(action.value, expand, path)\n\n // TODO: move setting type to jsonToData\n if (options && options.type) {\n // insert with type 'string' or 'value'\n newValue.type = options.type\n }\n // TODO: handle options.order\n\n const result = replace(updatedData, path, newValue)\n updatedData = result.data\n revert = result.revert.concat(revert)\n\n break\n }\n\n case 'copy': {\n const result = copy(updatedData, action.path, action.from, options)\n updatedData = result.data\n revert = result.revert.concat(revert)\n\n break\n }\n\n case 'move': {\n const result = move(updatedData, action.path, action.from, options)\n updatedData = result.data\n revert = result.revert.concat(revert)\n\n break\n }\n\n case 'test': {\n test(updatedData, action.path, action.value)\n\n break\n }\n\n default: {\n throw new Error('Unknown jsonpatch op ' + JSON.stringify(action.op))\n }\n }\n })\n\n // TODO: Simplify revert when possible:\n // when a previous action takes place on the same path, remove the first\n\n return {\n data: updatedData,\n revert: simplifyPatch(revert),\n error: null\n }\n }\n catch (error) {\n return {data, revert: [], error}\n }\n}\n\n/**\n * Replace an existing item\n * @param {JSONData} data\n * @param {Path} path\n * @param {JSONData} value\n * @return {{data: JSONData, revert: JSONPatch}}\n */\nexport function replace (data, path, value) {\n const dataPath = toDataPath(data, path)\n const oldValue = getIn(data, dataPath)\n\n return {\n // FIXME: keep the expanded state where possible\n data: setIn(data, dataPath, value),\n revert: [{\n op: 'replace',\n path: compileJSONPointer(path),\n value: dataToJson(oldValue),\n jsoneditor: {\n type: oldValue.type\n }\n }]\n }\n}\n\n/**\n * Remove an item or property\n * @param {JSONData} data\n * @param {string} path\n * @return {{data: JSONData, revert: JSONPatch}}\n */\nexport function remove (data, path) {\n // console.log('remove', path)\n const pathArray = parseJSONPointer(path)\n\n const parentPath = pathArray.slice(0, pathArray.length - 1)\n const parent = getIn(data, toDataPath(data, parentPath))\n const dataValue = getIn(data, toDataPath(data, pathArray))\n const value = dataToJson(dataValue)\n\n if (parent.type === 'Array') {\n const dataPath = toDataPath(data, pathArray)\n\n return {\n data: deleteIn(data, dataPath),\n revert: [{\n op: 'add',\n path,\n value,\n jsoneditor: {\n type: dataValue.type\n }\n }]\n }\n }\n else { // object.type === 'Object'\n const dataPath = toDataPath(data, pathArray)\n const prop = pathArray[pathArray.length - 1]\n\n dataPath.pop() // remove the 'value' property, we want to remove the whole object property\n return {\n data: deleteIn(data, dataPath),\n revert: [{\n op: 'add',\n path,\n value,\n jsoneditor: {\n type: dataValue.type,\n before: findNextProp(parent, prop)\n }\n }]\n }\n }\n}\n\n/**\n * Remove redundant actions from a JSONPatch array.\n * Actions are redundant when they are followed by an action\n * acting on the same path.\n * @param {JSONPatch} patch\n * @return {Array}\n */\nexport function simplifyPatch(patch) {\n const simplifiedPatch = []\n const paths = {}\n\n // loop over the patch from last to first\n for (var i = patch.length - 1; i >= 0; i--) {\n const action = patch[i]\n if (action.op === 'test') {\n // ignore test actions\n simplifiedPatch.unshift(action)\n }\n else {\n // test whether this path was already used\n // if not, add this action to the simplified patch\n if (paths[action.path] === undefined) {\n paths[action.path] = true\n simplifiedPatch.unshift(action)\n }\n }\n }\n\n return simplifiedPatch\n}\n\n\n/**\n * @param {JSONData} data\n * @param {string} path\n * @param {JSONData} value\n * @param {{before?: string}} [options]\n * @return {{data: JSONData, revert: JSONPatch}}\n * @private\n */\nexport function add (data, path, value, options) {\n const pathArray = parseJSONPointer(path)\n const parentPath = pathArray.slice(0, pathArray.length - 1)\n const dataPath = toDataPath(data, parentPath)\n const parent = getIn(data, dataPath)\n const resolvedPath = resolvePathIndex(data, pathArray)\n const prop = resolvedPath[resolvedPath.length - 1]\n\n let updatedData\n if (parent.type === 'Array') {\n updatedData = insertAt(data, dataPath.concat('items', prop), value)\n }\n else { // parent.type === 'Object'\n updatedData = updateIn(data, dataPath, (object) => {\n const newProp = { name: prop, value }\n const index = (options && typeof options.before === 'string')\n ? findPropertyIndex(object, options.before) // insert before\n : object.props.length // append\n\n return insertAt(object, ['props', index], newProp)\n })\n }\n\n if (parent.type === 'Object' && pathExists(data, resolvedPath)) {\n const oldValue = getIn(data, toDataPath(data, resolvedPath))\n\n return {\n data: updatedData,\n revert: [{\n op: 'replace',\n path: compileJSONPointer(resolvedPath),\n value: dataToJson(oldValue),\n jsoneditor: { type: oldValue.type }\n }]\n }\n }\n else {\n return {\n data: updatedData,\n revert: [{\n op: 'remove',\n path: compileJSONPointer(resolvedPath)\n }]\n }\n }\n}\n\n/**\n * Copy a value\n * @param {JSONData} data\n * @param {string} path\n * @param {string} from\n * @param {{before?: string}} [options]\n * @return {{data: JSONData, revert: JSONPatch}}\n * @private\n */\nexport function copy (data, path, from, options) {\n const value = getIn(data, toDataPath(data, parseJSONPointer(from)))\n\n return add(data, path, value, options)\n}\n\n/**\n * Move a value\n * @param {JSONData} data\n * @param {string} path\n * @param {string} from\n * @param {{before?: string}} [options]\n * @return {{data: JSONData, revert: JSONPatch}}\n * @private\n */\nexport function move (data, path, from, options) {\n const fromArray = parseJSONPointer(from)\n const dataValue = getIn(data, toDataPath(data, fromArray))\n\n const parentPath = fromArray.slice(0, fromArray.length - 1)\n const parent = getIn(data, toDataPath(data, parentPath))\n\n const result1 = remove(data, from)\n const result2 = add(result1.data, path, dataValue, options)\n\n const before = result1.revert[0].jsoneditor.before\n const beforeNeeded = (parent.type === 'Object' && before)\n\n if (result2.revert[0].op === 'replace') {\n const value = result2.revert[0].value\n const type = result2.revert[0].jsoneditor.type\n const options = beforeNeeded ? { type, before } : { type }\n\n return {\n data: result2.data,\n revert: [\n { op: 'move', from: path, path: from },\n { op: 'add', path, value, jsoneditor: options}\n ]\n }\n }\n else { // result2.revert[0].op === 'remove'\n return {\n data: result2.data,\n revert: beforeNeeded\n ? [{ op: 'move', from: path, path: from, jsoneditor: {before} }]\n : [{ op: 'move', from: path, path: from }]\n }\n }\n}\n\n/**\n * Test whether the data contains the provided value at the specified path.\n * Throws an error when the test fails.\n * @param {JSONData} data\n * @param {string} path\n * @param {*} value\n */\nexport function test (data, path, value) {\n if (value === undefined) {\n throw new Error('Test failed, no value provided')\n }\n\n const pathArray = parseJSONPointer(path)\n if (!pathExists(data, pathArray)) {\n throw new Error('Test failed, path not found')\n }\n\n const actualValue = getIn(data, toDataPath(data, pathArray))\n if (!isEqual(dataToJson(actualValue), value)) {\n throw new Error('Test failed, value differs')\n }\n}\n\n/**\n * Expand or collapse one or multiple items or properties\n * @param {JSONData} data\n * @param {function(path: Path) : boolean | Path} callback\n * When a path, the object/array at this path will be expanded/collapsed\n * When a function, all objects and arrays for which callback\n * returns true will be expanded/collapsed\n * @param {boolean} expanded New expanded state: true to expand, false to collapse\n * @return {JSONData}\n */\nexport function expand (data, callback, expanded) {\n // console.log('expand', callback, expand)\n\n if (typeof callback === 'function') {\n return expandRecursive(data, [], callback, expanded)\n }\n else if (Array.isArray(callback)) {\n const dataPath = toDataPath(data, callback)\n\n return setIn(data, dataPath.concat(['expanded']), expanded)\n }\n else {\n throw new Error('Callback function or path expected')\n }\n}\n\n/**\n * Traverse the json data, change the expanded state of all items/properties for\n * which `callback` returns true\n * @param {JSONData} data\n * @param {Path} path\n * @param {function(path: Path)} callback\n * All objects and arrays for which callback returns true will be\n * expanded/collapsed\n * @param {boolean} expanded New expanded state: true to expand, false to collapse\n * @return {*}\n * @private\n */\nfunction expandRecursive (data, path, callback, expanded) {\n switch (data.type) {\n case 'Array': {\n let updatedData = callback(path)\n ? setIn(data, ['expanded'], expanded)\n : data\n let updatedItems = updatedData.items\n\n updatedData.items.forEach((item, index) => {\n updatedItems = setIn(updatedItems, [index],\n expandRecursive(item, path.concat(index), callback, expanded))\n })\n\n return setIn(updatedData, ['items'], updatedItems)\n }\n\n case 'Object': {\n let updatedData = callback(path)\n ? setIn(data, ['expanded'], expanded)\n : data\n let updatedProps = updatedData.props\n\n updatedData.props.forEach((prop, index) => {\n updatedProps = setIn(updatedProps, [index, 'value'],\n expandRecursive(prop.value, path.concat(prop.name), callback, expanded))\n })\n\n return setIn(updatedData, ['props'], updatedProps)\n }\n\n default: // type 'string' or 'value'\n // don't do anything: a value can't be expanded, only arrays and objects can\n return data\n }\n}\n\n/**\n * Test whether a path exists in the json data\n * @param {JSONData} data\n * @param {Path} path\n * @return {boolean} Returns true if the path exists, else returns false\n * @private\n */\nexport function pathExists (data, path) {\n if (data === undefined) {\n return false\n }\n\n if (path.length === 0) {\n return true\n }\n\n let index\n if (data.type === 'Array') {\n // index of an array\n index = path[0]\n return pathExists(data.items[index], path.slice(1))\n }\n else {\n // object property. find the index of this property\n index = findPropertyIndex(data, path[0])\n const prop = data.props[index]\n\n return pathExists(prop && prop.value, path.slice(1))\n }\n}\n\n/**\n * Resolve the index for `arr/-`, replace it with an index value equal to the\n * length of the array\n * @param {JSONData} data\n * @param {Path} path\n * @return {Path}\n */\nexport function resolvePathIndex (data, path) {\n if (path[path.length - 1] === '-') {\n const parentPath = path.slice(0, path.length - 1)\n const parent = getIn(data, toDataPath(data, parentPath))\n\n if (parent.type === 'Array') {\n const index = parent.items.length\n const resolvedPath = path.slice(0)\n resolvedPath[resolvedPath.length - 1] = index\n\n return resolvedPath\n }\n }\n\n return path\n}\n\n/**\n * Find the property after provided property\n * @param {JSONData} parent\n * @param {string} prop\n * @return {string | null} Returns the name of the next property,\n * or null if there is none\n */\nexport function findNextProp (parent, prop) {\n const index = findPropertyIndex(parent, prop)\n if (index === -1) {\n return null\n }\n\n const next = parent.props[index + 1]\n return next && next.name || null\n}\n\n/**\n * Find the index of a property\n * @param {ObjectData} object\n * @param {string} prop\n * @return {number} Returns the index when found, -1 when not found\n */\nexport function findPropertyIndex (object, prop) {\n return object.props.findIndex(p => p.name === prop)\n}\n\n/**\n * Parse a JSON Pointer\n * WARNING: this is not a complete string implementation\n * @param {string} pointer\n * @return {Array}\n */\nexport function parseJSONPointer (pointer) {\n if (pointer === '/') {\n return []\n }\n\n const path = pointer.split('/')\n path.shift() // remove the first empty entry\n\n return path.map(p => p.replace(/~1/g, '/').replace(/~0/g, '~'))\n}\n\n/**\n * Compile a JSON Pointer\n * WARNING: this is not a complete string implementation\n * @param {Path} path\n * @return {string}\n */\nexport function compileJSONPointer (path) {\n return '/' + path\n .map(p => String(p).replace(/~/g, '~0').replace(/\\//g, '~1'))\n .join('/')\n}\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/jsonData.js\n **/","'use strict';\n\nimport clone from 'lodash/clone'\nimport { isObjectOrArray } from './typeUtils'\n\n/**\n * Immutability helpers\n *\n * inspiration:\n *\n * https://www.npmjs.com/package/seamless-immutable\n * https://www.npmjs.com/package/ih\n * https://www.npmjs.com/package/mutatis\n */\n\n\n/**\n * helper function to get a nested property in an object or array\n *\n * @param {Object | Array} object\n * @param {Path} path\n * @return {* | undefined} Returns the field when found, or undefined when the\n * path doesn't exist\n */\nexport function getIn (object, path) {\n let value = object\n let i = 0\n\n while(i < path.length) {\n if (isObjectOrArray(value)) {\n value = value[path[i]]\n }\n else {\n value = undefined\n }\n\n i++\n }\n\n return value\n}\n\n/**\n * helper function to replace a nested property in an object with a new value\n * without mutating the object itself.\n *\n * @param {Object | Array} object\n * @param {Path} path\n * @param {*} value\n * @return {Object | Array} Returns a new, updated object or array\n */\nexport function setIn (object, path, value) {\n if (path.length === 0) {\n return value\n }\n\n if (!isObjectOrArray(object)) {\n throw new Error('Path does not exist')\n }\n\n const key = path[0]\n const updatedValue = setIn(object[key], path.slice(1), value)\n if (object[key] === updatedValue) {\n // return original object unchanged when the new value is identical to the old one\n return object\n }\n else {\n const updatedObject = clone(object)\n updatedObject[key] = updatedValue\n return updatedObject\n }\n}\n/**\n * helper function to replace a nested property in an object with a new value\n * without mutating the object itself.\n *\n * @param {Object | Array} object\n * @param {Path} path\n * @param {function} callback\n * @return {Object | Array} Returns a new, updated object or array\n */\nexport function updateIn (object, path, callback) {\n if (path.length === 0) {\n return callback(object)\n }\n\n if (!isObjectOrArray(object)) {\n throw new Error('Path doesn\\'t exist')\n }\n\n const key = path[0]\n const updatedValue = updateIn(object[key], path.slice(1), callback)\n if (object[key] === updatedValue) {\n // return original object unchanged when the new value is identical to the old one\n return object\n }\n else {\n const updatedObject = clone(object)\n updatedObject[key] = updatedValue\n return updatedObject\n }\n}\n\n/**\n * helper function to delete a nested property in an object\n * without mutating the object itself.\n *\n * @param {Object | Array} object\n * @param {Path} path\n * @return {Object | Array} Returns a new, updated object or array\n */\nexport function deleteIn (object, path) {\n if (path.length === 0) {\n return object\n }\n\n if (!isObjectOrArray(object)) {\n return object\n }\n\n if (path.length === 1) {\n const key = path[0]\n if (object[key] === undefined) {\n // key doesn't exist. return object unchanged\n return object\n }\n else {\n const updatedObject = clone(object)\n\n if (Array.isArray(updatedObject)) {\n updatedObject.splice(key, 1)\n }\n else {\n delete updatedObject[key]\n }\n\n return updatedObject\n }\n }\n\n const key = path[0]\n const updatedValue = deleteIn(object[key], path.slice(1))\n if (object[key] === updatedValue) {\n // object is unchanged\n return object\n }\n else {\n const updatedObject = clone(object)\n updatedObject[key] = updatedValue\n return updatedObject\n }\n}\n\n/**\n * Insert a new item in an array at a specific index.\n * Example usage:\n *\n * insertAt({arr: [1,2,3]}, ['arr', '2'], 'inserted') // [1,2,'inserted',3]\n *\n * @param {Object | Array} object\n * @param {Path} path\n * @param {*} value\n * @return {Array}\n */\nexport function insertAt (object, path, value) {\n const parentPath = path.slice(0, path.length - 1)\n const index = path[path.length - 1]\n\n return updateIn(object, parentPath, (items) => {\n if (!Array.isArray(items)) {\n throw new TypeError('Array expected at path ' + JSON.stringify(parentPath))\n }\n\n const updatedItems = items.slice(0)\n\n updatedItems.splice(index, 0, value)\n\n return updatedItems\n })\n}\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/utils/immutabilityHelpers.js\n **/","var baseClone = require('./_baseClone');\n\n/**\n * Creates a shallow clone of `value`.\n *\n * **Note:** This method is loosely based on the\n * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm)\n * and supports cloning arrays, array buffers, booleans, date objects, maps,\n * numbers, `Object` objects, regexes, sets, strings, symbols, and typed\n * arrays. The own enumerable properties of `arguments` objects are cloned\n * as plain objects. An empty object is returned for uncloneable values such\n * as error objects, functions, DOM nodes, and WeakMaps.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to clone.\n * @returns {*} Returns the cloned value.\n * @see _.cloneDeep\n * @example\n *\n * var objects = [{ 'a': 1 }, { 'b': 2 }];\n *\n * var shallow = _.clone(objects);\n * console.log(shallow[0] === objects[0]);\n * // => true\n */\nfunction clone(value) {\n return baseClone(value, false, true);\n}\n\nmodule.exports = clone;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/clone.js\n ** module id = 8\n ** module chunks = 0\n **/","var Stack = require('./_Stack'),\n arrayEach = require('./_arrayEach'),\n assignValue = require('./_assignValue'),\n baseAssign = require('./_baseAssign'),\n cloneBuffer = require('./_cloneBuffer'),\n copyArray = require('./_copyArray'),\n copySymbols = require('./_copySymbols'),\n getAllKeys = require('./_getAllKeys'),\n getTag = require('./_getTag'),\n initCloneArray = require('./_initCloneArray'),\n initCloneByTag = require('./_initCloneByTag'),\n initCloneObject = require('./_initCloneObject'),\n isArray = require('./isArray'),\n isBuffer = require('./isBuffer'),\n isObject = require('./isObject'),\n keys = require('./keys');\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n arrayTag = '[object Array]',\n boolTag = '[object Boolean]',\n dateTag = '[object Date]',\n errorTag = '[object Error]',\n funcTag = '[object Function]',\n genTag = '[object GeneratorFunction]',\n mapTag = '[object Map]',\n numberTag = '[object Number]',\n objectTag = '[object Object]',\n regexpTag = '[object RegExp]',\n setTag = '[object Set]',\n stringTag = '[object String]',\n symbolTag = '[object Symbol]',\n weakMapTag = '[object WeakMap]';\n\nvar arrayBufferTag = '[object ArrayBuffer]',\n dataViewTag = '[object DataView]',\n float32Tag = '[object Float32Array]',\n float64Tag = '[object Float64Array]',\n int8Tag = '[object Int8Array]',\n int16Tag = '[object Int16Array]',\n int32Tag = '[object Int32Array]',\n uint8Tag = '[object Uint8Array]',\n uint8ClampedTag = '[object Uint8ClampedArray]',\n uint16Tag = '[object Uint16Array]',\n uint32Tag = '[object Uint32Array]';\n\n/** Used to identify `toStringTag` values supported by `_.clone`. */\nvar cloneableTags = {};\ncloneableTags[argsTag] = cloneableTags[arrayTag] =\ncloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] =\ncloneableTags[boolTag] = cloneableTags[dateTag] =\ncloneableTags[float32Tag] = cloneableTags[float64Tag] =\ncloneableTags[int8Tag] = cloneableTags[int16Tag] =\ncloneableTags[int32Tag] = cloneableTags[mapTag] =\ncloneableTags[numberTag] = cloneableTags[objectTag] =\ncloneableTags[regexpTag] = cloneableTags[setTag] =\ncloneableTags[stringTag] = cloneableTags[symbolTag] =\ncloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =\ncloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;\ncloneableTags[errorTag] = cloneableTags[funcTag] =\ncloneableTags[weakMapTag] = false;\n\n/**\n * The base implementation of `_.clone` and `_.cloneDeep` which tracks\n * traversed objects.\n *\n * @private\n * @param {*} value The value to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @param {boolean} [isFull] Specify a clone including symbols.\n * @param {Function} [customizer] The function to customize cloning.\n * @param {string} [key] The key of `value`.\n * @param {Object} [object] The parent object of `value`.\n * @param {Object} [stack] Tracks traversed objects and their clone counterparts.\n * @returns {*} Returns the cloned value.\n */\nfunction baseClone(value, isDeep, isFull, customizer, key, object, stack) {\n var result;\n if (customizer) {\n result = object ? customizer(value, key, object, stack) : customizer(value);\n }\n if (result !== undefined) {\n return result;\n }\n if (!isObject(value)) {\n return value;\n }\n var isArr = isArray(value);\n if (isArr) {\n result = initCloneArray(value);\n if (!isDeep) {\n return copyArray(value, result);\n }\n } else {\n var tag = getTag(value),\n isFunc = tag == funcTag || tag == genTag;\n\n if (isBuffer(value)) {\n return cloneBuffer(value, isDeep);\n }\n if (tag == objectTag || tag == argsTag || (isFunc && !object)) {\n result = initCloneObject(isFunc ? {} : value);\n if (!isDeep) {\n return copySymbols(value, baseAssign(result, value));\n }\n } else {\n if (!cloneableTags[tag]) {\n return object ? value : {};\n }\n result = initCloneByTag(value, tag, baseClone, isDeep);\n }\n }\n // Check for circular references and return its corresponding clone.\n stack || (stack = new Stack);\n var stacked = stack.get(value);\n if (stacked) {\n return stacked;\n }\n stack.set(value, result);\n\n var props = isArr ? undefined : (isFull ? getAllKeys : keys)(value);\n arrayEach(props || value, function(subValue, key) {\n if (props) {\n key = subValue;\n subValue = value[key];\n }\n // Recursively populate clone (susceptible to call stack limits).\n assignValue(result, key, baseClone(subValue, isDeep, isFull, customizer, key, value, stack));\n });\n return result;\n}\n\nmodule.exports = baseClone;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_baseClone.js\n ** module id = 9\n ** module chunks = 0\n **/","var ListCache = require('./_ListCache'),\n stackClear = require('./_stackClear'),\n stackDelete = require('./_stackDelete'),\n stackGet = require('./_stackGet'),\n stackHas = require('./_stackHas'),\n stackSet = require('./_stackSet');\n\n/**\n * Creates a stack cache object to store key-value pairs.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction Stack(entries) {\n var data = this.__data__ = new ListCache(entries);\n this.size = data.size;\n}\n\n// Add methods to `Stack`.\nStack.prototype.clear = stackClear;\nStack.prototype['delete'] = stackDelete;\nStack.prototype.get = stackGet;\nStack.prototype.has = stackHas;\nStack.prototype.set = stackSet;\n\nmodule.exports = Stack;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_Stack.js\n ** module id = 10\n ** module chunks = 0\n **/","var listCacheClear = require('./_listCacheClear'),\n listCacheDelete = require('./_listCacheDelete'),\n listCacheGet = require('./_listCacheGet'),\n listCacheHas = require('./_listCacheHas'),\n listCacheSet = require('./_listCacheSet');\n\n/**\n * Creates an list cache object.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction ListCache(entries) {\n var index = -1,\n length = entries ? entries.length : 0;\n\n this.clear();\n while (++index < length) {\n var entry = entries[index];\n this.set(entry[0], entry[1]);\n }\n}\n\n// Add methods to `ListCache`.\nListCache.prototype.clear = listCacheClear;\nListCache.prototype['delete'] = listCacheDelete;\nListCache.prototype.get = listCacheGet;\nListCache.prototype.has = listCacheHas;\nListCache.prototype.set = listCacheSet;\n\nmodule.exports = ListCache;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_ListCache.js\n ** module id = 11\n ** module chunks = 0\n **/","/**\n * Removes all key-value entries from the list cache.\n *\n * @private\n * @name clear\n * @memberOf ListCache\n */\nfunction listCacheClear() {\n this.__data__ = [];\n this.size = 0;\n}\n\nmodule.exports = listCacheClear;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_listCacheClear.js\n ** module id = 12\n ** module chunks = 0\n **/","var assocIndexOf = require('./_assocIndexOf');\n\n/** Used for built-in method references. */\nvar arrayProto = Array.prototype;\n\n/** Built-in value references. */\nvar splice = arrayProto.splice;\n\n/**\n * Removes `key` and its value from the list cache.\n *\n * @private\n * @name delete\n * @memberOf ListCache\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction listCacheDelete(key) {\n var data = this.__data__,\n index = assocIndexOf(data, key);\n\n if (index < 0) {\n return false;\n }\n var lastIndex = data.length - 1;\n if (index == lastIndex) {\n data.pop();\n } else {\n splice.call(data, index, 1);\n }\n --this.size;\n return true;\n}\n\nmodule.exports = listCacheDelete;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_listCacheDelete.js\n ** module id = 13\n ** module chunks = 0\n **/","var eq = require('./eq');\n\n/**\n * Gets the index at which the `key` is found in `array` of key-value pairs.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} key The key to search for.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\nfunction assocIndexOf(array, key) {\n var length = array.length;\n while (length--) {\n if (eq(array[length][0], key)) {\n return length;\n }\n }\n return -1;\n}\n\nmodule.exports = assocIndexOf;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_assocIndexOf.js\n ** module id = 14\n ** module chunks = 0\n **/","/**\n * Performs a\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * comparison between two values to determine if they are equivalent.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * var object = { 'a': 1 };\n * var other = { 'a': 1 };\n *\n * _.eq(object, object);\n * // => true\n *\n * _.eq(object, other);\n * // => false\n *\n * _.eq('a', 'a');\n * // => true\n *\n * _.eq('a', Object('a'));\n * // => false\n *\n * _.eq(NaN, NaN);\n * // => true\n */\nfunction eq(value, other) {\n return value === other || (value !== value && other !== other);\n}\n\nmodule.exports = eq;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/eq.js\n ** module id = 15\n ** module chunks = 0\n **/","var assocIndexOf = require('./_assocIndexOf');\n\n/**\n * Gets the list cache value for `key`.\n *\n * @private\n * @name get\n * @memberOf ListCache\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction listCacheGet(key) {\n var data = this.__data__,\n index = assocIndexOf(data, key);\n\n return index < 0 ? undefined : data[index][1];\n}\n\nmodule.exports = listCacheGet;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_listCacheGet.js\n ** module id = 16\n ** module chunks = 0\n **/","var assocIndexOf = require('./_assocIndexOf');\n\n/**\n * Checks if a list cache value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf ListCache\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction listCacheHas(key) {\n return assocIndexOf(this.__data__, key) > -1;\n}\n\nmodule.exports = listCacheHas;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_listCacheHas.js\n ** module id = 17\n ** module chunks = 0\n **/","var assocIndexOf = require('./_assocIndexOf');\n\n/**\n * Sets the list cache `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf ListCache\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the list cache instance.\n */\nfunction listCacheSet(key, value) {\n var data = this.__data__,\n index = assocIndexOf(data, key);\n\n if (index < 0) {\n ++this.size;\n data.push([key, value]);\n } else {\n data[index][1] = value;\n }\n return this;\n}\n\nmodule.exports = listCacheSet;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_listCacheSet.js\n ** module id = 18\n ** module chunks = 0\n **/","var ListCache = require('./_ListCache');\n\n/**\n * Removes all key-value entries from the stack.\n *\n * @private\n * @name clear\n * @memberOf Stack\n */\nfunction stackClear() {\n this.__data__ = new ListCache;\n this.size = 0;\n}\n\nmodule.exports = stackClear;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_stackClear.js\n ** module id = 19\n ** module chunks = 0\n **/","/**\n * Removes `key` and its value from the stack.\n *\n * @private\n * @name delete\n * @memberOf Stack\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction stackDelete(key) {\n var data = this.__data__,\n result = data['delete'](key);\n\n this.size = data.size;\n return result;\n}\n\nmodule.exports = stackDelete;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_stackDelete.js\n ** module id = 20\n ** module chunks = 0\n **/","/**\n * Gets the stack value for `key`.\n *\n * @private\n * @name get\n * @memberOf Stack\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction stackGet(key) {\n return this.__data__.get(key);\n}\n\nmodule.exports = stackGet;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_stackGet.js\n ** module id = 21\n ** module chunks = 0\n **/","/**\n * Checks if a stack value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf Stack\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction stackHas(key) {\n return this.__data__.has(key);\n}\n\nmodule.exports = stackHas;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_stackHas.js\n ** module id = 22\n ** module chunks = 0\n **/","var ListCache = require('./_ListCache'),\n Map = require('./_Map'),\n MapCache = require('./_MapCache');\n\n/** Used as the size to enable large array optimizations. */\nvar LARGE_ARRAY_SIZE = 200;\n\n/**\n * Sets the stack `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf Stack\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the stack cache instance.\n */\nfunction stackSet(key, value) {\n var data = this.__data__;\n if (data instanceof ListCache) {\n var pairs = data.__data__;\n if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {\n pairs.push([key, value]);\n this.size = ++data.size;\n return this;\n }\n data = this.__data__ = new MapCache(pairs);\n }\n data.set(key, value);\n this.size = data.size;\n return this;\n}\n\nmodule.exports = stackSet;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_stackSet.js\n ** module id = 23\n ** module chunks = 0\n **/","var getNative = require('./_getNative'),\n root = require('./_root');\n\n/* Built-in method references that are verified to be native. */\nvar Map = getNative(root, 'Map');\n\nmodule.exports = Map;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_Map.js\n ** module id = 24\n ** module chunks = 0\n **/","var baseIsNative = require('./_baseIsNative'),\n getValue = require('./_getValue');\n\n/**\n * Gets the native function at `key` of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {string} key The key of the method to get.\n * @returns {*} Returns the function if it's native, else `undefined`.\n */\nfunction getNative(object, key) {\n var value = getValue(object, key);\n return baseIsNative(value) ? value : undefined;\n}\n\nmodule.exports = getNative;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_getNative.js\n ** module id = 25\n ** module chunks = 0\n **/","var isFunction = require('./isFunction'),\n isMasked = require('./_isMasked'),\n isObject = require('./isObject'),\n toSource = require('./_toSource');\n\n/**\n * Used to match `RegExp`\n * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).\n */\nvar reRegExpChar = /[\\\\^$.*+?()[\\]{}|]/g;\n\n/** Used to detect host constructors (Safari). */\nvar reIsHostCtor = /^\\[object .+?Constructor\\]$/;\n\n/** Used for built-in method references. */\nvar funcProto = Function.prototype,\n objectProto = Object.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Used to detect if a method is native. */\nvar reIsNative = RegExp('^' +\n funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\\\$&')\n .replace(/hasOwnProperty|(function).*?(?=\\\\\\()| for .+?(?=\\\\\\])/g, '$1.*?') + '$'\n);\n\n/**\n * The base implementation of `_.isNative` without bad shim checks.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a native function,\n * else `false`.\n */\nfunction baseIsNative(value) {\n if (!isObject(value) || isMasked(value)) {\n return false;\n }\n var pattern = isFunction(value) ? reIsNative : reIsHostCtor;\n return pattern.test(toSource(value));\n}\n\nmodule.exports = baseIsNative;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_baseIsNative.js\n ** module id = 26\n ** module chunks = 0\n **/","var isObject = require('./isObject');\n\n/** `Object#toString` result references. */\nvar funcTag = '[object Function]',\n genTag = '[object GeneratorFunction]',\n proxyTag = '[object Proxy]';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar objectToString = objectProto.toString;\n\n/**\n * Checks if `value` is classified as a `Function` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a function, else `false`.\n * @example\n *\n * _.isFunction(_);\n * // => true\n *\n * _.isFunction(/abc/);\n * // => false\n */\nfunction isFunction(value) {\n // The use of `Object#toString` avoids issues with the `typeof` operator\n // in Safari 9 which returns 'object' for typed array and other constructors.\n var tag = isObject(value) ? objectToString.call(value) : '';\n return tag == funcTag || tag == genTag || tag == proxyTag;\n}\n\nmodule.exports = isFunction;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/isFunction.js\n ** module id = 27\n ** module chunks = 0\n **/","/**\n * Checks if `value` is the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(_.noop);\n * // => true\n *\n * _.isObject(null);\n * // => false\n */\nfunction isObject(value) {\n var type = typeof value;\n return value != null && (type == 'object' || type == 'function');\n}\n\nmodule.exports = isObject;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/isObject.js\n ** module id = 28\n ** module chunks = 0\n **/","var coreJsData = require('./_coreJsData');\n\n/** Used to detect methods masquerading as native. */\nvar maskSrcKey = (function() {\n var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');\n return uid ? ('Symbol(src)_1.' + uid) : '';\n}());\n\n/**\n * Checks if `func` has its source masked.\n *\n * @private\n * @param {Function} func The function to check.\n * @returns {boolean} Returns `true` if `func` is masked, else `false`.\n */\nfunction isMasked(func) {\n return !!maskSrcKey && (maskSrcKey in func);\n}\n\nmodule.exports = isMasked;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_isMasked.js\n ** module id = 29\n ** module chunks = 0\n **/","var root = require('./_root');\n\n/** Used to detect overreaching core-js shims. */\nvar coreJsData = root['__core-js_shared__'];\n\nmodule.exports = coreJsData;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_coreJsData.js\n ** module id = 30\n ** module chunks = 0\n **/","var freeGlobal = require('./_freeGlobal');\n\n/** Detect free variable `self`. */\nvar freeSelf = typeof self == 'object' && self && self.Object === Object && self;\n\n/** Used as a reference to the global object. */\nvar root = freeGlobal || freeSelf || Function('return this')();\n\nmodule.exports = root;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_root.js\n ** module id = 31\n ** module chunks = 0\n **/","/** Detect free variable `global` from Node.js. */\nvar freeGlobal = typeof global == 'object' && global && global.Object === Object && global;\n\nmodule.exports = freeGlobal;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_freeGlobal.js\n ** module id = 32\n ** module chunks = 0\n **/","/** Used for built-in method references. */\nvar funcProto = Function.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/**\n * Converts `func` to its source code.\n *\n * @private\n * @param {Function} func The function to process.\n * @returns {string} Returns the source code.\n */\nfunction toSource(func) {\n if (func != null) {\n try {\n return funcToString.call(func);\n } catch (e) {}\n try {\n return (func + '');\n } catch (e) {}\n }\n return '';\n}\n\nmodule.exports = toSource;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_toSource.js\n ** module id = 33\n ** module chunks = 0\n **/","/**\n * Gets the value at `key` of `object`.\n *\n * @private\n * @param {Object} [object] The object to query.\n * @param {string} key The key of the property to get.\n * @returns {*} Returns the property value.\n */\nfunction getValue(object, key) {\n return object == null ? undefined : object[key];\n}\n\nmodule.exports = getValue;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_getValue.js\n ** module id = 34\n ** module chunks = 0\n **/","var mapCacheClear = require('./_mapCacheClear'),\n mapCacheDelete = require('./_mapCacheDelete'),\n mapCacheGet = require('./_mapCacheGet'),\n mapCacheHas = require('./_mapCacheHas'),\n mapCacheSet = require('./_mapCacheSet');\n\n/**\n * Creates a map cache object to store key-value pairs.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction MapCache(entries) {\n var index = -1,\n length = entries ? entries.length : 0;\n\n this.clear();\n while (++index < length) {\n var entry = entries[index];\n this.set(entry[0], entry[1]);\n }\n}\n\n// Add methods to `MapCache`.\nMapCache.prototype.clear = mapCacheClear;\nMapCache.prototype['delete'] = mapCacheDelete;\nMapCache.prototype.get = mapCacheGet;\nMapCache.prototype.has = mapCacheHas;\nMapCache.prototype.set = mapCacheSet;\n\nmodule.exports = MapCache;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_MapCache.js\n ** module id = 35\n ** module chunks = 0\n **/","var Hash = require('./_Hash'),\n ListCache = require('./_ListCache'),\n Map = require('./_Map');\n\n/**\n * Removes all key-value entries from the map.\n *\n * @private\n * @name clear\n * @memberOf MapCache\n */\nfunction mapCacheClear() {\n this.size = 0;\n this.__data__ = {\n 'hash': new Hash,\n 'map': new (Map || ListCache),\n 'string': new Hash\n };\n}\n\nmodule.exports = mapCacheClear;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_mapCacheClear.js\n ** module id = 36\n ** module chunks = 0\n **/","var hashClear = require('./_hashClear'),\n hashDelete = require('./_hashDelete'),\n hashGet = require('./_hashGet'),\n hashHas = require('./_hashHas'),\n hashSet = require('./_hashSet');\n\n/**\n * Creates a hash object.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction Hash(entries) {\n var index = -1,\n length = entries ? entries.length : 0;\n\n this.clear();\n while (++index < length) {\n var entry = entries[index];\n this.set(entry[0], entry[1]);\n }\n}\n\n// Add methods to `Hash`.\nHash.prototype.clear = hashClear;\nHash.prototype['delete'] = hashDelete;\nHash.prototype.get = hashGet;\nHash.prototype.has = hashHas;\nHash.prototype.set = hashSet;\n\nmodule.exports = Hash;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_Hash.js\n ** module id = 37\n ** module chunks = 0\n **/","var nativeCreate = require('./_nativeCreate');\n\n/**\n * Removes all key-value entries from the hash.\n *\n * @private\n * @name clear\n * @memberOf Hash\n */\nfunction hashClear() {\n this.__data__ = nativeCreate ? nativeCreate(null) : {};\n this.size = 0;\n}\n\nmodule.exports = hashClear;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_hashClear.js\n ** module id = 38\n ** module chunks = 0\n **/","var getNative = require('./_getNative');\n\n/* Built-in method references that are verified to be native. */\nvar nativeCreate = getNative(Object, 'create');\n\nmodule.exports = nativeCreate;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_nativeCreate.js\n ** module id = 39\n ** module chunks = 0\n **/","/**\n * Removes `key` and its value from the hash.\n *\n * @private\n * @name delete\n * @memberOf Hash\n * @param {Object} hash The hash to modify.\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction hashDelete(key) {\n var result = this.has(key) && delete this.__data__[key];\n this.size -= result ? 1 : 0;\n return result;\n}\n\nmodule.exports = hashDelete;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_hashDelete.js\n ** module id = 40\n ** module chunks = 0\n **/","var nativeCreate = require('./_nativeCreate');\n\n/** Used to stand-in for `undefined` hash values. */\nvar HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Gets the hash value for `key`.\n *\n * @private\n * @name get\n * @memberOf Hash\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction hashGet(key) {\n var data = this.__data__;\n if (nativeCreate) {\n var result = data[key];\n return result === HASH_UNDEFINED ? undefined : result;\n }\n return hasOwnProperty.call(data, key) ? data[key] : undefined;\n}\n\nmodule.exports = hashGet;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_hashGet.js\n ** module id = 41\n ** module chunks = 0\n **/","var nativeCreate = require('./_nativeCreate');\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Checks if a hash value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf Hash\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction hashHas(key) {\n var data = this.__data__;\n return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key);\n}\n\nmodule.exports = hashHas;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_hashHas.js\n ** module id = 42\n ** module chunks = 0\n **/","var nativeCreate = require('./_nativeCreate');\n\n/** Used to stand-in for `undefined` hash values. */\nvar HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n/**\n * Sets the hash `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf Hash\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the hash instance.\n */\nfunction hashSet(key, value) {\n var data = this.__data__;\n this.size += this.has(key) ? 0 : 1;\n data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;\n return this;\n}\n\nmodule.exports = hashSet;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_hashSet.js\n ** module id = 43\n ** module chunks = 0\n **/","var getMapData = require('./_getMapData');\n\n/**\n * Removes `key` and its value from the map.\n *\n * @private\n * @name delete\n * @memberOf MapCache\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction mapCacheDelete(key) {\n var result = getMapData(this, key)['delete'](key);\n this.size -= result ? 1 : 0;\n return result;\n}\n\nmodule.exports = mapCacheDelete;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_mapCacheDelete.js\n ** module id = 44\n ** module chunks = 0\n **/","var isKeyable = require('./_isKeyable');\n\n/**\n * Gets the data for `map`.\n *\n * @private\n * @param {Object} map The map to query.\n * @param {string} key The reference key.\n * @returns {*} Returns the map data.\n */\nfunction getMapData(map, key) {\n var data = map.__data__;\n return isKeyable(key)\n ? data[typeof key == 'string' ? 'string' : 'hash']\n : data.map;\n}\n\nmodule.exports = getMapData;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_getMapData.js\n ** module id = 45\n ** module chunks = 0\n **/","/**\n * Checks if `value` is suitable for use as unique object key.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is suitable, else `false`.\n */\nfunction isKeyable(value) {\n var type = typeof value;\n return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')\n ? (value !== '__proto__')\n : (value === null);\n}\n\nmodule.exports = isKeyable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_isKeyable.js\n ** module id = 46\n ** module chunks = 0\n **/","var getMapData = require('./_getMapData');\n\n/**\n * Gets the map value for `key`.\n *\n * @private\n * @name get\n * @memberOf MapCache\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction mapCacheGet(key) {\n return getMapData(this, key).get(key);\n}\n\nmodule.exports = mapCacheGet;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_mapCacheGet.js\n ** module id = 47\n ** module chunks = 0\n **/","var getMapData = require('./_getMapData');\n\n/**\n * Checks if a map value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf MapCache\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction mapCacheHas(key) {\n return getMapData(this, key).has(key);\n}\n\nmodule.exports = mapCacheHas;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_mapCacheHas.js\n ** module id = 48\n ** module chunks = 0\n **/","var getMapData = require('./_getMapData');\n\n/**\n * Sets the map `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf MapCache\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the map cache instance.\n */\nfunction mapCacheSet(key, value) {\n var data = getMapData(this, key),\n size = data.size;\n\n data.set(key, value);\n this.size += data.size == size ? 0 : 1;\n return this;\n}\n\nmodule.exports = mapCacheSet;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_mapCacheSet.js\n ** module id = 49\n ** module chunks = 0\n **/","/**\n * A specialized version of `_.forEach` for arrays without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns `array`.\n */\nfunction arrayEach(array, iteratee) {\n var index = -1,\n length = array ? array.length : 0;\n\n while (++index < length) {\n if (iteratee(array[index], index, array) === false) {\n break;\n }\n }\n return array;\n}\n\nmodule.exports = arrayEach;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_arrayEach.js\n ** module id = 50\n ** module chunks = 0\n **/","var baseAssignValue = require('./_baseAssignValue'),\n eq = require('./eq');\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Assigns `value` to `key` of `object` if the existing value is not equivalent\n * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\nfunction assignValue(object, key, value) {\n var objValue = object[key];\n if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||\n (value === undefined && !(key in object))) {\n baseAssignValue(object, key, value);\n }\n}\n\nmodule.exports = assignValue;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_assignValue.js\n ** module id = 51\n ** module chunks = 0\n **/","var defineProperty = require('./_defineProperty');\n\n/**\n * The base implementation of `assignValue` and `assignMergeValue` without\n * value checks.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\nfunction baseAssignValue(object, key, value) {\n if (key == '__proto__' && defineProperty) {\n defineProperty(object, key, {\n 'configurable': true,\n 'enumerable': true,\n 'value': value,\n 'writable': true\n });\n } else {\n object[key] = value;\n }\n}\n\nmodule.exports = baseAssignValue;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_baseAssignValue.js\n ** module id = 52\n ** module chunks = 0\n **/","var getNative = require('./_getNative');\n\nvar defineProperty = (function() {\n try {\n var func = getNative(Object, 'defineProperty');\n func({}, '', {});\n return func;\n } catch (e) {}\n}());\n\nmodule.exports = defineProperty;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_defineProperty.js\n ** module id = 53\n ** module chunks = 0\n **/","var copyObject = require('./_copyObject'),\n keys = require('./keys');\n\n/**\n * The base implementation of `_.assign` without support for multiple sources\n * or `customizer` functions.\n *\n * @private\n * @param {Object} object The destination object.\n * @param {Object} source The source object.\n * @returns {Object} Returns `object`.\n */\nfunction baseAssign(object, source) {\n return object && copyObject(source, keys(source), object);\n}\n\nmodule.exports = baseAssign;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_baseAssign.js\n ** module id = 54\n ** module chunks = 0\n **/","var assignValue = require('./_assignValue'),\n baseAssignValue = require('./_baseAssignValue');\n\n/**\n * Copies properties of `source` to `object`.\n *\n * @private\n * @param {Object} source The object to copy properties from.\n * @param {Array} props The property identifiers to copy.\n * @param {Object} [object={}] The object to copy properties to.\n * @param {Function} [customizer] The function to customize copied values.\n * @returns {Object} Returns `object`.\n */\nfunction copyObject(source, props, object, customizer) {\n var isNew = !object;\n object || (object = {});\n\n var index = -1,\n length = props.length;\n\n while (++index < length) {\n var key = props[index];\n\n var newValue = customizer\n ? customizer(object[key], source[key], key, object, source)\n : undefined;\n\n if (newValue === undefined) {\n newValue = source[key];\n }\n if (isNew) {\n baseAssignValue(object, key, newValue);\n } else {\n assignValue(object, key, newValue);\n }\n }\n return object;\n}\n\nmodule.exports = copyObject;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_copyObject.js\n ** module id = 55\n ** module chunks = 0\n **/","var arrayLikeKeys = require('./_arrayLikeKeys'),\n baseKeys = require('./_baseKeys'),\n isArrayLike = require('./isArrayLike');\n\n/**\n * Creates an array of the own enumerable property names of `object`.\n *\n * **Note:** Non-object values are coerced to objects. See the\n * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)\n * for more details.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.keys(new Foo);\n * // => ['a', 'b'] (iteration order is not guaranteed)\n *\n * _.keys('hi');\n * // => ['0', '1']\n */\nfunction keys(object) {\n return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);\n}\n\nmodule.exports = keys;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/keys.js\n ** module id = 56\n ** module chunks = 0\n **/","var baseTimes = require('./_baseTimes'),\n isArguments = require('./isArguments'),\n isArray = require('./isArray'),\n isBuffer = require('./isBuffer'),\n isIndex = require('./_isIndex'),\n isTypedArray = require('./isTypedArray');\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Creates an array of the enumerable property names of the array-like `value`.\n *\n * @private\n * @param {*} value The value to query.\n * @param {boolean} inherited Specify returning inherited property names.\n * @returns {Array} Returns the array of property names.\n */\nfunction arrayLikeKeys(value, inherited) {\n var isArr = isArray(value),\n isArg = !isArr && isArguments(value),\n isBuff = !isArr && !isArg && isBuffer(value),\n isType = !isArr && !isArg && !isBuff && isTypedArray(value),\n skipIndexes = isArr || isArg || isBuff || isType,\n result = skipIndexes ? baseTimes(value.length, String) : [],\n length = result.length;\n\n for (var key in value) {\n if ((inherited || hasOwnProperty.call(value, key)) &&\n !(skipIndexes && (\n // Safari 9 has enumerable `arguments.length` in strict mode.\n key == 'length' ||\n // Node.js 0.10 has enumerable non-index properties on buffers.\n (isBuff && (key == 'offset' || key == 'parent')) ||\n // PhantomJS 2 has enumerable non-index properties on typed arrays.\n (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||\n // Skip index properties.\n isIndex(key, length)\n ))) {\n result.push(key);\n }\n }\n return result;\n}\n\nmodule.exports = arrayLikeKeys;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_arrayLikeKeys.js\n ** module id = 57\n ** module chunks = 0\n **/","/**\n * The base implementation of `_.times` without support for iteratee shorthands\n * or max array length checks.\n *\n * @private\n * @param {number} n The number of times to invoke `iteratee`.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the array of results.\n */\nfunction baseTimes(n, iteratee) {\n var index = -1,\n result = Array(n);\n\n while (++index < n) {\n result[index] = iteratee(index);\n }\n return result;\n}\n\nmodule.exports = baseTimes;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_baseTimes.js\n ** module id = 58\n ** module chunks = 0\n **/","var baseIsArguments = require('./_baseIsArguments'),\n isObjectLike = require('./isObjectLike');\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Built-in value references. */\nvar propertyIsEnumerable = objectProto.propertyIsEnumerable;\n\n/**\n * Checks if `value` is likely an `arguments` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n * else `false`.\n * @example\n *\n * _.isArguments(function() { return arguments; }());\n * // => true\n *\n * _.isArguments([1, 2, 3]);\n * // => false\n */\nvar isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {\n return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&\n !propertyIsEnumerable.call(value, 'callee');\n};\n\nmodule.exports = isArguments;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/isArguments.js\n ** module id = 59\n ** module chunks = 0\n **/","var isObjectLike = require('./isObjectLike');\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar objectToString = objectProto.toString;\n\n/**\n * The base implementation of `_.isArguments`.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n */\nfunction baseIsArguments(value) {\n return isObjectLike(value) && objectToString.call(value) == argsTag;\n}\n\nmodule.exports = baseIsArguments;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_baseIsArguments.js\n ** module id = 60\n ** module chunks = 0\n **/","/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return value != null && typeof value == 'object';\n}\n\nmodule.exports = isObjectLike;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/isObjectLike.js\n ** module id = 61\n ** module chunks = 0\n **/","/**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(document.body.children);\n * // => false\n *\n * _.isArray('abc');\n * // => false\n *\n * _.isArray(_.noop);\n * // => false\n */\nvar isArray = Array.isArray;\n\nmodule.exports = isArray;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/isArray.js\n ** module id = 62\n ** module chunks = 0\n **/","var root = require('./_root'),\n stubFalse = require('./stubFalse');\n\n/** Detect free variable `exports`. */\nvar freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;\n\n/** Detect free variable `module`. */\nvar freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;\n\n/** Detect the popular CommonJS extension `module.exports`. */\nvar moduleExports = freeModule && freeModule.exports === freeExports;\n\n/** Built-in value references. */\nvar Buffer = moduleExports ? root.Buffer : undefined;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined;\n\n/**\n * Checks if `value` is a buffer.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.\n * @example\n *\n * _.isBuffer(new Buffer(2));\n * // => true\n *\n * _.isBuffer(new Uint8Array(2));\n * // => false\n */\nvar isBuffer = nativeIsBuffer || stubFalse;\n\nmodule.exports = isBuffer;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/isBuffer.js\n ** module id = 63\n ** module chunks = 0\n **/","module.exports = function(module) {\r\n\tif(!module.webpackPolyfill) {\r\n\t\tmodule.deprecate = function() {};\r\n\t\tmodule.paths = [];\r\n\t\t// module.parent = undefined by default\r\n\t\tmodule.children = [];\r\n\t\tmodule.webpackPolyfill = 1;\r\n\t}\r\n\treturn module;\r\n}\r\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** (webpack)/buildin/module.js\n ** module id = 64\n ** module chunks = 0\n **/","/**\n * This method returns `false`.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {boolean} Returns `false`.\n * @example\n *\n * _.times(2, _.stubFalse);\n * // => [false, false]\n */\nfunction stubFalse() {\n return false;\n}\n\nmodule.exports = stubFalse;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/stubFalse.js\n ** module id = 65\n ** module chunks = 0\n **/","/** Used as references for various `Number` constants. */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/** Used to detect unsigned integer values. */\nvar reIsUint = /^(?:0|[1-9]\\d*)$/;\n\n/**\n * Checks if `value` is a valid array-like index.\n *\n * @private\n * @param {*} value The value to check.\n * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.\n * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.\n */\nfunction isIndex(value, length) {\n length = length == null ? MAX_SAFE_INTEGER : length;\n return !!length &&\n (typeof value == 'number' || reIsUint.test(value)) &&\n (value > -1 && value % 1 == 0 && value < length);\n}\n\nmodule.exports = isIndex;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_isIndex.js\n ** module id = 66\n ** module chunks = 0\n **/","var baseIsTypedArray = require('./_baseIsTypedArray'),\n baseUnary = require('./_baseUnary'),\n nodeUtil = require('./_nodeUtil');\n\n/* Node.js helper references. */\nvar nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;\n\n/**\n * Checks if `value` is classified as a typed array.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.\n * @example\n *\n * _.isTypedArray(new Uint8Array);\n * // => true\n *\n * _.isTypedArray([]);\n * // => false\n */\nvar isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;\n\nmodule.exports = isTypedArray;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/isTypedArray.js\n ** module id = 67\n ** module chunks = 0\n **/","var isLength = require('./isLength'),\n isObjectLike = require('./isObjectLike');\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n arrayTag = '[object Array]',\n boolTag = '[object Boolean]',\n dateTag = '[object Date]',\n errorTag = '[object Error]',\n funcTag = '[object Function]',\n mapTag = '[object Map]',\n numberTag = '[object Number]',\n objectTag = '[object Object]',\n regexpTag = '[object RegExp]',\n setTag = '[object Set]',\n stringTag = '[object String]',\n weakMapTag = '[object WeakMap]';\n\nvar arrayBufferTag = '[object ArrayBuffer]',\n dataViewTag = '[object DataView]',\n float32Tag = '[object Float32Array]',\n float64Tag = '[object Float64Array]',\n int8Tag = '[object Int8Array]',\n int16Tag = '[object Int16Array]',\n int32Tag = '[object Int32Array]',\n uint8Tag = '[object Uint8Array]',\n uint8ClampedTag = '[object Uint8ClampedArray]',\n uint16Tag = '[object Uint16Array]',\n uint32Tag = '[object Uint32Array]';\n\n/** Used to identify `toStringTag` values of typed arrays. */\nvar typedArrayTags = {};\ntypedArrayTags[float32Tag] = typedArrayTags[float64Tag] =\ntypedArrayTags[int8Tag] = typedArrayTags[int16Tag] =\ntypedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =\ntypedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =\ntypedArrayTags[uint32Tag] = true;\ntypedArrayTags[argsTag] = typedArrayTags[arrayTag] =\ntypedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =\ntypedArrayTags[dataViewTag] = typedArrayTags[dateTag] =\ntypedArrayTags[errorTag] = typedArrayTags[funcTag] =\ntypedArrayTags[mapTag] = typedArrayTags[numberTag] =\ntypedArrayTags[objectTag] = typedArrayTags[regexpTag] =\ntypedArrayTags[setTag] = typedArrayTags[stringTag] =\ntypedArrayTags[weakMapTag] = false;\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar objectToString = objectProto.toString;\n\n/**\n * The base implementation of `_.isTypedArray` without Node.js optimizations.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.\n */\nfunction baseIsTypedArray(value) {\n return isObjectLike(value) &&\n isLength(value.length) && !!typedArrayTags[objectToString.call(value)];\n}\n\nmodule.exports = baseIsTypedArray;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_baseIsTypedArray.js\n ** module id = 68\n ** module chunks = 0\n **/","/** Used as references for various `Number` constants. */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/**\n * Checks if `value` is a valid array-like length.\n *\n * **Note:** This method is loosely based on\n * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.\n * @example\n *\n * _.isLength(3);\n * // => true\n *\n * _.isLength(Number.MIN_VALUE);\n * // => false\n *\n * _.isLength(Infinity);\n * // => false\n *\n * _.isLength('3');\n * // => false\n */\nfunction isLength(value) {\n return typeof value == 'number' &&\n value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;\n}\n\nmodule.exports = isLength;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/isLength.js\n ** module id = 69\n ** module chunks = 0\n **/","/**\n * The base implementation of `_.unary` without support for storing metadata.\n *\n * @private\n * @param {Function} func The function to cap arguments for.\n * @returns {Function} Returns the new capped function.\n */\nfunction baseUnary(func) {\n return function(value) {\n return func(value);\n };\n}\n\nmodule.exports = baseUnary;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_baseUnary.js\n ** module id = 70\n ** module chunks = 0\n **/","var freeGlobal = require('./_freeGlobal');\n\n/** Detect free variable `exports`. */\nvar freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;\n\n/** Detect free variable `module`. */\nvar freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;\n\n/** Detect the popular CommonJS extension `module.exports`. */\nvar moduleExports = freeModule && freeModule.exports === freeExports;\n\n/** Detect free variable `process` from Node.js. */\nvar freeProcess = moduleExports && freeGlobal.process;\n\n/** Used to access faster Node.js helpers. */\nvar nodeUtil = (function() {\n try {\n return freeProcess && freeProcess.binding('util');\n } catch (e) {}\n}());\n\nmodule.exports = nodeUtil;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_nodeUtil.js\n ** module id = 71\n ** module chunks = 0\n **/","var isPrototype = require('./_isPrototype'),\n nativeKeys = require('./_nativeKeys');\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\nfunction baseKeys(object) {\n if (!isPrototype(object)) {\n return nativeKeys(object);\n }\n var result = [];\n for (var key in Object(object)) {\n if (hasOwnProperty.call(object, key) && key != 'constructor') {\n result.push(key);\n }\n }\n return result;\n}\n\nmodule.exports = baseKeys;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_baseKeys.js\n ** module id = 72\n ** module chunks = 0\n **/","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Checks if `value` is likely a prototype object.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.\n */\nfunction isPrototype(value) {\n var Ctor = value && value.constructor,\n proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;\n\n return value === proto;\n}\n\nmodule.exports = isPrototype;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_isPrototype.js\n ** module id = 73\n ** module chunks = 0\n **/","var overArg = require('./_overArg');\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeKeys = overArg(Object.keys, Object);\n\nmodule.exports = nativeKeys;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_nativeKeys.js\n ** module id = 74\n ** module chunks = 0\n **/","/**\n * Creates a unary function that invokes `func` with its argument transformed.\n *\n * @private\n * @param {Function} func The function to wrap.\n * @param {Function} transform The argument transform.\n * @returns {Function} Returns the new function.\n */\nfunction overArg(func, transform) {\n return function(arg) {\n return func(transform(arg));\n };\n}\n\nmodule.exports = overArg;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_overArg.js\n ** module id = 75\n ** module chunks = 0\n **/","var isFunction = require('./isFunction'),\n isLength = require('./isLength');\n\n/**\n * Checks if `value` is array-like. A value is considered array-like if it's\n * not a function and has a `value.length` that's an integer greater than or\n * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is array-like, else `false`.\n * @example\n *\n * _.isArrayLike([1, 2, 3]);\n * // => true\n *\n * _.isArrayLike(document.body.children);\n * // => true\n *\n * _.isArrayLike('abc');\n * // => true\n *\n * _.isArrayLike(_.noop);\n * // => false\n */\nfunction isArrayLike(value) {\n return value != null && isLength(value.length) && !isFunction(value);\n}\n\nmodule.exports = isArrayLike;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/isArrayLike.js\n ** module id = 76\n ** module chunks = 0\n **/","var root = require('./_root');\n\n/** Detect free variable `exports`. */\nvar freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;\n\n/** Detect free variable `module`. */\nvar freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;\n\n/** Detect the popular CommonJS extension `module.exports`. */\nvar moduleExports = freeModule && freeModule.exports === freeExports;\n\n/** Built-in value references. */\nvar Buffer = moduleExports ? root.Buffer : undefined,\n allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined;\n\n/**\n * Creates a clone of `buffer`.\n *\n * @private\n * @param {Buffer} buffer The buffer to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Buffer} Returns the cloned buffer.\n */\nfunction cloneBuffer(buffer, isDeep) {\n if (isDeep) {\n return buffer.slice();\n }\n var length = buffer.length,\n result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);\n\n buffer.copy(result);\n return result;\n}\n\nmodule.exports = cloneBuffer;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_cloneBuffer.js\n ** module id = 77\n ** module chunks = 0\n **/","/**\n * Copies the values of `source` to `array`.\n *\n * @private\n * @param {Array} source The array to copy values from.\n * @param {Array} [array=[]] The array to copy values to.\n * @returns {Array} Returns `array`.\n */\nfunction copyArray(source, array) {\n var index = -1,\n length = source.length;\n\n array || (array = Array(length));\n while (++index < length) {\n array[index] = source[index];\n }\n return array;\n}\n\nmodule.exports = copyArray;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_copyArray.js\n ** module id = 78\n ** module chunks = 0\n **/","var copyObject = require('./_copyObject'),\n getSymbols = require('./_getSymbols');\n\n/**\n * Copies own symbol properties of `source` to `object`.\n *\n * @private\n * @param {Object} source The object to copy symbols from.\n * @param {Object} [object={}] The object to copy symbols to.\n * @returns {Object} Returns `object`.\n */\nfunction copySymbols(source, object) {\n return copyObject(source, getSymbols(source), object);\n}\n\nmodule.exports = copySymbols;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_copySymbols.js\n ** module id = 79\n ** module chunks = 0\n **/","var overArg = require('./_overArg'),\n stubArray = require('./stubArray');\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeGetSymbols = Object.getOwnPropertySymbols;\n\n/**\n * Creates an array of the own enumerable symbol properties of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of symbols.\n */\nvar getSymbols = nativeGetSymbols ? overArg(nativeGetSymbols, Object) : stubArray;\n\nmodule.exports = getSymbols;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_getSymbols.js\n ** module id = 80\n ** module chunks = 0\n **/","/**\n * This method returns a new empty array.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {Array} Returns the new empty array.\n * @example\n *\n * var arrays = _.times(2, _.stubArray);\n *\n * console.log(arrays);\n * // => [[], []]\n *\n * console.log(arrays[0] === arrays[1]);\n * // => false\n */\nfunction stubArray() {\n return [];\n}\n\nmodule.exports = stubArray;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/stubArray.js\n ** module id = 81\n ** module chunks = 0\n **/","var baseGetAllKeys = require('./_baseGetAllKeys'),\n getSymbols = require('./_getSymbols'),\n keys = require('./keys');\n\n/**\n * Creates an array of own enumerable property names and symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names and symbols.\n */\nfunction getAllKeys(object) {\n return baseGetAllKeys(object, keys, getSymbols);\n}\n\nmodule.exports = getAllKeys;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_getAllKeys.js\n ** module id = 82\n ** module chunks = 0\n **/","var arrayPush = require('./_arrayPush'),\n isArray = require('./isArray');\n\n/**\n * The base implementation of `getAllKeys` and `getAllKeysIn` which uses\n * `keysFunc` and `symbolsFunc` to get the enumerable property names and\n * symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Function} keysFunc The function to get the keys of `object`.\n * @param {Function} symbolsFunc The function to get the symbols of `object`.\n * @returns {Array} Returns the array of property names and symbols.\n */\nfunction baseGetAllKeys(object, keysFunc, symbolsFunc) {\n var result = keysFunc(object);\n return isArray(object) ? result : arrayPush(result, symbolsFunc(object));\n}\n\nmodule.exports = baseGetAllKeys;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_baseGetAllKeys.js\n ** module id = 83\n ** module chunks = 0\n **/","/**\n * Appends the elements of `values` to `array`.\n *\n * @private\n * @param {Array} array The array to modify.\n * @param {Array} values The values to append.\n * @returns {Array} Returns `array`.\n */\nfunction arrayPush(array, values) {\n var index = -1,\n length = values.length,\n offset = array.length;\n\n while (++index < length) {\n array[offset + index] = values[index];\n }\n return array;\n}\n\nmodule.exports = arrayPush;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_arrayPush.js\n ** module id = 84\n ** module chunks = 0\n **/","var DataView = require('./_DataView'),\n Map = require('./_Map'),\n Promise = require('./_Promise'),\n Set = require('./_Set'),\n WeakMap = require('./_WeakMap'),\n baseGetTag = require('./_baseGetTag'),\n toSource = require('./_toSource');\n\n/** `Object#toString` result references. */\nvar mapTag = '[object Map]',\n objectTag = '[object Object]',\n promiseTag = '[object Promise]',\n setTag = '[object Set]',\n weakMapTag = '[object WeakMap]';\n\nvar dataViewTag = '[object DataView]';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar objectToString = objectProto.toString;\n\n/** Used to detect maps, sets, and weakmaps. */\nvar dataViewCtorString = toSource(DataView),\n mapCtorString = toSource(Map),\n promiseCtorString = toSource(Promise),\n setCtorString = toSource(Set),\n weakMapCtorString = toSource(WeakMap);\n\n/**\n * Gets the `toStringTag` of `value`.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the `toStringTag`.\n */\nvar getTag = baseGetTag;\n\n// Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.\nif ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||\n (Map && getTag(new Map) != mapTag) ||\n (Promise && getTag(Promise.resolve()) != promiseTag) ||\n (Set && getTag(new Set) != setTag) ||\n (WeakMap && getTag(new WeakMap) != weakMapTag)) {\n getTag = function(value) {\n var result = objectToString.call(value),\n Ctor = result == objectTag ? value.constructor : undefined,\n ctorString = Ctor ? toSource(Ctor) : undefined;\n\n if (ctorString) {\n switch (ctorString) {\n case dataViewCtorString: return dataViewTag;\n case mapCtorString: return mapTag;\n case promiseCtorString: return promiseTag;\n case setCtorString: return setTag;\n case weakMapCtorString: return weakMapTag;\n }\n }\n return result;\n };\n}\n\nmodule.exports = getTag;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_getTag.js\n ** module id = 85\n ** module chunks = 0\n **/","var getNative = require('./_getNative'),\n root = require('./_root');\n\n/* Built-in method references that are verified to be native. */\nvar DataView = getNative(root, 'DataView');\n\nmodule.exports = DataView;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_DataView.js\n ** module id = 86\n ** module chunks = 0\n **/","var getNative = require('./_getNative'),\n root = require('./_root');\n\n/* Built-in method references that are verified to be native. */\nvar Promise = getNative(root, 'Promise');\n\nmodule.exports = Promise;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_Promise.js\n ** module id = 87\n ** module chunks = 0\n **/","var getNative = require('./_getNative'),\n root = require('./_root');\n\n/* Built-in method references that are verified to be native. */\nvar Set = getNative(root, 'Set');\n\nmodule.exports = Set;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_Set.js\n ** module id = 88\n ** module chunks = 0\n **/","var getNative = require('./_getNative'),\n root = require('./_root');\n\n/* Built-in method references that are verified to be native. */\nvar WeakMap = getNative(root, 'WeakMap');\n\nmodule.exports = WeakMap;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_WeakMap.js\n ** module id = 89\n ** module chunks = 0\n **/","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar objectToString = objectProto.toString;\n\n/**\n * The base implementation of `getTag`.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the `toStringTag`.\n */\nfunction baseGetTag(value) {\n return objectToString.call(value);\n}\n\nmodule.exports = baseGetTag;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_baseGetTag.js\n ** module id = 90\n ** module chunks = 0\n **/","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Initializes an array clone.\n *\n * @private\n * @param {Array} array The array to clone.\n * @returns {Array} Returns the initialized clone.\n */\nfunction initCloneArray(array) {\n var length = array.length,\n result = array.constructor(length);\n\n // Add properties assigned by `RegExp#exec`.\n if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {\n result.index = array.index;\n result.input = array.input;\n }\n return result;\n}\n\nmodule.exports = initCloneArray;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_initCloneArray.js\n ** module id = 91\n ** module chunks = 0\n **/","var cloneArrayBuffer = require('./_cloneArrayBuffer'),\n cloneDataView = require('./_cloneDataView'),\n cloneMap = require('./_cloneMap'),\n cloneRegExp = require('./_cloneRegExp'),\n cloneSet = require('./_cloneSet'),\n cloneSymbol = require('./_cloneSymbol'),\n cloneTypedArray = require('./_cloneTypedArray');\n\n/** `Object#toString` result references. */\nvar boolTag = '[object Boolean]',\n dateTag = '[object Date]',\n mapTag = '[object Map]',\n numberTag = '[object Number]',\n regexpTag = '[object RegExp]',\n setTag = '[object Set]',\n stringTag = '[object String]',\n symbolTag = '[object Symbol]';\n\nvar arrayBufferTag = '[object ArrayBuffer]',\n dataViewTag = '[object DataView]',\n float32Tag = '[object Float32Array]',\n float64Tag = '[object Float64Array]',\n int8Tag = '[object Int8Array]',\n int16Tag = '[object Int16Array]',\n int32Tag = '[object Int32Array]',\n uint8Tag = '[object Uint8Array]',\n uint8ClampedTag = '[object Uint8ClampedArray]',\n uint16Tag = '[object Uint16Array]',\n uint32Tag = '[object Uint32Array]';\n\n/**\n * Initializes an object clone based on its `toStringTag`.\n *\n * **Note:** This function only supports cloning values with tags of\n * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.\n *\n * @private\n * @param {Object} object The object to clone.\n * @param {string} tag The `toStringTag` of the object to clone.\n * @param {Function} cloneFunc The function to clone values.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the initialized clone.\n */\nfunction initCloneByTag(object, tag, cloneFunc, isDeep) {\n var Ctor = object.constructor;\n switch (tag) {\n case arrayBufferTag:\n return cloneArrayBuffer(object);\n\n case boolTag:\n case dateTag:\n return new Ctor(+object);\n\n case dataViewTag:\n return cloneDataView(object, isDeep);\n\n case float32Tag: case float64Tag:\n case int8Tag: case int16Tag: case int32Tag:\n case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:\n return cloneTypedArray(object, isDeep);\n\n case mapTag:\n return cloneMap(object, isDeep, cloneFunc);\n\n case numberTag:\n case stringTag:\n return new Ctor(object);\n\n case regexpTag:\n return cloneRegExp(object);\n\n case setTag:\n return cloneSet(object, isDeep, cloneFunc);\n\n case symbolTag:\n return cloneSymbol(object);\n }\n}\n\nmodule.exports = initCloneByTag;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_initCloneByTag.js\n ** module id = 92\n ** module chunks = 0\n **/","var Uint8Array = require('./_Uint8Array');\n\n/**\n * Creates a clone of `arrayBuffer`.\n *\n * @private\n * @param {ArrayBuffer} arrayBuffer The array buffer to clone.\n * @returns {ArrayBuffer} Returns the cloned array buffer.\n */\nfunction cloneArrayBuffer(arrayBuffer) {\n var result = new arrayBuffer.constructor(arrayBuffer.byteLength);\n new Uint8Array(result).set(new Uint8Array(arrayBuffer));\n return result;\n}\n\nmodule.exports = cloneArrayBuffer;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_cloneArrayBuffer.js\n ** module id = 93\n ** module chunks = 0\n **/","var root = require('./_root');\n\n/** Built-in value references. */\nvar Uint8Array = root.Uint8Array;\n\nmodule.exports = Uint8Array;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_Uint8Array.js\n ** module id = 94\n ** module chunks = 0\n **/","var cloneArrayBuffer = require('./_cloneArrayBuffer');\n\n/**\n * Creates a clone of `dataView`.\n *\n * @private\n * @param {Object} dataView The data view to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the cloned data view.\n */\nfunction cloneDataView(dataView, isDeep) {\n var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;\n return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);\n}\n\nmodule.exports = cloneDataView;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_cloneDataView.js\n ** module id = 95\n ** module chunks = 0\n **/","var addMapEntry = require('./_addMapEntry'),\n arrayReduce = require('./_arrayReduce'),\n mapToArray = require('./_mapToArray');\n\n/**\n * Creates a clone of `map`.\n *\n * @private\n * @param {Object} map The map to clone.\n * @param {Function} cloneFunc The function to clone values.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the cloned map.\n */\nfunction cloneMap(map, isDeep, cloneFunc) {\n var array = isDeep ? cloneFunc(mapToArray(map), true) : mapToArray(map);\n return arrayReduce(array, addMapEntry, new map.constructor);\n}\n\nmodule.exports = cloneMap;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_cloneMap.js\n ** module id = 96\n ** module chunks = 0\n **/","/**\n * Adds the key-value `pair` to `map`.\n *\n * @private\n * @param {Object} map The map to modify.\n * @param {Array} pair The key-value pair to add.\n * @returns {Object} Returns `map`.\n */\nfunction addMapEntry(map, pair) {\n // Don't return `map.set` because it's not chainable in IE 11.\n map.set(pair[0], pair[1]);\n return map;\n}\n\nmodule.exports = addMapEntry;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_addMapEntry.js\n ** module id = 97\n ** module chunks = 0\n **/","/**\n * A specialized version of `_.reduce` for arrays without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @param {*} [accumulator] The initial value.\n * @param {boolean} [initAccum] Specify using the first element of `array` as\n * the initial value.\n * @returns {*} Returns the accumulated value.\n */\nfunction arrayReduce(array, iteratee, accumulator, initAccum) {\n var index = -1,\n length = array ? array.length : 0;\n\n if (initAccum && length) {\n accumulator = array[++index];\n }\n while (++index < length) {\n accumulator = iteratee(accumulator, array[index], index, array);\n }\n return accumulator;\n}\n\nmodule.exports = arrayReduce;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_arrayReduce.js\n ** module id = 98\n ** module chunks = 0\n **/","/**\n * Converts `map` to its key-value pairs.\n *\n * @private\n * @param {Object} map The map to convert.\n * @returns {Array} Returns the key-value pairs.\n */\nfunction mapToArray(map) {\n var index = -1,\n result = Array(map.size);\n\n map.forEach(function(value, key) {\n result[++index] = [key, value];\n });\n return result;\n}\n\nmodule.exports = mapToArray;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_mapToArray.js\n ** module id = 99\n ** module chunks = 0\n **/","/** Used to match `RegExp` flags from their coerced string values. */\nvar reFlags = /\\w*$/;\n\n/**\n * Creates a clone of `regexp`.\n *\n * @private\n * @param {Object} regexp The regexp to clone.\n * @returns {Object} Returns the cloned regexp.\n */\nfunction cloneRegExp(regexp) {\n var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));\n result.lastIndex = regexp.lastIndex;\n return result;\n}\n\nmodule.exports = cloneRegExp;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_cloneRegExp.js\n ** module id = 100\n ** module chunks = 0\n **/","var addSetEntry = require('./_addSetEntry'),\n arrayReduce = require('./_arrayReduce'),\n setToArray = require('./_setToArray');\n\n/**\n * Creates a clone of `set`.\n *\n * @private\n * @param {Object} set The set to clone.\n * @param {Function} cloneFunc The function to clone values.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the cloned set.\n */\nfunction cloneSet(set, isDeep, cloneFunc) {\n var array = isDeep ? cloneFunc(setToArray(set), true) : setToArray(set);\n return arrayReduce(array, addSetEntry, new set.constructor);\n}\n\nmodule.exports = cloneSet;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_cloneSet.js\n ** module id = 101\n ** module chunks = 0\n **/","/**\n * Adds `value` to `set`.\n *\n * @private\n * @param {Object} set The set to modify.\n * @param {*} value The value to add.\n * @returns {Object} Returns `set`.\n */\nfunction addSetEntry(set, value) {\n // Don't return `set.add` because it's not chainable in IE 11.\n set.add(value);\n return set;\n}\n\nmodule.exports = addSetEntry;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_addSetEntry.js\n ** module id = 102\n ** module chunks = 0\n **/","/**\n * Converts `set` to an array of its values.\n *\n * @private\n * @param {Object} set The set to convert.\n * @returns {Array} Returns the values.\n */\nfunction setToArray(set) {\n var index = -1,\n result = Array(set.size);\n\n set.forEach(function(value) {\n result[++index] = value;\n });\n return result;\n}\n\nmodule.exports = setToArray;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_setToArray.js\n ** module id = 103\n ** module chunks = 0\n **/","var Symbol = require('./_Symbol');\n\n/** Used to convert symbols to primitives and strings. */\nvar symbolProto = Symbol ? Symbol.prototype : undefined,\n symbolValueOf = symbolProto ? symbolProto.valueOf : undefined;\n\n/**\n * Creates a clone of the `symbol` object.\n *\n * @private\n * @param {Object} symbol The symbol object to clone.\n * @returns {Object} Returns the cloned symbol object.\n */\nfunction cloneSymbol(symbol) {\n return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};\n}\n\nmodule.exports = cloneSymbol;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_cloneSymbol.js\n ** module id = 104\n ** module chunks = 0\n **/","var root = require('./_root');\n\n/** Built-in value references. */\nvar Symbol = root.Symbol;\n\nmodule.exports = Symbol;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_Symbol.js\n ** module id = 105\n ** module chunks = 0\n **/","var cloneArrayBuffer = require('./_cloneArrayBuffer');\n\n/**\n * Creates a clone of `typedArray`.\n *\n * @private\n * @param {Object} typedArray The typed array to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the cloned typed array.\n */\nfunction cloneTypedArray(typedArray, isDeep) {\n var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;\n return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);\n}\n\nmodule.exports = cloneTypedArray;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_cloneTypedArray.js\n ** module id = 106\n ** module chunks = 0\n **/","var baseCreate = require('./_baseCreate'),\n getPrototype = require('./_getPrototype'),\n isPrototype = require('./_isPrototype');\n\n/**\n * Initializes an object clone.\n *\n * @private\n * @param {Object} object The object to clone.\n * @returns {Object} Returns the initialized clone.\n */\nfunction initCloneObject(object) {\n return (typeof object.constructor == 'function' && !isPrototype(object))\n ? baseCreate(getPrototype(object))\n : {};\n}\n\nmodule.exports = initCloneObject;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_initCloneObject.js\n ** module id = 107\n ** module chunks = 0\n **/","var isObject = require('./isObject');\n\n/** Built-in value references. */\nvar objectCreate = Object.create;\n\n/**\n * The base implementation of `_.create` without support for assigning\n * properties to the created object.\n *\n * @private\n * @param {Object} proto The object to inherit from.\n * @returns {Object} Returns the new object.\n */\nvar baseCreate = (function() {\n function object() {}\n return function(proto) {\n if (!isObject(proto)) {\n return {};\n }\n if (objectCreate) {\n return objectCreate(proto);\n }\n object.prototype = proto;\n var result = new object;\n object.prototype = undefined;\n return result;\n };\n}());\n\nmodule.exports = baseCreate;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_baseCreate.js\n ** module id = 108\n ** module chunks = 0\n **/","var overArg = require('./_overArg');\n\n/** Built-in value references. */\nvar getPrototype = overArg(Object.getPrototypeOf, Object);\n\nmodule.exports = getPrototype;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_getPrototype.js\n ** module id = 109\n ** module chunks = 0\n **/","\n// TODO: unit test isObject\n\n/**\n * Test whether a value is an Object (and not an Array!)\n *\n * @param {*} value\n * @return {boolean}\n */\nexport function isObject (value) {\n return typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value)\n}\n\n/**\n * Test whether a value is an Object or an Array\n *\n * @param {*} value\n * @return {boolean}\n */\nexport function isObjectOrArray (value) {\n return typeof value === 'object' && value !== null\n}\n\n/**\n * Get the type of a value\n * @param {*} value\n * @return {String} type\n */\nexport function valueType(value) {\n if (value === null) {\n return 'null'\n }\n if (value === undefined) {\n return 'undefined'\n }\n if (typeof value === 'number') {\n return 'number'\n }\n if (typeof value === 'string') {\n return 'string'\n }\n if (typeof value === 'boolean') {\n return 'boolean'\n }\n if (value instanceof RegExp) {\n return 'regexp'\n }\n if (Array.isArray(value)) {\n return 'Array'\n }\n\n return 'Object'\n}\n\n/**\n * Test whether a text contains a url (matches when a string starts\n * with 'http://*' or 'https://*' and has no whitespace characters)\n * @param {String} text\n */\nvar isUrlRegex = /^https?:\\/\\/\\S+$/\nexport function isUrl (text) {\n return (typeof text === 'string') && isUrlRegex.test(text)\n}\n\n/**\n * Convert contents of a string to the correct JSON type. This can be a string,\n * a number, a boolean, etc\n * @param {String} str\n * @return {*} castedStr\n * @private\n */\nexport function stringConvert (str) {\n const num = Number(str) // will nicely fail with '123ab'\n const numFloat = parseFloat(str) // will nicely fail with ' '\n\n if (str == '') {\n return ''\n }\n else if (str == 'null') {\n return null\n }\n else if (str == 'true') {\n return true\n }\n else if (str == 'false') {\n return false\n }\n else if (!isNaN(num) && !isNaN(numFloat)) {\n return num\n }\n else {\n return str\n }\n}\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/utils/typeUtils.js\n **/","var baseIsEqual = require('./_baseIsEqual');\n\n/**\n * Performs a deep comparison between two values to determine if they are\n * equivalent.\n *\n * **Note:** This method supports comparing arrays, array buffers, booleans,\n * date objects, error objects, maps, numbers, `Object` objects, regexes,\n * sets, strings, symbols, and typed arrays. `Object` objects are compared\n * by their own, not inherited, enumerable properties. Functions and DOM\n * nodes are **not** supported.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * var object = { 'a': 1 };\n * var other = { 'a': 1 };\n *\n * _.isEqual(object, other);\n * // => true\n *\n * object === other;\n * // => false\n */\nfunction isEqual(value, other) {\n return baseIsEqual(value, other);\n}\n\nmodule.exports = isEqual;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/isEqual.js\n ** module id = 111\n ** module chunks = 0\n **/","var baseIsEqualDeep = require('./_baseIsEqualDeep'),\n isObject = require('./isObject'),\n isObjectLike = require('./isObjectLike');\n\n/**\n * The base implementation of `_.isEqual` which supports partial comparisons\n * and tracks traversed objects.\n *\n * @private\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @param {Function} [customizer] The function to customize comparisons.\n * @param {boolean} [bitmask] The bitmask of comparison flags.\n * The bitmask may be composed of the following flags:\n * 1 - Unordered comparison\n * 2 - Partial comparison\n * @param {Object} [stack] Tracks traversed `value` and `other` objects.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n */\nfunction baseIsEqual(value, other, customizer, bitmask, stack) {\n if (value === other) {\n return true;\n }\n if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) {\n return value !== value && other !== other;\n }\n return baseIsEqualDeep(value, other, baseIsEqual, customizer, bitmask, stack);\n}\n\nmodule.exports = baseIsEqual;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_baseIsEqual.js\n ** module id = 112\n ** module chunks = 0\n **/","var Stack = require('./_Stack'),\n equalArrays = require('./_equalArrays'),\n equalByTag = require('./_equalByTag'),\n equalObjects = require('./_equalObjects'),\n getTag = require('./_getTag'),\n isArray = require('./isArray'),\n isBuffer = require('./isBuffer'),\n isTypedArray = require('./isTypedArray');\n\n/** Used to compose bitmasks for comparison styles. */\nvar PARTIAL_COMPARE_FLAG = 2;\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n arrayTag = '[object Array]',\n objectTag = '[object Object]';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * A specialized version of `baseIsEqual` for arrays and objects which performs\n * deep comparisons and tracks traversed objects enabling objects with circular\n * references to be compared.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Function} [customizer] The function to customize comparisons.\n * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual`\n * for more details.\n * @param {Object} [stack] Tracks traversed `object` and `other` objects.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\nfunction baseIsEqualDeep(object, other, equalFunc, customizer, bitmask, stack) {\n var objIsArr = isArray(object),\n othIsArr = isArray(other),\n objTag = arrayTag,\n othTag = arrayTag;\n\n if (!objIsArr) {\n objTag = getTag(object);\n objTag = objTag == argsTag ? objectTag : objTag;\n }\n if (!othIsArr) {\n othTag = getTag(other);\n othTag = othTag == argsTag ? objectTag : othTag;\n }\n var objIsObj = objTag == objectTag,\n othIsObj = othTag == objectTag,\n isSameTag = objTag == othTag;\n\n if (isSameTag && isBuffer(object)) {\n if (!isBuffer(other)) {\n return false;\n }\n objIsArr = true;\n objIsObj = false;\n }\n if (isSameTag && !objIsObj) {\n stack || (stack = new Stack);\n return (objIsArr || isTypedArray(object))\n ? equalArrays(object, other, equalFunc, customizer, bitmask, stack)\n : equalByTag(object, other, objTag, equalFunc, customizer, bitmask, stack);\n }\n if (!(bitmask & PARTIAL_COMPARE_FLAG)) {\n var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),\n othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');\n\n if (objIsWrapped || othIsWrapped) {\n var objUnwrapped = objIsWrapped ? object.value() : object,\n othUnwrapped = othIsWrapped ? other.value() : other;\n\n stack || (stack = new Stack);\n return equalFunc(objUnwrapped, othUnwrapped, customizer, bitmask, stack);\n }\n }\n if (!isSameTag) {\n return false;\n }\n stack || (stack = new Stack);\n return equalObjects(object, other, equalFunc, customizer, bitmask, stack);\n}\n\nmodule.exports = baseIsEqualDeep;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_baseIsEqualDeep.js\n ** module id = 113\n ** module chunks = 0\n **/","var SetCache = require('./_SetCache'),\n arraySome = require('./_arraySome'),\n cacheHas = require('./_cacheHas');\n\n/** Used to compose bitmasks for comparison styles. */\nvar UNORDERED_COMPARE_FLAG = 1,\n PARTIAL_COMPARE_FLAG = 2;\n\n/**\n * A specialized version of `baseIsEqualDeep` for arrays with support for\n * partial deep comparisons.\n *\n * @private\n * @param {Array} array The array to compare.\n * @param {Array} other The other array to compare.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Function} customizer The function to customize comparisons.\n * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual`\n * for more details.\n * @param {Object} stack Tracks traversed `array` and `other` objects.\n * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.\n */\nfunction equalArrays(array, other, equalFunc, customizer, bitmask, stack) {\n var isPartial = bitmask & PARTIAL_COMPARE_FLAG,\n arrLength = array.length,\n othLength = other.length;\n\n if (arrLength != othLength && !(isPartial && othLength > arrLength)) {\n return false;\n }\n // Assume cyclic values are equal.\n var stacked = stack.get(array);\n if (stacked && stack.get(other)) {\n return stacked == other;\n }\n var index = -1,\n result = true,\n seen = (bitmask & UNORDERED_COMPARE_FLAG) ? new SetCache : undefined;\n\n stack.set(array, other);\n stack.set(other, array);\n\n // Ignore non-index properties.\n while (++index < arrLength) {\n var arrValue = array[index],\n othValue = other[index];\n\n if (customizer) {\n var compared = isPartial\n ? customizer(othValue, arrValue, index, other, array, stack)\n : customizer(arrValue, othValue, index, array, other, stack);\n }\n if (compared !== undefined) {\n if (compared) {\n continue;\n }\n result = false;\n break;\n }\n // Recursively compare arrays (susceptible to call stack limits).\n if (seen) {\n if (!arraySome(other, function(othValue, othIndex) {\n if (!cacheHas(seen, othIndex) &&\n (arrValue === othValue || equalFunc(arrValue, othValue, customizer, bitmask, stack))) {\n return seen.push(othIndex);\n }\n })) {\n result = false;\n break;\n }\n } else if (!(\n arrValue === othValue ||\n equalFunc(arrValue, othValue, customizer, bitmask, stack)\n )) {\n result = false;\n break;\n }\n }\n stack['delete'](array);\n stack['delete'](other);\n return result;\n}\n\nmodule.exports = equalArrays;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_equalArrays.js\n ** module id = 114\n ** module chunks = 0\n **/","var MapCache = require('./_MapCache'),\n setCacheAdd = require('./_setCacheAdd'),\n setCacheHas = require('./_setCacheHas');\n\n/**\n *\n * Creates an array cache object to store unique values.\n *\n * @private\n * @constructor\n * @param {Array} [values] The values to cache.\n */\nfunction SetCache(values) {\n var index = -1,\n length = values ? values.length : 0;\n\n this.__data__ = new MapCache;\n while (++index < length) {\n this.add(values[index]);\n }\n}\n\n// Add methods to `SetCache`.\nSetCache.prototype.add = SetCache.prototype.push = setCacheAdd;\nSetCache.prototype.has = setCacheHas;\n\nmodule.exports = SetCache;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_SetCache.js\n ** module id = 115\n ** module chunks = 0\n **/","/** Used to stand-in for `undefined` hash values. */\nvar HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n/**\n * Adds `value` to the array cache.\n *\n * @private\n * @name add\n * @memberOf SetCache\n * @alias push\n * @param {*} value The value to cache.\n * @returns {Object} Returns the cache instance.\n */\nfunction setCacheAdd(value) {\n this.__data__.set(value, HASH_UNDEFINED);\n return this;\n}\n\nmodule.exports = setCacheAdd;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_setCacheAdd.js\n ** module id = 116\n ** module chunks = 0\n **/","/**\n * Checks if `value` is in the array cache.\n *\n * @private\n * @name has\n * @memberOf SetCache\n * @param {*} value The value to search for.\n * @returns {number} Returns `true` if `value` is found, else `false`.\n */\nfunction setCacheHas(value) {\n return this.__data__.has(value);\n}\n\nmodule.exports = setCacheHas;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_setCacheHas.js\n ** module id = 117\n ** module chunks = 0\n **/","/**\n * A specialized version of `_.some` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {boolean} Returns `true` if any element passes the predicate check,\n * else `false`.\n */\nfunction arraySome(array, predicate) {\n var index = -1,\n length = array ? array.length : 0;\n\n while (++index < length) {\n if (predicate(array[index], index, array)) {\n return true;\n }\n }\n return false;\n}\n\nmodule.exports = arraySome;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_arraySome.js\n ** module id = 118\n ** module chunks = 0\n **/","/**\n * Checks if a `cache` value for `key` exists.\n *\n * @private\n * @param {Object} cache The cache to query.\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction cacheHas(cache, key) {\n return cache.has(key);\n}\n\nmodule.exports = cacheHas;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_cacheHas.js\n ** module id = 119\n ** module chunks = 0\n **/","var Symbol = require('./_Symbol'),\n Uint8Array = require('./_Uint8Array'),\n eq = require('./eq'),\n equalArrays = require('./_equalArrays'),\n mapToArray = require('./_mapToArray'),\n setToArray = require('./_setToArray');\n\n/** Used to compose bitmasks for comparison styles. */\nvar UNORDERED_COMPARE_FLAG = 1,\n PARTIAL_COMPARE_FLAG = 2;\n\n/** `Object#toString` result references. */\nvar boolTag = '[object Boolean]',\n dateTag = '[object Date]',\n errorTag = '[object Error]',\n mapTag = '[object Map]',\n numberTag = '[object Number]',\n regexpTag = '[object RegExp]',\n setTag = '[object Set]',\n stringTag = '[object String]',\n symbolTag = '[object Symbol]';\n\nvar arrayBufferTag = '[object ArrayBuffer]',\n dataViewTag = '[object DataView]';\n\n/** Used to convert symbols to primitives and strings. */\nvar symbolProto = Symbol ? Symbol.prototype : undefined,\n symbolValueOf = symbolProto ? symbolProto.valueOf : undefined;\n\n/**\n * A specialized version of `baseIsEqualDeep` for comparing objects of\n * the same `toStringTag`.\n *\n * **Note:** This function only supports comparing values with tags of\n * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {string} tag The `toStringTag` of the objects to compare.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Function} customizer The function to customize comparisons.\n * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual`\n * for more details.\n * @param {Object} stack Tracks traversed `object` and `other` objects.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\nfunction equalByTag(object, other, tag, equalFunc, customizer, bitmask, stack) {\n switch (tag) {\n case dataViewTag:\n if ((object.byteLength != other.byteLength) ||\n (object.byteOffset != other.byteOffset)) {\n return false;\n }\n object = object.buffer;\n other = other.buffer;\n\n case arrayBufferTag:\n if ((object.byteLength != other.byteLength) ||\n !equalFunc(new Uint8Array(object), new Uint8Array(other))) {\n return false;\n }\n return true;\n\n case boolTag:\n case dateTag:\n case numberTag:\n // Coerce booleans to `1` or `0` and dates to milliseconds.\n // Invalid dates are coerced to `NaN`.\n return eq(+object, +other);\n\n case errorTag:\n return object.name == other.name && object.message == other.message;\n\n case regexpTag:\n case stringTag:\n // Coerce regexes to strings and treat strings, primitives and objects,\n // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring\n // for more details.\n return object == (other + '');\n\n case mapTag:\n var convert = mapToArray;\n\n case setTag:\n var isPartial = bitmask & PARTIAL_COMPARE_FLAG;\n convert || (convert = setToArray);\n\n if (object.size != other.size && !isPartial) {\n return false;\n }\n // Assume cyclic values are equal.\n var stacked = stack.get(object);\n if (stacked) {\n return stacked == other;\n }\n bitmask |= UNORDERED_COMPARE_FLAG;\n\n // Recursively compare objects (susceptible to call stack limits).\n stack.set(object, other);\n var result = equalArrays(convert(object), convert(other), equalFunc, customizer, bitmask, stack);\n stack['delete'](object);\n return result;\n\n case symbolTag:\n if (symbolValueOf) {\n return symbolValueOf.call(object) == symbolValueOf.call(other);\n }\n }\n return false;\n}\n\nmodule.exports = equalByTag;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_equalByTag.js\n ** module id = 120\n ** module chunks = 0\n **/","var keys = require('./keys');\n\n/** Used to compose bitmasks for comparison styles. */\nvar PARTIAL_COMPARE_FLAG = 2;\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * A specialized version of `baseIsEqualDeep` for objects with support for\n * partial deep comparisons.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Function} customizer The function to customize comparisons.\n * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual`\n * for more details.\n * @param {Object} stack Tracks traversed `object` and `other` objects.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\nfunction equalObjects(object, other, equalFunc, customizer, bitmask, stack) {\n var isPartial = bitmask & PARTIAL_COMPARE_FLAG,\n objProps = keys(object),\n objLength = objProps.length,\n othProps = keys(other),\n othLength = othProps.length;\n\n if (objLength != othLength && !isPartial) {\n return false;\n }\n var index = objLength;\n while (index--) {\n var key = objProps[index];\n if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {\n return false;\n }\n }\n // Assume cyclic values are equal.\n var stacked = stack.get(object);\n if (stacked && stack.get(other)) {\n return stacked == other;\n }\n var result = true;\n stack.set(object, other);\n stack.set(other, object);\n\n var skipCtor = isPartial;\n while (++index < objLength) {\n key = objProps[index];\n var objValue = object[key],\n othValue = other[key];\n\n if (customizer) {\n var compared = isPartial\n ? customizer(othValue, objValue, key, other, object, stack)\n : customizer(objValue, othValue, key, object, other, stack);\n }\n // Recursively compare objects (susceptible to call stack limits).\n if (!(compared === undefined\n ? (objValue === othValue || equalFunc(objValue, othValue, customizer, bitmask, stack))\n : compared\n )) {\n result = false;\n break;\n }\n skipCtor || (skipCtor = key == 'constructor');\n }\n if (result && !skipCtor) {\n var objCtor = object.constructor,\n othCtor = other.constructor;\n\n // Non `Object` object instances with different constructors are not equal.\n if (objCtor != othCtor &&\n ('constructor' in object && 'constructor' in other) &&\n !(typeof objCtor == 'function' && objCtor instanceof objCtor &&\n typeof othCtor == 'function' && othCtor instanceof othCtor)) {\n result = false;\n }\n }\n stack['delete'](object);\n stack['delete'](other);\n return result;\n}\n\nmodule.exports = equalObjects;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/lodash/_equalObjects.js\n ** module id = 121\n ** module chunks = 0\n **/","import { h, Component } from 'preact'\nimport ModeMenu from './ModeMenu'\nimport { toCapital } from '../utils/stringUtils'\n\nexport default class ModeButton extends Component {\n constructor (props) {\n super (props)\n\n this.state = {\n open: false // whether the menu is open or not\n }\n }\n\n /**\n * @param {{modes: string[], mode: string, onChangeMode: function, onError: function}} props\n * @param state\n * @return {*}\n */\n render (props, state) {\n return h('div', {class: 'jsoneditor-modes'}, [\n h('button', {\n title: 'Switch mode',\n onClick: this.handleOpen\n }, `${toCapital(props.mode)} \\u25BC`),\n\n h(ModeMenu, {\n ...props,\n open: state.open,\n onRequestClose: this.handleRequestClose\n })\n ])\n }\n\n handleOpen = () => {\n this.setState({open: true})\n }\n\n handleRequestClose = () => {\n this.setState({open: false})\n }\n}\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/menu/ModeButton.js\n **/","import { h, Component } from 'preact'\nimport { toCapital } from '../utils/stringUtils'\nimport { findParentNode } from '../utils/domUtils'\n\nexport default class ModeMenu extends Component {\n /**\n * @param {{open, modes, mode, onChangeMode, onRequestClose, onError}} props\n * @param {Object} state\n * @return {JSX.Element}\n */\n render (props, state) {\n if (props.open) {\n const items = props.modes.map(mode => {\n return h('button', {\n title: `Switch to ${mode} mode`,\n class: 'jsoneditor-menu-button jsoneditor-type-modes' +\n ((mode === props.mode) ? ' jsoneditor-selected' : ''),\n onClick: () => {\n try {\n props.onChangeMode(mode)\n props.onRequestClose()\n }\n catch (err) {\n props.onError(err)\n }\n }\n }, toCapital(mode))\n })\n\n return h('div', {\n class: 'jsoneditor-actionmenu jsoneditor-modemenu',\n nodemenu: 'true',\n }, items)\n }\n else {\n return null\n }\n }\n\n componentDidMount () {\n this.updateRequestCloseListener()\n }\n\n componentDidUpdate () {\n this.updateRequestCloseListener()\n }\n\n componentWillUnmount () {\n this.removeRequestCloseListener()\n }\n\n updateRequestCloseListener () {\n if (this.props.open) {\n this.addRequestCloseListener()\n }\n else {\n this.removeRequestCloseListener()\n }\n }\n\n addRequestCloseListener () {\n if (!this.handleRequestClose) {\n // Attach event listener on next tick, else the current click to open\n // the menu will immediately result in requestClose event as well\n setTimeout(() => {\n this.handleRequestClose = (event) => {\n if (!findParentNode(event.target, 'data-menu', 'true')) {\n this.props.onRequestClose()\n }\n }\n window.addEventListener('click', this.handleRequestClose)\n }, 0)\n }\n }\n\n removeRequestCloseListener () {\n if (this.handleRequestClose) {\n window.removeEventListener('click', this.handleRequestClose)\n this.handleRequestClose = null\n }\n }\n\n handleRequestClose = null\n}\n\n\n/** WEBPACK FOOTER **\n ** ./src/menu/ModeMenu.js\n **/","import { parseJSON } from './jsonUtils'\n\n/**\n * escape a text, such that it can be displayed safely in an HTML element\n * @param {String} text\n * @param {boolean} [escapeUnicode=false]\n * @return {String} escapedText\n */\nexport function escapeHTML (text, escapeUnicode = false) {\n if (typeof text !== 'string') {\n return String(text)\n }\n else {\n var htmlEscaped = String(text)\n .replace(/ /g, ' \\u00a0') // replace double space with an nbsp and space\n .replace(/^ /, '\\u00a0') // space at start\n .replace(/ $/, '\\u00a0') // space at end\n\n var json = JSON.stringify(htmlEscaped)\n var html = json.substring(1, json.length - 1)\n if (escapeUnicode === true) {\n html = escapeUnicodeChars(html)\n }\n return html\n }\n}\n\n/**\n * Escape unicode characters.\n * For example input '\\u2661' (length 1) will output '\\\\u2661' (length 5).\n * @param {string} text\n * @return {string}\n */\nfunction escapeUnicodeChars (text) {\n // see https://www.wikiwand.com/en/UTF-16\n // note: we leave surrogate pairs as two individual chars,\n // as JSON doesn't interpret them as a single unicode char.\n return text.replace(/[\\u007F-\\uFFFF]/g, function(c) {\n return '\\\\u'+('0000' + c.charCodeAt(0).toString(16)).slice(-4)\n })\n}\n\n/**\n * unescape a string.\n * @param {String} escapedText\n * @return {String} text\n */\nexport function unescapeHTML (escapedText) {\n var json = '\"' + escapeJSON(escapedText) + '\"'\n var htmlEscaped = parseJSON(json)\n\n return htmlEscaped.replace(/\\u00A0/g, ' ') // nbsp character\n}\n\n/**\n * escape a text to make it a valid JSON string. The method will:\n * - replace unescaped double quotes with '\\\"'\n * - replace unescaped backslash with '\\\\'\n * - replace returns with '\\n'\n * @param {String} text\n * @return {String} escapedText\n * @private\n */\nexport function escapeJSON (text) {\n // TODO: replace with some smart regex (only when a new solution is faster!)\n var escaped = ''\n var i = 0\n while (i < text.length) {\n var c = text.charAt(i)\n if (c == '\\n') {\n escaped += '\\\\n'\n }\n else if (c == '\\\\') {\n escaped += c\n i++\n\n c = text.charAt(i)\n if (c === '' || '\"\\\\/bfnrtu'.indexOf(c) == -1) {\n escaped += '\\\\' // no valid escape character\n }\n escaped += c\n }\n else if (c == '\"') {\n escaped += '\\\\\"'\n }\n else {\n escaped += c\n }\n i++\n }\n\n return escaped\n}\n\n/**\n * Find a unique name. Suffix the name with ' (copy)', '(copy 2)', etc\n * until a unique name is found\n * @param {string} name\n * @param {Array.} invalidNames\n */\nexport function findUniqueName (name, invalidNames) {\n let validName = name\n let i = 1\n\n while (invalidNames.includes(validName)) {\n const copy = 'copy' + (i > 1 ? (' ' + i) : '')\n validName = `${name} (${copy})`\n i++\n }\n\n return validName\n}\n\n/**\n * Transform a text into lower case with the first character upper case\n * @param {string} text\n * @return {string}\n */\nexport function toCapital(text) {\n return text[0].toUpperCase() + text.substr(1).toLowerCase()\n}\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/utils/stringUtils.js\n **/","/**\n * Get the inner text of an HTML element (for example a div element)\n * @param {Element} element\n * @param {Object} [buffer]\n * @return {String} innerText\n */\nexport function getInnerText (element, buffer) {\n var first = (buffer == undefined)\n if (first) {\n buffer = {\n 'text': '',\n 'flush': function () {\n var text = this.text\n this.text = ''\n return text\n },\n 'set': function (text) {\n this.text = text\n }\n }\n }\n\n // text node\n if (element.nodeValue) {\n return buffer.flush() + element.nodeValue\n }\n\n // divs or other HTML elements\n if (element.hasChildNodes()) {\n var childNodes = element.childNodes\n var innerText = ''\n\n for (var i = 0, iMax = childNodes.length; i < iMax; i++) {\n var child = childNodes[i]\n\n if (child.nodeName == 'DIV' || child.nodeName == 'P') {\n var prevChild = childNodes[i - 1]\n var prevName = prevChild ? prevChild.nodeName : undefined\n if (prevName && prevName != 'DIV' && prevName != 'P' && prevName != 'BR') {\n innerText += '\\n'\n buffer.flush()\n }\n innerText += getInnerText(child, buffer)\n buffer.set('\\n')\n }\n else if (child.nodeName == 'BR') {\n innerText += buffer.flush()\n buffer.set('\\n')\n }\n else {\n innerText += getInnerText(child, buffer)\n }\n }\n\n return innerText\n }\n else {\n if (element.nodeName == 'P' && getInternetExplorerVersion() != -1) {\n // On Internet Explorer, a

with hasChildNodes()==false is\n // rendered with a new line. Note that a

with\n // hasChildNodes()==true is rendered without a new line\n // Other browsers always ensure there is a
inside the

,\n // and if not, the

does not render a new line\n return buffer.flush()\n }\n }\n\n // br or unknown\n return ''\n}\n\n\n\n/**\n * Find the parent node of an element which has an attribute with given value.\n * Can return the element itself too.\n * @param {Element} elem\n * @param {string} attr\n * @param {string} value\n * @return {Element | null} Returns the parent element when found,\n * or null otherwise\n */\nexport function findParentNode (elem, attr, value) {\n let parent = elem\n\n while (parent && parent.getAttribute) {\n if (parent.getAttribute(attr) == value) {\n return parent\n }\n parent = parent.parentNode\n }\n\n return null\n}\n\n\n/**\n * Returns the version of Internet Explorer or a -1\n * (indicating the use of another browser).\n * Source: http://msdn.microsoft.com/en-us/library/ms537509(v=vs.85).aspx\n * @return {Number} Internet Explorer version, or -1 in case of an other browser\n */\nexport function getInternetExplorerVersion() {\n if (_ieVersion == -1) {\n var rv = -1 // Return value assumes failure.\n if (navigator.appName == 'Microsoft Internet Explorer')\n {\n var ua = navigator.userAgent\n var re = new RegExp(\"MSIE ([0-9]{1,}[\\.0-9]{0,})\")\n if (re.exec(ua) != null) {\n rv = parseFloat( RegExp.$1 )\n }\n }\n\n _ieVersion = rv\n }\n\n return _ieVersion\n}\n\n/**\n * cached internet explorer version\n * @type {Number}\n * @private\n */\nvar _ieVersion = -1\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/utils/domUtils.js\n **/","// load brace\nimport ace from 'brace'\n\n// load required ace plugins\nimport 'brace/mode/json'\nimport 'brace/ext/searchbox'\n\nexport default ace\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/assets/ace/index.js\n **/","/* ***** BEGIN LICENSE BLOCK *****\n * Distributed under the BSD license:\n *\n * Copyright (c) 2010, Ajax.org B.V.\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n * * Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * * Neither the name of Ajax.org B.V. nor the\n * names of its contributors may be used to endorse or promote products\n * derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * ***** END LICENSE BLOCK ***** */\n\n/**\n * Define a module along with a payload\n * @param module a name for the payload\n * @param payload a function to call with (acequire, exports, module) params\n */\n\n(function() {\n\nvar ACE_NAMESPACE = \"ace\";\n\nvar global = (function() { return this; })();\nif (!global && typeof window != \"undefined\") global = window; // strict mode\n\n\nif (!ACE_NAMESPACE && typeof acequirejs !== \"undefined\")\n return;\n\n\nvar define = function(module, deps, payload) {\n if (typeof module !== \"string\") {\n if (define.original)\n define.original.apply(this, arguments);\n else {\n console.error(\"dropping module because define wasn\\'t a string.\");\n console.trace();\n }\n return;\n }\n if (arguments.length == 2)\n payload = deps;\n if (!define.modules[module]) {\n define.payloads[module] = payload;\n define.modules[module] = null;\n }\n};\n\ndefine.modules = {};\ndefine.payloads = {};\n\n/**\n * Get at functionality define()ed using the function above\n */\nvar _acequire = function(parentId, module, callback) {\n if (typeof module === \"string\") {\n var payload = lookup(parentId, module);\n if (payload != undefined) {\n callback && callback();\n return payload;\n }\n } else if (Object.prototype.toString.call(module) === \"[object Array]\") {\n var params = [];\n for (var i = 0, l = module.length; i < l; ++i) {\n var dep = lookup(parentId, module[i]);\n if (dep == undefined && acequire.original)\n return;\n params.push(dep);\n }\n return callback && callback.apply(null, params) || true;\n }\n};\n\nvar acequire = function(module, callback) {\n var packagedModule = _acequire(\"\", module, callback);\n if (packagedModule == undefined && acequire.original)\n return acequire.original.apply(this, arguments);\n return packagedModule;\n};\n\nvar normalizeModule = function(parentId, moduleName) {\n // normalize plugin acequires\n if (moduleName.indexOf(\"!\") !== -1) {\n var chunks = moduleName.split(\"!\");\n return normalizeModule(parentId, chunks[0]) + \"!\" + normalizeModule(parentId, chunks[1]);\n }\n // normalize relative acequires\n if (moduleName.charAt(0) == \".\") {\n var base = parentId.split(\"/\").slice(0, -1).join(\"/\");\n moduleName = base + \"/\" + moduleName;\n\n while(moduleName.indexOf(\".\") !== -1 && previous != moduleName) {\n var previous = moduleName;\n moduleName = moduleName.replace(/\\/\\.\\//, \"/\").replace(/[^\\/]+\\/\\.\\.\\//, \"\");\n }\n }\n return moduleName;\n};\n\n/**\n * Internal function to lookup moduleNames and resolve them by calling the\n * definition function if needed.\n */\nvar lookup = function(parentId, moduleName) {\n moduleName = normalizeModule(parentId, moduleName);\n\n var module = define.modules[moduleName];\n if (!module) {\n module = define.payloads[moduleName];\n if (typeof module === 'function') {\n var exports = {};\n var mod = {\n id: moduleName,\n uri: '',\n exports: exports,\n packaged: true\n };\n\n var req = function(module, callback) {\n return _acequire(moduleName, module, callback);\n };\n\n var returnValue = module(req, exports, mod);\n exports = returnValue || mod.exports;\n define.modules[moduleName] = exports;\n delete define.payloads[moduleName];\n }\n module = define.modules[moduleName] = exports || module;\n }\n return module;\n};\n\nfunction exportAce(ns) {\n var root = global;\n if (ns) {\n if (!global[ns])\n global[ns] = {};\n root = global[ns];\n }\n\n if (!root.define || !root.define.packaged) {\n define.original = root.define;\n root.define = define;\n root.define.packaged = true;\n }\n\n if (!root.acequire || !root.acequire.packaged) {\n acequire.original = root.acequire;\n root.acequire = acequire;\n root.acequire.packaged = true;\n }\n}\n\nexportAce(ACE_NAMESPACE);\n\n})();\n\nace.define(\"ace/lib/regexp\",[\"require\",\"exports\",\"module\"], function(acequire, exports, module) {\n\"use strict\";\n\n var real = {\n exec: RegExp.prototype.exec,\n test: RegExp.prototype.test,\n match: String.prototype.match,\n replace: String.prototype.replace,\n split: String.prototype.split\n },\n compliantExecNpcg = real.exec.call(/()??/, \"\")[1] === undefined, // check `exec` handling of nonparticipating capturing groups\n compliantLastIndexIncrement = function () {\n var x = /^/g;\n real.test.call(x, \"\");\n return !x.lastIndex;\n }();\n\n if (compliantLastIndexIncrement && compliantExecNpcg)\n return;\n RegExp.prototype.exec = function (str) {\n var match = real.exec.apply(this, arguments),\n name, r2;\n if ( typeof(str) == 'string' && match) {\n if (!compliantExecNpcg && match.length > 1 && indexOf(match, \"\") > -1) {\n r2 = RegExp(this.source, real.replace.call(getNativeFlags(this), \"g\", \"\"));\n real.replace.call(str.slice(match.index), r2, function () {\n for (var i = 1; i < arguments.length - 2; i++) {\n if (arguments[i] === undefined)\n match[i] = undefined;\n }\n });\n }\n if (this._xregexp && this._xregexp.captureNames) {\n for (var i = 1; i < match.length; i++) {\n name = this._xregexp.captureNames[i - 1];\n if (name)\n match[name] = match[i];\n }\n }\n if (!compliantLastIndexIncrement && this.global && !match[0].length && (this.lastIndex > match.index))\n this.lastIndex--;\n }\n return match;\n };\n if (!compliantLastIndexIncrement) {\n RegExp.prototype.test = function (str) {\n var match = real.exec.call(this, str);\n if (match && this.global && !match[0].length && (this.lastIndex > match.index))\n this.lastIndex--;\n return !!match;\n };\n }\n\n function getNativeFlags (regex) {\n return (regex.global ? \"g\" : \"\") +\n (regex.ignoreCase ? \"i\" : \"\") +\n (regex.multiline ? \"m\" : \"\") +\n (regex.extended ? \"x\" : \"\") + // Proposed for ES4; included in AS3\n (regex.sticky ? \"y\" : \"\");\n }\n\n function indexOf (array, item, from) {\n if (Array.prototype.indexOf) // Use the native array method if available\n return array.indexOf(item, from);\n for (var i = from || 0; i < array.length; i++) {\n if (array[i] === item)\n return i;\n }\n return -1;\n }\n\n});\n\nace.define(\"ace/lib/es5-shim\",[\"require\",\"exports\",\"module\"], function(acequire, exports, module) {\n\nfunction Empty() {}\n\nif (!Function.prototype.bind) {\n Function.prototype.bind = function bind(that) { // .length is 1\n var target = this;\n if (typeof target != \"function\") {\n throw new TypeError(\"Function.prototype.bind called on incompatible \" + target);\n }\n var args = slice.call(arguments, 1); // for normal call\n var bound = function () {\n\n if (this instanceof bound) {\n\n var result = target.apply(\n this,\n args.concat(slice.call(arguments))\n );\n if (Object(result) === result) {\n return result;\n }\n return this;\n\n } else {\n return target.apply(\n that,\n args.concat(slice.call(arguments))\n );\n\n }\n\n };\n if(target.prototype) {\n Empty.prototype = target.prototype;\n bound.prototype = new Empty();\n Empty.prototype = null;\n }\n return bound;\n };\n}\nvar call = Function.prototype.call;\nvar prototypeOfArray = Array.prototype;\nvar prototypeOfObject = Object.prototype;\nvar slice = prototypeOfArray.slice;\nvar _toString = call.bind(prototypeOfObject.toString);\nvar owns = call.bind(prototypeOfObject.hasOwnProperty);\nvar defineGetter;\nvar defineSetter;\nvar lookupGetter;\nvar lookupSetter;\nvar supportsAccessors;\nif ((supportsAccessors = owns(prototypeOfObject, \"__defineGetter__\"))) {\n defineGetter = call.bind(prototypeOfObject.__defineGetter__);\n defineSetter = call.bind(prototypeOfObject.__defineSetter__);\n lookupGetter = call.bind(prototypeOfObject.__lookupGetter__);\n lookupSetter = call.bind(prototypeOfObject.__lookupSetter__);\n}\nif ([1,2].splice(0).length != 2) {\n if(function() { // test IE < 9 to splice bug - see issue #138\n function makeArray(l) {\n var a = new Array(l+2);\n a[0] = a[1] = 0;\n return a;\n }\n var array = [], lengthBefore;\n \n array.splice.apply(array, makeArray(20));\n array.splice.apply(array, makeArray(26));\n\n lengthBefore = array.length; //46\n array.splice(5, 0, \"XXX\"); // add one element\n\n lengthBefore + 1 == array.length\n\n if (lengthBefore + 1 == array.length) {\n return true;// has right splice implementation without bugs\n }\n }()) {//IE 6/7\n var array_splice = Array.prototype.splice;\n Array.prototype.splice = function(start, deleteCount) {\n if (!arguments.length) {\n return [];\n } else {\n return array_splice.apply(this, [\n start === void 0 ? 0 : start,\n deleteCount === void 0 ? (this.length - start) : deleteCount\n ].concat(slice.call(arguments, 2)))\n }\n };\n } else {//IE8\n Array.prototype.splice = function(pos, removeCount){\n var length = this.length;\n if (pos > 0) {\n if (pos > length)\n pos = length;\n } else if (pos == void 0) {\n pos = 0;\n } else if (pos < 0) {\n pos = Math.max(length + pos, 0);\n }\n\n if (!(pos+removeCount < length))\n removeCount = length - pos;\n\n var removed = this.slice(pos, pos+removeCount);\n var insert = slice.call(arguments, 2);\n var add = insert.length; \n if (pos === length) {\n if (add) {\n this.push.apply(this, insert);\n }\n } else {\n var remove = Math.min(removeCount, length - pos);\n var tailOldPos = pos + remove;\n var tailNewPos = tailOldPos + add - remove;\n var tailCount = length - tailOldPos;\n var lengthAfterRemove = length - remove;\n\n if (tailNewPos < tailOldPos) { // case A\n for (var i = 0; i < tailCount; ++i) {\n this[tailNewPos+i] = this[tailOldPos+i];\n }\n } else if (tailNewPos > tailOldPos) { // case B\n for (i = tailCount; i--; ) {\n this[tailNewPos+i] = this[tailOldPos+i];\n }\n } // else, add == remove (nothing to do)\n\n if (add && pos === lengthAfterRemove) {\n this.length = lengthAfterRemove; // truncate array\n this.push.apply(this, insert);\n } else {\n this.length = lengthAfterRemove + add; // reserves space\n for (i = 0; i < add; ++i) {\n this[pos+i] = insert[i];\n }\n }\n }\n return removed;\n };\n }\n}\nif (!Array.isArray) {\n Array.isArray = function isArray(obj) {\n return _toString(obj) == \"[object Array]\";\n };\n}\nvar boxedString = Object(\"a\"),\n splitString = boxedString[0] != \"a\" || !(0 in boxedString);\n\nif (!Array.prototype.forEach) {\n Array.prototype.forEach = function forEach(fun /*, thisp*/) {\n var object = toObject(this),\n self = splitString && _toString(this) == \"[object String]\" ?\n this.split(\"\") :\n object,\n thisp = arguments[1],\n i = -1,\n length = self.length >>> 0;\n if (_toString(fun) != \"[object Function]\") {\n throw new TypeError(); // TODO message\n }\n\n while (++i < length) {\n if (i in self) {\n fun.call(thisp, self[i], i, object);\n }\n }\n };\n}\nif (!Array.prototype.map) {\n Array.prototype.map = function map(fun /*, thisp*/) {\n var object = toObject(this),\n self = splitString && _toString(this) == \"[object String]\" ?\n this.split(\"\") :\n object,\n length = self.length >>> 0,\n result = Array(length),\n thisp = arguments[1];\n if (_toString(fun) != \"[object Function]\") {\n throw new TypeError(fun + \" is not a function\");\n }\n\n for (var i = 0; i < length; i++) {\n if (i in self)\n result[i] = fun.call(thisp, self[i], i, object);\n }\n return result;\n };\n}\nif (!Array.prototype.filter) {\n Array.prototype.filter = function filter(fun /*, thisp */) {\n var object = toObject(this),\n self = splitString && _toString(this) == \"[object String]\" ?\n this.split(\"\") :\n object,\n length = self.length >>> 0,\n result = [],\n value,\n thisp = arguments[1];\n if (_toString(fun) != \"[object Function]\") {\n throw new TypeError(fun + \" is not a function\");\n }\n\n for (var i = 0; i < length; i++) {\n if (i in self) {\n value = self[i];\n if (fun.call(thisp, value, i, object)) {\n result.push(value);\n }\n }\n }\n return result;\n };\n}\nif (!Array.prototype.every) {\n Array.prototype.every = function every(fun /*, thisp */) {\n var object = toObject(this),\n self = splitString && _toString(this) == \"[object String]\" ?\n this.split(\"\") :\n object,\n length = self.length >>> 0,\n thisp = arguments[1];\n if (_toString(fun) != \"[object Function]\") {\n throw new TypeError(fun + \" is not a function\");\n }\n\n for (var i = 0; i < length; i++) {\n if (i in self && !fun.call(thisp, self[i], i, object)) {\n return false;\n }\n }\n return true;\n };\n}\nif (!Array.prototype.some) {\n Array.prototype.some = function some(fun /*, thisp */) {\n var object = toObject(this),\n self = splitString && _toString(this) == \"[object String]\" ?\n this.split(\"\") :\n object,\n length = self.length >>> 0,\n thisp = arguments[1];\n if (_toString(fun) != \"[object Function]\") {\n throw new TypeError(fun + \" is not a function\");\n }\n\n for (var i = 0; i < length; i++) {\n if (i in self && fun.call(thisp, self[i], i, object)) {\n return true;\n }\n }\n return false;\n };\n}\nif (!Array.prototype.reduce) {\n Array.prototype.reduce = function reduce(fun /*, initial*/) {\n var object = toObject(this),\n self = splitString && _toString(this) == \"[object String]\" ?\n this.split(\"\") :\n object,\n length = self.length >>> 0;\n if (_toString(fun) != \"[object Function]\") {\n throw new TypeError(fun + \" is not a function\");\n }\n if (!length && arguments.length == 1) {\n throw new TypeError(\"reduce of empty array with no initial value\");\n }\n\n var i = 0;\n var result;\n if (arguments.length >= 2) {\n result = arguments[1];\n } else {\n do {\n if (i in self) {\n result = self[i++];\n break;\n }\n if (++i >= length) {\n throw new TypeError(\"reduce of empty array with no initial value\");\n }\n } while (true);\n }\n\n for (; i < length; i++) {\n if (i in self) {\n result = fun.call(void 0, result, self[i], i, object);\n }\n }\n\n return result;\n };\n}\nif (!Array.prototype.reduceRight) {\n Array.prototype.reduceRight = function reduceRight(fun /*, initial*/) {\n var object = toObject(this),\n self = splitString && _toString(this) == \"[object String]\" ?\n this.split(\"\") :\n object,\n length = self.length >>> 0;\n if (_toString(fun) != \"[object Function]\") {\n throw new TypeError(fun + \" is not a function\");\n }\n if (!length && arguments.length == 1) {\n throw new TypeError(\"reduceRight of empty array with no initial value\");\n }\n\n var result, i = length - 1;\n if (arguments.length >= 2) {\n result = arguments[1];\n } else {\n do {\n if (i in self) {\n result = self[i--];\n break;\n }\n if (--i < 0) {\n throw new TypeError(\"reduceRight of empty array with no initial value\");\n }\n } while (true);\n }\n\n do {\n if (i in this) {\n result = fun.call(void 0, result, self[i], i, object);\n }\n } while (i--);\n\n return result;\n };\n}\nif (!Array.prototype.indexOf || ([0, 1].indexOf(1, 2) != -1)) {\n Array.prototype.indexOf = function indexOf(sought /*, fromIndex */ ) {\n var self = splitString && _toString(this) == \"[object String]\" ?\n this.split(\"\") :\n toObject(this),\n length = self.length >>> 0;\n\n if (!length) {\n return -1;\n }\n\n var i = 0;\n if (arguments.length > 1) {\n i = toInteger(arguments[1]);\n }\n i = i >= 0 ? i : Math.max(0, length + i);\n for (; i < length; i++) {\n if (i in self && self[i] === sought) {\n return i;\n }\n }\n return -1;\n };\n}\nif (!Array.prototype.lastIndexOf || ([0, 1].lastIndexOf(0, -3) != -1)) {\n Array.prototype.lastIndexOf = function lastIndexOf(sought /*, fromIndex */) {\n var self = splitString && _toString(this) == \"[object String]\" ?\n this.split(\"\") :\n toObject(this),\n length = self.length >>> 0;\n\n if (!length) {\n return -1;\n }\n var i = length - 1;\n if (arguments.length > 1) {\n i = Math.min(i, toInteger(arguments[1]));\n }\n i = i >= 0 ? i : length - Math.abs(i);\n for (; i >= 0; i--) {\n if (i in self && sought === self[i]) {\n return i;\n }\n }\n return -1;\n };\n}\nif (!Object.getPrototypeOf) {\n Object.getPrototypeOf = function getPrototypeOf(object) {\n return object.__proto__ || (\n object.constructor ?\n object.constructor.prototype :\n prototypeOfObject\n );\n };\n}\nif (!Object.getOwnPropertyDescriptor) {\n var ERR_NON_OBJECT = \"Object.getOwnPropertyDescriptor called on a \" +\n \"non-object: \";\n Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) {\n if ((typeof object != \"object\" && typeof object != \"function\") || object === null)\n throw new TypeError(ERR_NON_OBJECT + object);\n if (!owns(object, property))\n return;\n\n var descriptor, getter, setter;\n descriptor = { enumerable: true, configurable: true };\n if (supportsAccessors) {\n var prototype = object.__proto__;\n object.__proto__ = prototypeOfObject;\n\n var getter = lookupGetter(object, property);\n var setter = lookupSetter(object, property);\n object.__proto__ = prototype;\n\n if (getter || setter) {\n if (getter) descriptor.get = getter;\n if (setter) descriptor.set = setter;\n return descriptor;\n }\n }\n descriptor.value = object[property];\n return descriptor;\n };\n}\nif (!Object.getOwnPropertyNames) {\n Object.getOwnPropertyNames = function getOwnPropertyNames(object) {\n return Object.keys(object);\n };\n}\nif (!Object.create) {\n var createEmpty;\n if (Object.prototype.__proto__ === null) {\n createEmpty = function () {\n return { \"__proto__\": null };\n };\n } else {\n createEmpty = function () {\n var empty = {};\n for (var i in empty)\n empty[i] = null;\n empty.constructor =\n empty.hasOwnProperty =\n empty.propertyIsEnumerable =\n empty.isPrototypeOf =\n empty.toLocaleString =\n empty.toString =\n empty.valueOf =\n empty.__proto__ = null;\n return empty;\n }\n }\n\n Object.create = function create(prototype, properties) {\n var object;\n if (prototype === null) {\n object = createEmpty();\n } else {\n if (typeof prototype != \"object\")\n throw new TypeError(\"typeof prototype[\"+(typeof prototype)+\"] != 'object'\");\n var Type = function () {};\n Type.prototype = prototype;\n object = new Type();\n object.__proto__ = prototype;\n }\n if (properties !== void 0)\n Object.defineProperties(object, properties);\n return object;\n };\n}\n\nfunction doesDefinePropertyWork(object) {\n try {\n Object.defineProperty(object, \"sentinel\", {});\n return \"sentinel\" in object;\n } catch (exception) {\n }\n}\nif (Object.defineProperty) {\n var definePropertyWorksOnObject = doesDefinePropertyWork({});\n var definePropertyWorksOnDom = typeof document == \"undefined\" ||\n doesDefinePropertyWork(document.createElement(\"div\"));\n if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) {\n var definePropertyFallback = Object.defineProperty;\n }\n}\n\nif (!Object.defineProperty || definePropertyFallback) {\n var ERR_NON_OBJECT_DESCRIPTOR = \"Property description must be an object: \";\n var ERR_NON_OBJECT_TARGET = \"Object.defineProperty called on non-object: \"\n var ERR_ACCESSORS_NOT_SUPPORTED = \"getters & setters can not be defined \" +\n \"on this javascript engine\";\n\n Object.defineProperty = function defineProperty(object, property, descriptor) {\n if ((typeof object != \"object\" && typeof object != \"function\") || object === null)\n throw new TypeError(ERR_NON_OBJECT_TARGET + object);\n if ((typeof descriptor != \"object\" && typeof descriptor != \"function\") || descriptor === null)\n throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor);\n if (definePropertyFallback) {\n try {\n return definePropertyFallback.call(Object, object, property, descriptor);\n } catch (exception) {\n }\n }\n if (owns(descriptor, \"value\")) {\n\n if (supportsAccessors && (lookupGetter(object, property) ||\n lookupSetter(object, property)))\n {\n var prototype = object.__proto__;\n object.__proto__ = prototypeOfObject;\n delete object[property];\n object[property] = descriptor.value;\n object.__proto__ = prototype;\n } else {\n object[property] = descriptor.value;\n }\n } else {\n if (!supportsAccessors)\n throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);\n if (owns(descriptor, \"get\"))\n defineGetter(object, property, descriptor.get);\n if (owns(descriptor, \"set\"))\n defineSetter(object, property, descriptor.set);\n }\n\n return object;\n };\n}\nif (!Object.defineProperties) {\n Object.defineProperties = function defineProperties(object, properties) {\n for (var property in properties) {\n if (owns(properties, property))\n Object.defineProperty(object, property, properties[property]);\n }\n return object;\n };\n}\nif (!Object.seal) {\n Object.seal = function seal(object) {\n return object;\n };\n}\nif (!Object.freeze) {\n Object.freeze = function freeze(object) {\n return object;\n };\n}\ntry {\n Object.freeze(function () {});\n} catch (exception) {\n Object.freeze = (function freeze(freezeObject) {\n return function freeze(object) {\n if (typeof object == \"function\") {\n return object;\n } else {\n return freezeObject(object);\n }\n };\n })(Object.freeze);\n}\nif (!Object.preventExtensions) {\n Object.preventExtensions = function preventExtensions(object) {\n return object;\n };\n}\nif (!Object.isSealed) {\n Object.isSealed = function isSealed(object) {\n return false;\n };\n}\nif (!Object.isFrozen) {\n Object.isFrozen = function isFrozen(object) {\n return false;\n };\n}\nif (!Object.isExtensible) {\n Object.isExtensible = function isExtensible(object) {\n if (Object(object) === object) {\n throw new TypeError(); // TODO message\n }\n var name = '';\n while (owns(object, name)) {\n name += '?';\n }\n object[name] = true;\n var returnValue = owns(object, name);\n delete object[name];\n return returnValue;\n };\n}\nif (!Object.keys) {\n var hasDontEnumBug = true,\n dontEnums = [\n \"toString\",\n \"toLocaleString\",\n \"valueOf\",\n \"hasOwnProperty\",\n \"isPrototypeOf\",\n \"propertyIsEnumerable\",\n \"constructor\"\n ],\n dontEnumsLength = dontEnums.length;\n\n for (var key in {\"toString\": null}) {\n hasDontEnumBug = false;\n }\n\n Object.keys = function keys(object) {\n\n if (\n (typeof object != \"object\" && typeof object != \"function\") ||\n object === null\n ) {\n throw new TypeError(\"Object.keys called on a non-object\");\n }\n\n var keys = [];\n for (var name in object) {\n if (owns(object, name)) {\n keys.push(name);\n }\n }\n\n if (hasDontEnumBug) {\n for (var i = 0, ii = dontEnumsLength; i < ii; i++) {\n var dontEnum = dontEnums[i];\n if (owns(object, dontEnum)) {\n keys.push(dontEnum);\n }\n }\n }\n return keys;\n };\n\n}\nif (!Date.now) {\n Date.now = function now() {\n return new Date().getTime();\n };\n}\nvar ws = \"\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\xA0\\u1680\\u180E\\u2000\\u2001\\u2002\\u2003\" +\n \"\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000\\u2028\" +\n \"\\u2029\\uFEFF\";\nif (!String.prototype.trim || ws.trim()) {\n ws = \"[\" + ws + \"]\";\n var trimBeginRegexp = new RegExp(\"^\" + ws + ws + \"*\"),\n trimEndRegexp = new RegExp(ws + ws + \"*$\");\n String.prototype.trim = function trim() {\n return String(this).replace(trimBeginRegexp, \"\").replace(trimEndRegexp, \"\");\n };\n}\n\nfunction toInteger(n) {\n n = +n;\n if (n !== n) { // isNaN\n n = 0;\n } else if (n !== 0 && n !== (1/0) && n !== -(1/0)) {\n n = (n > 0 || -1) * Math.floor(Math.abs(n));\n }\n return n;\n}\n\nfunction isPrimitive(input) {\n var type = typeof input;\n return (\n input === null ||\n type === \"undefined\" ||\n type === \"boolean\" ||\n type === \"number\" ||\n type === \"string\"\n );\n}\n\nfunction toPrimitive(input) {\n var val, valueOf, toString;\n if (isPrimitive(input)) {\n return input;\n }\n valueOf = input.valueOf;\n if (typeof valueOf === \"function\") {\n val = valueOf.call(input);\n if (isPrimitive(val)) {\n return val;\n }\n }\n toString = input.toString;\n if (typeof toString === \"function\") {\n val = toString.call(input);\n if (isPrimitive(val)) {\n return val;\n }\n }\n throw new TypeError();\n}\nvar toObject = function (o) {\n if (o == null) { // this matches both null and undefined\n throw new TypeError(\"can't convert \"+o+\" to object\");\n }\n return Object(o);\n};\n\n});\n\nace.define(\"ace/lib/fixoldbrowsers\",[\"require\",\"exports\",\"module\",\"ace/lib/regexp\",\"ace/lib/es5-shim\"], function(acequire, exports, module) {\n\"use strict\";\n\nacequire(\"./regexp\");\nacequire(\"./es5-shim\");\n\n});\n\nace.define(\"ace/lib/dom\",[\"require\",\"exports\",\"module\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar XHTML_NS = \"http://www.w3.org/1999/xhtml\";\n\nexports.getDocumentHead = function(doc) {\n if (!doc)\n doc = document;\n return doc.head || doc.getElementsByTagName(\"head\")[0] || doc.documentElement;\n};\n\nexports.createElement = function(tag, ns) {\n return document.createElementNS ?\n document.createElementNS(ns || XHTML_NS, tag) :\n document.createElement(tag);\n};\n\nexports.hasCssClass = function(el, name) {\n var classes = (el.className || \"\").split(/\\s+/g);\n return classes.indexOf(name) !== -1;\n};\nexports.addCssClass = function(el, name) {\n if (!exports.hasCssClass(el, name)) {\n el.className += \" \" + name;\n }\n};\nexports.removeCssClass = function(el, name) {\n var classes = el.className.split(/\\s+/g);\n while (true) {\n var index = classes.indexOf(name);\n if (index == -1) {\n break;\n }\n classes.splice(index, 1);\n }\n el.className = classes.join(\" \");\n};\n\nexports.toggleCssClass = function(el, name) {\n var classes = el.className.split(/\\s+/g), add = true;\n while (true) {\n var index = classes.indexOf(name);\n if (index == -1) {\n break;\n }\n add = false;\n classes.splice(index, 1);\n }\n if (add)\n classes.push(name);\n\n el.className = classes.join(\" \");\n return add;\n};\nexports.setCssClass = function(node, className, include) {\n if (include) {\n exports.addCssClass(node, className);\n } else {\n exports.removeCssClass(node, className);\n }\n};\n\nexports.hasCssString = function(id, doc) {\n var index = 0, sheets;\n doc = doc || document;\n\n if (doc.createStyleSheet && (sheets = doc.styleSheets)) {\n while (index < sheets.length)\n if (sheets[index++].owningElement.id === id) return true;\n } else if ((sheets = doc.getElementsByTagName(\"style\"))) {\n while (index < sheets.length)\n if (sheets[index++].id === id) return true;\n }\n\n return false;\n};\n\nexports.importCssString = function importCssString(cssText, id, doc) {\n doc = doc || document;\n if (id && exports.hasCssString(id, doc))\n return null;\n \n var style;\n \n if (id)\n cssText += \"\\n/*# sourceURL=ace/css/\" + id + \" */\";\n \n if (doc.createStyleSheet) {\n style = doc.createStyleSheet();\n style.cssText = cssText;\n if (id)\n style.owningElement.id = id;\n } else {\n style = exports.createElement(\"style\");\n style.appendChild(doc.createTextNode(cssText));\n if (id)\n style.id = id;\n\n exports.getDocumentHead(doc).appendChild(style);\n }\n};\n\nexports.importCssStylsheet = function(uri, doc) {\n if (doc.createStyleSheet) {\n doc.createStyleSheet(uri);\n } else {\n var link = exports.createElement('link');\n link.rel = 'stylesheet';\n link.href = uri;\n\n exports.getDocumentHead(doc).appendChild(link);\n }\n};\n\nexports.getInnerWidth = function(element) {\n return (\n parseInt(exports.computedStyle(element, \"paddingLeft\"), 10) +\n parseInt(exports.computedStyle(element, \"paddingRight\"), 10) + \n element.clientWidth\n );\n};\n\nexports.getInnerHeight = function(element) {\n return (\n parseInt(exports.computedStyle(element, \"paddingTop\"), 10) +\n parseInt(exports.computedStyle(element, \"paddingBottom\"), 10) +\n element.clientHeight\n );\n};\n\nexports.scrollbarWidth = function(document) {\n var inner = exports.createElement(\"ace_inner\");\n inner.style.width = \"100%\";\n inner.style.minWidth = \"0px\";\n inner.style.height = \"200px\";\n inner.style.display = \"block\";\n\n var outer = exports.createElement(\"ace_outer\");\n var style = outer.style;\n\n style.position = \"absolute\";\n style.left = \"-10000px\";\n style.overflow = \"hidden\";\n style.width = \"200px\";\n style.minWidth = \"0px\";\n style.height = \"150px\";\n style.display = \"block\";\n\n outer.appendChild(inner);\n\n var body = document.documentElement;\n body.appendChild(outer);\n\n var noScrollbar = inner.offsetWidth;\n\n style.overflow = \"scroll\";\n var withScrollbar = inner.offsetWidth;\n\n if (noScrollbar == withScrollbar) {\n withScrollbar = outer.clientWidth;\n }\n\n body.removeChild(outer);\n\n return noScrollbar-withScrollbar;\n};\n\nif (typeof document == \"undefined\") {\n exports.importCssString = function() {};\n return;\n}\n\nif (window.pageYOffset !== undefined) {\n exports.getPageScrollTop = function() {\n return window.pageYOffset;\n };\n\n exports.getPageScrollLeft = function() {\n return window.pageXOffset;\n };\n}\nelse {\n exports.getPageScrollTop = function() {\n return document.body.scrollTop;\n };\n\n exports.getPageScrollLeft = function() {\n return document.body.scrollLeft;\n };\n}\n\nif (window.getComputedStyle)\n exports.computedStyle = function(element, style) {\n if (style)\n return (window.getComputedStyle(element, \"\") || {})[style] || \"\";\n return window.getComputedStyle(element, \"\") || {};\n };\nelse\n exports.computedStyle = function(element, style) {\n if (style)\n return element.currentStyle[style];\n return element.currentStyle;\n };\nexports.setInnerHtml = function(el, innerHtml) {\n var element = el.cloneNode(false);//document.createElement(\"div\");\n element.innerHTML = innerHtml;\n el.parentNode.replaceChild(element, el);\n return element;\n};\n\nif (\"textContent\" in document.documentElement) {\n exports.setInnerText = function(el, innerText) {\n el.textContent = innerText;\n };\n\n exports.getInnerText = function(el) {\n return el.textContent;\n };\n}\nelse {\n exports.setInnerText = function(el, innerText) {\n el.innerText = innerText;\n };\n\n exports.getInnerText = function(el) {\n return el.innerText;\n };\n}\n\nexports.getParentWindow = function(document) {\n return document.defaultView || document.parentWindow;\n};\n\n});\n\nace.define(\"ace/lib/oop\",[\"require\",\"exports\",\"module\"], function(acequire, exports, module) {\n\"use strict\";\n\nexports.inherits = function(ctor, superCtor) {\n ctor.super_ = superCtor;\n ctor.prototype = Object.create(superCtor.prototype, {\n constructor: {\n value: ctor,\n enumerable: false,\n writable: true,\n configurable: true\n }\n });\n};\n\nexports.mixin = function(obj, mixin) {\n for (var key in mixin) {\n obj[key] = mixin[key];\n }\n return obj;\n};\n\nexports.implement = function(proto, mixin) {\n exports.mixin(proto, mixin);\n};\n\n});\n\nace.define(\"ace/lib/keys\",[\"require\",\"exports\",\"module\",\"ace/lib/fixoldbrowsers\",\"ace/lib/oop\"], function(acequire, exports, module) {\n\"use strict\";\n\nacequire(\"./fixoldbrowsers\");\n\nvar oop = acequire(\"./oop\");\nvar Keys = (function() {\n var ret = {\n MODIFIER_KEYS: {\n 16: 'Shift', 17: 'Ctrl', 18: 'Alt', 224: 'Meta'\n },\n\n KEY_MODS: {\n \"ctrl\": 1, \"alt\": 2, \"option\" : 2, \"shift\": 4,\n \"super\": 8, \"meta\": 8, \"command\": 8, \"cmd\": 8\n },\n\n FUNCTION_KEYS : {\n 8 : \"Backspace\",\n 9 : \"Tab\",\n 13 : \"Return\",\n 19 : \"Pause\",\n 27 : \"Esc\",\n 32 : \"Space\",\n 33 : \"PageUp\",\n 34 : \"PageDown\",\n 35 : \"End\",\n 36 : \"Home\",\n 37 : \"Left\",\n 38 : \"Up\",\n 39 : \"Right\",\n 40 : \"Down\",\n 44 : \"Print\",\n 45 : \"Insert\",\n 46 : \"Delete\",\n 96 : \"Numpad0\",\n 97 : \"Numpad1\",\n 98 : \"Numpad2\",\n 99 : \"Numpad3\",\n 100: \"Numpad4\",\n 101: \"Numpad5\",\n 102: \"Numpad6\",\n 103: \"Numpad7\",\n 104: \"Numpad8\",\n 105: \"Numpad9\",\n '-13': \"NumpadEnter\",\n 112: \"F1\",\n 113: \"F2\",\n 114: \"F3\",\n 115: \"F4\",\n 116: \"F5\",\n 117: \"F6\",\n 118: \"F7\",\n 119: \"F8\",\n 120: \"F9\",\n 121: \"F10\",\n 122: \"F11\",\n 123: \"F12\",\n 144: \"Numlock\",\n 145: \"Scrolllock\"\n },\n\n PRINTABLE_KEYS: {\n 32: ' ', 48: '0', 49: '1', 50: '2', 51: '3', 52: '4', 53: '5',\n 54: '6', 55: '7', 56: '8', 57: '9', 59: ';', 61: '=', 65: 'a',\n 66: 'b', 67: 'c', 68: 'd', 69: 'e', 70: 'f', 71: 'g', 72: 'h',\n 73: 'i', 74: 'j', 75: 'k', 76: 'l', 77: 'm', 78: 'n', 79: 'o',\n 80: 'p', 81: 'q', 82: 'r', 83: 's', 84: 't', 85: 'u', 86: 'v',\n 87: 'w', 88: 'x', 89: 'y', 90: 'z', 107: '+', 109: '-', 110: '.',\n 186: ';', 187: '=', 188: ',', 189: '-', 190: '.', 191: '/', 192: '`',\n 219: '[', 220: '\\\\',221: ']', 222: \"'\", 111: '/', 106: '*'\n }\n };\n var name, i;\n for (i in ret.FUNCTION_KEYS) {\n name = ret.FUNCTION_KEYS[i].toLowerCase();\n ret[name] = parseInt(i, 10);\n }\n for (i in ret.PRINTABLE_KEYS) {\n name = ret.PRINTABLE_KEYS[i].toLowerCase();\n ret[name] = parseInt(i, 10);\n }\n oop.mixin(ret, ret.MODIFIER_KEYS);\n oop.mixin(ret, ret.PRINTABLE_KEYS);\n oop.mixin(ret, ret.FUNCTION_KEYS);\n ret.enter = ret[\"return\"];\n ret.escape = ret.esc;\n ret.del = ret[\"delete\"];\n ret[173] = '-';\n \n (function() {\n var mods = [\"cmd\", \"ctrl\", \"alt\", \"shift\"];\n for (var i = Math.pow(2, mods.length); i--;) { \n ret.KEY_MODS[i] = mods.filter(function(x) {\n return i & ret.KEY_MODS[x];\n }).join(\"-\") + \"-\";\n }\n })();\n\n ret.KEY_MODS[0] = \"\";\n ret.KEY_MODS[-1] = \"input-\";\n\n return ret;\n})();\noop.mixin(exports, Keys);\n\nexports.keyCodeToString = function(keyCode) {\n var keyString = Keys[keyCode];\n if (typeof keyString != \"string\")\n keyString = String.fromCharCode(keyCode);\n return keyString.toLowerCase();\n};\n\n});\n\nace.define(\"ace/lib/useragent\",[\"require\",\"exports\",\"module\"], function(acequire, exports, module) {\n\"use strict\";\nexports.OS = {\n LINUX: \"LINUX\",\n MAC: \"MAC\",\n WINDOWS: \"WINDOWS\"\n};\nexports.getOS = function() {\n if (exports.isMac) {\n return exports.OS.MAC;\n } else if (exports.isLinux) {\n return exports.OS.LINUX;\n } else {\n return exports.OS.WINDOWS;\n }\n};\nif (typeof navigator != \"object\")\n return;\n\nvar os = (navigator.platform.match(/mac|win|linux/i) || [\"other\"])[0].toLowerCase();\nvar ua = navigator.userAgent;\nexports.isWin = (os == \"win\");\nexports.isMac = (os == \"mac\");\nexports.isLinux = (os == \"linux\");\nexports.isIE = \n (navigator.appName == \"Microsoft Internet Explorer\" || navigator.appName.indexOf(\"MSAppHost\") >= 0)\n ? parseFloat((ua.match(/(?:MSIE |Trident\\/[0-9]+[\\.0-9]+;.*rv:)([0-9]+[\\.0-9]+)/)||[])[1])\n : parseFloat((ua.match(/(?:Trident\\/[0-9]+[\\.0-9]+;.*rv:)([0-9]+[\\.0-9]+)/)||[])[1]); // for ie\n \nexports.isOldIE = exports.isIE && exports.isIE < 9;\nexports.isGecko = exports.isMozilla = (window.Controllers || window.controllers) && window.navigator.product === \"Gecko\";\nexports.isOldGecko = exports.isGecko && parseInt((ua.match(/rv\\:(\\d+)/)||[])[1], 10) < 4;\nexports.isOpera = window.opera && Object.prototype.toString.call(window.opera) == \"[object Opera]\";\nexports.isWebKit = parseFloat(ua.split(\"WebKit/\")[1]) || undefined;\n\nexports.isChrome = parseFloat(ua.split(\" Chrome/\")[1]) || undefined;\n\nexports.isAIR = ua.indexOf(\"AdobeAIR\") >= 0;\n\nexports.isIPad = ua.indexOf(\"iPad\") >= 0;\n\nexports.isTouchPad = ua.indexOf(\"TouchPad\") >= 0;\n\nexports.isChromeOS = ua.indexOf(\" CrOS \") >= 0;\n\n});\n\nace.define(\"ace/lib/event\",[\"require\",\"exports\",\"module\",\"ace/lib/keys\",\"ace/lib/useragent\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar keys = acequire(\"./keys\");\nvar useragent = acequire(\"./useragent\");\n\nvar pressedKeys = null;\nvar ts = 0;\n\nexports.addListener = function(elem, type, callback) {\n if (elem.addEventListener) {\n return elem.addEventListener(type, callback, false);\n }\n if (elem.attachEvent) {\n var wrapper = function() {\n callback.call(elem, window.event);\n };\n callback._wrapper = wrapper;\n elem.attachEvent(\"on\" + type, wrapper);\n }\n};\n\nexports.removeListener = function(elem, type, callback) {\n if (elem.removeEventListener) {\n return elem.removeEventListener(type, callback, false);\n }\n if (elem.detachEvent) {\n elem.detachEvent(\"on\" + type, callback._wrapper || callback);\n }\n};\nexports.stopEvent = function(e) {\n exports.stopPropagation(e);\n exports.preventDefault(e);\n return false;\n};\n\nexports.stopPropagation = function(e) {\n if (e.stopPropagation)\n e.stopPropagation();\n else\n e.cancelBubble = true;\n};\n\nexports.preventDefault = function(e) {\n if (e.preventDefault)\n e.preventDefault();\n else\n e.returnValue = false;\n};\nexports.getButton = function(e) {\n if (e.type == \"dblclick\")\n return 0;\n if (e.type == \"contextmenu\" || (useragent.isMac && (e.ctrlKey && !e.altKey && !e.shiftKey)))\n return 2;\n if (e.preventDefault) {\n return e.button;\n }\n else {\n return {1:0, 2:2, 4:1}[e.button];\n }\n};\n\nexports.capture = function(el, eventHandler, releaseCaptureHandler) {\n function onMouseUp(e) {\n eventHandler && eventHandler(e);\n releaseCaptureHandler && releaseCaptureHandler(e);\n\n exports.removeListener(document, \"mousemove\", eventHandler, true);\n exports.removeListener(document, \"mouseup\", onMouseUp, true);\n exports.removeListener(document, \"dragstart\", onMouseUp, true);\n }\n\n exports.addListener(document, \"mousemove\", eventHandler, true);\n exports.addListener(document, \"mouseup\", onMouseUp, true);\n exports.addListener(document, \"dragstart\", onMouseUp, true);\n \n return onMouseUp;\n};\n\nexports.addTouchMoveListener = function (el, callback) {\n if (\"ontouchmove\" in el) {\n var startx, starty;\n exports.addListener(el, \"touchstart\", function (e) {\n var touchObj = e.changedTouches[0];\n startx = touchObj.clientX;\n starty = touchObj.clientY;\n });\n exports.addListener(el, \"touchmove\", function (e) {\n var factor = 1,\n touchObj = e.changedTouches[0];\n\n e.wheelX = -(touchObj.clientX - startx) / factor;\n e.wheelY = -(touchObj.clientY - starty) / factor;\n\n startx = touchObj.clientX;\n starty = touchObj.clientY;\n\n callback(e);\n });\n } \n};\n\nexports.addMouseWheelListener = function(el, callback) {\n if (\"onmousewheel\" in el) {\n exports.addListener(el, \"mousewheel\", function(e) {\n var factor = 8;\n if (e.wheelDeltaX !== undefined) {\n e.wheelX = -e.wheelDeltaX / factor;\n e.wheelY = -e.wheelDeltaY / factor;\n } else {\n e.wheelX = 0;\n e.wheelY = -e.wheelDelta / factor;\n }\n callback(e);\n });\n } else if (\"onwheel\" in el) {\n exports.addListener(el, \"wheel\", function(e) {\n var factor = 0.35;\n switch (e.deltaMode) {\n case e.DOM_DELTA_PIXEL:\n e.wheelX = e.deltaX * factor || 0;\n e.wheelY = e.deltaY * factor || 0;\n break;\n case e.DOM_DELTA_LINE:\n case e.DOM_DELTA_PAGE:\n e.wheelX = (e.deltaX || 0) * 5;\n e.wheelY = (e.deltaY || 0) * 5;\n break;\n }\n \n callback(e);\n });\n } else {\n exports.addListener(el, \"DOMMouseScroll\", function(e) {\n if (e.axis && e.axis == e.HORIZONTAL_AXIS) {\n e.wheelX = (e.detail || 0) * 5;\n e.wheelY = 0;\n } else {\n e.wheelX = 0;\n e.wheelY = (e.detail || 0) * 5;\n }\n callback(e);\n });\n }\n};\n\nexports.addMultiMouseDownListener = function(elements, timeouts, eventHandler, callbackName) {\n var clicks = 0;\n var startX, startY, timer; \n var eventNames = {\n 2: \"dblclick\",\n 3: \"tripleclick\",\n 4: \"quadclick\"\n };\n\n function onMousedown(e) {\n if (exports.getButton(e) !== 0) {\n clicks = 0;\n } else if (e.detail > 1) {\n clicks++;\n if (clicks > 4)\n clicks = 1;\n } else {\n clicks = 1;\n }\n if (useragent.isIE) {\n var isNewClick = Math.abs(e.clientX - startX) > 5 || Math.abs(e.clientY - startY) > 5;\n if (!timer || isNewClick)\n clicks = 1;\n if (timer)\n clearTimeout(timer);\n timer = setTimeout(function() {timer = null}, timeouts[clicks - 1] || 600);\n\n if (clicks == 1) {\n startX = e.clientX;\n startY = e.clientY;\n }\n }\n \n e._clicks = clicks;\n\n eventHandler[callbackName](\"mousedown\", e);\n\n if (clicks > 4)\n clicks = 0;\n else if (clicks > 1)\n return eventHandler[callbackName](eventNames[clicks], e);\n }\n function onDblclick(e) {\n clicks = 2;\n if (timer)\n clearTimeout(timer);\n timer = setTimeout(function() {timer = null}, timeouts[clicks - 1] || 600);\n eventHandler[callbackName](\"mousedown\", e);\n eventHandler[callbackName](eventNames[clicks], e);\n }\n if (!Array.isArray(elements))\n elements = [elements];\n elements.forEach(function(el) {\n exports.addListener(el, \"mousedown\", onMousedown);\n if (useragent.isOldIE)\n exports.addListener(el, \"dblclick\", onDblclick);\n });\n};\n\nvar getModifierHash = useragent.isMac && useragent.isOpera && !(\"KeyboardEvent\" in window)\n ? function(e) {\n return 0 | (e.metaKey ? 1 : 0) | (e.altKey ? 2 : 0) | (e.shiftKey ? 4 : 0) | (e.ctrlKey ? 8 : 0);\n }\n : function(e) {\n return 0 | (e.ctrlKey ? 1 : 0) | (e.altKey ? 2 : 0) | (e.shiftKey ? 4 : 0) | (e.metaKey ? 8 : 0);\n };\n\nexports.getModifierString = function(e) {\n return keys.KEY_MODS[getModifierHash(e)];\n};\n\nfunction normalizeCommandKeys(callback, e, keyCode) {\n var hashId = getModifierHash(e);\n\n if (!useragent.isMac && pressedKeys) {\n if (pressedKeys.OSKey)\n hashId |= 8;\n if (pressedKeys.altGr) {\n if ((3 & hashId) != 3)\n pressedKeys.altGr = 0;\n else\n return;\n }\n if (keyCode === 18 || keyCode === 17) {\n var location = \"location\" in e ? e.location : e.keyLocation;\n if (keyCode === 17 && location === 1) {\n if (pressedKeys[keyCode] == 1)\n ts = e.timeStamp;\n } else if (keyCode === 18 && hashId === 3 && location === 2) {\n var dt = e.timeStamp - ts;\n if (dt < 50)\n pressedKeys.altGr = true;\n }\n }\n }\n \n if (keyCode in keys.MODIFIER_KEYS) {\n keyCode = -1;\n }\n if (hashId & 8 && (keyCode >= 91 && keyCode <= 93)) {\n keyCode = -1;\n }\n \n if (!hashId && keyCode === 13) {\n var location = \"location\" in e ? e.location : e.keyLocation;\n if (location === 3) {\n callback(e, hashId, -keyCode);\n if (e.defaultPrevented)\n return;\n }\n }\n \n if (useragent.isChromeOS && hashId & 8) {\n callback(e, hashId, keyCode);\n if (e.defaultPrevented)\n return;\n else\n hashId &= ~8;\n }\n if (!hashId && !(keyCode in keys.FUNCTION_KEYS) && !(keyCode in keys.PRINTABLE_KEYS)) {\n return false;\n }\n \n return callback(e, hashId, keyCode);\n}\n\n\nexports.addCommandKeyListener = function(el, callback) {\n var addListener = exports.addListener;\n if (useragent.isOldGecko || (useragent.isOpera && !(\"KeyboardEvent\" in window))) {\n var lastKeyDownKeyCode = null;\n addListener(el, \"keydown\", function(e) {\n lastKeyDownKeyCode = e.keyCode;\n });\n addListener(el, \"keypress\", function(e) {\n return normalizeCommandKeys(callback, e, lastKeyDownKeyCode);\n });\n } else {\n var lastDefaultPrevented = null;\n\n addListener(el, \"keydown\", function(e) {\n var keyCode = e.keyCode;\n pressedKeys[keyCode] = (pressedKeys[keyCode] || 0) + 1;\n if (keyCode == 91 || keyCode == 92) {\n pressedKeys.OSKey = true;\n } else if (pressedKeys.OSKey) {\n if (e.timeStamp - pressedKeys.lastT > 200 && pressedKeys.count == 1)\n resetPressedKeys();\n }\n if (pressedKeys[keyCode] == 1)\n pressedKeys.count++;\n pressedKeys.lastT = e.timeStamp;\n var result = normalizeCommandKeys(callback, e, keyCode);\n lastDefaultPrevented = e.defaultPrevented;\n return result;\n });\n\n addListener(el, \"keypress\", function(e) {\n if (lastDefaultPrevented && (e.ctrlKey || e.altKey || e.shiftKey || e.metaKey)) {\n exports.stopEvent(e);\n lastDefaultPrevented = null;\n }\n });\n\n addListener(el, \"keyup\", function(e) {\n var keyCode = e.keyCode;\n if (!pressedKeys[keyCode]) {\n resetPressedKeys();\n } else {\n pressedKeys.count = Math.max(pressedKeys.count - 1, 0);\n }\n if (keyCode == 91 || keyCode == 92) {\n pressedKeys.OSKey = false;\n }\n pressedKeys[keyCode] = null;\n });\n\n if (!pressedKeys) {\n resetPressedKeys();\n addListener(window, \"focus\", resetPressedKeys);\n }\n }\n};\nfunction resetPressedKeys() {\n pressedKeys = Object.create(null);\n pressedKeys.count = 0;\n pressedKeys.lastT = 0;\n}\n\nif (typeof window == \"object\" && window.postMessage && !useragent.isOldIE) {\n var postMessageId = 1;\n exports.nextTick = function(callback, win) {\n win = win || window;\n var messageName = \"zero-timeout-message-\" + postMessageId;\n exports.addListener(win, \"message\", function listener(e) {\n if (e.data == messageName) {\n exports.stopPropagation(e);\n exports.removeListener(win, \"message\", listener);\n callback();\n }\n });\n win.postMessage(messageName, \"*\");\n };\n}\n\n\nexports.nextFrame = typeof window == \"object\" && (window.requestAnimationFrame\n || window.mozRequestAnimationFrame\n || window.webkitRequestAnimationFrame\n || window.msRequestAnimationFrame\n || window.oRequestAnimationFrame);\n\nif (exports.nextFrame)\n exports.nextFrame = exports.nextFrame.bind(window);\nelse\n exports.nextFrame = function(callback) {\n setTimeout(callback, 17);\n };\n});\n\nace.define(\"ace/lib/lang\",[\"require\",\"exports\",\"module\"], function(acequire, exports, module) {\n\"use strict\";\n\nexports.last = function(a) {\n return a[a.length - 1];\n};\n\nexports.stringReverse = function(string) {\n return string.split(\"\").reverse().join(\"\");\n};\n\nexports.stringRepeat = function (string, count) {\n var result = '';\n while (count > 0) {\n if (count & 1)\n result += string;\n\n if (count >>= 1)\n string += string;\n }\n return result;\n};\n\nvar trimBeginRegexp = /^\\s\\s*/;\nvar trimEndRegexp = /\\s\\s*$/;\n\nexports.stringTrimLeft = function (string) {\n return string.replace(trimBeginRegexp, '');\n};\n\nexports.stringTrimRight = function (string) {\n return string.replace(trimEndRegexp, '');\n};\n\nexports.copyObject = function(obj) {\n var copy = {};\n for (var key in obj) {\n copy[key] = obj[key];\n }\n return copy;\n};\n\nexports.copyArray = function(array){\n var copy = [];\n for (var i=0, l=array.length; i 1);\n return ev.preventDefault();\n };\n\n this.startSelect = function(pos, waitForClickSelection) {\n pos = pos || this.editor.renderer.screenToTextCoordinates(this.x, this.y);\n var editor = this.editor;\n editor.$blockScrolling++;\n if (this.mousedownEvent.getShiftKey())\n editor.selection.selectToPosition(pos);\n else if (!waitForClickSelection)\n editor.selection.moveToPosition(pos);\n if (!waitForClickSelection)\n this.select();\n if (editor.renderer.scroller.setCapture) {\n editor.renderer.scroller.setCapture();\n }\n editor.setStyle(\"ace_selecting\");\n this.setState(\"select\");\n editor.$blockScrolling--;\n };\n\n this.select = function() {\n var anchor, editor = this.editor;\n var cursor = editor.renderer.screenToTextCoordinates(this.x, this.y);\n editor.$blockScrolling++;\n if (this.$clickSelection) {\n var cmp = this.$clickSelection.comparePoint(cursor);\n\n if (cmp == -1) {\n anchor = this.$clickSelection.end;\n } else if (cmp == 1) {\n anchor = this.$clickSelection.start;\n } else {\n var orientedRange = calcRangeOrientation(this.$clickSelection, cursor);\n cursor = orientedRange.cursor;\n anchor = orientedRange.anchor;\n }\n editor.selection.setSelectionAnchor(anchor.row, anchor.column);\n }\n editor.selection.selectToPosition(cursor);\n editor.$blockScrolling--;\n editor.renderer.scrollCursorIntoView();\n };\n\n this.extendSelectionBy = function(unitName) {\n var anchor, editor = this.editor;\n var cursor = editor.renderer.screenToTextCoordinates(this.x, this.y);\n var range = editor.selection[unitName](cursor.row, cursor.column);\n editor.$blockScrolling++;\n if (this.$clickSelection) {\n var cmpStart = this.$clickSelection.comparePoint(range.start);\n var cmpEnd = this.$clickSelection.comparePoint(range.end);\n\n if (cmpStart == -1 && cmpEnd <= 0) {\n anchor = this.$clickSelection.end;\n if (range.end.row != cursor.row || range.end.column != cursor.column)\n cursor = range.start;\n } else if (cmpEnd == 1 && cmpStart >= 0) {\n anchor = this.$clickSelection.start;\n if (range.start.row != cursor.row || range.start.column != cursor.column)\n cursor = range.end;\n } else if (cmpStart == -1 && cmpEnd == 1) {\n cursor = range.end;\n anchor = range.start;\n } else {\n var orientedRange = calcRangeOrientation(this.$clickSelection, cursor);\n cursor = orientedRange.cursor;\n anchor = orientedRange.anchor;\n }\n editor.selection.setSelectionAnchor(anchor.row, anchor.column);\n }\n editor.selection.selectToPosition(cursor);\n editor.$blockScrolling--;\n editor.renderer.scrollCursorIntoView();\n };\n\n this.selectEnd =\n this.selectAllEnd =\n this.selectByWordsEnd =\n this.selectByLinesEnd = function() {\n this.$clickSelection = null;\n this.editor.unsetStyle(\"ace_selecting\");\n if (this.editor.renderer.scroller.releaseCapture) {\n this.editor.renderer.scroller.releaseCapture();\n }\n };\n\n this.focusWait = function() {\n var distance = calcDistance(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y);\n var time = Date.now();\n\n if (distance > DRAG_OFFSET || time - this.mousedownEvent.time > this.$focusTimout)\n this.startSelect(this.mousedownEvent.getDocumentPosition());\n };\n\n this.onDoubleClick = function(ev) {\n var pos = ev.getDocumentPosition();\n var editor = this.editor;\n var session = editor.session;\n\n var range = session.getBracketRange(pos);\n if (range) {\n if (range.isEmpty()) {\n range.start.column--;\n range.end.column++;\n }\n this.setState(\"select\");\n } else {\n range = editor.selection.getWordRange(pos.row, pos.column);\n this.setState(\"selectByWords\");\n }\n this.$clickSelection = range;\n this.select();\n };\n\n this.onTripleClick = function(ev) {\n var pos = ev.getDocumentPosition();\n var editor = this.editor;\n\n this.setState(\"selectByLines\");\n var range = editor.getSelectionRange();\n if (range.isMultiLine() && range.contains(pos.row, pos.column)) {\n this.$clickSelection = editor.selection.getLineRange(range.start.row);\n this.$clickSelection.end = editor.selection.getLineRange(range.end.row).end;\n } else {\n this.$clickSelection = editor.selection.getLineRange(pos.row);\n }\n this.select();\n };\n\n this.onQuadClick = function(ev) {\n var editor = this.editor;\n\n editor.selectAll();\n this.$clickSelection = editor.getSelectionRange();\n this.setState(\"selectAll\");\n };\n\n this.onMouseWheel = function(ev) {\n if (ev.getAccelKey())\n return;\n if (ev.getShiftKey() && ev.wheelY && !ev.wheelX) {\n ev.wheelX = ev.wheelY;\n ev.wheelY = 0;\n }\n\n var t = ev.domEvent.timeStamp;\n var dt = t - (this.$lastScrollTime||0);\n \n var editor = this.editor;\n var isScrolable = editor.renderer.isScrollableBy(ev.wheelX * ev.speed, ev.wheelY * ev.speed);\n if (isScrolable || dt < 200) {\n this.$lastScrollTime = t;\n editor.renderer.scrollBy(ev.wheelX * ev.speed, ev.wheelY * ev.speed);\n return ev.stop();\n }\n };\n \n this.onTouchMove = function (ev) {\n var t = ev.domEvent.timeStamp;\n var dt = t - (this.$lastScrollTime || 0);\n\n var editor = this.editor;\n var isScrolable = editor.renderer.isScrollableBy(ev.wheelX * ev.speed, ev.wheelY * ev.speed);\n if (isScrolable || dt < 200) {\n this.$lastScrollTime = t;\n editor.renderer.scrollBy(ev.wheelX * ev.speed, ev.wheelY * ev.speed);\n return ev.stop();\n }\n };\n\n}).call(DefaultHandlers.prototype);\n\nexports.DefaultHandlers = DefaultHandlers;\n\nfunction calcDistance(ax, ay, bx, by) {\n return Math.sqrt(Math.pow(bx - ax, 2) + Math.pow(by - ay, 2));\n}\n\nfunction calcRangeOrientation(range, cursor) {\n if (range.start.row == range.end.row)\n var cmp = 2 * cursor.column - range.start.column - range.end.column;\n else if (range.start.row == range.end.row - 1 && !range.start.column && !range.end.column)\n var cmp = cursor.column - 4;\n else\n var cmp = 2 * cursor.row - range.start.row - range.end.row;\n\n if (cmp < 0)\n return {cursor: range.start, anchor: range.end};\n else\n return {cursor: range.end, anchor: range.start};\n}\n\n});\n\nace.define(\"ace/tooltip\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/dom\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar oop = acequire(\"./lib/oop\");\nvar dom = acequire(\"./lib/dom\");\nfunction Tooltip (parentNode) {\n this.isOpen = false;\n this.$element = null;\n this.$parentNode = parentNode;\n}\n\n(function() {\n this.$init = function() {\n this.$element = dom.createElement(\"div\");\n this.$element.className = \"ace_tooltip\";\n this.$element.style.display = \"none\";\n this.$parentNode.appendChild(this.$element);\n return this.$element;\n };\n this.getElement = function() {\n return this.$element || this.$init();\n };\n this.setText = function(text) {\n dom.setInnerText(this.getElement(), text);\n };\n this.setHtml = function(html) {\n this.getElement().innerHTML = html;\n };\n this.setPosition = function(x, y) {\n this.getElement().style.left = x + \"px\";\n this.getElement().style.top = y + \"px\";\n };\n this.setClassName = function(className) {\n dom.addCssClass(this.getElement(), className);\n };\n this.show = function(text, x, y) {\n if (text != null)\n this.setText(text);\n if (x != null && y != null)\n this.setPosition(x, y);\n if (!this.isOpen) {\n this.getElement().style.display = \"block\";\n this.isOpen = true;\n }\n };\n\n this.hide = function() {\n if (this.isOpen) {\n this.getElement().style.display = \"none\";\n this.isOpen = false;\n }\n };\n this.getHeight = function() {\n return this.getElement().offsetHeight;\n };\n this.getWidth = function() {\n return this.getElement().offsetWidth;\n };\n\n}).call(Tooltip.prototype);\n\nexports.Tooltip = Tooltip;\n});\n\nace.define(\"ace/mouse/default_gutter_handler\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\",\"ace/lib/oop\",\"ace/lib/event\",\"ace/tooltip\"], function(acequire, exports, module) {\n\"use strict\";\nvar dom = acequire(\"../lib/dom\");\nvar oop = acequire(\"../lib/oop\");\nvar event = acequire(\"../lib/event\");\nvar Tooltip = acequire(\"../tooltip\").Tooltip;\n\nfunction GutterHandler(mouseHandler) {\n var editor = mouseHandler.editor;\n var gutter = editor.renderer.$gutterLayer;\n var tooltip = new GutterTooltip(editor.container);\n\n mouseHandler.editor.setDefaultHandler(\"guttermousedown\", function(e) {\n if (!editor.isFocused() || e.getButton() != 0)\n return;\n var gutterRegion = gutter.getRegion(e);\n\n if (gutterRegion == \"foldWidgets\")\n return;\n\n var row = e.getDocumentPosition().row;\n var selection = editor.session.selection;\n\n if (e.getShiftKey())\n selection.selectTo(row, 0);\n else {\n if (e.domEvent.detail == 2) {\n editor.selectAll();\n return e.preventDefault();\n }\n mouseHandler.$clickSelection = editor.selection.getLineRange(row);\n }\n mouseHandler.setState(\"selectByLines\");\n mouseHandler.captureMouse(e);\n return e.preventDefault();\n });\n\n\n var tooltipTimeout, mouseEvent, tooltipAnnotation;\n\n function showTooltip() {\n var row = mouseEvent.getDocumentPosition().row;\n var annotation = gutter.$annotations[row];\n if (!annotation)\n return hideTooltip();\n\n var maxRow = editor.session.getLength();\n if (row == maxRow) {\n var screenRow = editor.renderer.pixelToScreenCoordinates(0, mouseEvent.y).row;\n var pos = mouseEvent.$pos;\n if (screenRow > editor.session.documentToScreenRow(pos.row, pos.column))\n return hideTooltip();\n }\n\n if (tooltipAnnotation == annotation)\n return;\n tooltipAnnotation = annotation.text.join(\"
\");\n\n tooltip.setHtml(tooltipAnnotation);\n tooltip.show();\n editor.on(\"mousewheel\", hideTooltip);\n\n if (mouseHandler.$tooltipFollowsMouse) {\n moveTooltip(mouseEvent);\n } else {\n var gutterElement = mouseEvent.domEvent.target;\n var rect = gutterElement.getBoundingClientRect();\n var style = tooltip.getElement().style;\n style.left = rect.right + \"px\";\n style.top = rect.bottom + \"px\";\n }\n }\n\n function hideTooltip() {\n if (tooltipTimeout)\n tooltipTimeout = clearTimeout(tooltipTimeout);\n if (tooltipAnnotation) {\n tooltip.hide();\n tooltipAnnotation = null;\n editor.removeEventListener(\"mousewheel\", hideTooltip);\n }\n }\n\n function moveTooltip(e) {\n tooltip.setPosition(e.x, e.y);\n }\n\n mouseHandler.editor.setDefaultHandler(\"guttermousemove\", function(e) {\n var target = e.domEvent.target || e.domEvent.srcElement;\n if (dom.hasCssClass(target, \"ace_fold-widget\"))\n return hideTooltip();\n\n if (tooltipAnnotation && mouseHandler.$tooltipFollowsMouse)\n moveTooltip(e);\n\n mouseEvent = e;\n if (tooltipTimeout)\n return;\n tooltipTimeout = setTimeout(function() {\n tooltipTimeout = null;\n if (mouseEvent && !mouseHandler.isMousePressed)\n showTooltip();\n else\n hideTooltip();\n }, 50);\n });\n\n event.addListener(editor.renderer.$gutter, \"mouseout\", function(e) {\n mouseEvent = null;\n if (!tooltipAnnotation || tooltipTimeout)\n return;\n\n tooltipTimeout = setTimeout(function() {\n tooltipTimeout = null;\n hideTooltip();\n }, 50);\n });\n \n editor.on(\"changeSession\", hideTooltip);\n}\n\nfunction GutterTooltip(parentNode) {\n Tooltip.call(this, parentNode);\n}\n\noop.inherits(GutterTooltip, Tooltip);\n\n(function(){\n this.setPosition = function(x, y) {\n var windowWidth = window.innerWidth || document.documentElement.clientWidth;\n var windowHeight = window.innerHeight || document.documentElement.clientHeight;\n var width = this.getWidth();\n var height = this.getHeight();\n x += 15;\n y += 15;\n if (x + width > windowWidth) {\n x -= (x + width) - windowWidth;\n }\n if (y + height > windowHeight) {\n y -= 20 + height;\n }\n Tooltip.prototype.setPosition.call(this, x, y);\n };\n\n}).call(GutterTooltip.prototype);\n\n\n\nexports.GutterHandler = GutterHandler;\n\n});\n\nace.define(\"ace/mouse/mouse_event\",[\"require\",\"exports\",\"module\",\"ace/lib/event\",\"ace/lib/useragent\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar event = acequire(\"../lib/event\");\nvar useragent = acequire(\"../lib/useragent\");\nvar MouseEvent = exports.MouseEvent = function(domEvent, editor) {\n this.domEvent = domEvent;\n this.editor = editor;\n \n this.x = this.clientX = domEvent.clientX;\n this.y = this.clientY = domEvent.clientY;\n\n this.$pos = null;\n this.$inSelection = null;\n \n this.propagationStopped = false;\n this.defaultPrevented = false;\n};\n\n(function() { \n \n this.stopPropagation = function() {\n event.stopPropagation(this.domEvent);\n this.propagationStopped = true;\n };\n \n this.preventDefault = function() {\n event.preventDefault(this.domEvent);\n this.defaultPrevented = true;\n };\n \n this.stop = function() {\n this.stopPropagation();\n this.preventDefault();\n };\n this.getDocumentPosition = function() {\n if (this.$pos)\n return this.$pos;\n \n this.$pos = this.editor.renderer.screenToTextCoordinates(this.clientX, this.clientY);\n return this.$pos;\n };\n this.inSelection = function() {\n if (this.$inSelection !== null)\n return this.$inSelection;\n \n var editor = this.editor;\n \n\n var selectionRange = editor.getSelectionRange();\n if (selectionRange.isEmpty())\n this.$inSelection = false;\n else {\n var pos = this.getDocumentPosition();\n this.$inSelection = selectionRange.contains(pos.row, pos.column);\n }\n\n return this.$inSelection;\n };\n this.getButton = function() {\n return event.getButton(this.domEvent);\n };\n this.getShiftKey = function() {\n return this.domEvent.shiftKey;\n };\n \n this.getAccelKey = useragent.isMac\n ? function() { return this.domEvent.metaKey; }\n : function() { return this.domEvent.ctrlKey; };\n \n}).call(MouseEvent.prototype);\n\n});\n\nace.define(\"ace/mouse/dragdrop_handler\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\",\"ace/lib/event\",\"ace/lib/useragent\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar dom = acequire(\"../lib/dom\");\nvar event = acequire(\"../lib/event\");\nvar useragent = acequire(\"../lib/useragent\");\n\nvar AUTOSCROLL_DELAY = 200;\nvar SCROLL_CURSOR_DELAY = 200;\nvar SCROLL_CURSOR_HYSTERESIS = 5;\n\nfunction DragdropHandler(mouseHandler) {\n\n var editor = mouseHandler.editor;\n\n var blankImage = dom.createElement(\"img\");\n blankImage.src = \"data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\";\n if (useragent.isOpera)\n blankImage.style.cssText = \"width:1px;height:1px;position:fixed;top:0;left:0;z-index:2147483647;opacity:0;\";\n\n var exports = [\"dragWait\", \"dragWaitEnd\", \"startDrag\", \"dragReadyEnd\", \"onMouseDrag\"];\n\n exports.forEach(function(x) {\n mouseHandler[x] = this[x];\n }, this);\n editor.addEventListener(\"mousedown\", this.onMouseDown.bind(mouseHandler));\n\n\n var mouseTarget = editor.container;\n var dragSelectionMarker, x, y;\n var timerId, range;\n var dragCursor, counter = 0;\n var dragOperation;\n var isInternal;\n var autoScrollStartTime;\n var cursorMovedTime;\n var cursorPointOnCaretMoved;\n\n this.onDragStart = function(e) {\n if (this.cancelDrag || !mouseTarget.draggable) {\n var self = this;\n setTimeout(function(){\n self.startSelect();\n self.captureMouse(e);\n }, 0);\n return e.preventDefault();\n }\n range = editor.getSelectionRange();\n\n var dataTransfer = e.dataTransfer;\n dataTransfer.effectAllowed = editor.getReadOnly() ? \"copy\" : \"copyMove\";\n if (useragent.isOpera) {\n editor.container.appendChild(blankImage);\n blankImage.scrollTop = 0;\n }\n dataTransfer.setDragImage && dataTransfer.setDragImage(blankImage, 0, 0);\n if (useragent.isOpera) {\n editor.container.removeChild(blankImage);\n }\n dataTransfer.clearData();\n dataTransfer.setData(\"Text\", editor.session.getTextRange());\n\n isInternal = true;\n this.setState(\"drag\");\n };\n\n this.onDragEnd = function(e) {\n mouseTarget.draggable = false;\n isInternal = false;\n this.setState(null);\n if (!editor.getReadOnly()) {\n var dropEffect = e.dataTransfer.dropEffect;\n if (!dragOperation && dropEffect == \"move\")\n editor.session.remove(editor.getSelectionRange());\n editor.renderer.$cursorLayer.setBlinking(true);\n }\n this.editor.unsetStyle(\"ace_dragging\");\n this.editor.renderer.setCursorStyle(\"\");\n };\n\n this.onDragEnter = function(e) {\n if (editor.getReadOnly() || !canAccept(e.dataTransfer))\n return;\n x = e.clientX;\n y = e.clientY;\n if (!dragSelectionMarker)\n addDragMarker();\n counter++;\n e.dataTransfer.dropEffect = dragOperation = getDropEffect(e);\n return event.preventDefault(e);\n };\n\n this.onDragOver = function(e) {\n if (editor.getReadOnly() || !canAccept(e.dataTransfer))\n return;\n x = e.clientX;\n y = e.clientY;\n if (!dragSelectionMarker) {\n addDragMarker();\n counter++;\n }\n if (onMouseMoveTimer !== null)\n onMouseMoveTimer = null;\n\n e.dataTransfer.dropEffect = dragOperation = getDropEffect(e);\n return event.preventDefault(e);\n };\n\n this.onDragLeave = function(e) {\n counter--;\n if (counter <= 0 && dragSelectionMarker) {\n clearDragMarker();\n dragOperation = null;\n return event.preventDefault(e);\n }\n };\n\n this.onDrop = function(e) {\n if (!dragCursor)\n return;\n var dataTransfer = e.dataTransfer;\n if (isInternal) {\n switch (dragOperation) {\n case \"move\":\n if (range.contains(dragCursor.row, dragCursor.column)) {\n range = {\n start: dragCursor,\n end: dragCursor\n };\n } else {\n range = editor.moveText(range, dragCursor);\n }\n break;\n case \"copy\":\n range = editor.moveText(range, dragCursor, true);\n break;\n }\n } else {\n var dropData = dataTransfer.getData('Text');\n range = {\n start: dragCursor,\n end: editor.session.insert(dragCursor, dropData)\n };\n editor.focus();\n dragOperation = null;\n }\n clearDragMarker();\n return event.preventDefault(e);\n };\n\n event.addListener(mouseTarget, \"dragstart\", this.onDragStart.bind(mouseHandler));\n event.addListener(mouseTarget, \"dragend\", this.onDragEnd.bind(mouseHandler));\n event.addListener(mouseTarget, \"dragenter\", this.onDragEnter.bind(mouseHandler));\n event.addListener(mouseTarget, \"dragover\", this.onDragOver.bind(mouseHandler));\n event.addListener(mouseTarget, \"dragleave\", this.onDragLeave.bind(mouseHandler));\n event.addListener(mouseTarget, \"drop\", this.onDrop.bind(mouseHandler));\n\n function scrollCursorIntoView(cursor, prevCursor) {\n var now = Date.now();\n var vMovement = !prevCursor || cursor.row != prevCursor.row;\n var hMovement = !prevCursor || cursor.column != prevCursor.column;\n if (!cursorMovedTime || vMovement || hMovement) {\n editor.$blockScrolling += 1;\n editor.moveCursorToPosition(cursor);\n editor.$blockScrolling -= 1;\n cursorMovedTime = now;\n cursorPointOnCaretMoved = {x: x, y: y};\n } else {\n var distance = calcDistance(cursorPointOnCaretMoved.x, cursorPointOnCaretMoved.y, x, y);\n if (distance > SCROLL_CURSOR_HYSTERESIS) {\n cursorMovedTime = null;\n } else if (now - cursorMovedTime >= SCROLL_CURSOR_DELAY) {\n editor.renderer.scrollCursorIntoView();\n cursorMovedTime = null;\n }\n }\n }\n\n function autoScroll(cursor, prevCursor) {\n var now = Date.now();\n var lineHeight = editor.renderer.layerConfig.lineHeight;\n var characterWidth = editor.renderer.layerConfig.characterWidth;\n var editorRect = editor.renderer.scroller.getBoundingClientRect();\n var offsets = {\n x: {\n left: x - editorRect.left,\n right: editorRect.right - x\n },\n y: {\n top: y - editorRect.top,\n bottom: editorRect.bottom - y\n }\n };\n var nearestXOffset = Math.min(offsets.x.left, offsets.x.right);\n var nearestYOffset = Math.min(offsets.y.top, offsets.y.bottom);\n var scrollCursor = {row: cursor.row, column: cursor.column};\n if (nearestXOffset / characterWidth <= 2) {\n scrollCursor.column += (offsets.x.left < offsets.x.right ? -3 : +2);\n }\n if (nearestYOffset / lineHeight <= 1) {\n scrollCursor.row += (offsets.y.top < offsets.y.bottom ? -1 : +1);\n }\n var vScroll = cursor.row != scrollCursor.row;\n var hScroll = cursor.column != scrollCursor.column;\n var vMovement = !prevCursor || cursor.row != prevCursor.row;\n if (vScroll || (hScroll && !vMovement)) {\n if (!autoScrollStartTime)\n autoScrollStartTime = now;\n else if (now - autoScrollStartTime >= AUTOSCROLL_DELAY)\n editor.renderer.scrollCursorIntoView(scrollCursor);\n } else {\n autoScrollStartTime = null;\n }\n }\n\n function onDragInterval() {\n var prevCursor = dragCursor;\n dragCursor = editor.renderer.screenToTextCoordinates(x, y);\n scrollCursorIntoView(dragCursor, prevCursor);\n autoScroll(dragCursor, prevCursor);\n }\n\n function addDragMarker() {\n range = editor.selection.toOrientedRange();\n dragSelectionMarker = editor.session.addMarker(range, \"ace_selection\", editor.getSelectionStyle());\n editor.clearSelection();\n if (editor.isFocused())\n editor.renderer.$cursorLayer.setBlinking(false);\n clearInterval(timerId);\n onDragInterval();\n timerId = setInterval(onDragInterval, 20);\n counter = 0;\n event.addListener(document, \"mousemove\", onMouseMove);\n }\n\n function clearDragMarker() {\n clearInterval(timerId);\n editor.session.removeMarker(dragSelectionMarker);\n dragSelectionMarker = null;\n editor.$blockScrolling += 1;\n editor.selection.fromOrientedRange(range);\n editor.$blockScrolling -= 1;\n if (editor.isFocused() && !isInternal)\n editor.renderer.$cursorLayer.setBlinking(!editor.getReadOnly());\n range = null;\n dragCursor = null;\n counter = 0;\n autoScrollStartTime = null;\n cursorMovedTime = null;\n event.removeListener(document, \"mousemove\", onMouseMove);\n }\n var onMouseMoveTimer = null;\n function onMouseMove() {\n if (onMouseMoveTimer == null) {\n onMouseMoveTimer = setTimeout(function() {\n if (onMouseMoveTimer != null && dragSelectionMarker)\n clearDragMarker();\n }, 20);\n }\n }\n\n function canAccept(dataTransfer) {\n var types = dataTransfer.types;\n return !types || Array.prototype.some.call(types, function(type) {\n return type == 'text/plain' || type == 'Text';\n });\n }\n\n function getDropEffect(e) {\n var copyAllowed = ['copy', 'copymove', 'all', 'uninitialized'];\n var moveAllowed = ['move', 'copymove', 'linkmove', 'all', 'uninitialized'];\n\n var copyModifierState = useragent.isMac ? e.altKey : e.ctrlKey;\n var effectAllowed = \"uninitialized\";\n try {\n effectAllowed = e.dataTransfer.effectAllowed.toLowerCase();\n } catch (e) {}\n var dropEffect = \"none\";\n\n if (copyModifierState && copyAllowed.indexOf(effectAllowed) >= 0)\n dropEffect = \"copy\";\n else if (moveAllowed.indexOf(effectAllowed) >= 0)\n dropEffect = \"move\";\n else if (copyAllowed.indexOf(effectAllowed) >= 0)\n dropEffect = \"copy\";\n\n return dropEffect;\n }\n}\n\n(function() {\n\n this.dragWait = function() {\n var interval = Date.now() - this.mousedownEvent.time;\n if (interval > this.editor.getDragDelay())\n this.startDrag();\n };\n\n this.dragWaitEnd = function() {\n var target = this.editor.container;\n target.draggable = false;\n this.startSelect(this.mousedownEvent.getDocumentPosition());\n this.selectEnd();\n };\n\n this.dragReadyEnd = function(e) {\n this.editor.renderer.$cursorLayer.setBlinking(!this.editor.getReadOnly());\n this.editor.unsetStyle(\"ace_dragging\");\n this.editor.renderer.setCursorStyle(\"\");\n this.dragWaitEnd();\n };\n\n this.startDrag = function(){\n this.cancelDrag = false;\n var editor = this.editor;\n var target = editor.container;\n target.draggable = true;\n editor.renderer.$cursorLayer.setBlinking(false);\n editor.setStyle(\"ace_dragging\");\n var cursorStyle = useragent.isWin ? \"default\" : \"move\";\n editor.renderer.setCursorStyle(cursorStyle);\n this.setState(\"dragReady\");\n };\n\n this.onMouseDrag = function(e) {\n var target = this.editor.container;\n if (useragent.isIE && this.state == \"dragReady\") {\n var distance = calcDistance(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y);\n if (distance > 3)\n target.dragDrop();\n }\n if (this.state === \"dragWait\") {\n var distance = calcDistance(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y);\n if (distance > 0) {\n target.draggable = false;\n this.startSelect(this.mousedownEvent.getDocumentPosition());\n }\n }\n };\n\n this.onMouseDown = function(e) {\n if (!this.$dragEnabled)\n return;\n this.mousedownEvent = e;\n var editor = this.editor;\n\n var inSelection = e.inSelection();\n var button = e.getButton();\n var clickCount = e.domEvent.detail || 1;\n if (clickCount === 1 && button === 0 && inSelection) {\n if (e.editor.inMultiSelectMode && (e.getAccelKey() || e.getShiftKey()))\n return;\n this.mousedownEvent.time = Date.now();\n var eventTarget = e.domEvent.target || e.domEvent.srcElement;\n if (\"unselectable\" in eventTarget)\n eventTarget.unselectable = \"on\";\n if (editor.getDragDelay()) {\n if (useragent.isWebKit) {\n this.cancelDrag = true;\n var mouseTarget = editor.container;\n mouseTarget.draggable = true;\n }\n this.setState(\"dragWait\");\n } else {\n this.startDrag();\n }\n this.captureMouse(e, this.onMouseDrag.bind(this));\n e.defaultPrevented = true;\n }\n };\n\n}).call(DragdropHandler.prototype);\n\n\nfunction calcDistance(ax, ay, bx, by) {\n return Math.sqrt(Math.pow(bx - ax, 2) + Math.pow(by - ay, 2));\n}\n\nexports.DragdropHandler = DragdropHandler;\n\n});\n\nace.define(\"ace/lib/net\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\"], function(acequire, exports, module) {\n\"use strict\";\nvar dom = acequire(\"./dom\");\n\nexports.get = function (url, callback) {\n var xhr = new XMLHttpRequest();\n xhr.open('GET', url, true);\n xhr.onreadystatechange = function () {\n if (xhr.readyState === 4) {\n callback(xhr.responseText);\n }\n };\n xhr.send(null);\n};\n\nexports.loadScript = function(path, callback) {\n var head = dom.getDocumentHead();\n var s = document.createElement('script');\n\n s.src = path;\n head.appendChild(s);\n\n s.onload = s.onreadystatechange = function(_, isAbort) {\n if (isAbort || !s.readyState || s.readyState == \"loaded\" || s.readyState == \"complete\") {\n s = s.onload = s.onreadystatechange = null;\n if (!isAbort)\n callback();\n }\n };\n};\nexports.qualifyURL = function(url) {\n var a = document.createElement('a');\n a.href = url;\n return a.href;\n}\n\n});\n\nace.define(\"ace/lib/event_emitter\",[\"require\",\"exports\",\"module\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar EventEmitter = {};\nvar stopPropagation = function() { this.propagationStopped = true; };\nvar preventDefault = function() { this.defaultPrevented = true; };\n\nEventEmitter._emit =\nEventEmitter._dispatchEvent = function(eventName, e) {\n this._eventRegistry || (this._eventRegistry = {});\n this._defaultHandlers || (this._defaultHandlers = {});\n\n var listeners = this._eventRegistry[eventName] || [];\n var defaultHandler = this._defaultHandlers[eventName];\n if (!listeners.length && !defaultHandler)\n return;\n\n if (typeof e != \"object\" || !e)\n e = {};\n\n if (!e.type)\n e.type = eventName;\n if (!e.stopPropagation)\n e.stopPropagation = stopPropagation;\n if (!e.preventDefault)\n e.preventDefault = preventDefault;\n\n listeners = listeners.slice();\n for (var i=0; i 1)\n base = parts[parts.length - 2];\n var path = options[component + \"Path\"];\n if (path == null) {\n path = options.basePath;\n } else if (sep == \"/\") {\n component = sep = \"\";\n }\n if (path && path.slice(-1) != \"/\")\n path += \"/\";\n return path + component + sep + base + this.get(\"suffix\");\n};\n\nexports.setModuleUrl = function(name, subst) {\n return options.$moduleUrls[name] = subst;\n};\n\nexports.$loading = {};\nexports.loadModule = function(moduleName, onLoad) {\n var module, moduleType;\n if (Array.isArray(moduleName)) {\n moduleType = moduleName[0];\n moduleName = moduleName[1];\n }\n\n try {\n module = acequire(moduleName);\n } catch (e) {}\n if (module && !exports.$loading[moduleName])\n return onLoad && onLoad(module);\n\n if (!exports.$loading[moduleName])\n exports.$loading[moduleName] = [];\n\n exports.$loading[moduleName].push(onLoad);\n\n if (exports.$loading[moduleName].length > 1)\n return;\n\n var afterLoad = function() {\n acequire([moduleName], function(module) {\n exports._emit(\"load.module\", {name: moduleName, module: module});\n var listeners = exports.$loading[moduleName];\n exports.$loading[moduleName] = null;\n listeners.forEach(function(onLoad) {\n onLoad && onLoad(module);\n });\n });\n };\n\n if (!exports.get(\"packaged\"))\n return afterLoad();\n net.loadScript(exports.moduleUrl(moduleName, moduleType), afterLoad);\n};\ninit(true);function init(packaged) {\n\n if (!global || !global.document)\n return;\n \n options.packaged = packaged || acequire.packaged || module.packaged || (global.define && define.packaged);\n\n var scriptOptions = {};\n var scriptUrl = \"\";\n var currentScript = (document.currentScript || document._currentScript ); // native or polyfill\n var currentDocument = currentScript && currentScript.ownerDocument || document;\n \n var scripts = currentDocument.getElementsByTagName(\"script\");\n for (var i=0; i [\" + this.end.row + \"/\" + this.end.column + \"]\");\n };\n\n this.contains = function(row, column) {\n return this.compare(row, column) == 0;\n };\n this.compareRange = function(range) {\n var cmp,\n end = range.end,\n start = range.start;\n\n cmp = this.compare(end.row, end.column);\n if (cmp == 1) {\n cmp = this.compare(start.row, start.column);\n if (cmp == 1) {\n return 2;\n } else if (cmp == 0) {\n return 1;\n } else {\n return 0;\n }\n } else if (cmp == -1) {\n return -2;\n } else {\n cmp = this.compare(start.row, start.column);\n if (cmp == -1) {\n return -1;\n } else if (cmp == 1) {\n return 42;\n } else {\n return 0;\n }\n }\n };\n this.comparePoint = function(p) {\n return this.compare(p.row, p.column);\n };\n this.containsRange = function(range) {\n return this.comparePoint(range.start) == 0 && this.comparePoint(range.end) == 0;\n };\n this.intersects = function(range) {\n var cmp = this.compareRange(range);\n return (cmp == -1 || cmp == 0 || cmp == 1);\n };\n this.isEnd = function(row, column) {\n return this.end.row == row && this.end.column == column;\n };\n this.isStart = function(row, column) {\n return this.start.row == row && this.start.column == column;\n };\n this.setStart = function(row, column) {\n if (typeof row == \"object\") {\n this.start.column = row.column;\n this.start.row = row.row;\n } else {\n this.start.row = row;\n this.start.column = column;\n }\n };\n this.setEnd = function(row, column) {\n if (typeof row == \"object\") {\n this.end.column = row.column;\n this.end.row = row.row;\n } else {\n this.end.row = row;\n this.end.column = column;\n }\n };\n this.inside = function(row, column) {\n if (this.compare(row, column) == 0) {\n if (this.isEnd(row, column) || this.isStart(row, column)) {\n return false;\n } else {\n return true;\n }\n }\n return false;\n };\n this.insideStart = function(row, column) {\n if (this.compare(row, column) == 0) {\n if (this.isEnd(row, column)) {\n return false;\n } else {\n return true;\n }\n }\n return false;\n };\n this.insideEnd = function(row, column) {\n if (this.compare(row, column) == 0) {\n if (this.isStart(row, column)) {\n return false;\n } else {\n return true;\n }\n }\n return false;\n };\n this.compare = function(row, column) {\n if (!this.isMultiLine()) {\n if (row === this.start.row) {\n return column < this.start.column ? -1 : (column > this.end.column ? 1 : 0);\n }\n }\n\n if (row < this.start.row)\n return -1;\n\n if (row > this.end.row)\n return 1;\n\n if (this.start.row === row)\n return column >= this.start.column ? 0 : -1;\n\n if (this.end.row === row)\n return column <= this.end.column ? 0 : 1;\n\n return 0;\n };\n this.compareStart = function(row, column) {\n if (this.start.row == row && this.start.column == column) {\n return -1;\n } else {\n return this.compare(row, column);\n }\n };\n this.compareEnd = function(row, column) {\n if (this.end.row == row && this.end.column == column) {\n return 1;\n } else {\n return this.compare(row, column);\n }\n };\n this.compareInside = function(row, column) {\n if (this.end.row == row && this.end.column == column) {\n return 1;\n } else if (this.start.row == row && this.start.column == column) {\n return -1;\n } else {\n return this.compare(row, column);\n }\n };\n this.clipRows = function(firstRow, lastRow) {\n if (this.end.row > lastRow)\n var end = {row: lastRow + 1, column: 0};\n else if (this.end.row < firstRow)\n var end = {row: firstRow, column: 0};\n\n if (this.start.row > lastRow)\n var start = {row: lastRow + 1, column: 0};\n else if (this.start.row < firstRow)\n var start = {row: firstRow, column: 0};\n\n return Range.fromPoints(start || this.start, end || this.end);\n };\n this.extend = function(row, column) {\n var cmp = this.compare(row, column);\n\n if (cmp == 0)\n return this;\n else if (cmp == -1)\n var start = {row: row, column: column};\n else\n var end = {row: row, column: column};\n\n return Range.fromPoints(start || this.start, end || this.end);\n };\n\n this.isEmpty = function() {\n return (this.start.row === this.end.row && this.start.column === this.end.column);\n };\n this.isMultiLine = function() {\n return (this.start.row !== this.end.row);\n };\n this.clone = function() {\n return Range.fromPoints(this.start, this.end);\n };\n this.collapseRows = function() {\n if (this.end.column == 0)\n return new Range(this.start.row, 0, Math.max(this.start.row, this.end.row-1), 0)\n else\n return new Range(this.start.row, 0, this.end.row, 0)\n };\n this.toScreenRange = function(session) {\n var screenPosStart = session.documentToScreenPosition(this.start);\n var screenPosEnd = session.documentToScreenPosition(this.end);\n\n return new Range(\n screenPosStart.row, screenPosStart.column,\n screenPosEnd.row, screenPosEnd.column\n );\n };\n this.moveBy = function(row, column) {\n this.start.row += row;\n this.start.column += column;\n this.end.row += row;\n this.end.column += column;\n };\n\n}).call(Range.prototype);\nRange.fromPoints = function(start, end) {\n return new Range(start.row, start.column, end.row, end.column);\n};\nRange.comparePoints = comparePoints;\n\nRange.comparePoints = function(p1, p2) {\n return p1.row - p2.row || p1.column - p2.column;\n};\n\n\nexports.Range = Range;\n});\n\nace.define(\"ace/selection\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/lang\",\"ace/lib/event_emitter\",\"ace/range\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar oop = acequire(\"./lib/oop\");\nvar lang = acequire(\"./lib/lang\");\nvar EventEmitter = acequire(\"./lib/event_emitter\").EventEmitter;\nvar Range = acequire(\"./range\").Range;\nvar Selection = function(session) {\n this.session = session;\n this.doc = session.getDocument();\n\n this.clearSelection();\n this.lead = this.selectionLead = this.doc.createAnchor(0, 0);\n this.anchor = this.selectionAnchor = this.doc.createAnchor(0, 0);\n\n var self = this;\n this.lead.on(\"change\", function(e) {\n self._emit(\"changeCursor\");\n if (!self.$isEmpty)\n self._emit(\"changeSelection\");\n if (!self.$keepDesiredColumnOnChange && e.old.column != e.value.column)\n self.$desiredColumn = null;\n });\n\n this.selectionAnchor.on(\"change\", function() {\n if (!self.$isEmpty)\n self._emit(\"changeSelection\");\n });\n};\n\n(function() {\n\n oop.implement(this, EventEmitter);\n this.isEmpty = function() {\n return (this.$isEmpty || (\n this.anchor.row == this.lead.row &&\n this.anchor.column == this.lead.column\n ));\n };\n this.isMultiLine = function() {\n if (this.isEmpty()) {\n return false;\n }\n\n return this.getRange().isMultiLine();\n };\n this.getCursor = function() {\n return this.lead.getPosition();\n };\n this.setSelectionAnchor = function(row, column) {\n this.anchor.setPosition(row, column);\n\n if (this.$isEmpty) {\n this.$isEmpty = false;\n this._emit(\"changeSelection\");\n }\n };\n this.getSelectionAnchor = function() {\n if (this.$isEmpty)\n return this.getSelectionLead();\n else\n return this.anchor.getPosition();\n };\n this.getSelectionLead = function() {\n return this.lead.getPosition();\n };\n this.shiftSelection = function(columns) {\n if (this.$isEmpty) {\n this.moveCursorTo(this.lead.row, this.lead.column + columns);\n return;\n }\n\n var anchor = this.getSelectionAnchor();\n var lead = this.getSelectionLead();\n\n var isBackwards = this.isBackwards();\n\n if (!isBackwards || anchor.column !== 0)\n this.setSelectionAnchor(anchor.row, anchor.column + columns);\n\n if (isBackwards || lead.column !== 0) {\n this.$moveSelection(function() {\n this.moveCursorTo(lead.row, lead.column + columns);\n });\n }\n };\n this.isBackwards = function() {\n var anchor = this.anchor;\n var lead = this.lead;\n return (anchor.row > lead.row || (anchor.row == lead.row && anchor.column > lead.column));\n };\n this.getRange = function() {\n var anchor = this.anchor;\n var lead = this.lead;\n\n if (this.isEmpty())\n return Range.fromPoints(lead, lead);\n\n if (this.isBackwards()) {\n return Range.fromPoints(lead, anchor);\n }\n else {\n return Range.fromPoints(anchor, lead);\n }\n };\n this.clearSelection = function() {\n if (!this.$isEmpty) {\n this.$isEmpty = true;\n this._emit(\"changeSelection\");\n }\n };\n this.selectAll = function() {\n var lastRow = this.doc.getLength() - 1;\n this.setSelectionAnchor(0, 0);\n this.moveCursorTo(lastRow, this.doc.getLine(lastRow).length);\n };\n this.setRange =\n this.setSelectionRange = function(range, reverse) {\n if (reverse) {\n this.setSelectionAnchor(range.end.row, range.end.column);\n this.selectTo(range.start.row, range.start.column);\n } else {\n this.setSelectionAnchor(range.start.row, range.start.column);\n this.selectTo(range.end.row, range.end.column);\n }\n if (this.getRange().isEmpty())\n this.$isEmpty = true;\n this.$desiredColumn = null;\n };\n\n this.$moveSelection = function(mover) {\n var lead = this.lead;\n if (this.$isEmpty)\n this.setSelectionAnchor(lead.row, lead.column);\n\n mover.call(this);\n };\n this.selectTo = function(row, column) {\n this.$moveSelection(function() {\n this.moveCursorTo(row, column);\n });\n };\n this.selectToPosition = function(pos) {\n this.$moveSelection(function() {\n this.moveCursorToPosition(pos);\n });\n };\n this.moveTo = function(row, column) {\n this.clearSelection();\n this.moveCursorTo(row, column);\n };\n this.moveToPosition = function(pos) {\n this.clearSelection();\n this.moveCursorToPosition(pos);\n };\n this.selectUp = function() {\n this.$moveSelection(this.moveCursorUp);\n };\n this.selectDown = function() {\n this.$moveSelection(this.moveCursorDown);\n };\n this.selectRight = function() {\n this.$moveSelection(this.moveCursorRight);\n };\n this.selectLeft = function() {\n this.$moveSelection(this.moveCursorLeft);\n };\n this.selectLineStart = function() {\n this.$moveSelection(this.moveCursorLineStart);\n };\n this.selectLineEnd = function() {\n this.$moveSelection(this.moveCursorLineEnd);\n };\n this.selectFileEnd = function() {\n this.$moveSelection(this.moveCursorFileEnd);\n };\n this.selectFileStart = function() {\n this.$moveSelection(this.moveCursorFileStart);\n };\n this.selectWordRight = function() {\n this.$moveSelection(this.moveCursorWordRight);\n };\n this.selectWordLeft = function() {\n this.$moveSelection(this.moveCursorWordLeft);\n };\n this.getWordRange = function(row, column) {\n if (typeof column == \"undefined\") {\n var cursor = row || this.lead;\n row = cursor.row;\n column = cursor.column;\n }\n return this.session.getWordRange(row, column);\n };\n this.selectWord = function() {\n this.setSelectionRange(this.getWordRange());\n };\n this.selectAWord = function() {\n var cursor = this.getCursor();\n var range = this.session.getAWordRange(cursor.row, cursor.column);\n this.setSelectionRange(range);\n };\n\n this.getLineRange = function(row, excludeLastChar) {\n var rowStart = typeof row == \"number\" ? row : this.lead.row;\n var rowEnd;\n\n var foldLine = this.session.getFoldLine(rowStart);\n if (foldLine) {\n rowStart = foldLine.start.row;\n rowEnd = foldLine.end.row;\n } else {\n rowEnd = rowStart;\n }\n if (excludeLastChar === true)\n return new Range(rowStart, 0, rowEnd, this.session.getLine(rowEnd).length);\n else\n return new Range(rowStart, 0, rowEnd + 1, 0);\n };\n this.selectLine = function() {\n this.setSelectionRange(this.getLineRange());\n };\n this.moveCursorUp = function() {\n this.moveCursorBy(-1, 0);\n };\n this.moveCursorDown = function() {\n this.moveCursorBy(1, 0);\n };\n this.moveCursorLeft = function() {\n var cursor = this.lead.getPosition(),\n fold;\n\n if (fold = this.session.getFoldAt(cursor.row, cursor.column, -1)) {\n this.moveCursorTo(fold.start.row, fold.start.column);\n } else if (cursor.column === 0) {\n if (cursor.row > 0) {\n this.moveCursorTo(cursor.row - 1, this.doc.getLine(cursor.row - 1).length);\n }\n }\n else {\n var tabSize = this.session.getTabSize();\n if (this.session.isTabStop(cursor) && this.doc.getLine(cursor.row).slice(cursor.column-tabSize, cursor.column).split(\" \").length-1 == tabSize)\n this.moveCursorBy(0, -tabSize);\n else\n this.moveCursorBy(0, -1);\n }\n };\n this.moveCursorRight = function() {\n var cursor = this.lead.getPosition(),\n fold;\n if (fold = this.session.getFoldAt(cursor.row, cursor.column, 1)) {\n this.moveCursorTo(fold.end.row, fold.end.column);\n }\n else if (this.lead.column == this.doc.getLine(this.lead.row).length) {\n if (this.lead.row < this.doc.getLength() - 1) {\n this.moveCursorTo(this.lead.row + 1, 0);\n }\n }\n else {\n var tabSize = this.session.getTabSize();\n var cursor = this.lead;\n if (this.session.isTabStop(cursor) && this.doc.getLine(cursor.row).slice(cursor.column, cursor.column+tabSize).split(\" \").length-1 == tabSize)\n this.moveCursorBy(0, tabSize);\n else\n this.moveCursorBy(0, 1);\n }\n };\n this.moveCursorLineStart = function() {\n var row = this.lead.row;\n var column = this.lead.column;\n var screenRow = this.session.documentToScreenRow(row, column);\n var firstColumnPosition = this.session.screenToDocumentPosition(screenRow, 0);\n var beforeCursor = this.session.getDisplayLine(\n row, null, firstColumnPosition.row,\n firstColumnPosition.column\n );\n\n var leadingSpace = beforeCursor.match(/^\\s*/);\n if (leadingSpace[0].length != column && !this.session.$useEmacsStyleLineStart)\n firstColumnPosition.column += leadingSpace[0].length;\n this.moveCursorToPosition(firstColumnPosition);\n };\n this.moveCursorLineEnd = function() {\n var lead = this.lead;\n var lineEnd = this.session.getDocumentLastRowColumnPosition(lead.row, lead.column);\n if (this.lead.column == lineEnd.column) {\n var line = this.session.getLine(lineEnd.row);\n if (lineEnd.column == line.length) {\n var textEnd = line.search(/\\s+$/);\n if (textEnd > 0)\n lineEnd.column = textEnd;\n }\n }\n\n this.moveCursorTo(lineEnd.row, lineEnd.column);\n };\n this.moveCursorFileEnd = function() {\n var row = this.doc.getLength() - 1;\n var column = this.doc.getLine(row).length;\n this.moveCursorTo(row, column);\n };\n this.moveCursorFileStart = function() {\n this.moveCursorTo(0, 0);\n };\n this.moveCursorLongWordRight = function() {\n var row = this.lead.row;\n var column = this.lead.column;\n var line = this.doc.getLine(row);\n var rightOfCursor = line.substring(column);\n\n var match;\n this.session.nonTokenRe.lastIndex = 0;\n this.session.tokenRe.lastIndex = 0;\n var fold = this.session.getFoldAt(row, column, 1);\n if (fold) {\n this.moveCursorTo(fold.end.row, fold.end.column);\n return;\n }\n if (match = this.session.nonTokenRe.exec(rightOfCursor)) {\n column += this.session.nonTokenRe.lastIndex;\n this.session.nonTokenRe.lastIndex = 0;\n rightOfCursor = line.substring(column);\n }\n if (column >= line.length) {\n this.moveCursorTo(row, line.length);\n this.moveCursorRight();\n if (row < this.doc.getLength() - 1)\n this.moveCursorWordRight();\n return;\n }\n if (match = this.session.tokenRe.exec(rightOfCursor)) {\n column += this.session.tokenRe.lastIndex;\n this.session.tokenRe.lastIndex = 0;\n }\n\n this.moveCursorTo(row, column);\n };\n this.moveCursorLongWordLeft = function() {\n var row = this.lead.row;\n var column = this.lead.column;\n var fold;\n if (fold = this.session.getFoldAt(row, column, -1)) {\n this.moveCursorTo(fold.start.row, fold.start.column);\n return;\n }\n\n var str = this.session.getFoldStringAt(row, column, -1);\n if (str == null) {\n str = this.doc.getLine(row).substring(0, column);\n }\n\n var leftOfCursor = lang.stringReverse(str);\n var match;\n this.session.nonTokenRe.lastIndex = 0;\n this.session.tokenRe.lastIndex = 0;\n if (match = this.session.nonTokenRe.exec(leftOfCursor)) {\n column -= this.session.nonTokenRe.lastIndex;\n leftOfCursor = leftOfCursor.slice(this.session.nonTokenRe.lastIndex);\n this.session.nonTokenRe.lastIndex = 0;\n }\n if (column <= 0) {\n this.moveCursorTo(row, 0);\n this.moveCursorLeft();\n if (row > 0)\n this.moveCursorWordLeft();\n return;\n }\n if (match = this.session.tokenRe.exec(leftOfCursor)) {\n column -= this.session.tokenRe.lastIndex;\n this.session.tokenRe.lastIndex = 0;\n }\n\n this.moveCursorTo(row, column);\n };\n\n this.$shortWordEndIndex = function(rightOfCursor) {\n var match, index = 0, ch;\n var whitespaceRe = /\\s/;\n var tokenRe = this.session.tokenRe;\n\n tokenRe.lastIndex = 0;\n if (match = this.session.tokenRe.exec(rightOfCursor)) {\n index = this.session.tokenRe.lastIndex;\n } else {\n while ((ch = rightOfCursor[index]) && whitespaceRe.test(ch))\n index ++;\n\n if (index < 1) {\n tokenRe.lastIndex = 0;\n while ((ch = rightOfCursor[index]) && !tokenRe.test(ch)) {\n tokenRe.lastIndex = 0;\n index ++;\n if (whitespaceRe.test(ch)) {\n if (index > 2) {\n index--;\n break;\n } else {\n while ((ch = rightOfCursor[index]) && whitespaceRe.test(ch))\n index ++;\n if (index > 2)\n break;\n }\n }\n }\n }\n }\n tokenRe.lastIndex = 0;\n\n return index;\n };\n\n this.moveCursorShortWordRight = function() {\n var row = this.lead.row;\n var column = this.lead.column;\n var line = this.doc.getLine(row);\n var rightOfCursor = line.substring(column);\n\n var fold = this.session.getFoldAt(row, column, 1);\n if (fold)\n return this.moveCursorTo(fold.end.row, fold.end.column);\n\n if (column == line.length) {\n var l = this.doc.getLength();\n do {\n row++;\n rightOfCursor = this.doc.getLine(row);\n } while (row < l && /^\\s*$/.test(rightOfCursor));\n\n if (!/^\\s+/.test(rightOfCursor))\n rightOfCursor = \"\";\n column = 0;\n }\n\n var index = this.$shortWordEndIndex(rightOfCursor);\n\n this.moveCursorTo(row, column + index);\n };\n\n this.moveCursorShortWordLeft = function() {\n var row = this.lead.row;\n var column = this.lead.column;\n\n var fold;\n if (fold = this.session.getFoldAt(row, column, -1))\n return this.moveCursorTo(fold.start.row, fold.start.column);\n\n var line = this.session.getLine(row).substring(0, column);\n if (column === 0) {\n do {\n row--;\n line = this.doc.getLine(row);\n } while (row > 0 && /^\\s*$/.test(line));\n\n column = line.length;\n if (!/\\s+$/.test(line))\n line = \"\";\n }\n\n var leftOfCursor = lang.stringReverse(line);\n var index = this.$shortWordEndIndex(leftOfCursor);\n\n return this.moveCursorTo(row, column - index);\n };\n\n this.moveCursorWordRight = function() {\n if (this.session.$selectLongWords)\n this.moveCursorLongWordRight();\n else\n this.moveCursorShortWordRight();\n };\n\n this.moveCursorWordLeft = function() {\n if (this.session.$selectLongWords)\n this.moveCursorLongWordLeft();\n else\n this.moveCursorShortWordLeft();\n };\n this.moveCursorBy = function(rows, chars) {\n var screenPos = this.session.documentToScreenPosition(\n this.lead.row,\n this.lead.column\n );\n\n if (chars === 0) {\n if (this.$desiredColumn)\n screenPos.column = this.$desiredColumn;\n else\n this.$desiredColumn = screenPos.column;\n }\n\n var docPos = this.session.screenToDocumentPosition(screenPos.row + rows, screenPos.column);\n \n if (rows !== 0 && chars === 0 && docPos.row === this.lead.row && docPos.column === this.lead.column) {\n if (this.session.lineWidgets && this.session.lineWidgets[docPos.row]) {\n if (docPos.row > 0 || rows > 0)\n docPos.row++;\n }\n }\n this.moveCursorTo(docPos.row, docPos.column + chars, chars === 0);\n };\n this.moveCursorToPosition = function(position) {\n this.moveCursorTo(position.row, position.column);\n };\n this.moveCursorTo = function(row, column, keepDesiredColumn) {\n var fold = this.session.getFoldAt(row, column, 1);\n if (fold) {\n row = fold.start.row;\n column = fold.start.column;\n }\n\n this.$keepDesiredColumnOnChange = true;\n this.lead.setPosition(row, column);\n this.$keepDesiredColumnOnChange = false;\n\n if (!keepDesiredColumn)\n this.$desiredColumn = null;\n };\n this.moveCursorToScreen = function(row, column, keepDesiredColumn) {\n var pos = this.session.screenToDocumentPosition(row, column);\n this.moveCursorTo(pos.row, pos.column, keepDesiredColumn);\n };\n this.detach = function() {\n this.lead.detach();\n this.anchor.detach();\n this.session = this.doc = null;\n };\n\n this.fromOrientedRange = function(range) {\n this.setSelectionRange(range, range.cursor == range.start);\n this.$desiredColumn = range.desiredColumn || this.$desiredColumn;\n };\n\n this.toOrientedRange = function(range) {\n var r = this.getRange();\n if (range) {\n range.start.column = r.start.column;\n range.start.row = r.start.row;\n range.end.column = r.end.column;\n range.end.row = r.end.row;\n } else {\n range = r;\n }\n\n range.cursor = this.isBackwards() ? range.start : range.end;\n range.desiredColumn = this.$desiredColumn;\n return range;\n };\n this.getRangeOfMovements = function(func) {\n var start = this.getCursor();\n try {\n func(this);\n var end = this.getCursor();\n return Range.fromPoints(start,end);\n } catch(e) {\n return Range.fromPoints(start,start);\n } finally {\n this.moveCursorToPosition(start);\n }\n };\n\n this.toJSON = function() {\n if (this.rangeCount) {\n var data = this.ranges.map(function(r) {\n var r1 = r.clone();\n r1.isBackwards = r.cursor == r.start;\n return r1;\n });\n } else {\n var data = this.getRange();\n data.isBackwards = this.isBackwards();\n }\n return data;\n };\n\n this.fromJSON = function(data) {\n if (data.start == undefined) {\n if (this.rangeList) {\n this.toSingleRange(data[0]);\n for (var i = data.length; i--; ) {\n var r = Range.fromPoints(data[i].start, data[i].end);\n if (data[i].isBackwards)\n r.cursor = r.start;\n this.addRange(r, true);\n }\n return;\n } else\n data = data[0];\n }\n if (this.rangeList)\n this.toSingleRange(data);\n this.setSelectionRange(data, data.isBackwards);\n };\n\n this.isEqual = function(data) {\n if ((data.length || this.rangeCount) && data.length != this.rangeCount)\n return false;\n if (!data.length || !this.ranges)\n return this.getRange().isEqual(data);\n\n for (var i = this.ranges.length; i--; ) {\n if (!this.ranges[i].isEqual(data[i]))\n return false;\n }\n return true;\n };\n\n}).call(Selection.prototype);\n\nexports.Selection = Selection;\n});\n\nace.define(\"ace/tokenizer\",[\"require\",\"exports\",\"module\",\"ace/config\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar config = acequire(\"./config\");\nvar MAX_TOKEN_COUNT = 2000;\nvar Tokenizer = function(rules) {\n this.states = rules;\n\n this.regExps = {};\n this.matchMappings = {};\n for (var key in this.states) {\n var state = this.states[key];\n var ruleRegExps = [];\n var matchTotal = 0;\n var mapping = this.matchMappings[key] = {defaultToken: \"text\"};\n var flag = \"g\";\n\n var splitterRurles = [];\n for (var i = 0; i < state.length; i++) {\n var rule = state[i];\n if (rule.defaultToken)\n mapping.defaultToken = rule.defaultToken;\n if (rule.caseInsensitive)\n flag = \"gi\";\n if (rule.regex == null)\n continue;\n\n if (rule.regex instanceof RegExp)\n rule.regex = rule.regex.toString().slice(1, -1);\n var adjustedregex = rule.regex;\n var matchcount = new RegExp(\"(?:(\" + adjustedregex + \")|(.))\").exec(\"a\").length - 2;\n if (Array.isArray(rule.token)) {\n if (rule.token.length == 1 || matchcount == 1) {\n rule.token = rule.token[0];\n } else if (matchcount - 1 != rule.token.length) {\n this.reportError(\"number of classes and regexp groups doesn't match\", { \n rule: rule,\n groupCount: matchcount - 1\n });\n rule.token = rule.token[0];\n } else {\n rule.tokenArray = rule.token;\n rule.token = null;\n rule.onMatch = this.$arrayTokens;\n }\n } else if (typeof rule.token == \"function\" && !rule.onMatch) {\n if (matchcount > 1)\n rule.onMatch = this.$applyToken;\n else\n rule.onMatch = rule.token;\n }\n\n if (matchcount > 1) {\n if (/\\\\\\d/.test(rule.regex)) {\n adjustedregex = rule.regex.replace(/\\\\([0-9]+)/g, function(match, digit) {\n return \"\\\\\" + (parseInt(digit, 10) + matchTotal + 1);\n });\n } else {\n matchcount = 1;\n adjustedregex = this.removeCapturingGroups(rule.regex);\n }\n if (!rule.splitRegex && typeof rule.token != \"string\")\n splitterRurles.push(rule); // flag will be known only at the very end\n }\n\n mapping[matchTotal] = i;\n matchTotal += matchcount;\n\n ruleRegExps.push(adjustedregex);\n if (!rule.onMatch)\n rule.onMatch = null;\n }\n \n if (!ruleRegExps.length) {\n mapping[0] = 0;\n ruleRegExps.push(\"$\");\n }\n \n splitterRurles.forEach(function(rule) {\n rule.splitRegex = this.createSplitterRegexp(rule.regex, flag);\n }, this);\n\n this.regExps[key] = new RegExp(\"(\" + ruleRegExps.join(\")|(\") + \")|($)\", flag);\n }\n};\n\n(function() {\n this.$setMaxTokenCount = function(m) {\n MAX_TOKEN_COUNT = m | 0;\n };\n \n this.$applyToken = function(str) {\n var values = this.splitRegex.exec(str).slice(1);\n var types = this.token.apply(this, values);\n if (typeof types === \"string\")\n return [{type: types, value: str}];\n\n var tokens = [];\n for (var i = 0, l = types.length; i < l; i++) {\n if (values[i])\n tokens[tokens.length] = {\n type: types[i],\n value: values[i]\n };\n }\n return tokens;\n };\n\n this.$arrayTokens = function(str) {\n if (!str)\n return [];\n var values = this.splitRegex.exec(str);\n if (!values)\n return \"text\";\n var tokens = [];\n var types = this.tokenArray;\n for (var i = 0, l = types.length; i < l; i++) {\n if (values[i + 1])\n tokens[tokens.length] = {\n type: types[i],\n value: values[i + 1]\n };\n }\n return tokens;\n };\n\n this.removeCapturingGroups = function(src) {\n var r = src.replace(\n /\\[(?:\\\\.|[^\\]])*?\\]|\\\\.|\\(\\?[:=!]|(\\()/g,\n function(x, y) {return y ? \"(?:\" : x;}\n );\n return r;\n };\n\n this.createSplitterRegexp = function(src, flag) {\n if (src.indexOf(\"(?=\") != -1) {\n var stack = 0;\n var inChClass = false;\n var lastCapture = {};\n src.replace(/(\\\\.)|(\\((?:\\?[=!])?)|(\\))|([\\[\\]])/g, function(\n m, esc, parenOpen, parenClose, square, index\n ) {\n if (inChClass) {\n inChClass = square != \"]\";\n } else if (square) {\n inChClass = true;\n } else if (parenClose) {\n if (stack == lastCapture.stack) {\n lastCapture.end = index+1;\n lastCapture.stack = -1;\n }\n stack--;\n } else if (parenOpen) {\n stack++;\n if (parenOpen.length != 1) {\n lastCapture.stack = stack\n lastCapture.start = index;\n }\n }\n return m;\n });\n\n if (lastCapture.end != null && /^\\)*$/.test(src.substr(lastCapture.end)))\n src = src.substring(0, lastCapture.start) + src.substr(lastCapture.end);\n }\n if (src.charAt(0) != \"^\") src = \"^\" + src;\n if (src.charAt(src.length - 1) != \"$\") src += \"$\";\n \n return new RegExp(src, (flag||\"\").replace(\"g\", \"\"));\n };\n this.getLineTokens = function(line, startState) {\n if (startState && typeof startState != \"string\") {\n var stack = startState.slice(0);\n startState = stack[0];\n if (startState === \"#tmp\") {\n stack.shift()\n startState = stack.shift()\n }\n } else\n var stack = [];\n\n var currentState = startState || \"start\";\n var state = this.states[currentState];\n if (!state) {\n currentState = \"start\";\n state = this.states[currentState];\n }\n var mapping = this.matchMappings[currentState];\n var re = this.regExps[currentState];\n re.lastIndex = 0;\n\n var match, tokens = [];\n var lastIndex = 0;\n var matchAttempts = 0;\n\n var token = {type: null, value: \"\"};\n\n while (match = re.exec(line)) {\n var type = mapping.defaultToken;\n var rule = null;\n var value = match[0];\n var index = re.lastIndex;\n\n if (index - value.length > lastIndex) {\n var skipped = line.substring(lastIndex, index - value.length);\n if (token.type == type) {\n token.value += skipped;\n } else {\n if (token.type)\n tokens.push(token);\n token = {type: type, value: skipped};\n }\n }\n\n for (var i = 0; i < match.length-2; i++) {\n if (match[i + 1] === undefined)\n continue;\n\n rule = state[mapping[i]];\n\n if (rule.onMatch)\n type = rule.onMatch(value, currentState, stack);\n else\n type = rule.token;\n\n if (rule.next) {\n if (typeof rule.next == \"string\") {\n currentState = rule.next;\n } else {\n currentState = rule.next(currentState, stack);\n }\n \n state = this.states[currentState];\n if (!state) {\n this.reportError(\"state doesn't exist\", currentState);\n currentState = \"start\";\n state = this.states[currentState];\n }\n mapping = this.matchMappings[currentState];\n lastIndex = index;\n re = this.regExps[currentState];\n re.lastIndex = index;\n }\n break;\n }\n\n if (value) {\n if (typeof type === \"string\") {\n if ((!rule || rule.merge !== false) && token.type === type) {\n token.value += value;\n } else {\n if (token.type)\n tokens.push(token);\n token = {type: type, value: value};\n }\n } else if (type) {\n if (token.type)\n tokens.push(token);\n token = {type: null, value: \"\"};\n for (var i = 0; i < type.length; i++)\n tokens.push(type[i]);\n }\n }\n\n if (lastIndex == line.length)\n break;\n\n lastIndex = index;\n\n if (matchAttempts++ > MAX_TOKEN_COUNT) {\n if (matchAttempts > 2 * line.length) {\n this.reportError(\"infinite loop with in ace tokenizer\", {\n startState: startState,\n line: line\n });\n }\n while (lastIndex < line.length) {\n if (token.type)\n tokens.push(token);\n token = {\n value: line.substring(lastIndex, lastIndex += 2000),\n type: \"overflow\"\n };\n }\n currentState = \"start\";\n stack = [];\n break;\n }\n }\n\n if (token.type)\n tokens.push(token);\n \n if (stack.length > 1) {\n if (stack[0] !== currentState)\n stack.unshift(\"#tmp\", currentState);\n }\n return {\n tokens : tokens,\n state : stack.length ? stack : currentState\n };\n };\n \n this.reportError = config.reportError;\n \n}).call(Tokenizer.prototype);\n\nexports.Tokenizer = Tokenizer;\n});\n\nace.define(\"ace/mode/text_highlight_rules\",[\"require\",\"exports\",\"module\",\"ace/lib/lang\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar lang = acequire(\"../lib/lang\");\n\nvar TextHighlightRules = function() {\n\n this.$rules = {\n \"start\" : [{\n token : \"empty_line\",\n regex : '^$'\n }, {\n defaultToken : \"text\"\n }]\n };\n};\n\n(function() {\n\n this.addRules = function(rules, prefix) {\n if (!prefix) {\n for (var key in rules)\n this.$rules[key] = rules[key];\n return;\n }\n for (var key in rules) {\n var state = rules[key];\n for (var i = 0; i < state.length; i++) {\n var rule = state[i];\n if (rule.next || rule.onMatch) {\n if (typeof rule.next == \"string\") {\n if (rule.next.indexOf(prefix) !== 0)\n rule.next = prefix + rule.next;\n }\n if (rule.nextState && rule.nextState.indexOf(prefix) !== 0)\n rule.nextState = prefix + rule.nextState;\n }\n }\n this.$rules[prefix + key] = state;\n }\n };\n\n this.getRules = function() {\n return this.$rules;\n };\n\n this.embedRules = function (HighlightRules, prefix, escapeRules, states, append) {\n var embedRules = typeof HighlightRules == \"function\"\n ? new HighlightRules().getRules()\n : HighlightRules;\n if (states) {\n for (var i = 0; i < states.length; i++)\n states[i] = prefix + states[i];\n } else {\n states = [];\n for (var key in embedRules)\n states.push(prefix + key);\n }\n\n this.addRules(embedRules, prefix);\n\n if (escapeRules) {\n var addRules = Array.prototype[append ? \"push\" : \"unshift\"];\n for (var i = 0; i < states.length; i++)\n addRules.apply(this.$rules[states[i]], lang.deepCopy(escapeRules));\n }\n\n if (!this.$embeds)\n this.$embeds = [];\n this.$embeds.push(prefix);\n };\n\n this.getEmbeds = function() {\n return this.$embeds;\n };\n\n var pushState = function(currentState, stack) {\n if (currentState != \"start\" || stack.length)\n stack.unshift(this.nextState, currentState);\n return this.nextState;\n };\n var popState = function(currentState, stack) {\n stack.shift();\n return stack.shift() || \"start\";\n };\n\n this.normalizeRules = function() {\n var id = 0;\n var rules = this.$rules;\n function processState(key) {\n var state = rules[key];\n state.processed = true;\n for (var i = 0; i < state.length; i++) {\n var rule = state[i];\n if (!rule.regex && rule.start) {\n rule.regex = rule.start;\n if (!rule.next)\n rule.next = [];\n rule.next.push({\n defaultToken: rule.token\n }, {\n token: rule.token + \".end\",\n regex: rule.end || rule.start,\n next: \"pop\"\n });\n rule.token = rule.token + \".start\";\n rule.push = true;\n }\n var next = rule.next || rule.push;\n if (next && Array.isArray(next)) {\n var stateName = rule.stateName;\n if (!stateName) {\n stateName = rule.token;\n if (typeof stateName != \"string\")\n stateName = stateName[0] || \"\";\n if (rules[stateName])\n stateName += id++;\n }\n rules[stateName] = next;\n rule.next = stateName;\n processState(stateName);\n } else if (next == \"pop\") {\n rule.next = popState;\n }\n\n if (rule.push) {\n rule.nextState = rule.next || rule.push;\n rule.next = pushState;\n delete rule.push;\n }\n\n if (rule.rules) {\n for (var r in rule.rules) {\n if (rules[r]) {\n if (rules[r].push)\n rules[r].push.apply(rules[r], rule.rules[r]);\n } else {\n rules[r] = rule.rules[r];\n }\n }\n }\n if (rule.include || typeof rule == \"string\") {\n var includeName = rule.include || rule;\n var toInsert = rules[includeName];\n } else if (Array.isArray(rule))\n toInsert = rule;\n\n if (toInsert) {\n var args = [i, 1].concat(toInsert);\n if (rule.noEscape)\n args = args.filter(function(x) {return !x.next;});\n state.splice.apply(state, args);\n i--;\n toInsert = null;\n }\n \n if (rule.keywordMap) {\n rule.token = this.createKeywordMapper(\n rule.keywordMap, rule.defaultToken || \"text\", rule.caseInsensitive\n );\n delete rule.defaultToken;\n }\n }\n }\n Object.keys(rules).forEach(processState, this);\n };\n\n this.createKeywordMapper = function(map, defaultToken, ignoreCase, splitChar) {\n var keywords = Object.create(null);\n Object.keys(map).forEach(function(className) {\n var a = map[className];\n if (ignoreCase)\n a = a.toLowerCase();\n var list = a.split(splitChar || \"|\");\n for (var i = list.length; i--; )\n keywords[list[i]] = className;\n });\n if (Object.getPrototypeOf(keywords)) {\n keywords.__proto__ = null;\n }\n this.$keywordList = Object.keys(keywords);\n map = null;\n return ignoreCase\n ? function(value) {return keywords[value.toLowerCase()] || defaultToken }\n : function(value) {return keywords[value] || defaultToken };\n };\n\n this.getKeywords = function() {\n return this.$keywords;\n };\n\n}).call(TextHighlightRules.prototype);\n\nexports.TextHighlightRules = TextHighlightRules;\n});\n\nace.define(\"ace/mode/behaviour\",[\"require\",\"exports\",\"module\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar Behaviour = function() {\n this.$behaviours = {};\n};\n\n(function () {\n\n this.add = function (name, action, callback) {\n switch (undefined) {\n case this.$behaviours:\n this.$behaviours = {};\n case this.$behaviours[name]:\n this.$behaviours[name] = {};\n }\n this.$behaviours[name][action] = callback;\n }\n \n this.addBehaviours = function (behaviours) {\n for (var key in behaviours) {\n for (var action in behaviours[key]) {\n this.add(key, action, behaviours[key][action]);\n }\n }\n }\n \n this.remove = function (name) {\n if (this.$behaviours && this.$behaviours[name]) {\n delete this.$behaviours[name];\n }\n }\n \n this.inherit = function (mode, filter) {\n if (typeof mode === \"function\") {\n var behaviours = new mode().getBehaviours(filter);\n } else {\n var behaviours = mode.getBehaviours(filter);\n }\n this.addBehaviours(behaviours);\n }\n \n this.getBehaviours = function (filter) {\n if (!filter) {\n return this.$behaviours;\n } else {\n var ret = {}\n for (var i = 0; i < filter.length; i++) {\n if (this.$behaviours[filter[i]]) {\n ret[filter[i]] = this.$behaviours[filter[i]];\n }\n }\n return ret;\n }\n }\n\n}).call(Behaviour.prototype);\n\nexports.Behaviour = Behaviour;\n});\n\nace.define(\"ace/unicode\",[\"require\",\"exports\",\"module\"], function(acequire, exports, module) {\n\"use strict\";\nexports.packages = {};\n\naddUnicodePackage({\n L: \"0041-005A0061-007A00AA00B500BA00C0-00D600D8-00F600F8-02C102C6-02D102E0-02E402EC02EE0370-037403760377037A-037D03860388-038A038C038E-03A103A3-03F503F7-0481048A-05250531-055605590561-058705D0-05EA05F0-05F20621-064A066E066F0671-06D306D506E506E606EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA07F407F507FA0800-0815081A082408280904-0939093D09500958-0961097109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E460E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EC60EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10A0-10C510D0-10FA10FC1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317D717DC1820-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541AA71B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C7D1CE9-1CEC1CEE-1CF11D00-1DBF1E00-1F151F18-1F1D1F20-1F451F48-1F4D1F50-1F571F591F5B1F5D1F5F-1F7D1F80-1FB41FB6-1FBC1FBE1FC2-1FC41FC6-1FCC1FD0-1FD31FD6-1FDB1FE0-1FEC1FF2-1FF41FF6-1FFC2071207F2090-209421022107210A-211321152119-211D212421262128212A-212D212F-2139213C-213F2145-2149214E218321842C00-2C2E2C30-2C5E2C60-2CE42CEB-2CEE2D00-2D252D30-2D652D6F2D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE2E2F300530063031-3035303B303C3041-3096309D-309F30A1-30FA30FC-30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A48CA4D0-A4FDA500-A60CA610-A61FA62AA62BA640-A65FA662-A66EA67F-A697A6A0-A6E5A717-A71FA722-A788A78BA78CA7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2A9CFAA00-AA28AA40-AA42AA44-AA4BAA60-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADB-AADDABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB00-FB06FB13-FB17FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF21-FF3AFF41-FF5AFF66-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC\",\n Ll: \"0061-007A00AA00B500BA00DF-00F600F8-00FF01010103010501070109010B010D010F01110113011501170119011B011D011F01210123012501270129012B012D012F01310133013501370138013A013C013E014001420144014601480149014B014D014F01510153015501570159015B015D015F01610163016501670169016B016D016F0171017301750177017A017C017E-0180018301850188018C018D019201950199-019B019E01A101A301A501A801AA01AB01AD01B001B401B601B901BA01BD-01BF01C601C901CC01CE01D001D201D401D601D801DA01DC01DD01DF01E101E301E501E701E901EB01ED01EF01F001F301F501F901FB01FD01FF02010203020502070209020B020D020F02110213021502170219021B021D021F02210223022502270229022B022D022F02310233-0239023C023F0240024202470249024B024D024F-02930295-02AF037103730377037B-037D039003AC-03CE03D003D103D5-03D703D903DB03DD03DF03E103E303E503E703E903EB03ED03EF-03F303F503F803FB03FC0430-045F04610463046504670469046B046D046F04710473047504770479047B047D047F0481048B048D048F04910493049504970499049B049D049F04A104A304A504A704A904AB04AD04AF04B104B304B504B704B904BB04BD04BF04C204C404C604C804CA04CC04CE04CF04D104D304D504D704D904DB04DD04DF04E104E304E504E704E904EB04ED04EF04F104F304F504F704F904FB04FD04FF05010503050505070509050B050D050F05110513051505170519051B051D051F0521052305250561-05871D00-1D2B1D62-1D771D79-1D9A1E011E031E051E071E091E0B1E0D1E0F1E111E131E151E171E191E1B1E1D1E1F1E211E231E251E271E291E2B1E2D1E2F1E311E331E351E371E391E3B1E3D1E3F1E411E431E451E471E491E4B1E4D1E4F1E511E531E551E571E591E5B1E5D1E5F1E611E631E651E671E691E6B1E6D1E6F1E711E731E751E771E791E7B1E7D1E7F1E811E831E851E871E891E8B1E8D1E8F1E911E931E95-1E9D1E9F1EA11EA31EA51EA71EA91EAB1EAD1EAF1EB11EB31EB51EB71EB91EBB1EBD1EBF1EC11EC31EC51EC71EC91ECB1ECD1ECF1ED11ED31ED51ED71ED91EDB1EDD1EDF1EE11EE31EE51EE71EE91EEB1EED1EEF1EF11EF31EF51EF71EF91EFB1EFD1EFF-1F071F10-1F151F20-1F271F30-1F371F40-1F451F50-1F571F60-1F671F70-1F7D1F80-1F871F90-1F971FA0-1FA71FB0-1FB41FB61FB71FBE1FC2-1FC41FC61FC71FD0-1FD31FD61FD71FE0-1FE71FF2-1FF41FF61FF7210A210E210F2113212F21342139213C213D2146-2149214E21842C30-2C5E2C612C652C662C682C6A2C6C2C712C732C742C76-2C7C2C812C832C852C872C892C8B2C8D2C8F2C912C932C952C972C992C9B2C9D2C9F2CA12CA32CA52CA72CA92CAB2CAD2CAF2CB12CB32CB52CB72CB92CBB2CBD2CBF2CC12CC32CC52CC72CC92CCB2CCD2CCF2CD12CD32CD52CD72CD92CDB2CDD2CDF2CE12CE32CE42CEC2CEE2D00-2D25A641A643A645A647A649A64BA64DA64FA651A653A655A657A659A65BA65DA65FA663A665A667A669A66BA66DA681A683A685A687A689A68BA68DA68FA691A693A695A697A723A725A727A729A72BA72DA72F-A731A733A735A737A739A73BA73DA73FA741A743A745A747A749A74BA74DA74FA751A753A755A757A759A75BA75DA75FA761A763A765A767A769A76BA76DA76FA771-A778A77AA77CA77FA781A783A785A787A78CFB00-FB06FB13-FB17FF41-FF5A\",\n Lu: \"0041-005A00C0-00D600D8-00DE01000102010401060108010A010C010E01100112011401160118011A011C011E01200122012401260128012A012C012E01300132013401360139013B013D013F0141014301450147014A014C014E01500152015401560158015A015C015E01600162016401660168016A016C016E017001720174017601780179017B017D018101820184018601870189-018B018E-0191019301940196-0198019C019D019F01A001A201A401A601A701A901AC01AE01AF01B1-01B301B501B701B801BC01C401C701CA01CD01CF01D101D301D501D701D901DB01DE01E001E201E401E601E801EA01EC01EE01F101F401F6-01F801FA01FC01FE02000202020402060208020A020C020E02100212021402160218021A021C021E02200222022402260228022A022C022E02300232023A023B023D023E02410243-02460248024A024C024E03700372037603860388-038A038C038E038F0391-03A103A3-03AB03CF03D2-03D403D803DA03DC03DE03E003E203E403E603E803EA03EC03EE03F403F703F903FA03FD-042F04600462046404660468046A046C046E04700472047404760478047A047C047E0480048A048C048E04900492049404960498049A049C049E04A004A204A404A604A804AA04AC04AE04B004B204B404B604B804BA04BC04BE04C004C104C304C504C704C904CB04CD04D004D204D404D604D804DA04DC04DE04E004E204E404E604E804EA04EC04EE04F004F204F404F604F804FA04FC04FE05000502050405060508050A050C050E05100512051405160518051A051C051E0520052205240531-055610A0-10C51E001E021E041E061E081E0A1E0C1E0E1E101E121E141E161E181E1A1E1C1E1E1E201E221E241E261E281E2A1E2C1E2E1E301E321E341E361E381E3A1E3C1E3E1E401E421E441E461E481E4A1E4C1E4E1E501E521E541E561E581E5A1E5C1E5E1E601E621E641E661E681E6A1E6C1E6E1E701E721E741E761E781E7A1E7C1E7E1E801E821E841E861E881E8A1E8C1E8E1E901E921E941E9E1EA01EA21EA41EA61EA81EAA1EAC1EAE1EB01EB21EB41EB61EB81EBA1EBC1EBE1EC01EC21EC41EC61EC81ECA1ECC1ECE1ED01ED21ED41ED61ED81EDA1EDC1EDE1EE01EE21EE41EE61EE81EEA1EEC1EEE1EF01EF21EF41EF61EF81EFA1EFC1EFE1F08-1F0F1F18-1F1D1F28-1F2F1F38-1F3F1F48-1F4D1F591F5B1F5D1F5F1F68-1F6F1FB8-1FBB1FC8-1FCB1FD8-1FDB1FE8-1FEC1FF8-1FFB21022107210B-210D2110-211221152119-211D212421262128212A-212D2130-2133213E213F214521832C00-2C2E2C602C62-2C642C672C692C6B2C6D-2C702C722C752C7E-2C802C822C842C862C882C8A2C8C2C8E2C902C922C942C962C982C9A2C9C2C9E2CA02CA22CA42CA62CA82CAA2CAC2CAE2CB02CB22CB42CB62CB82CBA2CBC2CBE2CC02CC22CC42CC62CC82CCA2CCC2CCE2CD02CD22CD42CD62CD82CDA2CDC2CDE2CE02CE22CEB2CEDA640A642A644A646A648A64AA64CA64EA650A652A654A656A658A65AA65CA65EA662A664A666A668A66AA66CA680A682A684A686A688A68AA68CA68EA690A692A694A696A722A724A726A728A72AA72CA72EA732A734A736A738A73AA73CA73EA740A742A744A746A748A74AA74CA74EA750A752A754A756A758A75AA75CA75EA760A762A764A766A768A76AA76CA76EA779A77BA77DA77EA780A782A784A786A78BFF21-FF3A\",\n Lt: \"01C501C801CB01F21F88-1F8F1F98-1F9F1FA8-1FAF1FBC1FCC1FFC\",\n Lm: \"02B0-02C102C6-02D102E0-02E402EC02EE0374037A0559064006E506E607F407F507FA081A0824082809710E460EC610FC17D718431AA71C78-1C7D1D2C-1D611D781D9B-1DBF2071207F2090-20942C7D2D6F2E2F30053031-3035303B309D309E30FC-30FEA015A4F8-A4FDA60CA67FA717-A71FA770A788A9CFAA70AADDFF70FF9EFF9F\",\n Lo: \"01BB01C0-01C3029405D0-05EA05F0-05F20621-063F0641-064A066E066F0671-06D306D506EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA0800-08150904-0939093D09500958-096109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E450E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10D0-10FA1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317DC1820-18421844-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C771CE9-1CEC1CEE-1CF12135-21382D30-2D652D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE3006303C3041-3096309F30A1-30FA30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A014A016-A48CA4D0-A4F7A500-A60BA610-A61FA62AA62BA66EA6A0-A6E5A7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2AA00-AA28AA40-AA42AA44-AA4BAA60-AA6FAA71-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADBAADCABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF66-FF6FFF71-FF9DFFA0-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC\",\n M: \"0300-036F0483-04890591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DE-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0903093C093E-094E0951-0955096209630981-098309BC09BE-09C409C709C809CB-09CD09D709E209E30A01-0A030A3C0A3E-0A420A470A480A4B-0A4D0A510A700A710A750A81-0A830ABC0ABE-0AC50AC7-0AC90ACB-0ACD0AE20AE30B01-0B030B3C0B3E-0B440B470B480B4B-0B4D0B560B570B620B630B820BBE-0BC20BC6-0BC80BCA-0BCD0BD70C01-0C030C3E-0C440C46-0C480C4A-0C4D0C550C560C620C630C820C830CBC0CBE-0CC40CC6-0CC80CCA-0CCD0CD50CD60CE20CE30D020D030D3E-0D440D46-0D480D4A-0D4D0D570D620D630D820D830DCA0DCF-0DD40DD60DD8-0DDF0DF20DF30E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F3E0F3F0F71-0F840F860F870F90-0F970F99-0FBC0FC6102B-103E1056-1059105E-10601062-10641067-106D1071-10741082-108D108F109A-109D135F1712-17141732-1734175217531772177317B6-17D317DD180B-180D18A91920-192B1930-193B19B0-19C019C819C91A17-1A1B1A55-1A5E1A60-1A7C1A7F1B00-1B041B34-1B441B6B-1B731B80-1B821BA1-1BAA1C24-1C371CD0-1CD21CD4-1CE81CED1CF21DC0-1DE61DFD-1DFF20D0-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66F-A672A67CA67DA6F0A6F1A802A806A80BA823-A827A880A881A8B4-A8C4A8E0-A8F1A926-A92DA947-A953A980-A983A9B3-A9C0AA29-AA36AA43AA4CAA4DAA7BAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE3-ABEAABECABEDFB1EFE00-FE0FFE20-FE26\",\n Mn: \"0300-036F0483-04870591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DF-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0902093C0941-0948094D0951-095509620963098109BC09C1-09C409CD09E209E30A010A020A3C0A410A420A470A480A4B-0A4D0A510A700A710A750A810A820ABC0AC1-0AC50AC70AC80ACD0AE20AE30B010B3C0B3F0B41-0B440B4D0B560B620B630B820BC00BCD0C3E-0C400C46-0C480C4A-0C4D0C550C560C620C630CBC0CBF0CC60CCC0CCD0CE20CE30D41-0D440D4D0D620D630DCA0DD2-0DD40DD60E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F71-0F7E0F80-0F840F860F870F90-0F970F99-0FBC0FC6102D-10301032-10371039103A103D103E10581059105E-10601071-1074108210851086108D109D135F1712-17141732-1734175217531772177317B7-17BD17C617C9-17D317DD180B-180D18A91920-19221927192819321939-193B1A171A181A561A58-1A5E1A601A621A65-1A6C1A73-1A7C1A7F1B00-1B031B341B36-1B3A1B3C1B421B6B-1B731B801B811BA2-1BA51BA81BA91C2C-1C331C361C371CD0-1CD21CD4-1CE01CE2-1CE81CED1DC0-1DE61DFD-1DFF20D0-20DC20E120E5-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66FA67CA67DA6F0A6F1A802A806A80BA825A826A8C4A8E0-A8F1A926-A92DA947-A951A980-A982A9B3A9B6-A9B9A9BCAA29-AA2EAA31AA32AA35AA36AA43AA4CAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE5ABE8ABEDFB1EFE00-FE0FFE20-FE26\",\n Mc: \"0903093E-09400949-094C094E0982098309BE-09C009C709C809CB09CC09D70A030A3E-0A400A830ABE-0AC00AC90ACB0ACC0B020B030B3E0B400B470B480B4B0B4C0B570BBE0BBF0BC10BC20BC6-0BC80BCA-0BCC0BD70C01-0C030C41-0C440C820C830CBE0CC0-0CC40CC70CC80CCA0CCB0CD50CD60D020D030D3E-0D400D46-0D480D4A-0D4C0D570D820D830DCF-0DD10DD8-0DDF0DF20DF30F3E0F3F0F7F102B102C10311038103B103C105610571062-10641067-106D108310841087-108C108F109A-109C17B617BE-17C517C717C81923-19261929-192B193019311933-193819B0-19C019C819C91A19-1A1B1A551A571A611A631A641A6D-1A721B041B351B3B1B3D-1B411B431B441B821BA11BA61BA71BAA1C24-1C2B1C341C351CE11CF2A823A824A827A880A881A8B4-A8C3A952A953A983A9B4A9B5A9BAA9BBA9BD-A9C0AA2FAA30AA33AA34AA4DAA7BABE3ABE4ABE6ABE7ABE9ABEAABEC\",\n Me: \"0488048906DE20DD-20E020E2-20E4A670-A672\",\n N: \"0030-003900B200B300B900BC-00BE0660-066906F0-06F907C0-07C90966-096F09E6-09EF09F4-09F90A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BF20C66-0C6F0C78-0C7E0CE6-0CEF0D66-0D750E50-0E590ED0-0ED90F20-0F331040-10491090-10991369-137C16EE-16F017E0-17E917F0-17F91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C5920702074-20792080-20892150-21822185-21892460-249B24EA-24FF2776-27932CFD30073021-30293038-303A3192-31953220-32293251-325F3280-328932B1-32BFA620-A629A6E6-A6EFA830-A835A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19\",\n Nd: \"0030-00390660-066906F0-06F907C0-07C90966-096F09E6-09EF0A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BEF0C66-0C6F0CE6-0CEF0D66-0D6F0E50-0E590ED0-0ED90F20-0F291040-10491090-109917E0-17E91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C59A620-A629A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19\",\n Nl: \"16EE-16F02160-21822185-218830073021-30293038-303AA6E6-A6EF\",\n No: \"00B200B300B900BC-00BE09F4-09F90BF0-0BF20C78-0C7E0D70-0D750F2A-0F331369-137C17F0-17F920702074-20792080-20892150-215F21892460-249B24EA-24FF2776-27932CFD3192-31953220-32293251-325F3280-328932B1-32BFA830-A835\",\n P: \"0021-00230025-002A002C-002F003A003B003F0040005B-005D005F007B007D00A100AB00B700BB00BF037E0387055A-055F0589058A05BE05C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F3A-0F3D0F850FD0-0FD4104A-104F10FB1361-13681400166D166E169B169C16EB-16ED1735173617D4-17D617D8-17DA1800-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD32010-20272030-20432045-20512053-205E207D207E208D208E2329232A2768-277527C527C627E6-27EF2983-299829D8-29DB29FC29FD2CF9-2CFC2CFE2CFF2E00-2E2E2E302E313001-30033008-30113014-301F3030303D30A030FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFD3EFD3FFE10-FE19FE30-FE52FE54-FE61FE63FE68FE6AFE6BFF01-FF03FF05-FF0AFF0C-FF0FFF1AFF1BFF1FFF20FF3B-FF3DFF3FFF5BFF5DFF5F-FF65\",\n Pd: \"002D058A05BE140018062010-20152E172E1A301C303030A0FE31FE32FE58FE63FF0D\",\n Ps: \"0028005B007B0F3A0F3C169B201A201E2045207D208D23292768276A276C276E27702772277427C527E627E827EA27EC27EE2983298529872989298B298D298F299129932995299729D829DA29FC2E222E242E262E283008300A300C300E3010301430163018301A301DFD3EFE17FE35FE37FE39FE3BFE3DFE3FFE41FE43FE47FE59FE5BFE5DFF08FF3BFF5BFF5FFF62\",\n Pe: \"0029005D007D0F3B0F3D169C2046207E208E232A2769276B276D276F27712773277527C627E727E927EB27ED27EF298429862988298A298C298E2990299229942996299829D929DB29FD2E232E252E272E293009300B300D300F3011301530173019301B301E301FFD3FFE18FE36FE38FE3AFE3CFE3EFE40FE42FE44FE48FE5AFE5CFE5EFF09FF3DFF5DFF60FF63\",\n Pi: \"00AB2018201B201C201F20392E022E042E092E0C2E1C2E20\",\n Pf: \"00BB2019201D203A2E032E052E0A2E0D2E1D2E21\",\n Pc: \"005F203F20402054FE33FE34FE4D-FE4FFF3F\",\n Po: \"0021-00230025-0027002A002C002E002F003A003B003F0040005C00A100B700BF037E0387055A-055F058905C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F850FD0-0FD4104A-104F10FB1361-1368166D166E16EB-16ED1735173617D4-17D617D8-17DA1800-18051807-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD3201620172020-20272030-2038203B-203E2041-20432047-205120532055-205E2CF9-2CFC2CFE2CFF2E002E012E06-2E082E0B2E0E-2E162E182E192E1B2E1E2E1F2E2A-2E2E2E302E313001-3003303D30FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFE10-FE16FE19FE30FE45FE46FE49-FE4CFE50-FE52FE54-FE57FE5F-FE61FE68FE6AFE6BFF01-FF03FF05-FF07FF0AFF0CFF0EFF0FFF1AFF1BFF1FFF20FF3CFF61FF64FF65\",\n S: \"0024002B003C-003E005E0060007C007E00A2-00A900AC00AE-00B100B400B600B800D700F702C2-02C502D2-02DF02E5-02EB02ED02EF-02FF03750384038503F604820606-0608060B060E060F06E906FD06FE07F609F209F309FA09FB0AF10B700BF3-0BFA0C7F0CF10CF20D790E3F0F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-139917DB194019E0-19FF1B61-1B6A1B74-1B7C1FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE20442052207A-207C208A-208C20A0-20B8210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B2140-2144214A-214D214F2190-2328232B-23E82400-24262440-244A249C-24E92500-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE27C0-27C427C7-27CA27CC27D0-27E527F0-29822999-29D729DC-29FB29FE-2B4C2B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F309B309C319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A700-A716A720A721A789A78AA828-A82BA836-A839AA77-AA79FB29FDFCFDFDFE62FE64-FE66FE69FF04FF0BFF1C-FF1EFF3EFF40FF5CFF5EFFE0-FFE6FFE8-FFEEFFFCFFFD\",\n Sm: \"002B003C-003E007C007E00AC00B100D700F703F60606-060820442052207A-207C208A-208C2140-2144214B2190-2194219A219B21A021A321A621AE21CE21CF21D221D421F4-22FF2308-230B23202321237C239B-23B323DC-23E125B725C125F8-25FF266F27C0-27C427C7-27CA27CC27D0-27E527F0-27FF2900-29822999-29D729DC-29FB29FE-2AFF2B30-2B442B47-2B4CFB29FE62FE64-FE66FF0BFF1C-FF1EFF5CFF5EFFE2FFE9-FFEC\",\n Sc: \"002400A2-00A5060B09F209F309FB0AF10BF90E3F17DB20A0-20B8A838FDFCFE69FF04FFE0FFE1FFE5FFE6\",\n Sk: \"005E006000A800AF00B400B802C2-02C502D2-02DF02E5-02EB02ED02EF-02FF0375038403851FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE309B309CA700-A716A720A721A789A78AFF3EFF40FFE3\",\n So: \"00A600A700A900AE00B000B60482060E060F06E906FD06FE07F609FA0B700BF3-0BF80BFA0C7F0CF10CF20D790F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-1399194019E0-19FF1B61-1B6A1B74-1B7C210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B214A214C214D214F2195-2199219C-219F21A121A221A421A521A7-21AD21AF-21CD21D021D121D321D5-21F32300-2307230C-231F2322-2328232B-237B237D-239A23B4-23DB23E2-23E82400-24262440-244A249C-24E92500-25B625B8-25C025C2-25F72600-266E2670-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE2800-28FF2B00-2B2F2B452B462B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A828-A82BA836A837A839AA77-AA79FDFDFFE4FFE8FFEDFFEEFFFCFFFD\",\n Z: \"002000A01680180E2000-200A20282029202F205F3000\",\n Zs: \"002000A01680180E2000-200A202F205F3000\",\n Zl: \"2028\",\n Zp: \"2029\",\n C: \"0000-001F007F-009F00AD03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-0605061C061D0620065F06DD070E070F074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17B417B517DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF200B-200F202A-202E2060-206F20722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-F8FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFD-FF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFFBFFFEFFFF\",\n Cc: \"0000-001F007F-009F\",\n Cf: \"00AD0600-060306DD070F17B417B5200B-200F202A-202E2060-2064206A-206FFEFFFFF9-FFFB\",\n Co: \"E000-F8FF\",\n Cs: \"D800-DFFF\",\n Cn: \"03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-05FF06040605061C061D0620065F070E074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF2065-206920722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-D7FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFDFEFEFF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFF8FFFEFFFF\"\n});\n\nfunction addUnicodePackage (pack) {\n var codePoint = /\\w{4}/g;\n for (var name in pack)\n exports.packages[name] = pack[name].replace(codePoint, \"\\\\u$&\");\n}\n\n});\n\nace.define(\"ace/token_iterator\",[\"require\",\"exports\",\"module\"], function(acequire, exports, module) {\n\"use strict\";\nvar TokenIterator = function(session, initialRow, initialColumn) {\n this.$session = session;\n this.$row = initialRow;\n this.$rowTokens = session.getTokens(initialRow);\n\n var token = session.getTokenAt(initialRow, initialColumn);\n this.$tokenIndex = token ? token.index : -1;\n};\n\n(function() { \n this.stepBackward = function() {\n this.$tokenIndex -= 1;\n \n while (this.$tokenIndex < 0) {\n this.$row -= 1;\n if (this.$row < 0) {\n this.$row = 0;\n return null;\n }\n \n this.$rowTokens = this.$session.getTokens(this.$row);\n this.$tokenIndex = this.$rowTokens.length - 1;\n }\n \n return this.$rowTokens[this.$tokenIndex];\n }; \n this.stepForward = function() {\n this.$tokenIndex += 1;\n var rowCount;\n while (this.$tokenIndex >= this.$rowTokens.length) {\n this.$row += 1;\n if (!rowCount)\n rowCount = this.$session.getLength();\n if (this.$row >= rowCount) {\n this.$row = rowCount - 1;\n return null;\n }\n\n this.$rowTokens = this.$session.getTokens(this.$row);\n this.$tokenIndex = 0;\n }\n \n return this.$rowTokens[this.$tokenIndex];\n }; \n this.getCurrentToken = function () {\n return this.$rowTokens[this.$tokenIndex];\n }; \n this.getCurrentTokenRow = function () {\n return this.$row;\n }; \n this.getCurrentTokenColumn = function() {\n var rowTokens = this.$rowTokens;\n var tokenIndex = this.$tokenIndex;\n var column = rowTokens[tokenIndex].start;\n if (column !== undefined)\n return column;\n \n column = 0;\n while (tokenIndex > 0) {\n tokenIndex -= 1;\n column += rowTokens[tokenIndex].value.length;\n }\n \n return column; \n };\n this.getCurrentTokenPosition = function() {\n return {row: this.$row, column: this.getCurrentTokenColumn()};\n };\n \n}).call(TokenIterator.prototype);\n\nexports.TokenIterator = TokenIterator;\n});\n\nace.define(\"ace/mode/text\",[\"require\",\"exports\",\"module\",\"ace/tokenizer\",\"ace/mode/text_highlight_rules\",\"ace/mode/behaviour\",\"ace/unicode\",\"ace/lib/lang\",\"ace/token_iterator\",\"ace/range\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar Tokenizer = acequire(\"../tokenizer\").Tokenizer;\nvar TextHighlightRules = acequire(\"./text_highlight_rules\").TextHighlightRules;\nvar Behaviour = acequire(\"./behaviour\").Behaviour;\nvar unicode = acequire(\"../unicode\");\nvar lang = acequire(\"../lib/lang\");\nvar TokenIterator = acequire(\"../token_iterator\").TokenIterator;\nvar Range = acequire(\"../range\").Range;\n\nvar Mode = function() {\n this.HighlightRules = TextHighlightRules;\n this.$behaviour = new Behaviour();\n};\n\n(function() {\n\n this.tokenRe = new RegExp(\"^[\"\n + unicode.packages.L\n + unicode.packages.Mn + unicode.packages.Mc\n + unicode.packages.Nd\n + unicode.packages.Pc + \"\\\\$_]+\", \"g\"\n );\n\n this.nonTokenRe = new RegExp(\"^(?:[^\"\n + unicode.packages.L\n + unicode.packages.Mn + unicode.packages.Mc\n + unicode.packages.Nd\n + unicode.packages.Pc + \"\\\\$_]|\\\\s])+\", \"g\"\n );\n\n this.getTokenizer = function() {\n if (!this.$tokenizer) {\n this.$highlightRules = this.$highlightRules || new this.HighlightRules();\n this.$tokenizer = new Tokenizer(this.$highlightRules.getRules());\n }\n return this.$tokenizer;\n };\n\n this.lineCommentStart = \"\";\n this.blockComment = \"\";\n\n this.toggleCommentLines = function(state, session, startRow, endRow) {\n var doc = session.doc;\n\n var ignoreBlankLines = true;\n var shouldRemove = true;\n var minIndent = Infinity;\n var tabSize = session.getTabSize();\n var insertAtTabStop = false;\n\n if (!this.lineCommentStart) {\n if (!this.blockComment)\n return false;\n var lineCommentStart = this.blockComment.start;\n var lineCommentEnd = this.blockComment.end;\n var regexpStart = new RegExp(\"^(\\\\s*)(?:\" + lang.escapeRegExp(lineCommentStart) + \")\");\n var regexpEnd = new RegExp(\"(?:\" + lang.escapeRegExp(lineCommentEnd) + \")\\\\s*$\");\n\n var comment = function(line, i) {\n if (testRemove(line, i))\n return;\n if (!ignoreBlankLines || /\\S/.test(line)) {\n doc.insertInLine({row: i, column: line.length}, lineCommentEnd);\n doc.insertInLine({row: i, column: minIndent}, lineCommentStart);\n }\n };\n\n var uncomment = function(line, i) {\n var m;\n if (m = line.match(regexpEnd))\n doc.removeInLine(i, line.length - m[0].length, line.length);\n if (m = line.match(regexpStart))\n doc.removeInLine(i, m[1].length, m[0].length);\n };\n\n var testRemove = function(line, row) {\n if (regexpStart.test(line))\n return true;\n var tokens = session.getTokens(row);\n for (var i = 0; i < tokens.length; i++) {\n if (tokens[i].type === \"comment\")\n return true;\n }\n };\n } else {\n if (Array.isArray(this.lineCommentStart)) {\n var regexpStart = this.lineCommentStart.map(lang.escapeRegExp).join(\"|\");\n var lineCommentStart = this.lineCommentStart[0];\n } else {\n var regexpStart = lang.escapeRegExp(this.lineCommentStart);\n var lineCommentStart = this.lineCommentStart;\n }\n regexpStart = new RegExp(\"^(\\\\s*)(?:\" + regexpStart + \") ?\");\n \n insertAtTabStop = session.getUseSoftTabs();\n\n var uncomment = function(line, i) {\n var m = line.match(regexpStart);\n if (!m) return;\n var start = m[1].length, end = m[0].length;\n if (!shouldInsertSpace(line, start, end) && m[0][end - 1] == \" \")\n end--;\n doc.removeInLine(i, start, end);\n };\n var commentWithSpace = lineCommentStart + \" \";\n var comment = function(line, i) {\n if (!ignoreBlankLines || /\\S/.test(line)) {\n if (shouldInsertSpace(line, minIndent, minIndent))\n doc.insertInLine({row: i, column: minIndent}, commentWithSpace);\n else\n doc.insertInLine({row: i, column: minIndent}, lineCommentStart);\n }\n };\n var testRemove = function(line, i) {\n return regexpStart.test(line);\n };\n \n var shouldInsertSpace = function(line, before, after) {\n var spaces = 0;\n while (before-- && line.charAt(before) == \" \")\n spaces++;\n if (spaces % tabSize != 0)\n return false;\n var spaces = 0;\n while (line.charAt(after++) == \" \")\n spaces++;\n if (tabSize > 2)\n return spaces % tabSize != tabSize - 1;\n else\n return spaces % tabSize == 0;\n return true;\n };\n }\n\n function iter(fun) {\n for (var i = startRow; i <= endRow; i++)\n fun(doc.getLine(i), i);\n }\n\n\n var minEmptyLength = Infinity;\n iter(function(line, i) {\n var indent = line.search(/\\S/);\n if (indent !== -1) {\n if (indent < minIndent)\n minIndent = indent;\n if (shouldRemove && !testRemove(line, i))\n shouldRemove = false;\n } else if (minEmptyLength > line.length) {\n minEmptyLength = line.length;\n }\n });\n\n if (minIndent == Infinity) {\n minIndent = minEmptyLength;\n ignoreBlankLines = false;\n shouldRemove = false;\n }\n\n if (insertAtTabStop && minIndent % tabSize != 0)\n minIndent = Math.floor(minIndent / tabSize) * tabSize;\n\n iter(shouldRemove ? uncomment : comment);\n };\n\n this.toggleBlockComment = function(state, session, range, cursor) {\n var comment = this.blockComment;\n if (!comment)\n return;\n if (!comment.start && comment[0])\n comment = comment[0];\n\n var iterator = new TokenIterator(session, cursor.row, cursor.column);\n var token = iterator.getCurrentToken();\n\n var sel = session.selection;\n var initialRange = session.selection.toOrientedRange();\n var startRow, colDiff;\n\n if (token && /comment/.test(token.type)) {\n var startRange, endRange;\n while (token && /comment/.test(token.type)) {\n var i = token.value.indexOf(comment.start);\n if (i != -1) {\n var row = iterator.getCurrentTokenRow();\n var column = iterator.getCurrentTokenColumn() + i;\n startRange = new Range(row, column, row, column + comment.start.length);\n break;\n }\n token = iterator.stepBackward();\n }\n\n var iterator = new TokenIterator(session, cursor.row, cursor.column);\n var token = iterator.getCurrentToken();\n while (token && /comment/.test(token.type)) {\n var i = token.value.indexOf(comment.end);\n if (i != -1) {\n var row = iterator.getCurrentTokenRow();\n var column = iterator.getCurrentTokenColumn() + i;\n endRange = new Range(row, column, row, column + comment.end.length);\n break;\n }\n token = iterator.stepForward();\n }\n if (endRange)\n session.remove(endRange);\n if (startRange) {\n session.remove(startRange);\n startRow = startRange.start.row;\n colDiff = -comment.start.length;\n }\n } else {\n colDiff = comment.start.length;\n startRow = range.start.row;\n session.insert(range.end, comment.end);\n session.insert(range.start, comment.start);\n }\n if (initialRange.start.row == startRow)\n initialRange.start.column += colDiff;\n if (initialRange.end.row == startRow)\n initialRange.end.column += colDiff;\n session.selection.fromOrientedRange(initialRange);\n };\n\n this.getNextLineIndent = function(state, line, tab) {\n return this.$getIndent(line);\n };\n\n this.checkOutdent = function(state, line, input) {\n return false;\n };\n\n this.autoOutdent = function(state, doc, row) {\n };\n\n this.$getIndent = function(line) {\n return line.match(/^\\s*/)[0];\n };\n\n this.createWorker = function(session) {\n return null;\n };\n\n this.createModeDelegates = function (mapping) {\n this.$embeds = [];\n this.$modes = {};\n for (var i in mapping) {\n if (mapping[i]) {\n this.$embeds.push(i);\n this.$modes[i] = new mapping[i]();\n }\n }\n\n var delegations = [\"toggleBlockComment\", \"toggleCommentLines\", \"getNextLineIndent\", \n \"checkOutdent\", \"autoOutdent\", \"transformAction\", \"getCompletions\"];\n\n for (var i = 0; i < delegations.length; i++) {\n (function(scope) {\n var functionName = delegations[i];\n var defaultHandler = scope[functionName];\n scope[delegations[i]] = function() {\n return this.$delegator(functionName, arguments, defaultHandler);\n };\n }(this));\n }\n };\n\n this.$delegator = function(method, args, defaultHandler) {\n var state = args[0];\n if (typeof state != \"string\")\n state = state[0];\n for (var i = 0; i < this.$embeds.length; i++) {\n if (!this.$modes[this.$embeds[i]]) continue;\n\n var split = state.split(this.$embeds[i]);\n if (!split[0] && split[1]) {\n args[0] = split[1];\n var mode = this.$modes[this.$embeds[i]];\n return mode[method].apply(mode, args);\n }\n }\n var ret = defaultHandler.apply(this, args);\n return defaultHandler ? ret : undefined;\n };\n\n this.transformAction = function(state, action, editor, session, param) {\n if (this.$behaviour) {\n var behaviours = this.$behaviour.getBehaviours();\n for (var key in behaviours) {\n if (behaviours[key][action]) {\n var ret = behaviours[key][action].apply(this, arguments);\n if (ret) {\n return ret;\n }\n }\n }\n }\n };\n \n this.getKeywords = function(append) {\n if (!this.completionKeywords) {\n var rules = this.$tokenizer.rules;\n var completionKeywords = [];\n for (var rule in rules) {\n var ruleItr = rules[rule];\n for (var r = 0, l = ruleItr.length; r < l; r++) {\n if (typeof ruleItr[r].token === \"string\") {\n if (/keyword|support|storage/.test(ruleItr[r].token))\n completionKeywords.push(ruleItr[r].regex);\n }\n else if (typeof ruleItr[r].token === \"object\") {\n for (var a = 0, aLength = ruleItr[r].token.length; a < aLength; a++) { \n if (/keyword|support|storage/.test(ruleItr[r].token[a])) {\n var rule = ruleItr[r].regex.match(/\\(.+?\\)/g)[a];\n completionKeywords.push(rule.substr(1, rule.length - 2));\n }\n }\n }\n }\n }\n this.completionKeywords = completionKeywords;\n }\n if (!append)\n return this.$keywordList;\n return completionKeywords.concat(this.$keywordList || []);\n };\n \n this.$createKeywordList = function() {\n if (!this.$highlightRules)\n this.getTokenizer();\n return this.$keywordList = this.$highlightRules.$keywordList || [];\n };\n\n this.getCompletions = function(state, session, pos, prefix) {\n var keywords = this.$keywordList || this.$createKeywordList();\n return keywords.map(function(word) {\n return {\n name: word,\n value: word,\n score: 0,\n meta: \"keyword\"\n };\n });\n };\n\n this.$id = \"ace/mode/text\";\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n});\n\nace.define(\"ace/apply_delta\",[\"require\",\"exports\",\"module\"], function(acequire, exports, module) {\n\"use strict\";\n\nfunction throwDeltaError(delta, errorText){\n console.log(\"Invalid Delta:\", delta);\n throw \"Invalid Delta: \" + errorText;\n}\n\nfunction positionInDocument(docLines, position) {\n return position.row >= 0 && position.row < docLines.length &&\n position.column >= 0 && position.column <= docLines[position.row].length;\n}\n\nfunction validateDelta(docLines, delta) {\n if (delta.action != \"insert\" && delta.action != \"remove\")\n throwDeltaError(delta, \"delta.action must be 'insert' or 'remove'\");\n if (!(delta.lines instanceof Array))\n throwDeltaError(delta, \"delta.lines must be an Array\");\n if (!delta.start || !delta.end)\n throwDeltaError(delta, \"delta.start/end must be an present\");\n var start = delta.start;\n if (!positionInDocument(docLines, delta.start))\n throwDeltaError(delta, \"delta.start must be contained in document\");\n var end = delta.end;\n if (delta.action == \"remove\" && !positionInDocument(docLines, end))\n throwDeltaError(delta, \"delta.end must contained in document for 'remove' actions\");\n var numRangeRows = end.row - start.row;\n var numRangeLastLineChars = (end.column - (numRangeRows == 0 ? start.column : 0));\n if (numRangeRows != delta.lines.length - 1 || delta.lines[numRangeRows].length != numRangeLastLineChars)\n throwDeltaError(delta, \"delta.range must match delta lines\");\n}\n\nexports.applyDelta = function(docLines, delta, doNotValidate) {\n \n var row = delta.start.row;\n var startColumn = delta.start.column;\n var line = docLines[row] || \"\";\n switch (delta.action) {\n case \"insert\":\n var lines = delta.lines;\n if (lines.length === 1) {\n docLines[row] = line.substring(0, startColumn) + delta.lines[0] + line.substring(startColumn);\n } else {\n var args = [row, 1].concat(delta.lines);\n docLines.splice.apply(docLines, args);\n docLines[row] = line.substring(0, startColumn) + docLines[row];\n docLines[row + delta.lines.length - 1] += line.substring(startColumn);\n }\n break;\n case \"remove\":\n var endColumn = delta.end.column;\n var endRow = delta.end.row;\n if (row === endRow) {\n docLines[row] = line.substring(0, startColumn) + line.substring(endColumn);\n } else {\n docLines.splice(\n row, endRow - row + 1,\n line.substring(0, startColumn) + docLines[endRow].substring(endColumn)\n );\n }\n break;\n }\n}\n});\n\nace.define(\"ace/anchor\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/event_emitter\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar oop = acequire(\"./lib/oop\");\nvar EventEmitter = acequire(\"./lib/event_emitter\").EventEmitter;\n\nvar Anchor = exports.Anchor = function(doc, row, column) {\n this.$onChange = this.onChange.bind(this);\n this.attach(doc);\n \n if (typeof column == \"undefined\")\n this.setPosition(row.row, row.column);\n else\n this.setPosition(row, column);\n};\n\n(function() {\n\n oop.implement(this, EventEmitter);\n this.getPosition = function() {\n return this.$clipPositionToDocument(this.row, this.column);\n };\n this.getDocument = function() {\n return this.document;\n };\n this.$insertRight = false;\n this.onChange = function(delta) {\n if (delta.start.row == delta.end.row && delta.start.row != this.row)\n return;\n\n if (delta.start.row > this.row)\n return;\n \n var point = $getTransformedPoint(delta, {row: this.row, column: this.column}, this.$insertRight);\n this.setPosition(point.row, point.column, true);\n };\n \n function $pointsInOrder(point1, point2, equalPointsInOrder) {\n var bColIsAfter = equalPointsInOrder ? point1.column <= point2.column : point1.column < point2.column;\n return (point1.row < point2.row) || (point1.row == point2.row && bColIsAfter);\n }\n \n function $getTransformedPoint(delta, point, moveIfEqual) {\n var deltaIsInsert = delta.action == \"insert\";\n var deltaRowShift = (deltaIsInsert ? 1 : -1) * (delta.end.row - delta.start.row);\n var deltaColShift = (deltaIsInsert ? 1 : -1) * (delta.end.column - delta.start.column);\n var deltaStart = delta.start;\n var deltaEnd = deltaIsInsert ? deltaStart : delta.end; // Collapse insert range.\n if ($pointsInOrder(point, deltaStart, moveIfEqual)) {\n return {\n row: point.row,\n column: point.column\n };\n }\n if ($pointsInOrder(deltaEnd, point, !moveIfEqual)) {\n return {\n row: point.row + deltaRowShift,\n column: point.column + (point.row == deltaEnd.row ? deltaColShift : 0)\n };\n }\n \n return {\n row: deltaStart.row,\n column: deltaStart.column\n };\n }\n this.setPosition = function(row, column, noClip) {\n var pos;\n if (noClip) {\n pos = {\n row: row,\n column: column\n };\n } else {\n pos = this.$clipPositionToDocument(row, column);\n }\n\n if (this.row == pos.row && this.column == pos.column)\n return;\n\n var old = {\n row: this.row,\n column: this.column\n };\n\n this.row = pos.row;\n this.column = pos.column;\n this._signal(\"change\", {\n old: old,\n value: pos\n });\n };\n this.detach = function() {\n this.document.removeEventListener(\"change\", this.$onChange);\n };\n this.attach = function(doc) {\n this.document = doc || this.document;\n this.document.on(\"change\", this.$onChange);\n };\n this.$clipPositionToDocument = function(row, column) {\n var pos = {};\n\n if (row >= this.document.getLength()) {\n pos.row = Math.max(0, this.document.getLength() - 1);\n pos.column = this.document.getLine(pos.row).length;\n }\n else if (row < 0) {\n pos.row = 0;\n pos.column = 0;\n }\n else {\n pos.row = row;\n pos.column = Math.min(this.document.getLine(pos.row).length, Math.max(0, column));\n }\n\n if (column < 0)\n pos.column = 0;\n\n return pos;\n };\n\n}).call(Anchor.prototype);\n\n});\n\nace.define(\"ace/document\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/apply_delta\",\"ace/lib/event_emitter\",\"ace/range\",\"ace/anchor\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar oop = acequire(\"./lib/oop\");\nvar applyDelta = acequire(\"./apply_delta\").applyDelta;\nvar EventEmitter = acequire(\"./lib/event_emitter\").EventEmitter;\nvar Range = acequire(\"./range\").Range;\nvar Anchor = acequire(\"./anchor\").Anchor;\n\nvar Document = function(textOrLines) {\n this.$lines = [\"\"];\n if (textOrLines.length === 0) {\n this.$lines = [\"\"];\n } else if (Array.isArray(textOrLines)) {\n this.insertMergedLines({row: 0, column: 0}, textOrLines);\n } else {\n this.insert({row: 0, column:0}, textOrLines);\n }\n};\n\n(function() {\n\n oop.implement(this, EventEmitter);\n this.setValue = function(text) {\n var len = this.getLength() - 1;\n this.remove(new Range(0, 0, len, this.getLine(len).length));\n this.insert({row: 0, column: 0}, text);\n };\n this.getValue = function() {\n return this.getAllLines().join(this.getNewLineCharacter());\n };\n this.createAnchor = function(row, column) {\n return new Anchor(this, row, column);\n };\n if (\"aaa\".split(/a/).length === 0) {\n this.$split = function(text) {\n return text.replace(/\\r\\n|\\r/g, \"\\n\").split(\"\\n\");\n };\n } else {\n this.$split = function(text) {\n return text.split(/\\r\\n|\\r|\\n/);\n };\n }\n\n\n this.$detectNewLine = function(text) {\n var match = text.match(/^.*?(\\r\\n|\\r|\\n)/m);\n this.$autoNewLine = match ? match[1] : \"\\n\";\n this._signal(\"changeNewLineMode\");\n };\n this.getNewLineCharacter = function() {\n switch (this.$newLineMode) {\n case \"windows\":\n return \"\\r\\n\";\n case \"unix\":\n return \"\\n\";\n default:\n return this.$autoNewLine || \"\\n\";\n }\n };\n\n this.$autoNewLine = \"\";\n this.$newLineMode = \"auto\";\n this.setNewLineMode = function(newLineMode) {\n if (this.$newLineMode === newLineMode)\n return;\n\n this.$newLineMode = newLineMode;\n this._signal(\"changeNewLineMode\");\n };\n this.getNewLineMode = function() {\n return this.$newLineMode;\n };\n this.isNewLine = function(text) {\n return (text == \"\\r\\n\" || text == \"\\r\" || text == \"\\n\");\n };\n this.getLine = function(row) {\n return this.$lines[row] || \"\";\n };\n this.getLines = function(firstRow, lastRow) {\n return this.$lines.slice(firstRow, lastRow + 1);\n };\n this.getAllLines = function() {\n return this.getLines(0, this.getLength());\n };\n this.getLength = function() {\n return this.$lines.length;\n };\n this.getTextRange = function(range) {\n return this.getLinesForRange(range).join(this.getNewLineCharacter());\n };\n this.getLinesForRange = function(range) {\n var lines;\n if (range.start.row === range.end.row) {\n lines = [this.getLine(range.start.row).substring(range.start.column, range.end.column)];\n } else {\n lines = this.getLines(range.start.row, range.end.row);\n lines[0] = (lines[0] || \"\").substring(range.start.column);\n var l = lines.length - 1;\n if (range.end.row - range.start.row == l)\n lines[l] = lines[l].substring(0, range.end.column);\n }\n return lines;\n };\n this.insertLines = function(row, lines) {\n console.warn(\"Use of document.insertLines is deprecated. Use the insertFullLines method instead.\");\n return this.insertFullLines(row, lines);\n };\n this.removeLines = function(firstRow, lastRow) {\n console.warn(\"Use of document.removeLines is deprecated. Use the removeFullLines method instead.\");\n return this.removeFullLines(firstRow, lastRow);\n };\n this.insertNewLine = function(position) {\n console.warn(\"Use of document.insertNewLine is deprecated. Use insertMergedLines(position, [\\'\\', \\'\\']) instead.\");\n return this.insertMergedLines(position, [\"\", \"\"]);\n };\n this.insert = function(position, text) {\n if (this.getLength() <= 1)\n this.$detectNewLine(text);\n \n return this.insertMergedLines(position, this.$split(text));\n };\n this.insertInLine = function(position, text) {\n var start = this.clippedPos(position.row, position.column);\n var end = this.pos(position.row, position.column + text.length);\n \n this.applyDelta({\n start: start,\n end: end,\n action: \"insert\",\n lines: [text]\n }, true);\n \n return this.clonePos(end);\n };\n \n this.clippedPos = function(row, column) {\n var length = this.getLength();\n if (row === undefined) {\n row = length;\n } else if (row < 0) {\n row = 0;\n } else if (row >= length) {\n row = length - 1;\n column = undefined;\n }\n var line = this.getLine(row);\n if (column == undefined)\n column = line.length;\n column = Math.min(Math.max(column, 0), line.length);\n return {row: row, column: column};\n };\n \n this.clonePos = function(pos) {\n return {row: pos.row, column: pos.column};\n };\n \n this.pos = function(row, column) {\n return {row: row, column: column};\n };\n \n this.$clipPosition = function(position) {\n var length = this.getLength();\n if (position.row >= length) {\n position.row = Math.max(0, length - 1);\n position.column = this.getLine(length - 1).length;\n } else {\n position.row = Math.max(0, position.row);\n position.column = Math.min(Math.max(position.column, 0), this.getLine(position.row).length);\n }\n return position;\n };\n this.insertFullLines = function(row, lines) {\n row = Math.min(Math.max(row, 0), this.getLength());\n var column = 0;\n if (row < this.getLength()) {\n lines = lines.concat([\"\"]);\n column = 0;\n } else {\n lines = [\"\"].concat(lines);\n row--;\n column = this.$lines[row].length;\n }\n this.insertMergedLines({row: row, column: column}, lines);\n }; \n this.insertMergedLines = function(position, lines) {\n var start = this.clippedPos(position.row, position.column);\n var end = {\n row: start.row + lines.length - 1,\n column: (lines.length == 1 ? start.column : 0) + lines[lines.length - 1].length\n };\n \n this.applyDelta({\n start: start,\n end: end,\n action: \"insert\",\n lines: lines\n });\n \n return this.clonePos(end);\n };\n this.remove = function(range) {\n var start = this.clippedPos(range.start.row, range.start.column);\n var end = this.clippedPos(range.end.row, range.end.column);\n this.applyDelta({\n start: start,\n end: end,\n action: \"remove\",\n lines: this.getLinesForRange({start: start, end: end})\n });\n return this.clonePos(start);\n };\n this.removeInLine = function(row, startColumn, endColumn) {\n var start = this.clippedPos(row, startColumn);\n var end = this.clippedPos(row, endColumn);\n \n this.applyDelta({\n start: start,\n end: end,\n action: \"remove\",\n lines: this.getLinesForRange({start: start, end: end})\n }, true);\n \n return this.clonePos(start);\n };\n this.removeFullLines = function(firstRow, lastRow) {\n firstRow = Math.min(Math.max(0, firstRow), this.getLength() - 1);\n lastRow = Math.min(Math.max(0, lastRow ), this.getLength() - 1);\n var deleteFirstNewLine = lastRow == this.getLength() - 1 && firstRow > 0;\n var deleteLastNewLine = lastRow < this.getLength() - 1;\n var startRow = ( deleteFirstNewLine ? firstRow - 1 : firstRow );\n var startCol = ( deleteFirstNewLine ? this.getLine(startRow).length : 0 );\n var endRow = ( deleteLastNewLine ? lastRow + 1 : lastRow );\n var endCol = ( deleteLastNewLine ? 0 : this.getLine(endRow).length ); \n var range = new Range(startRow, startCol, endRow, endCol);\n var deletedLines = this.$lines.slice(firstRow, lastRow + 1);\n \n this.applyDelta({\n start: range.start,\n end: range.end,\n action: \"remove\",\n lines: this.getLinesForRange(range)\n });\n return deletedLines;\n };\n this.removeNewLine = function(row) {\n if (row < this.getLength() - 1 && row >= 0) {\n this.applyDelta({\n start: this.pos(row, this.getLine(row).length),\n end: this.pos(row + 1, 0),\n action: \"remove\",\n lines: [\"\", \"\"]\n });\n }\n };\n this.replace = function(range, text) {\n if (!(range instanceof Range))\n range = Range.fromPoints(range.start, range.end);\n if (text.length === 0 && range.isEmpty())\n return range.start;\n if (text == this.getTextRange(range))\n return range.end;\n\n this.remove(range);\n var end;\n if (text) {\n end = this.insert(range.start, text);\n }\n else {\n end = range.start;\n }\n \n return end;\n };\n this.applyDeltas = function(deltas) {\n for (var i=0; i=0; i--) {\n this.revertDelta(deltas[i]);\n }\n };\n this.applyDelta = function(delta, doNotValidate) {\n var isInsert = delta.action == \"insert\";\n if (isInsert ? delta.lines.length <= 1 && !delta.lines[0]\n : !Range.comparePoints(delta.start, delta.end)) {\n return;\n }\n \n if (isInsert && delta.lines.length > 20000)\n this.$splitAndapplyLargeDelta(delta, 20000);\n applyDelta(this.$lines, delta, doNotValidate);\n this._signal(\"change\", delta);\n };\n \n this.$splitAndapplyLargeDelta = function(delta, MAX) {\n var lines = delta.lines;\n var l = lines.length;\n var row = delta.start.row; \n var column = delta.start.column;\n var from = 0, to = 0;\n do {\n from = to;\n to += MAX - 1;\n var chunk = lines.slice(from, to);\n if (to > l) {\n delta.lines = chunk;\n delta.start.row = row + from;\n delta.start.column = column;\n break;\n }\n chunk.push(\"\");\n this.applyDelta({\n start: this.pos(row + from, column),\n end: this.pos(row + to, column = 0),\n action: delta.action,\n lines: chunk\n }, true);\n } while(true);\n };\n this.revertDelta = function(delta) {\n this.applyDelta({\n start: this.clonePos(delta.start),\n end: this.clonePos(delta.end),\n action: (delta.action == \"insert\" ? \"remove\" : \"insert\"),\n lines: delta.lines.slice()\n });\n };\n this.indexToPosition = function(index, startRow) {\n var lines = this.$lines || this.getAllLines();\n var newlineLength = this.getNewLineCharacter().length;\n for (var i = startRow || 0, l = lines.length; i < l; i++) {\n index -= lines[i].length + newlineLength;\n if (index < 0)\n return {row: i, column: index + lines[i].length + newlineLength};\n }\n return {row: l-1, column: lines[l-1].length};\n };\n this.positionToIndex = function(pos, startRow) {\n var lines = this.$lines || this.getAllLines();\n var newlineLength = this.getNewLineCharacter().length;\n var index = 0;\n var row = Math.min(pos.row, lines.length);\n for (var i = startRow || 0; i < row; ++i)\n index += lines[i].length + newlineLength;\n\n return index + pos.column;\n };\n\n}).call(Document.prototype);\n\nexports.Document = Document;\n});\n\nace.define(\"ace/background_tokenizer\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/event_emitter\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar oop = acequire(\"./lib/oop\");\nvar EventEmitter = acequire(\"./lib/event_emitter\").EventEmitter;\n\nvar BackgroundTokenizer = function(tokenizer, editor) {\n this.running = false;\n this.lines = [];\n this.states = [];\n this.currentLine = 0;\n this.tokenizer = tokenizer;\n\n var self = this;\n\n this.$worker = function() {\n if (!self.running) { return; }\n\n var workerStart = new Date();\n var currentLine = self.currentLine;\n var endLine = -1;\n var doc = self.doc;\n\n var startLine = currentLine;\n while (self.lines[currentLine])\n currentLine++;\n \n var len = doc.getLength();\n var processedLines = 0;\n self.running = false;\n while (currentLine < len) {\n self.$tokenizeRow(currentLine);\n endLine = currentLine;\n do {\n currentLine++;\n } while (self.lines[currentLine]);\n processedLines ++;\n if ((processedLines % 5 === 0) && (new Date() - workerStart) > 20) { \n self.running = setTimeout(self.$worker, 20);\n break;\n }\n }\n self.currentLine = currentLine;\n \n if (startLine <= endLine)\n self.fireUpdateEvent(startLine, endLine);\n };\n};\n\n(function(){\n\n oop.implement(this, EventEmitter);\n this.setTokenizer = function(tokenizer) {\n this.tokenizer = tokenizer;\n this.lines = [];\n this.states = [];\n\n this.start(0);\n };\n this.setDocument = function(doc) {\n this.doc = doc;\n this.lines = [];\n this.states = [];\n\n this.stop();\n };\n this.fireUpdateEvent = function(firstRow, lastRow) {\n var data = {\n first: firstRow,\n last: lastRow\n };\n this._signal(\"update\", {data: data});\n };\n this.start = function(startRow) {\n this.currentLine = Math.min(startRow || 0, this.currentLine, this.doc.getLength());\n this.lines.splice(this.currentLine, this.lines.length);\n this.states.splice(this.currentLine, this.states.length);\n\n this.stop();\n this.running = setTimeout(this.$worker, 700);\n };\n \n this.scheduleStart = function() {\n if (!this.running)\n this.running = setTimeout(this.$worker, 700);\n }\n\n this.$updateOnChange = function(delta) {\n var startRow = delta.start.row;\n var len = delta.end.row - startRow;\n\n if (len === 0) {\n this.lines[startRow] = null;\n } else if (delta.action == \"remove\") {\n this.lines.splice(startRow, len + 1, null);\n this.states.splice(startRow, len + 1, null);\n } else {\n var args = Array(len + 1);\n args.unshift(startRow, 1);\n this.lines.splice.apply(this.lines, args);\n this.states.splice.apply(this.states, args);\n }\n\n this.currentLine = Math.min(startRow, this.currentLine, this.doc.getLength());\n\n this.stop();\n };\n this.stop = function() {\n if (this.running)\n clearTimeout(this.running);\n this.running = false;\n };\n this.getTokens = function(row) {\n return this.lines[row] || this.$tokenizeRow(row);\n };\n this.getState = function(row) {\n if (this.currentLine == row)\n this.$tokenizeRow(row);\n return this.states[row] || \"start\";\n };\n\n this.$tokenizeRow = function(row) {\n var line = this.doc.getLine(row);\n var state = this.states[row - 1];\n\n var data = this.tokenizer.getLineTokens(line, state, row);\n\n if (this.states[row] + \"\" !== data.state + \"\") {\n this.states[row] = data.state;\n this.lines[row + 1] = null;\n if (this.currentLine > row + 1)\n this.currentLine = row + 1;\n } else if (this.currentLine == row) {\n this.currentLine = row + 1;\n }\n\n return this.lines[row] = data.tokens;\n };\n\n}).call(BackgroundTokenizer.prototype);\n\nexports.BackgroundTokenizer = BackgroundTokenizer;\n});\n\nace.define(\"ace/search_highlight\",[\"require\",\"exports\",\"module\",\"ace/lib/lang\",\"ace/lib/oop\",\"ace/range\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar lang = acequire(\"./lib/lang\");\nvar oop = acequire(\"./lib/oop\");\nvar Range = acequire(\"./range\").Range;\n\nvar SearchHighlight = function(regExp, clazz, type) {\n this.setRegexp(regExp);\n this.clazz = clazz;\n this.type = type || \"text\";\n};\n\n(function() {\n this.MAX_RANGES = 500;\n \n this.setRegexp = function(regExp) {\n if (this.regExp+\"\" == regExp+\"\")\n return;\n this.regExp = regExp;\n this.cache = [];\n };\n\n this.update = function(html, markerLayer, session, config) {\n if (!this.regExp)\n return;\n var start = config.firstRow, end = config.lastRow;\n\n for (var i = start; i <= end; i++) {\n var ranges = this.cache[i];\n if (ranges == null) {\n ranges = lang.getMatchOffsets(session.getLine(i), this.regExp);\n if (ranges.length > this.MAX_RANGES)\n ranges = ranges.slice(0, this.MAX_RANGES);\n ranges = ranges.map(function(match) {\n return new Range(i, match.offset, i, match.offset + match.length);\n });\n this.cache[i] = ranges.length ? ranges : \"\";\n }\n\n for (var j = ranges.length; j --; ) {\n markerLayer.drawSingleLineMarker(\n html, ranges[j].toScreenRange(session), this.clazz, config);\n }\n }\n };\n\n}).call(SearchHighlight.prototype);\n\nexports.SearchHighlight = SearchHighlight;\n});\n\nace.define(\"ace/edit_session/fold_line\",[\"require\",\"exports\",\"module\",\"ace/range\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar Range = acequire(\"../range\").Range;\nfunction FoldLine(foldData, folds) {\n this.foldData = foldData;\n if (Array.isArray(folds)) {\n this.folds = folds;\n } else {\n folds = this.folds = [ folds ];\n }\n\n var last = folds[folds.length - 1];\n this.range = new Range(folds[0].start.row, folds[0].start.column,\n last.end.row, last.end.column);\n this.start = this.range.start;\n this.end = this.range.end;\n\n this.folds.forEach(function(fold) {\n fold.setFoldLine(this);\n }, this);\n}\n\n(function() {\n this.shiftRow = function(shift) {\n this.start.row += shift;\n this.end.row += shift;\n this.folds.forEach(function(fold) {\n fold.start.row += shift;\n fold.end.row += shift;\n });\n };\n\n this.addFold = function(fold) {\n if (fold.sameRow) {\n if (fold.start.row < this.startRow || fold.endRow > this.endRow) {\n throw new Error(\"Can't add a fold to this FoldLine as it has no connection\");\n }\n this.folds.push(fold);\n this.folds.sort(function(a, b) {\n return -a.range.compareEnd(b.start.row, b.start.column);\n });\n if (this.range.compareEnd(fold.start.row, fold.start.column) > 0) {\n this.end.row = fold.end.row;\n this.end.column = fold.end.column;\n } else if (this.range.compareStart(fold.end.row, fold.end.column) < 0) {\n this.start.row = fold.start.row;\n this.start.column = fold.start.column;\n }\n } else if (fold.start.row == this.end.row) {\n this.folds.push(fold);\n this.end.row = fold.end.row;\n this.end.column = fold.end.column;\n } else if (fold.end.row == this.start.row) {\n this.folds.unshift(fold);\n this.start.row = fold.start.row;\n this.start.column = fold.start.column;\n } else {\n throw new Error(\"Trying to add fold to FoldRow that doesn't have a matching row\");\n }\n fold.foldLine = this;\n };\n\n this.containsRow = function(row) {\n return row >= this.start.row && row <= this.end.row;\n };\n\n this.walk = function(callback, endRow, endColumn) {\n var lastEnd = 0,\n folds = this.folds,\n fold,\n cmp, stop, isNewRow = true;\n\n if (endRow == null) {\n endRow = this.end.row;\n endColumn = this.end.column;\n }\n\n for (var i = 0; i < folds.length; i++) {\n fold = folds[i];\n\n cmp = fold.range.compareStart(endRow, endColumn);\n if (cmp == -1) {\n callback(null, endRow, endColumn, lastEnd, isNewRow);\n return;\n }\n\n stop = callback(null, fold.start.row, fold.start.column, lastEnd, isNewRow);\n stop = !stop && callback(fold.placeholder, fold.start.row, fold.start.column, lastEnd);\n if (stop || cmp === 0) {\n return;\n }\n isNewRow = !fold.sameRow;\n lastEnd = fold.end.column;\n }\n callback(null, endRow, endColumn, lastEnd, isNewRow);\n };\n\n this.getNextFoldTo = function(row, column) {\n var fold, cmp;\n for (var i = 0; i < this.folds.length; i++) {\n fold = this.folds[i];\n cmp = fold.range.compareEnd(row, column);\n if (cmp == -1) {\n return {\n fold: fold,\n kind: \"after\"\n };\n } else if (cmp === 0) {\n return {\n fold: fold,\n kind: \"inside\"\n };\n }\n }\n return null;\n };\n\n this.addRemoveChars = function(row, column, len) {\n var ret = this.getNextFoldTo(row, column),\n fold, folds;\n if (ret) {\n fold = ret.fold;\n if (ret.kind == \"inside\"\n && fold.start.column != column\n && fold.start.row != row)\n {\n window.console && window.console.log(row, column, fold);\n } else if (fold.start.row == row) {\n folds = this.folds;\n var i = folds.indexOf(fold);\n if (i === 0) {\n this.start.column += len;\n }\n for (i; i < folds.length; i++) {\n fold = folds[i];\n fold.start.column += len;\n if (!fold.sameRow) {\n return;\n }\n fold.end.column += len;\n }\n this.end.column += len;\n }\n }\n };\n\n this.split = function(row, column) {\n var pos = this.getNextFoldTo(row, column);\n \n if (!pos || pos.kind == \"inside\")\n return null;\n \n var fold = pos.fold;\n var folds = this.folds;\n var foldData = this.foldData;\n \n var i = folds.indexOf(fold);\n var foldBefore = folds[i - 1];\n this.end.row = foldBefore.end.row;\n this.end.column = foldBefore.end.column;\n folds = folds.splice(i, folds.length - i);\n\n var newFoldLine = new FoldLine(foldData, folds);\n foldData.splice(foldData.indexOf(this) + 1, 0, newFoldLine);\n return newFoldLine;\n };\n\n this.merge = function(foldLineNext) {\n var folds = foldLineNext.folds;\n for (var i = 0; i < folds.length; i++) {\n this.addFold(folds[i]);\n }\n var foldData = this.foldData;\n foldData.splice(foldData.indexOf(foldLineNext), 1);\n };\n\n this.toString = function() {\n var ret = [this.range.toString() + \": [\" ];\n\n this.folds.forEach(function(fold) {\n ret.push(\" \" + fold.toString());\n });\n ret.push(\"]\");\n return ret.join(\"\\n\");\n };\n\n this.idxToPosition = function(idx) {\n var lastFoldEndColumn = 0;\n\n for (var i = 0; i < this.folds.length; i++) {\n var fold = this.folds[i];\n\n idx -= fold.start.column - lastFoldEndColumn;\n if (idx < 0) {\n return {\n row: fold.start.row,\n column: fold.start.column + idx\n };\n }\n\n idx -= fold.placeholder.length;\n if (idx < 0) {\n return fold.start;\n }\n\n lastFoldEndColumn = fold.end.column;\n }\n\n return {\n row: this.end.row,\n column: this.end.column + idx\n };\n };\n}).call(FoldLine.prototype);\n\nexports.FoldLine = FoldLine;\n});\n\nace.define(\"ace/range_list\",[\"require\",\"exports\",\"module\",\"ace/range\"], function(acequire, exports, module) {\n\"use strict\";\nvar Range = acequire(\"./range\").Range;\nvar comparePoints = Range.comparePoints;\n\nvar RangeList = function() {\n this.ranges = [];\n};\n\n(function() {\n this.comparePoints = comparePoints;\n\n this.pointIndex = function(pos, excludeEdges, startIndex) {\n var list = this.ranges;\n\n for (var i = startIndex || 0; i < list.length; i++) {\n var range = list[i];\n var cmpEnd = comparePoints(pos, range.end);\n if (cmpEnd > 0)\n continue;\n var cmpStart = comparePoints(pos, range.start);\n if (cmpEnd === 0)\n return excludeEdges && cmpStart !== 0 ? -i-2 : i;\n if (cmpStart > 0 || (cmpStart === 0 && !excludeEdges))\n return i;\n\n return -i-1;\n }\n return -i - 1;\n };\n\n this.add = function(range) {\n var excludeEdges = !range.isEmpty();\n var startIndex = this.pointIndex(range.start, excludeEdges);\n if (startIndex < 0)\n startIndex = -startIndex - 1;\n\n var endIndex = this.pointIndex(range.end, excludeEdges, startIndex);\n\n if (endIndex < 0)\n endIndex = -endIndex - 1;\n else\n endIndex++;\n return this.ranges.splice(startIndex, endIndex - startIndex, range);\n };\n\n this.addList = function(list) {\n var removed = [];\n for (var i = list.length; i--; ) {\n removed.push.apply(removed, this.add(list[i]));\n }\n return removed;\n };\n\n this.substractPoint = function(pos) {\n var i = this.pointIndex(pos);\n\n if (i >= 0)\n return this.ranges.splice(i, 1);\n };\n this.merge = function() {\n var removed = [];\n var list = this.ranges;\n \n list = list.sort(function(a, b) {\n return comparePoints(a.start, b.start);\n });\n \n var next = list[0], range;\n for (var i = 1; i < list.length; i++) {\n range = next;\n next = list[i];\n var cmp = comparePoints(range.end, next.start);\n if (cmp < 0)\n continue;\n\n if (cmp == 0 && !range.isEmpty() && !next.isEmpty())\n continue;\n\n if (comparePoints(range.end, next.end) < 0) {\n range.end.row = next.end.row;\n range.end.column = next.end.column;\n }\n\n list.splice(i, 1);\n removed.push(next);\n next = range;\n i--;\n }\n \n this.ranges = list;\n\n return removed;\n };\n\n this.contains = function(row, column) {\n return this.pointIndex({row: row, column: column}) >= 0;\n };\n\n this.containsPoint = function(pos) {\n return this.pointIndex(pos) >= 0;\n };\n\n this.rangeAtPoint = function(pos) {\n var i = this.pointIndex(pos);\n if (i >= 0)\n return this.ranges[i];\n };\n\n\n this.clipRows = function(startRow, endRow) {\n var list = this.ranges;\n if (list[0].start.row > endRow || list[list.length - 1].start.row < startRow)\n return [];\n\n var startIndex = this.pointIndex({row: startRow, column: 0});\n if (startIndex < 0)\n startIndex = -startIndex - 1;\n var endIndex = this.pointIndex({row: endRow, column: 0}, startIndex);\n if (endIndex < 0)\n endIndex = -endIndex - 1;\n\n var clipped = [];\n for (var i = startIndex; i < endIndex; i++) {\n clipped.push(list[i]);\n }\n return clipped;\n };\n\n this.removeAll = function() {\n return this.ranges.splice(0, this.ranges.length);\n };\n\n this.attach = function(session) {\n if (this.session)\n this.detach();\n\n this.session = session;\n this.onChange = this.$onChange.bind(this);\n\n this.session.on('change', this.onChange);\n };\n\n this.detach = function() {\n if (!this.session)\n return;\n this.session.removeListener('change', this.onChange);\n this.session = null;\n };\n\n this.$onChange = function(delta) {\n if (delta.action == \"insert\"){\n var start = delta.start;\n var end = delta.end;\n } else {\n var end = delta.start;\n var start = delta.end;\n }\n var startRow = start.row;\n var endRow = end.row;\n var lineDif = endRow - startRow;\n\n var colDiff = -start.column + end.column;\n var ranges = this.ranges;\n\n for (var i = 0, n = ranges.length; i < n; i++) {\n var r = ranges[i];\n if (r.end.row < startRow)\n continue;\n if (r.start.row > startRow)\n break;\n\n if (r.start.row == startRow && r.start.column >= start.column ) {\n if (r.start.column == start.column && this.$insertRight) {\n } else {\n r.start.column += colDiff;\n r.start.row += lineDif;\n }\n }\n if (r.end.row == startRow && r.end.column >= start.column) {\n if (r.end.column == start.column && this.$insertRight) {\n continue;\n }\n if (r.end.column == start.column && colDiff > 0 && i < n - 1) { \n if (r.end.column > r.start.column && r.end.column == ranges[i+1].start.column)\n r.end.column -= colDiff;\n }\n r.end.column += colDiff;\n r.end.row += lineDif;\n }\n }\n\n if (lineDif != 0 && i < n) {\n for (; i < n; i++) {\n var r = ranges[i];\n r.start.row += lineDif;\n r.end.row += lineDif;\n }\n }\n };\n\n}).call(RangeList.prototype);\n\nexports.RangeList = RangeList;\n});\n\nace.define(\"ace/edit_session/fold\",[\"require\",\"exports\",\"module\",\"ace/range\",\"ace/range_list\",\"ace/lib/oop\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar Range = acequire(\"../range\").Range;\nvar RangeList = acequire(\"../range_list\").RangeList;\nvar oop = acequire(\"../lib/oop\")\nvar Fold = exports.Fold = function(range, placeholder) {\n this.foldLine = null;\n this.placeholder = placeholder;\n this.range = range;\n this.start = range.start;\n this.end = range.end;\n\n this.sameRow = range.start.row == range.end.row;\n this.subFolds = this.ranges = [];\n};\n\noop.inherits(Fold, RangeList);\n\n(function() {\n\n this.toString = function() {\n return '\"' + this.placeholder + '\" ' + this.range.toString();\n };\n\n this.setFoldLine = function(foldLine) {\n this.foldLine = foldLine;\n this.subFolds.forEach(function(fold) {\n fold.setFoldLine(foldLine);\n });\n };\n\n this.clone = function() {\n var range = this.range.clone();\n var fold = new Fold(range, this.placeholder);\n this.subFolds.forEach(function(subFold) {\n fold.subFolds.push(subFold.clone());\n });\n fold.collapseChildren = this.collapseChildren;\n return fold;\n };\n\n this.addSubFold = function(fold) {\n if (this.range.isEqual(fold))\n return;\n\n if (!this.range.containsRange(fold))\n throw new Error(\"A fold can't intersect already existing fold\" + fold.range + this.range);\n consumeRange(fold, this.start);\n\n var row = fold.start.row, column = fold.start.column;\n for (var i = 0, cmp = -1; i < this.subFolds.length; i++) {\n cmp = this.subFolds[i].range.compare(row, column);\n if (cmp != 1)\n break;\n }\n var afterStart = this.subFolds[i];\n\n if (cmp == 0)\n return afterStart.addSubFold(fold);\n var row = fold.range.end.row, column = fold.range.end.column;\n for (var j = i, cmp = -1; j < this.subFolds.length; j++) {\n cmp = this.subFolds[j].range.compare(row, column);\n if (cmp != 1)\n break;\n }\n var afterEnd = this.subFolds[j];\n\n if (cmp == 0)\n throw new Error(\"A fold can't intersect already existing fold\" + fold.range + this.range);\n\n var consumedFolds = this.subFolds.splice(i, j - i, fold);\n fold.setFoldLine(this.foldLine);\n\n return fold;\n };\n \n this.restoreRange = function(range) {\n return restoreRange(range, this.start);\n };\n\n}).call(Fold.prototype);\n\nfunction consumePoint(point, anchor) {\n point.row -= anchor.row;\n if (point.row == 0)\n point.column -= anchor.column;\n}\nfunction consumeRange(range, anchor) {\n consumePoint(range.start, anchor);\n consumePoint(range.end, anchor);\n}\nfunction restorePoint(point, anchor) {\n if (point.row == 0)\n point.column += anchor.column;\n point.row += anchor.row;\n}\nfunction restoreRange(range, anchor) {\n restorePoint(range.start, anchor);\n restorePoint(range.end, anchor);\n}\n\n});\n\nace.define(\"ace/edit_session/folding\",[\"require\",\"exports\",\"module\",\"ace/range\",\"ace/edit_session/fold_line\",\"ace/edit_session/fold\",\"ace/token_iterator\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar Range = acequire(\"../range\").Range;\nvar FoldLine = acequire(\"./fold_line\").FoldLine;\nvar Fold = acequire(\"./fold\").Fold;\nvar TokenIterator = acequire(\"../token_iterator\").TokenIterator;\n\nfunction Folding() {\n this.getFoldAt = function(row, column, side) {\n var foldLine = this.getFoldLine(row);\n if (!foldLine)\n return null;\n\n var folds = foldLine.folds;\n for (var i = 0; i < folds.length; i++) {\n var fold = folds[i];\n if (fold.range.contains(row, column)) {\n if (side == 1 && fold.range.isEnd(row, column)) {\n continue;\n } else if (side == -1 && fold.range.isStart(row, column)) {\n continue;\n }\n return fold;\n }\n }\n };\n this.getFoldsInRange = function(range) {\n var start = range.start;\n var end = range.end;\n var foldLines = this.$foldData;\n var foundFolds = [];\n\n start.column += 1;\n end.column -= 1;\n\n for (var i = 0; i < foldLines.length; i++) {\n var cmp = foldLines[i].range.compareRange(range);\n if (cmp == 2) {\n continue;\n }\n else if (cmp == -2) {\n break;\n }\n\n var folds = foldLines[i].folds;\n for (var j = 0; j < folds.length; j++) {\n var fold = folds[j];\n cmp = fold.range.compareRange(range);\n if (cmp == -2) {\n break;\n } else if (cmp == 2) {\n continue;\n } else\n if (cmp == 42) {\n break;\n }\n foundFolds.push(fold);\n }\n }\n start.column -= 1;\n end.column += 1;\n\n return foundFolds;\n };\n\n this.getFoldsInRangeList = function(ranges) {\n if (Array.isArray(ranges)) {\n var folds = [];\n ranges.forEach(function(range) {\n folds = folds.concat(this.getFoldsInRange(range));\n }, this);\n } else {\n var folds = this.getFoldsInRange(ranges);\n }\n return folds;\n };\n this.getAllFolds = function() {\n var folds = [];\n var foldLines = this.$foldData;\n \n for (var i = 0; i < foldLines.length; i++)\n for (var j = 0; j < foldLines[i].folds.length; j++)\n folds.push(foldLines[i].folds[j]);\n\n return folds;\n };\n this.getFoldStringAt = function(row, column, trim, foldLine) {\n foldLine = foldLine || this.getFoldLine(row);\n if (!foldLine)\n return null;\n\n var lastFold = {\n end: { column: 0 }\n };\n var str, fold;\n for (var i = 0; i < foldLine.folds.length; i++) {\n fold = foldLine.folds[i];\n var cmp = fold.range.compareEnd(row, column);\n if (cmp == -1) {\n str = this\n .getLine(fold.start.row)\n .substring(lastFold.end.column, fold.start.column);\n break;\n }\n else if (cmp === 0) {\n return null;\n }\n lastFold = fold;\n }\n if (!str)\n str = this.getLine(fold.start.row).substring(lastFold.end.column);\n\n if (trim == -1)\n return str.substring(0, column - lastFold.end.column);\n else if (trim == 1)\n return str.substring(column - lastFold.end.column);\n else\n return str;\n };\n\n this.getFoldLine = function(docRow, startFoldLine) {\n var foldData = this.$foldData;\n var i = 0;\n if (startFoldLine)\n i = foldData.indexOf(startFoldLine);\n if (i == -1)\n i = 0;\n for (i; i < foldData.length; i++) {\n var foldLine = foldData[i];\n if (foldLine.start.row <= docRow && foldLine.end.row >= docRow) {\n return foldLine;\n } else if (foldLine.end.row > docRow) {\n return null;\n }\n }\n return null;\n };\n this.getNextFoldLine = function(docRow, startFoldLine) {\n var foldData = this.$foldData;\n var i = 0;\n if (startFoldLine)\n i = foldData.indexOf(startFoldLine);\n if (i == -1)\n i = 0;\n for (i; i < foldData.length; i++) {\n var foldLine = foldData[i];\n if (foldLine.end.row >= docRow) {\n return foldLine;\n }\n }\n return null;\n };\n\n this.getFoldedRowCount = function(first, last) {\n var foldData = this.$foldData, rowCount = last-first+1;\n for (var i = 0; i < foldData.length; i++) {\n var foldLine = foldData[i],\n end = foldLine.end.row,\n start = foldLine.start.row;\n if (end >= last) {\n if (start < last) {\n if (start >= first)\n rowCount -= last-start;\n else\n rowCount = 0; // in one fold\n }\n break;\n } else if (end >= first){\n if (start >= first) // fold inside range\n rowCount -= end-start;\n else\n rowCount -= end-first+1;\n }\n }\n return rowCount;\n };\n\n this.$addFoldLine = function(foldLine) {\n this.$foldData.push(foldLine);\n this.$foldData.sort(function(a, b) {\n return a.start.row - b.start.row;\n });\n return foldLine;\n };\n this.addFold = function(placeholder, range) {\n var foldData = this.$foldData;\n var added = false;\n var fold;\n \n if (placeholder instanceof Fold)\n fold = placeholder;\n else {\n fold = new Fold(range, placeholder);\n fold.collapseChildren = range.collapseChildren;\n }\n this.$clipRangeToDocument(fold.range);\n\n var startRow = fold.start.row;\n var startColumn = fold.start.column;\n var endRow = fold.end.row;\n var endColumn = fold.end.column;\n if (!(startRow < endRow || \n startRow == endRow && startColumn <= endColumn - 2))\n throw new Error(\"The range has to be at least 2 characters width\");\n\n var startFold = this.getFoldAt(startRow, startColumn, 1);\n var endFold = this.getFoldAt(endRow, endColumn, -1);\n if (startFold && endFold == startFold)\n return startFold.addSubFold(fold);\n\n if (startFold && !startFold.range.isStart(startRow, startColumn))\n this.removeFold(startFold);\n \n if (endFold && !endFold.range.isEnd(endRow, endColumn))\n this.removeFold(endFold);\n var folds = this.getFoldsInRange(fold.range);\n if (folds.length > 0) {\n this.removeFolds(folds);\n folds.forEach(function(subFold) {\n fold.addSubFold(subFold);\n });\n }\n\n for (var i = 0; i < foldData.length; i++) {\n var foldLine = foldData[i];\n if (endRow == foldLine.start.row) {\n foldLine.addFold(fold);\n added = true;\n break;\n } else if (startRow == foldLine.end.row) {\n foldLine.addFold(fold);\n added = true;\n if (!fold.sameRow) {\n var foldLineNext = foldData[i + 1];\n if (foldLineNext && foldLineNext.start.row == endRow) {\n foldLine.merge(foldLineNext);\n break;\n }\n }\n break;\n } else if (endRow <= foldLine.start.row) {\n break;\n }\n }\n\n if (!added)\n foldLine = this.$addFoldLine(new FoldLine(this.$foldData, fold));\n\n if (this.$useWrapMode)\n this.$updateWrapData(foldLine.start.row, foldLine.start.row);\n else\n this.$updateRowLengthCache(foldLine.start.row, foldLine.start.row);\n this.$modified = true;\n this._signal(\"changeFold\", { data: fold, action: \"add\" });\n\n return fold;\n };\n\n this.addFolds = function(folds) {\n folds.forEach(function(fold) {\n this.addFold(fold);\n }, this);\n };\n\n this.removeFold = function(fold) {\n var foldLine = fold.foldLine;\n var startRow = foldLine.start.row;\n var endRow = foldLine.end.row;\n\n var foldLines = this.$foldData;\n var folds = foldLine.folds;\n if (folds.length == 1) {\n foldLines.splice(foldLines.indexOf(foldLine), 1);\n } else\n if (foldLine.range.isEnd(fold.end.row, fold.end.column)) {\n folds.pop();\n foldLine.end.row = folds[folds.length - 1].end.row;\n foldLine.end.column = folds[folds.length - 1].end.column;\n } else\n if (foldLine.range.isStart(fold.start.row, fold.start.column)) {\n folds.shift();\n foldLine.start.row = folds[0].start.row;\n foldLine.start.column = folds[0].start.column;\n } else\n if (fold.sameRow) {\n folds.splice(folds.indexOf(fold), 1);\n } else\n {\n var newFoldLine = foldLine.split(fold.start.row, fold.start.column);\n folds = newFoldLine.folds;\n folds.shift();\n newFoldLine.start.row = folds[0].start.row;\n newFoldLine.start.column = folds[0].start.column;\n }\n\n if (!this.$updating) {\n if (this.$useWrapMode)\n this.$updateWrapData(startRow, endRow);\n else\n this.$updateRowLengthCache(startRow, endRow);\n }\n this.$modified = true;\n this._signal(\"changeFold\", { data: fold, action: \"remove\" });\n };\n\n this.removeFolds = function(folds) {\n var cloneFolds = [];\n for (var i = 0; i < folds.length; i++) {\n cloneFolds.push(folds[i]);\n }\n\n cloneFolds.forEach(function(fold) {\n this.removeFold(fold);\n }, this);\n this.$modified = true;\n };\n\n this.expandFold = function(fold) {\n this.removeFold(fold);\n fold.subFolds.forEach(function(subFold) {\n fold.restoreRange(subFold);\n this.addFold(subFold);\n }, this);\n if (fold.collapseChildren > 0) {\n this.foldAll(fold.start.row+1, fold.end.row, fold.collapseChildren-1);\n }\n fold.subFolds = [];\n };\n\n this.expandFolds = function(folds) {\n folds.forEach(function(fold) {\n this.expandFold(fold);\n }, this);\n };\n\n this.unfold = function(location, expandInner) {\n var range, folds;\n if (location == null) {\n range = new Range(0, 0, this.getLength(), 0);\n expandInner = true;\n } else if (typeof location == \"number\")\n range = new Range(location, 0, location, this.getLine(location).length);\n else if (\"row\" in location)\n range = Range.fromPoints(location, location);\n else\n range = location;\n \n folds = this.getFoldsInRangeList(range);\n if (expandInner) {\n this.removeFolds(folds);\n } else {\n var subFolds = folds;\n while (subFolds.length) {\n this.expandFolds(subFolds);\n subFolds = this.getFoldsInRangeList(range);\n }\n }\n if (folds.length)\n return folds;\n };\n this.isRowFolded = function(docRow, startFoldRow) {\n return !!this.getFoldLine(docRow, startFoldRow);\n };\n\n this.getRowFoldEnd = function(docRow, startFoldRow) {\n var foldLine = this.getFoldLine(docRow, startFoldRow);\n return foldLine ? foldLine.end.row : docRow;\n };\n\n this.getRowFoldStart = function(docRow, startFoldRow) {\n var foldLine = this.getFoldLine(docRow, startFoldRow);\n return foldLine ? foldLine.start.row : docRow;\n };\n\n this.getFoldDisplayLine = function(foldLine, endRow, endColumn, startRow, startColumn) {\n if (startRow == null)\n startRow = foldLine.start.row;\n if (startColumn == null)\n startColumn = 0;\n if (endRow == null)\n endRow = foldLine.end.row;\n if (endColumn == null)\n endColumn = this.getLine(endRow).length;\n var doc = this.doc;\n var textLine = \"\";\n\n foldLine.walk(function(placeholder, row, column, lastColumn) {\n if (row < startRow)\n return;\n if (row == startRow) {\n if (column < startColumn)\n return;\n lastColumn = Math.max(startColumn, lastColumn);\n }\n\n if (placeholder != null) {\n textLine += placeholder;\n } else {\n textLine += doc.getLine(row).substring(lastColumn, column);\n }\n }, endRow, endColumn);\n return textLine;\n };\n\n this.getDisplayLine = function(row, endColumn, startRow, startColumn) {\n var foldLine = this.getFoldLine(row);\n\n if (!foldLine) {\n var line;\n line = this.doc.getLine(row);\n return line.substring(startColumn || 0, endColumn || line.length);\n } else {\n return this.getFoldDisplayLine(\n foldLine, row, endColumn, startRow, startColumn);\n }\n };\n\n this.$cloneFoldData = function() {\n var fd = [];\n fd = this.$foldData.map(function(foldLine) {\n var folds = foldLine.folds.map(function(fold) {\n return fold.clone();\n });\n return new FoldLine(fd, folds);\n });\n\n return fd;\n };\n\n this.toggleFold = function(tryToUnfold) {\n var selection = this.selection;\n var range = selection.getRange();\n var fold;\n var bracketPos;\n\n if (range.isEmpty()) {\n var cursor = range.start;\n fold = this.getFoldAt(cursor.row, cursor.column);\n\n if (fold) {\n this.expandFold(fold);\n return;\n } else if (bracketPos = this.findMatchingBracket(cursor)) {\n if (range.comparePoint(bracketPos) == 1) {\n range.end = bracketPos;\n } else {\n range.start = bracketPos;\n range.start.column++;\n range.end.column--;\n }\n } else if (bracketPos = this.findMatchingBracket({row: cursor.row, column: cursor.column + 1})) {\n if (range.comparePoint(bracketPos) == 1)\n range.end = bracketPos;\n else\n range.start = bracketPos;\n\n range.start.column++;\n } else {\n range = this.getCommentFoldRange(cursor.row, cursor.column) || range;\n }\n } else {\n var folds = this.getFoldsInRange(range);\n if (tryToUnfold && folds.length) {\n this.expandFolds(folds);\n return;\n } else if (folds.length == 1 ) {\n fold = folds[0];\n }\n }\n\n if (!fold)\n fold = this.getFoldAt(range.start.row, range.start.column);\n\n if (fold && fold.range.toString() == range.toString()) {\n this.expandFold(fold);\n return;\n }\n\n var placeholder = \"...\";\n if (!range.isMultiLine()) {\n placeholder = this.getTextRange(range);\n if (placeholder.length < 4)\n return;\n placeholder = placeholder.trim().substring(0, 2) + \"..\";\n }\n\n this.addFold(placeholder, range);\n };\n\n this.getCommentFoldRange = function(row, column, dir) {\n var iterator = new TokenIterator(this, row, column);\n var token = iterator.getCurrentToken();\n if (token && /^comment|string/.test(token.type)) {\n var range = new Range();\n var re = new RegExp(token.type.replace(/\\..*/, \"\\\\.\"));\n if (dir != 1) {\n do {\n token = iterator.stepBackward();\n } while (token && re.test(token.type));\n iterator.stepForward();\n }\n \n range.start.row = iterator.getCurrentTokenRow();\n range.start.column = iterator.getCurrentTokenColumn() + 2;\n\n iterator = new TokenIterator(this, row, column);\n \n if (dir != -1) {\n do {\n token = iterator.stepForward();\n } while (token && re.test(token.type));\n token = iterator.stepBackward();\n } else\n token = iterator.getCurrentToken();\n\n range.end.row = iterator.getCurrentTokenRow();\n range.end.column = iterator.getCurrentTokenColumn() + token.value.length - 2;\n return range;\n }\n };\n\n this.foldAll = function(startRow, endRow, depth) {\n if (depth == undefined)\n depth = 100000; // JSON.stringify doesn't hanle Infinity\n var foldWidgets = this.foldWidgets;\n if (!foldWidgets)\n return; // mode doesn't support folding\n endRow = endRow || this.getLength();\n startRow = startRow || 0;\n for (var row = startRow; row < endRow; row++) {\n if (foldWidgets[row] == null)\n foldWidgets[row] = this.getFoldWidget(row);\n if (foldWidgets[row] != \"start\")\n continue;\n\n var range = this.getFoldWidgetRange(row);\n if (range && range.isMultiLine()\n && range.end.row <= endRow\n && range.start.row >= startRow\n ) {\n row = range.end.row;\n try {\n var fold = this.addFold(\"...\", range);\n if (fold)\n fold.collapseChildren = depth;\n } catch(e) {}\n }\n }\n };\n this.$foldStyles = {\n \"manual\": 1,\n \"markbegin\": 1,\n \"markbeginend\": 1\n };\n this.$foldStyle = \"markbegin\";\n this.setFoldStyle = function(style) {\n if (!this.$foldStyles[style])\n throw new Error(\"invalid fold style: \" + style + \"[\" + Object.keys(this.$foldStyles).join(\", \") + \"]\");\n \n if (this.$foldStyle == style)\n return;\n\n this.$foldStyle = style;\n \n if (style == \"manual\")\n this.unfold();\n var mode = this.$foldMode;\n this.$setFolding(null);\n this.$setFolding(mode);\n };\n\n this.$setFolding = function(foldMode) {\n if (this.$foldMode == foldMode)\n return;\n \n this.$foldMode = foldMode;\n \n this.off('change', this.$updateFoldWidgets);\n this.off('tokenizerUpdate', this.$tokenizerUpdateFoldWidgets);\n this._signal(\"changeAnnotation\");\n \n if (!foldMode || this.$foldStyle == \"manual\") {\n this.foldWidgets = null;\n return;\n }\n \n this.foldWidgets = [];\n this.getFoldWidget = foldMode.getFoldWidget.bind(foldMode, this, this.$foldStyle);\n this.getFoldWidgetRange = foldMode.getFoldWidgetRange.bind(foldMode, this, this.$foldStyle);\n \n this.$updateFoldWidgets = this.updateFoldWidgets.bind(this);\n this.$tokenizerUpdateFoldWidgets = this.tokenizerUpdateFoldWidgets.bind(this);\n this.on('change', this.$updateFoldWidgets);\n this.on('tokenizerUpdate', this.$tokenizerUpdateFoldWidgets);\n };\n\n this.getParentFoldRangeData = function (row, ignoreCurrent) {\n var fw = this.foldWidgets;\n if (!fw || (ignoreCurrent && fw[row]))\n return {};\n\n var i = row - 1, firstRange;\n while (i >= 0) {\n var c = fw[i];\n if (c == null)\n c = fw[i] = this.getFoldWidget(i);\n\n if (c == \"start\") {\n var range = this.getFoldWidgetRange(i);\n if (!firstRange)\n firstRange = range;\n if (range && range.end.row >= row)\n break;\n }\n i--;\n }\n\n return {\n range: i !== -1 && range,\n firstRange: firstRange\n };\n };\n\n this.onFoldWidgetClick = function(row, e) {\n e = e.domEvent;\n var options = {\n children: e.shiftKey,\n all: e.ctrlKey || e.metaKey,\n siblings: e.altKey\n };\n \n var range = this.$toggleFoldWidget(row, options);\n if (!range) {\n var el = (e.target || e.srcElement);\n if (el && /ace_fold-widget/.test(el.className))\n el.className += \" ace_invalid\";\n }\n };\n \n this.$toggleFoldWidget = function(row, options) {\n if (!this.getFoldWidget)\n return;\n var type = this.getFoldWidget(row);\n var line = this.getLine(row);\n\n var dir = type === \"end\" ? -1 : 1;\n var fold = this.getFoldAt(row, dir === -1 ? 0 : line.length, dir);\n\n if (fold) {\n if (options.children || options.all)\n this.removeFold(fold);\n else\n this.expandFold(fold);\n return;\n }\n\n var range = this.getFoldWidgetRange(row, true);\n if (range && !range.isMultiLine()) {\n fold = this.getFoldAt(range.start.row, range.start.column, 1);\n if (fold && range.isEqual(fold.range)) {\n this.removeFold(fold);\n return;\n }\n }\n \n if (options.siblings) {\n var data = this.getParentFoldRangeData(row);\n if (data.range) {\n var startRow = data.range.start.row + 1;\n var endRow = data.range.end.row;\n }\n this.foldAll(startRow, endRow, options.all ? 10000 : 0);\n } else if (options.children) {\n endRow = range ? range.end.row : this.getLength();\n this.foldAll(row + 1, endRow, options.all ? 10000 : 0);\n } else if (range) {\n if (options.all) \n range.collapseChildren = 10000;\n this.addFold(\"...\", range);\n }\n \n return range;\n };\n \n \n \n this.toggleFoldWidget = function(toggleParent) {\n var row = this.selection.getCursor().row;\n row = this.getRowFoldStart(row);\n var range = this.$toggleFoldWidget(row, {});\n \n if (range)\n return;\n var data = this.getParentFoldRangeData(row, true);\n range = data.range || data.firstRange;\n \n if (range) {\n row = range.start.row;\n var fold = this.getFoldAt(row, this.getLine(row).length, 1);\n\n if (fold) {\n this.removeFold(fold);\n } else {\n this.addFold(\"...\", range);\n }\n }\n };\n\n this.updateFoldWidgets = function(delta) {\n var firstRow = delta.start.row;\n var len = delta.end.row - firstRow;\n\n if (len === 0) {\n this.foldWidgets[firstRow] = null;\n } else if (delta.action == 'remove') {\n this.foldWidgets.splice(firstRow, len + 1, null);\n } else {\n var args = Array(len + 1);\n args.unshift(firstRow, 1);\n this.foldWidgets.splice.apply(this.foldWidgets, args);\n }\n };\n this.tokenizerUpdateFoldWidgets = function(e) {\n var rows = e.data;\n if (rows.first != rows.last) {\n if (this.foldWidgets.length > rows.first)\n this.foldWidgets.splice(rows.first, this.foldWidgets.length);\n }\n };\n}\n\nexports.Folding = Folding;\n\n});\n\nace.define(\"ace/edit_session/bracket_match\",[\"require\",\"exports\",\"module\",\"ace/token_iterator\",\"ace/range\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar TokenIterator = acequire(\"../token_iterator\").TokenIterator;\nvar Range = acequire(\"../range\").Range;\n\n\nfunction BracketMatch() {\n\n this.findMatchingBracket = function(position, chr) {\n if (position.column == 0) return null;\n\n var charBeforeCursor = chr || this.getLine(position.row).charAt(position.column-1);\n if (charBeforeCursor == \"\") return null;\n\n var match = charBeforeCursor.match(/([\\(\\[\\{])|([\\)\\]\\}])/);\n if (!match)\n return null;\n\n if (match[1])\n return this.$findClosingBracket(match[1], position);\n else\n return this.$findOpeningBracket(match[2], position);\n };\n \n this.getBracketRange = function(pos) {\n var line = this.getLine(pos.row);\n var before = true, range;\n\n var chr = line.charAt(pos.column-1);\n var match = chr && chr.match(/([\\(\\[\\{])|([\\)\\]\\}])/);\n if (!match) {\n chr = line.charAt(pos.column);\n pos = {row: pos.row, column: pos.column + 1};\n match = chr && chr.match(/([\\(\\[\\{])|([\\)\\]\\}])/);\n before = false;\n }\n if (!match)\n return null;\n\n if (match[1]) {\n var bracketPos = this.$findClosingBracket(match[1], pos);\n if (!bracketPos)\n return null;\n range = Range.fromPoints(pos, bracketPos);\n if (!before) {\n range.end.column++;\n range.start.column--;\n }\n range.cursor = range.end;\n } else {\n var bracketPos = this.$findOpeningBracket(match[2], pos);\n if (!bracketPos)\n return null;\n range = Range.fromPoints(bracketPos, pos);\n if (!before) {\n range.start.column++;\n range.end.column--;\n }\n range.cursor = range.start;\n }\n \n return range;\n };\n\n this.$brackets = {\n \")\": \"(\",\n \"(\": \")\",\n \"]\": \"[\",\n \"[\": \"]\",\n \"{\": \"}\",\n \"}\": \"{\"\n };\n\n this.$findOpeningBracket = function(bracket, position, typeRe) {\n var openBracket = this.$brackets[bracket];\n var depth = 1;\n\n var iterator = new TokenIterator(this, position.row, position.column);\n var token = iterator.getCurrentToken();\n if (!token)\n token = iterator.stepForward();\n if (!token)\n return;\n \n if (!typeRe){\n typeRe = new RegExp(\n \"(\\\\.?\" +\n token.type.replace(\".\", \"\\\\.\").replace(\"rparen\", \".paren\")\n .replace(/\\b(?:end)\\b/, \"(?:start|begin|end)\")\n + \")+\"\n );\n }\n var valueIndex = position.column - iterator.getCurrentTokenColumn() - 2;\n var value = token.value;\n \n while (true) {\n \n while (valueIndex >= 0) {\n var chr = value.charAt(valueIndex);\n if (chr == openBracket) {\n depth -= 1;\n if (depth == 0) {\n return {row: iterator.getCurrentTokenRow(),\n column: valueIndex + iterator.getCurrentTokenColumn()};\n }\n }\n else if (chr == bracket) {\n depth += 1;\n }\n valueIndex -= 1;\n }\n do {\n token = iterator.stepBackward();\n } while (token && !typeRe.test(token.type));\n\n if (token == null)\n break;\n \n value = token.value;\n valueIndex = value.length - 1;\n }\n \n return null;\n };\n\n this.$findClosingBracket = function(bracket, position, typeRe) {\n var closingBracket = this.$brackets[bracket];\n var depth = 1;\n\n var iterator = new TokenIterator(this, position.row, position.column);\n var token = iterator.getCurrentToken();\n if (!token)\n token = iterator.stepForward();\n if (!token)\n return;\n\n if (!typeRe){\n typeRe = new RegExp(\n \"(\\\\.?\" +\n token.type.replace(\".\", \"\\\\.\").replace(\"lparen\", \".paren\")\n .replace(/\\b(?:start|begin)\\b/, \"(?:start|begin|end)\")\n + \")+\"\n );\n }\n var valueIndex = position.column - iterator.getCurrentTokenColumn();\n\n while (true) {\n\n var value = token.value;\n var valueLength = value.length;\n while (valueIndex < valueLength) {\n var chr = value.charAt(valueIndex);\n if (chr == closingBracket) {\n depth -= 1;\n if (depth == 0) {\n return {row: iterator.getCurrentTokenRow(),\n column: valueIndex + iterator.getCurrentTokenColumn()};\n }\n }\n else if (chr == bracket) {\n depth += 1;\n }\n valueIndex += 1;\n }\n do {\n token = iterator.stepForward();\n } while (token && !typeRe.test(token.type));\n\n if (token == null)\n break;\n\n valueIndex = 0;\n }\n \n return null;\n };\n}\nexports.BracketMatch = BracketMatch;\n\n});\n\nace.define(\"ace/edit_session\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/lang\",\"ace/config\",\"ace/lib/event_emitter\",\"ace/selection\",\"ace/mode/text\",\"ace/range\",\"ace/document\",\"ace/background_tokenizer\",\"ace/search_highlight\",\"ace/edit_session/folding\",\"ace/edit_session/bracket_match\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar oop = acequire(\"./lib/oop\");\nvar lang = acequire(\"./lib/lang\");\nvar config = acequire(\"./config\");\nvar EventEmitter = acequire(\"./lib/event_emitter\").EventEmitter;\nvar Selection = acequire(\"./selection\").Selection;\nvar TextMode = acequire(\"./mode/text\").Mode;\nvar Range = acequire(\"./range\").Range;\nvar Document = acequire(\"./document\").Document;\nvar BackgroundTokenizer = acequire(\"./background_tokenizer\").BackgroundTokenizer;\nvar SearchHighlight = acequire(\"./search_highlight\").SearchHighlight;\n\nvar EditSession = function(text, mode) {\n this.$breakpoints = [];\n this.$decorations = [];\n this.$frontMarkers = {};\n this.$backMarkers = {};\n this.$markerId = 1;\n this.$undoSelect = true;\n\n this.$foldData = [];\n this.$foldData.toString = function() {\n return this.join(\"\\n\");\n };\n this.on(\"changeFold\", this.onChangeFold.bind(this));\n this.$onChange = this.onChange.bind(this);\n\n if (typeof text != \"object\" || !text.getLine)\n text = new Document(text);\n\n this.setDocument(text);\n this.selection = new Selection(this);\n\n config.resetOptions(this);\n this.setMode(mode);\n config._signal(\"session\", this);\n};\n\n\n(function() {\n\n oop.implement(this, EventEmitter);\n this.setDocument = function(doc) {\n if (this.doc)\n this.doc.removeListener(\"change\", this.$onChange);\n\n this.doc = doc;\n doc.on(\"change\", this.$onChange);\n\n if (this.bgTokenizer)\n this.bgTokenizer.setDocument(this.getDocument());\n\n this.resetCaches();\n };\n this.getDocument = function() {\n return this.doc;\n };\n this.$resetRowCache = function(docRow) {\n if (!docRow) {\n this.$docRowCache = [];\n this.$screenRowCache = [];\n return;\n }\n var l = this.$docRowCache.length;\n var i = this.$getRowCacheIndex(this.$docRowCache, docRow) + 1;\n if (l > i) {\n this.$docRowCache.splice(i, l);\n this.$screenRowCache.splice(i, l);\n }\n };\n\n this.$getRowCacheIndex = function(cacheArray, val) {\n var low = 0;\n var hi = cacheArray.length - 1;\n\n while (low <= hi) {\n var mid = (low + hi) >> 1;\n var c = cacheArray[mid];\n\n if (val > c)\n low = mid + 1;\n else if (val < c)\n hi = mid - 1;\n else\n return mid;\n }\n\n return low -1;\n };\n\n this.resetCaches = function() {\n this.$modified = true;\n this.$wrapData = [];\n this.$rowLengthCache = [];\n this.$resetRowCache(0);\n if (this.bgTokenizer)\n this.bgTokenizer.start(0);\n };\n\n this.onChangeFold = function(e) {\n var fold = e.data;\n this.$resetRowCache(fold.start.row);\n };\n\n this.onChange = function(delta) {\n this.$modified = true;\n\n this.$resetRowCache(delta.start.row);\n\n var removedFolds = this.$updateInternalDataOnChange(delta);\n if (!this.$fromUndo && this.$undoManager && !delta.ignore) {\n this.$deltasDoc.push(delta);\n if (removedFolds && removedFolds.length != 0) {\n this.$deltasFold.push({\n action: \"removeFolds\",\n folds: removedFolds\n });\n }\n\n this.$informUndoManager.schedule();\n }\n\n this.bgTokenizer && this.bgTokenizer.$updateOnChange(delta);\n this._signal(\"change\", delta);\n };\n this.setValue = function(text) {\n this.doc.setValue(text);\n this.selection.moveTo(0, 0);\n\n this.$resetRowCache(0);\n this.$deltas = [];\n this.$deltasDoc = [];\n this.$deltasFold = [];\n this.setUndoManager(this.$undoManager);\n this.getUndoManager().reset();\n };\n this.getValue =\n this.toString = function() {\n return this.doc.getValue();\n };\n this.getSelection = function() {\n return this.selection;\n };\n this.getState = function(row) {\n return this.bgTokenizer.getState(row);\n };\n this.getTokens = function(row) {\n return this.bgTokenizer.getTokens(row);\n };\n this.getTokenAt = function(row, column) {\n var tokens = this.bgTokenizer.getTokens(row);\n var token, c = 0;\n if (column == null) {\n i = tokens.length - 1;\n c = this.getLine(row).length;\n } else {\n for (var i = 0; i < tokens.length; i++) {\n c += tokens[i].value.length;\n if (c >= column)\n break;\n }\n }\n token = tokens[i];\n if (!token)\n return null;\n token.index = i;\n token.start = c - token.value.length;\n return token;\n };\n this.setUndoManager = function(undoManager) {\n this.$undoManager = undoManager;\n this.$deltas = [];\n this.$deltasDoc = [];\n this.$deltasFold = [];\n\n if (this.$informUndoManager)\n this.$informUndoManager.cancel();\n\n if (undoManager) {\n var self = this;\n\n this.$syncInformUndoManager = function() {\n self.$informUndoManager.cancel();\n\n if (self.$deltasFold.length) {\n self.$deltas.push({\n group: \"fold\",\n deltas: self.$deltasFold\n });\n self.$deltasFold = [];\n }\n\n if (self.$deltasDoc.length) {\n self.$deltas.push({\n group: \"doc\",\n deltas: self.$deltasDoc\n });\n self.$deltasDoc = [];\n }\n\n if (self.$deltas.length > 0) {\n undoManager.execute({\n action: \"aceupdate\",\n args: [self.$deltas, self],\n merge: self.mergeUndoDeltas\n });\n }\n self.mergeUndoDeltas = false;\n self.$deltas = [];\n };\n this.$informUndoManager = lang.delayedCall(this.$syncInformUndoManager);\n }\n };\n this.markUndoGroup = function() {\n if (this.$syncInformUndoManager)\n this.$syncInformUndoManager();\n };\n \n this.$defaultUndoManager = {\n undo: function() {},\n redo: function() {},\n reset: function() {}\n };\n this.getUndoManager = function() {\n return this.$undoManager || this.$defaultUndoManager;\n };\n this.getTabString = function() {\n if (this.getUseSoftTabs()) {\n return lang.stringRepeat(\" \", this.getTabSize());\n } else {\n return \"\\t\";\n }\n };\n this.setUseSoftTabs = function(val) {\n this.setOption(\"useSoftTabs\", val);\n };\n this.getUseSoftTabs = function() {\n return this.$useSoftTabs && !this.$mode.$indentWithTabs;\n };\n this.setTabSize = function(tabSize) {\n this.setOption(\"tabSize\", tabSize);\n };\n this.getTabSize = function() {\n return this.$tabSize;\n };\n this.isTabStop = function(position) {\n return this.$useSoftTabs && (position.column % this.$tabSize === 0);\n };\n\n this.$overwrite = false;\n this.setOverwrite = function(overwrite) {\n this.setOption(\"overwrite\", overwrite);\n };\n this.getOverwrite = function() {\n return this.$overwrite;\n };\n this.toggleOverwrite = function() {\n this.setOverwrite(!this.$overwrite);\n };\n this.addGutterDecoration = function(row, className) {\n if (!this.$decorations[row])\n this.$decorations[row] = \"\";\n this.$decorations[row] += \" \" + className;\n this._signal(\"changeBreakpoint\", {});\n };\n this.removeGutterDecoration = function(row, className) {\n this.$decorations[row] = (this.$decorations[row] || \"\").replace(\" \" + className, \"\");\n this._signal(\"changeBreakpoint\", {});\n };\n this.getBreakpoints = function() {\n return this.$breakpoints;\n };\n this.setBreakpoints = function(rows) {\n this.$breakpoints = [];\n for (var i=0; i 0)\n inToken = !!line.charAt(column - 1).match(this.tokenRe);\n\n if (!inToken)\n inToken = !!line.charAt(column).match(this.tokenRe);\n\n if (inToken)\n var re = this.tokenRe;\n else if (/^\\s+$/.test(line.slice(column-1, column+1)))\n var re = /\\s/;\n else\n var re = this.nonTokenRe;\n\n var start = column;\n if (start > 0) {\n do {\n start--;\n }\n while (start >= 0 && line.charAt(start).match(re));\n start++;\n }\n\n var end = column;\n while (end < line.length && line.charAt(end).match(re)) {\n end++;\n }\n\n return new Range(row, start, row, end);\n };\n this.getAWordRange = function(row, column) {\n var wordRange = this.getWordRange(row, column);\n var line = this.getLine(wordRange.end.row);\n\n while (line.charAt(wordRange.end.column).match(/[ \\t]/)) {\n wordRange.end.column += 1;\n }\n return wordRange;\n };\n this.setNewLineMode = function(newLineMode) {\n this.doc.setNewLineMode(newLineMode);\n };\n this.getNewLineMode = function() {\n return this.doc.getNewLineMode();\n };\n this.setUseWorker = function(useWorker) { this.setOption(\"useWorker\", useWorker); };\n this.getUseWorker = function() { return this.$useWorker; };\n this.onReloadTokenizer = function(e) {\n var rows = e.data;\n this.bgTokenizer.start(rows.first);\n this._signal(\"tokenizerUpdate\", e);\n };\n\n this.$modes = {};\n this.$mode = null;\n this.$modeId = null;\n this.setMode = function(mode, cb) {\n if (mode && typeof mode === \"object\") {\n if (mode.getTokenizer)\n return this.$onChangeMode(mode);\n var options = mode;\n var path = options.path;\n } else {\n path = mode || \"ace/mode/text\";\n }\n if (!this.$modes[\"ace/mode/text\"])\n this.$modes[\"ace/mode/text\"] = new TextMode();\n\n if (this.$modes[path] && !options) {\n this.$onChangeMode(this.$modes[path]);\n cb && cb();\n return;\n }\n this.$modeId = path;\n config.loadModule([\"mode\", path], function(m) {\n if (this.$modeId !== path)\n return cb && cb();\n if (this.$modes[path] && !options) {\n this.$onChangeMode(this.$modes[path]);\n } else if (m && m.Mode) {\n m = new m.Mode(options);\n if (!options) {\n this.$modes[path] = m;\n m.$id = path;\n }\n this.$onChangeMode(m);\n }\n cb && cb();\n }.bind(this));\n if (!this.$mode)\n this.$onChangeMode(this.$modes[\"ace/mode/text\"], true);\n };\n\n this.$onChangeMode = function(mode, $isPlaceholder) {\n if (!$isPlaceholder)\n this.$modeId = mode.$id;\n if (this.$mode === mode) \n return;\n\n this.$mode = mode;\n\n this.$stopWorker();\n\n if (this.$useWorker)\n this.$startWorker();\n\n var tokenizer = mode.getTokenizer();\n\n if(tokenizer.addEventListener !== undefined) {\n var onReloadTokenizer = this.onReloadTokenizer.bind(this);\n tokenizer.addEventListener(\"update\", onReloadTokenizer);\n }\n\n if (!this.bgTokenizer) {\n this.bgTokenizer = new BackgroundTokenizer(tokenizer);\n var _self = this;\n this.bgTokenizer.addEventListener(\"update\", function(e) {\n _self._signal(\"tokenizerUpdate\", e);\n });\n } else {\n this.bgTokenizer.setTokenizer(tokenizer);\n }\n\n this.bgTokenizer.setDocument(this.getDocument());\n\n this.tokenRe = mode.tokenRe;\n this.nonTokenRe = mode.nonTokenRe;\n\n \n if (!$isPlaceholder) {\n if (mode.attachToSession)\n mode.attachToSession(this);\n this.$options.wrapMethod.set.call(this, this.$wrapMethod);\n this.$setFolding(mode.foldingRules);\n this.bgTokenizer.start(0);\n this._emit(\"changeMode\");\n }\n };\n\n this.$stopWorker = function() {\n if (this.$worker) {\n this.$worker.terminate();\n this.$worker = null;\n }\n };\n\n this.$startWorker = function() {\n try {\n this.$worker = this.$mode.createWorker(this);\n } catch (e) {\n config.warn(\"Could not load worker\", e);\n this.$worker = null;\n }\n };\n this.getMode = function() {\n return this.$mode;\n };\n\n this.$scrollTop = 0;\n this.setScrollTop = function(scrollTop) {\n if (this.$scrollTop === scrollTop || isNaN(scrollTop))\n return;\n\n this.$scrollTop = scrollTop;\n this._signal(\"changeScrollTop\", scrollTop);\n };\n this.getScrollTop = function() {\n return this.$scrollTop;\n };\n\n this.$scrollLeft = 0;\n this.setScrollLeft = function(scrollLeft) {\n if (this.$scrollLeft === scrollLeft || isNaN(scrollLeft))\n return;\n\n this.$scrollLeft = scrollLeft;\n this._signal(\"changeScrollLeft\", scrollLeft);\n };\n this.getScrollLeft = function() {\n return this.$scrollLeft;\n };\n this.getScreenWidth = function() {\n this.$computeWidth();\n if (this.lineWidgets) \n return Math.max(this.getLineWidgetMaxWidth(), this.screenWidth);\n return this.screenWidth;\n };\n \n this.getLineWidgetMaxWidth = function() {\n if (this.lineWidgetsWidth != null) return this.lineWidgetsWidth;\n var width = 0;\n this.lineWidgets.forEach(function(w) {\n if (w && w.screenWidth > width)\n width = w.screenWidth;\n });\n return this.lineWidgetWidth = width;\n };\n\n this.$computeWidth = function(force) {\n if (this.$modified || force) {\n this.$modified = false;\n\n if (this.$useWrapMode)\n return this.screenWidth = this.$wrapLimit;\n\n var lines = this.doc.getAllLines();\n var cache = this.$rowLengthCache;\n var longestScreenLine = 0;\n var foldIndex = 0;\n var foldLine = this.$foldData[foldIndex];\n var foldStart = foldLine ? foldLine.start.row : Infinity;\n var len = lines.length;\n\n for (var i = 0; i < len; i++) {\n if (i > foldStart) {\n i = foldLine.end.row + 1;\n if (i >= len)\n break;\n foldLine = this.$foldData[foldIndex++];\n foldStart = foldLine ? foldLine.start.row : Infinity;\n }\n\n if (cache[i] == null)\n cache[i] = this.$getStringScreenWidth(lines[i])[0];\n\n if (cache[i] > longestScreenLine)\n longestScreenLine = cache[i];\n }\n this.screenWidth = longestScreenLine;\n }\n };\n this.getLine = function(row) {\n return this.doc.getLine(row);\n };\n this.getLines = function(firstRow, lastRow) {\n return this.doc.getLines(firstRow, lastRow);\n };\n this.getLength = function() {\n return this.doc.getLength();\n };\n this.getTextRange = function(range) {\n return this.doc.getTextRange(range || this.selection.getRange());\n };\n this.insert = function(position, text) {\n return this.doc.insert(position, text);\n };\n this.remove = function(range) {\n return this.doc.remove(range);\n };\n this.removeFullLines = function(firstRow, lastRow){\n return this.doc.removeFullLines(firstRow, lastRow);\n };\n this.undoChanges = function(deltas, dontSelect) {\n if (!deltas.length)\n return;\n\n this.$fromUndo = true;\n var lastUndoRange = null;\n for (var i = deltas.length - 1; i != -1; i--) {\n var delta = deltas[i];\n if (delta.group == \"doc\") {\n this.doc.revertDeltas(delta.deltas);\n lastUndoRange =\n this.$getUndoSelection(delta.deltas, true, lastUndoRange);\n } else {\n delta.deltas.forEach(function(foldDelta) {\n this.addFolds(foldDelta.folds);\n }, this);\n }\n }\n this.$fromUndo = false;\n lastUndoRange &&\n this.$undoSelect &&\n !dontSelect &&\n this.selection.setSelectionRange(lastUndoRange);\n return lastUndoRange;\n };\n this.redoChanges = function(deltas, dontSelect) {\n if (!deltas.length)\n return;\n\n this.$fromUndo = true;\n var lastUndoRange = null;\n for (var i = 0; i < deltas.length; i++) {\n var delta = deltas[i];\n if (delta.group == \"doc\") {\n this.doc.applyDeltas(delta.deltas);\n lastUndoRange =\n this.$getUndoSelection(delta.deltas, false, lastUndoRange);\n }\n }\n this.$fromUndo = false;\n lastUndoRange &&\n this.$undoSelect &&\n !dontSelect &&\n this.selection.setSelectionRange(lastUndoRange);\n return lastUndoRange;\n };\n this.setUndoSelect = function(enable) {\n this.$undoSelect = enable;\n };\n\n this.$getUndoSelection = function(deltas, isUndo, lastUndoRange) {\n function isInsert(delta) {\n return isUndo ? delta.action !== \"insert\" : delta.action === \"insert\";\n }\n\n var delta = deltas[0];\n var range, point;\n var lastDeltaIsInsert = false;\n if (isInsert(delta)) {\n range = Range.fromPoints(delta.start, delta.end);\n lastDeltaIsInsert = true;\n } else {\n range = Range.fromPoints(delta.start, delta.start);\n lastDeltaIsInsert = false;\n }\n\n for (var i = 1; i < deltas.length; i++) {\n delta = deltas[i];\n if (isInsert(delta)) {\n point = delta.start;\n if (range.compare(point.row, point.column) == -1) {\n range.setStart(point);\n }\n point = delta.end;\n if (range.compare(point.row, point.column) == 1) {\n range.setEnd(point);\n }\n lastDeltaIsInsert = true;\n } else {\n point = delta.start;\n if (range.compare(point.row, point.column) == -1) {\n range = Range.fromPoints(delta.start, delta.start);\n }\n lastDeltaIsInsert = false;\n }\n }\n if (lastUndoRange != null) {\n if (Range.comparePoints(lastUndoRange.start, range.start) === 0) {\n lastUndoRange.start.column += range.end.column - range.start.column;\n lastUndoRange.end.column += range.end.column - range.start.column;\n }\n\n var cmp = lastUndoRange.compareRange(range);\n if (cmp == 1) {\n range.setStart(lastUndoRange.start);\n } else if (cmp == -1) {\n range.setEnd(lastUndoRange.end);\n }\n }\n\n return range;\n };\n this.replace = function(range, text) {\n return this.doc.replace(range, text);\n };\n this.moveText = function(fromRange, toPosition, copy) {\n var text = this.getTextRange(fromRange);\n var folds = this.getFoldsInRange(fromRange);\n\n var toRange = Range.fromPoints(toPosition, toPosition);\n if (!copy) {\n this.remove(fromRange);\n var rowDiff = fromRange.start.row - fromRange.end.row;\n var collDiff = rowDiff ? -fromRange.end.column : fromRange.start.column - fromRange.end.column;\n if (collDiff) {\n if (toRange.start.row == fromRange.end.row && toRange.start.column > fromRange.end.column)\n toRange.start.column += collDiff;\n if (toRange.end.row == fromRange.end.row && toRange.end.column > fromRange.end.column)\n toRange.end.column += collDiff;\n }\n if (rowDiff && toRange.start.row >= fromRange.end.row) {\n toRange.start.row += rowDiff;\n toRange.end.row += rowDiff;\n }\n }\n\n toRange.end = this.insert(toRange.start, text);\n if (folds.length) {\n var oldStart = fromRange.start;\n var newStart = toRange.start;\n var rowDiff = newStart.row - oldStart.row;\n var collDiff = newStart.column - oldStart.column;\n this.addFolds(folds.map(function(x) {\n x = x.clone();\n if (x.start.row == oldStart.row)\n x.start.column += collDiff;\n if (x.end.row == oldStart.row)\n x.end.column += collDiff;\n x.start.row += rowDiff;\n x.end.row += rowDiff;\n return x;\n }));\n }\n\n return toRange;\n };\n this.indentRows = function(startRow, endRow, indentString) {\n indentString = indentString.replace(/\\t/g, this.getTabString());\n for (var row=startRow; row<=endRow; row++)\n this.doc.insertInLine({row: row, column: 0}, indentString);\n };\n this.outdentRows = function (range) {\n var rowRange = range.collapseRows();\n var deleteRange = new Range(0, 0, 0, 0);\n var size = this.getTabSize();\n\n for (var i = rowRange.start.row; i <= rowRange.end.row; ++i) {\n var line = this.getLine(i);\n\n deleteRange.start.row = i;\n deleteRange.end.row = i;\n for (var j = 0; j < size; ++j)\n if (line.charAt(j) != ' ')\n break;\n if (j < size && line.charAt(j) == '\\t') {\n deleteRange.start.column = j;\n deleteRange.end.column = j + 1;\n } else {\n deleteRange.start.column = 0;\n deleteRange.end.column = j;\n }\n this.remove(deleteRange);\n }\n };\n\n this.$moveLines = function(firstRow, lastRow, dir) {\n firstRow = this.getRowFoldStart(firstRow);\n lastRow = this.getRowFoldEnd(lastRow);\n if (dir < 0) {\n var row = this.getRowFoldStart(firstRow + dir);\n if (row < 0) return 0;\n var diff = row-firstRow;\n } else if (dir > 0) {\n var row = this.getRowFoldEnd(lastRow + dir);\n if (row > this.doc.getLength()-1) return 0;\n var diff = row-lastRow;\n } else {\n firstRow = this.$clipRowToDocument(firstRow);\n lastRow = this.$clipRowToDocument(lastRow);\n var diff = lastRow - firstRow + 1;\n }\n\n var range = new Range(firstRow, 0, lastRow, Number.MAX_VALUE);\n var folds = this.getFoldsInRange(range).map(function(x){\n x = x.clone();\n x.start.row += diff;\n x.end.row += diff;\n return x;\n });\n \n var lines = dir == 0\n ? this.doc.getLines(firstRow, lastRow)\n : this.doc.removeFullLines(firstRow, lastRow);\n this.doc.insertFullLines(firstRow+diff, lines);\n folds.length && this.addFolds(folds);\n return diff;\n };\n this.moveLinesUp = function(firstRow, lastRow) {\n return this.$moveLines(firstRow, lastRow, -1);\n };\n this.moveLinesDown = function(firstRow, lastRow) {\n return this.$moveLines(firstRow, lastRow, 1);\n };\n this.duplicateLines = function(firstRow, lastRow) {\n return this.$moveLines(firstRow, lastRow, 0);\n };\n\n\n this.$clipRowToDocument = function(row) {\n return Math.max(0, Math.min(row, this.doc.getLength()-1));\n };\n\n this.$clipColumnToRow = function(row, column) {\n if (column < 0)\n return 0;\n return Math.min(this.doc.getLine(row).length, column);\n };\n\n\n this.$clipPositionToDocument = function(row, column) {\n column = Math.max(0, column);\n\n if (row < 0) {\n row = 0;\n column = 0;\n } else {\n var len = this.doc.getLength();\n if (row >= len) {\n row = len - 1;\n column = this.doc.getLine(len-1).length;\n } else {\n column = Math.min(this.doc.getLine(row).length, column);\n }\n }\n\n return {\n row: row,\n column: column\n };\n };\n\n this.$clipRangeToDocument = function(range) {\n if (range.start.row < 0) {\n range.start.row = 0;\n range.start.column = 0;\n } else {\n range.start.column = this.$clipColumnToRow(\n range.start.row,\n range.start.column\n );\n }\n\n var len = this.doc.getLength() - 1;\n if (range.end.row > len) {\n range.end.row = len;\n range.end.column = this.doc.getLine(len).length;\n } else {\n range.end.column = this.$clipColumnToRow(\n range.end.row,\n range.end.column\n );\n }\n return range;\n };\n this.$wrapLimit = 80;\n this.$useWrapMode = false;\n this.$wrapLimitRange = {\n min : null,\n max : null\n };\n this.setUseWrapMode = function(useWrapMode) {\n if (useWrapMode != this.$useWrapMode) {\n this.$useWrapMode = useWrapMode;\n this.$modified = true;\n this.$resetRowCache(0);\n if (useWrapMode) {\n var len = this.getLength();\n this.$wrapData = Array(len);\n this.$updateWrapData(0, len - 1);\n }\n\n this._signal(\"changeWrapMode\");\n }\n };\n this.getUseWrapMode = function() {\n return this.$useWrapMode;\n };\n this.setWrapLimitRange = function(min, max) {\n if (this.$wrapLimitRange.min !== min || this.$wrapLimitRange.max !== max) {\n this.$wrapLimitRange = { min: min, max: max };\n this.$modified = true;\n if (this.$useWrapMode)\n this._signal(\"changeWrapMode\");\n }\n };\n this.adjustWrapLimit = function(desiredLimit, $printMargin) {\n var limits = this.$wrapLimitRange;\n if (limits.max < 0)\n limits = {min: $printMargin, max: $printMargin};\n var wrapLimit = this.$constrainWrapLimit(desiredLimit, limits.min, limits.max);\n if (wrapLimit != this.$wrapLimit && wrapLimit > 1) {\n this.$wrapLimit = wrapLimit;\n this.$modified = true;\n if (this.$useWrapMode) {\n this.$updateWrapData(0, this.getLength() - 1);\n this.$resetRowCache(0);\n this._signal(\"changeWrapLimit\");\n }\n return true;\n }\n return false;\n };\n\n this.$constrainWrapLimit = function(wrapLimit, min, max) {\n if (min)\n wrapLimit = Math.max(min, wrapLimit);\n\n if (max)\n wrapLimit = Math.min(max, wrapLimit);\n\n return wrapLimit;\n };\n this.getWrapLimit = function() {\n return this.$wrapLimit;\n };\n this.setWrapLimit = function (limit) {\n this.setWrapLimitRange(limit, limit);\n };\n this.getWrapLimitRange = function() {\n return {\n min : this.$wrapLimitRange.min,\n max : this.$wrapLimitRange.max\n };\n };\n\n this.$updateInternalDataOnChange = function(delta) {\n var useWrapMode = this.$useWrapMode;\n var action = delta.action;\n var start = delta.start;\n var end = delta.end;\n var firstRow = start.row;\n var lastRow = end.row;\n var len = lastRow - firstRow;\n var removedFolds = null;\n \n this.$updating = true;\n if (len != 0) {\n if (action === \"remove\") {\n this[useWrapMode ? \"$wrapData\" : \"$rowLengthCache\"].splice(firstRow, len);\n\n var foldLines = this.$foldData;\n removedFolds = this.getFoldsInRange(delta);\n this.removeFolds(removedFolds);\n\n var foldLine = this.getFoldLine(end.row);\n var idx = 0;\n if (foldLine) {\n foldLine.addRemoveChars(end.row, end.column, start.column - end.column);\n foldLine.shiftRow(-len);\n\n var foldLineBefore = this.getFoldLine(firstRow);\n if (foldLineBefore && foldLineBefore !== foldLine) {\n foldLineBefore.merge(foldLine);\n foldLine = foldLineBefore;\n }\n idx = foldLines.indexOf(foldLine) + 1;\n }\n\n for (idx; idx < foldLines.length; idx++) {\n var foldLine = foldLines[idx];\n if (foldLine.start.row >= end.row) {\n foldLine.shiftRow(-len);\n }\n }\n\n lastRow = firstRow;\n } else {\n var args = Array(len);\n args.unshift(firstRow, 0);\n var arr = useWrapMode ? this.$wrapData : this.$rowLengthCache\n arr.splice.apply(arr, args);\n var foldLines = this.$foldData;\n var foldLine = this.getFoldLine(firstRow);\n var idx = 0;\n if (foldLine) {\n var cmp = foldLine.range.compareInside(start.row, start.column);\n if (cmp == 0) {\n foldLine = foldLine.split(start.row, start.column);\n if (foldLine) {\n foldLine.shiftRow(len);\n foldLine.addRemoveChars(lastRow, 0, end.column - start.column);\n }\n } else\n if (cmp == -1) {\n foldLine.addRemoveChars(firstRow, 0, end.column - start.column);\n foldLine.shiftRow(len);\n }\n idx = foldLines.indexOf(foldLine) + 1;\n }\n\n for (idx; idx < foldLines.length; idx++) {\n var foldLine = foldLines[idx];\n if (foldLine.start.row >= firstRow) {\n foldLine.shiftRow(len);\n }\n }\n }\n } else {\n len = Math.abs(delta.start.column - delta.end.column);\n if (action === \"remove\") {\n removedFolds = this.getFoldsInRange(delta);\n this.removeFolds(removedFolds);\n\n len = -len;\n }\n var foldLine = this.getFoldLine(firstRow);\n if (foldLine) {\n foldLine.addRemoveChars(firstRow, start.column, len);\n }\n }\n\n if (useWrapMode && this.$wrapData.length != this.doc.getLength()) {\n console.error(\"doc.getLength() and $wrapData.length have to be the same!\");\n }\n this.$updating = false;\n\n if (useWrapMode)\n this.$updateWrapData(firstRow, lastRow);\n else\n this.$updateRowLengthCache(firstRow, lastRow);\n\n return removedFolds;\n };\n\n this.$updateRowLengthCache = function(firstRow, lastRow, b) {\n this.$rowLengthCache[firstRow] = null;\n this.$rowLengthCache[lastRow] = null;\n };\n\n this.$updateWrapData = function(firstRow, lastRow) {\n var lines = this.doc.getAllLines();\n var tabSize = this.getTabSize();\n var wrapData = this.$wrapData;\n var wrapLimit = this.$wrapLimit;\n var tokens;\n var foldLine;\n\n var row = firstRow;\n lastRow = Math.min(lastRow, lines.length - 1);\n while (row <= lastRow) {\n foldLine = this.getFoldLine(row, foldLine);\n if (!foldLine) {\n tokens = this.$getDisplayTokens(lines[row]);\n wrapData[row] = this.$computeWrapSplits(tokens, wrapLimit, tabSize);\n row ++;\n } else {\n tokens = [];\n foldLine.walk(function(placeholder, row, column, lastColumn) {\n var walkTokens;\n if (placeholder != null) {\n walkTokens = this.$getDisplayTokens(\n placeholder, tokens.length);\n walkTokens[0] = PLACEHOLDER_START;\n for (var i = 1; i < walkTokens.length; i++) {\n walkTokens[i] = PLACEHOLDER_BODY;\n }\n } else {\n walkTokens = this.$getDisplayTokens(\n lines[row].substring(lastColumn, column),\n tokens.length);\n }\n tokens = tokens.concat(walkTokens);\n }.bind(this),\n foldLine.end.row,\n lines[foldLine.end.row].length + 1\n );\n\n wrapData[foldLine.start.row] = this.$computeWrapSplits(tokens, wrapLimit, tabSize);\n row = foldLine.end.row + 1;\n }\n }\n };\n var CHAR = 1,\n CHAR_EXT = 2,\n PLACEHOLDER_START = 3,\n PLACEHOLDER_BODY = 4,\n PUNCTUATION = 9,\n SPACE = 10,\n TAB = 11,\n TAB_SPACE = 12;\n\n\n this.$computeWrapSplits = function(tokens, wrapLimit, tabSize) {\n if (tokens.length == 0) {\n return [];\n }\n\n var splits = [];\n var displayLength = tokens.length;\n var lastSplit = 0, lastDocSplit = 0;\n\n var isCode = this.$wrapAsCode;\n\n var indentedSoftWrap = this.$indentedSoftWrap;\n var maxIndent = wrapLimit <= Math.max(2 * tabSize, 8)\n || indentedSoftWrap === false ? 0 : Math.floor(wrapLimit / 2);\n\n function getWrapIndent() {\n var indentation = 0;\n if (maxIndent === 0)\n return indentation;\n if (indentedSoftWrap) {\n for (var i = 0; i < tokens.length; i++) {\n var token = tokens[i];\n if (token == SPACE)\n indentation += 1;\n else if (token == TAB)\n indentation += tabSize;\n else if (token == TAB_SPACE)\n continue;\n else\n break;\n }\n }\n if (isCode && indentedSoftWrap !== false)\n indentation += tabSize;\n return Math.min(indentation, maxIndent);\n }\n function addSplit(screenPos) {\n var displayed = tokens.slice(lastSplit, screenPos);\n var len = displayed.length;\n displayed.join(\"\")\n .replace(/12/g, function() {\n len -= 1;\n })\n .replace(/2/g, function() {\n len -= 1;\n });\n\n if (!splits.length) {\n indent = getWrapIndent();\n splits.indent = indent;\n }\n lastDocSplit += len;\n splits.push(lastDocSplit);\n lastSplit = screenPos;\n }\n var indent = 0;\n while (displayLength - lastSplit > wrapLimit - indent) {\n var split = lastSplit + wrapLimit - indent;\n if (tokens[split - 1] >= SPACE && tokens[split] >= SPACE) {\n addSplit(split);\n continue;\n }\n if (tokens[split] == PLACEHOLDER_START || tokens[split] == PLACEHOLDER_BODY) {\n for (split; split != lastSplit - 1; split--) {\n if (tokens[split] == PLACEHOLDER_START) {\n break;\n }\n }\n if (split > lastSplit) {\n addSplit(split);\n continue;\n }\n split = lastSplit + wrapLimit;\n for (split; split < tokens.length; split++) {\n if (tokens[split] != PLACEHOLDER_BODY) {\n break;\n }\n }\n if (split == tokens.length) {\n break; // Breaks the while-loop.\n }\n addSplit(split);\n continue;\n }\n var minSplit = Math.max(split - (wrapLimit -(wrapLimit>>2)), lastSplit - 1);\n while (split > minSplit && tokens[split] < PLACEHOLDER_START) {\n split --;\n }\n if (isCode) {\n while (split > minSplit && tokens[split] < PLACEHOLDER_START) {\n split --;\n }\n while (split > minSplit && tokens[split] == PUNCTUATION) {\n split --;\n }\n } else {\n while (split > minSplit && tokens[split] < SPACE) {\n split --;\n }\n }\n if (split > minSplit) {\n addSplit(++split);\n continue;\n }\n split = lastSplit + wrapLimit;\n if (tokens[split] == CHAR_EXT)\n split--;\n addSplit(split - indent);\n }\n return splits;\n };\n this.$getDisplayTokens = function(str, offset) {\n var arr = [];\n var tabSize;\n offset = offset || 0;\n\n for (var i = 0; i < str.length; i++) {\n var c = str.charCodeAt(i);\n if (c == 9) {\n tabSize = this.getScreenTabSize(arr.length + offset);\n arr.push(TAB);\n for (var n = 1; n < tabSize; n++) {\n arr.push(TAB_SPACE);\n }\n }\n else if (c == 32) {\n arr.push(SPACE);\n } else if((c > 39 && c < 48) || (c > 57 && c < 64)) {\n arr.push(PUNCTUATION);\n }\n else if (c >= 0x1100 && isFullWidth(c)) {\n arr.push(CHAR, CHAR_EXT);\n } else {\n arr.push(CHAR);\n }\n }\n return arr;\n };\n this.$getStringScreenWidth = function(str, maxScreenColumn, screenColumn) {\n if (maxScreenColumn == 0)\n return [0, 0];\n if (maxScreenColumn == null)\n maxScreenColumn = Infinity;\n screenColumn = screenColumn || 0;\n\n var c, column;\n for (column = 0; column < str.length; column++) {\n c = str.charCodeAt(column);\n if (c == 9) {\n screenColumn += this.getScreenTabSize(screenColumn);\n }\n else if (c >= 0x1100 && isFullWidth(c)) {\n screenColumn += 2;\n } else {\n screenColumn += 1;\n }\n if (screenColumn > maxScreenColumn) {\n break;\n }\n }\n\n return [screenColumn, column];\n };\n\n this.lineWidgets = null;\n this.getRowLength = function(row) {\n if (this.lineWidgets)\n var h = this.lineWidgets[row] && this.lineWidgets[row].rowCount || 0;\n else \n h = 0\n if (!this.$useWrapMode || !this.$wrapData[row]) {\n return 1 + h;\n } else {\n return this.$wrapData[row].length + 1 + h;\n }\n };\n this.getRowLineCount = function(row) {\n if (!this.$useWrapMode || !this.$wrapData[row]) {\n return 1;\n } else {\n return this.$wrapData[row].length + 1;\n }\n };\n\n this.getRowWrapIndent = function(screenRow) {\n if (this.$useWrapMode) {\n var pos = this.screenToDocumentPosition(screenRow, Number.MAX_VALUE);\n var splits = this.$wrapData[pos.row];\n return splits.length && splits[0] < pos.column ? splits.indent : 0;\n } else {\n return 0;\n }\n }\n this.getScreenLastRowColumn = function(screenRow) {\n var pos = this.screenToDocumentPosition(screenRow, Number.MAX_VALUE);\n return this.documentToScreenColumn(pos.row, pos.column);\n };\n this.getDocumentLastRowColumn = function(docRow, docColumn) {\n var screenRow = this.documentToScreenRow(docRow, docColumn);\n return this.getScreenLastRowColumn(screenRow);\n };\n this.getDocumentLastRowColumnPosition = function(docRow, docColumn) {\n var screenRow = this.documentToScreenRow(docRow, docColumn);\n return this.screenToDocumentPosition(screenRow, Number.MAX_VALUE / 10);\n };\n this.getRowSplitData = function(row) {\n if (!this.$useWrapMode) {\n return undefined;\n } else {\n return this.$wrapData[row];\n }\n };\n this.getScreenTabSize = function(screenColumn) {\n return this.$tabSize - screenColumn % this.$tabSize;\n };\n\n\n this.screenToDocumentRow = function(screenRow, screenColumn) {\n return this.screenToDocumentPosition(screenRow, screenColumn).row;\n };\n\n\n this.screenToDocumentColumn = function(screenRow, screenColumn) {\n return this.screenToDocumentPosition(screenRow, screenColumn).column;\n };\n this.screenToDocumentPosition = function(screenRow, screenColumn) {\n if (screenRow < 0)\n return {row: 0, column: 0};\n\n var line;\n var docRow = 0;\n var docColumn = 0;\n var column;\n var row = 0;\n var rowLength = 0;\n\n var rowCache = this.$screenRowCache;\n var i = this.$getRowCacheIndex(rowCache, screenRow);\n var l = rowCache.length;\n if (l && i >= 0) {\n var row = rowCache[i];\n var docRow = this.$docRowCache[i];\n var doCache = screenRow > rowCache[l - 1];\n } else {\n var doCache = !l;\n }\n\n var maxRow = this.getLength() - 1;\n var foldLine = this.getNextFoldLine(docRow);\n var foldStart = foldLine ? foldLine.start.row : Infinity;\n\n while (row <= screenRow) {\n rowLength = this.getRowLength(docRow);\n if (row + rowLength > screenRow || docRow >= maxRow) {\n break;\n } else {\n row += rowLength;\n docRow++;\n if (docRow > foldStart) {\n docRow = foldLine.end.row+1;\n foldLine = this.getNextFoldLine(docRow, foldLine);\n foldStart = foldLine ? foldLine.start.row : Infinity;\n }\n }\n\n if (doCache) {\n this.$docRowCache.push(docRow);\n this.$screenRowCache.push(row);\n }\n }\n\n if (foldLine && foldLine.start.row <= docRow) {\n line = this.getFoldDisplayLine(foldLine);\n docRow = foldLine.start.row;\n } else if (row + rowLength <= screenRow || docRow > maxRow) {\n return {\n row: maxRow,\n column: this.getLine(maxRow).length\n };\n } else {\n line = this.getLine(docRow);\n foldLine = null;\n }\n var wrapIndent = 0;\n if (this.$useWrapMode) {\n var splits = this.$wrapData[docRow];\n if (splits) {\n var splitIndex = Math.floor(screenRow - row);\n column = splits[splitIndex];\n if(splitIndex > 0 && splits.length) {\n wrapIndent = splits.indent;\n docColumn = splits[splitIndex - 1] || splits[splits.length - 1];\n line = line.substring(docColumn);\n }\n }\n }\n\n docColumn += this.$getStringScreenWidth(line, screenColumn - wrapIndent)[1];\n if (this.$useWrapMode && docColumn >= column)\n docColumn = column - 1;\n\n if (foldLine)\n return foldLine.idxToPosition(docColumn);\n\n return {row: docRow, column: docColumn};\n };\n this.documentToScreenPosition = function(docRow, docColumn) {\n if (typeof docColumn === \"undefined\")\n var pos = this.$clipPositionToDocument(docRow.row, docRow.column);\n else\n pos = this.$clipPositionToDocument(docRow, docColumn);\n\n docRow = pos.row;\n docColumn = pos.column;\n\n var screenRow = 0;\n var foldStartRow = null;\n var fold = null;\n fold = this.getFoldAt(docRow, docColumn, 1);\n if (fold) {\n docRow = fold.start.row;\n docColumn = fold.start.column;\n }\n\n var rowEnd, row = 0;\n\n\n var rowCache = this.$docRowCache;\n var i = this.$getRowCacheIndex(rowCache, docRow);\n var l = rowCache.length;\n if (l && i >= 0) {\n var row = rowCache[i];\n var screenRow = this.$screenRowCache[i];\n var doCache = docRow > rowCache[l - 1];\n } else {\n var doCache = !l;\n }\n\n var foldLine = this.getNextFoldLine(row);\n var foldStart = foldLine ?foldLine.start.row :Infinity;\n\n while (row < docRow) {\n if (row >= foldStart) {\n rowEnd = foldLine.end.row + 1;\n if (rowEnd > docRow)\n break;\n foldLine = this.getNextFoldLine(rowEnd, foldLine);\n foldStart = foldLine ?foldLine.start.row :Infinity;\n }\n else {\n rowEnd = row + 1;\n }\n\n screenRow += this.getRowLength(row);\n row = rowEnd;\n\n if (doCache) {\n this.$docRowCache.push(row);\n this.$screenRowCache.push(screenRow);\n }\n }\n var textLine = \"\";\n if (foldLine && row >= foldStart) {\n textLine = this.getFoldDisplayLine(foldLine, docRow, docColumn);\n foldStartRow = foldLine.start.row;\n } else {\n textLine = this.getLine(docRow).substring(0, docColumn);\n foldStartRow = docRow;\n }\n var wrapIndent = 0;\n if (this.$useWrapMode) {\n var wrapRow = this.$wrapData[foldStartRow];\n if (wrapRow) {\n var screenRowOffset = 0;\n while (textLine.length >= wrapRow[screenRowOffset]) {\n screenRow ++;\n screenRowOffset++;\n }\n textLine = textLine.substring(\n wrapRow[screenRowOffset - 1] || 0, textLine.length\n );\n wrapIndent = screenRowOffset > 0 ? wrapRow.indent : 0;\n }\n }\n\n return {\n row: screenRow,\n column: wrapIndent + this.$getStringScreenWidth(textLine)[0]\n };\n };\n this.documentToScreenColumn = function(row, docColumn) {\n return this.documentToScreenPosition(row, docColumn).column;\n };\n this.documentToScreenRow = function(docRow, docColumn) {\n return this.documentToScreenPosition(docRow, docColumn).row;\n };\n this.getScreenLength = function() {\n var screenRows = 0;\n var fold = null;\n if (!this.$useWrapMode) {\n screenRows = this.getLength();\n var foldData = this.$foldData;\n for (var i = 0; i < foldData.length; i++) {\n fold = foldData[i];\n screenRows -= fold.end.row - fold.start.row;\n }\n } else {\n var lastRow = this.$wrapData.length;\n var row = 0, i = 0;\n var fold = this.$foldData[i++];\n var foldStart = fold ? fold.start.row :Infinity;\n\n while (row < lastRow) {\n var splits = this.$wrapData[row];\n screenRows += splits ? splits.length + 1 : 1;\n row ++;\n if (row > foldStart) {\n row = fold.end.row+1;\n fold = this.$foldData[i++];\n foldStart = fold ?fold.start.row :Infinity;\n }\n }\n }\n if (this.lineWidgets)\n screenRows += this.$getWidgetScreenLength();\n\n return screenRows;\n };\n this.$setFontMetrics = function(fm) {\n if (!this.$enableVarChar) return;\n this.$getStringScreenWidth = function(str, maxScreenColumn, screenColumn) {\n if (maxScreenColumn === 0)\n return [0, 0];\n if (!maxScreenColumn)\n maxScreenColumn = Infinity;\n screenColumn = screenColumn || 0;\n \n var c, column;\n for (column = 0; column < str.length; column++) {\n c = str.charAt(column);\n if (c === \"\\t\") {\n screenColumn += this.getScreenTabSize(screenColumn);\n } else {\n screenColumn += fm.getCharacterWidth(c);\n }\n if (screenColumn > maxScreenColumn) {\n break;\n }\n }\n \n return [screenColumn, column];\n };\n };\n \n this.destroy = function() {\n if (this.bgTokenizer) {\n this.bgTokenizer.setDocument(null);\n this.bgTokenizer = null;\n }\n this.$stopWorker();\n };\n function isFullWidth(c) {\n if (c < 0x1100)\n return false;\n return c >= 0x1100 && c <= 0x115F ||\n c >= 0x11A3 && c <= 0x11A7 ||\n c >= 0x11FA && c <= 0x11FF ||\n c >= 0x2329 && c <= 0x232A ||\n c >= 0x2E80 && c <= 0x2E99 ||\n c >= 0x2E9B && c <= 0x2EF3 ||\n c >= 0x2F00 && c <= 0x2FD5 ||\n c >= 0x2FF0 && c <= 0x2FFB ||\n c >= 0x3000 && c <= 0x303E ||\n c >= 0x3041 && c <= 0x3096 ||\n c >= 0x3099 && c <= 0x30FF ||\n c >= 0x3105 && c <= 0x312D ||\n c >= 0x3131 && c <= 0x318E ||\n c >= 0x3190 && c <= 0x31BA ||\n c >= 0x31C0 && c <= 0x31E3 ||\n c >= 0x31F0 && c <= 0x321E ||\n c >= 0x3220 && c <= 0x3247 ||\n c >= 0x3250 && c <= 0x32FE ||\n c >= 0x3300 && c <= 0x4DBF ||\n c >= 0x4E00 && c <= 0xA48C ||\n c >= 0xA490 && c <= 0xA4C6 ||\n c >= 0xA960 && c <= 0xA97C ||\n c >= 0xAC00 && c <= 0xD7A3 ||\n c >= 0xD7B0 && c <= 0xD7C6 ||\n c >= 0xD7CB && c <= 0xD7FB ||\n c >= 0xF900 && c <= 0xFAFF ||\n c >= 0xFE10 && c <= 0xFE19 ||\n c >= 0xFE30 && c <= 0xFE52 ||\n c >= 0xFE54 && c <= 0xFE66 ||\n c >= 0xFE68 && c <= 0xFE6B ||\n c >= 0xFF01 && c <= 0xFF60 ||\n c >= 0xFFE0 && c <= 0xFFE6;\n }\n\n}).call(EditSession.prototype);\n\nacequire(\"./edit_session/folding\").Folding.call(EditSession.prototype);\nacequire(\"./edit_session/bracket_match\").BracketMatch.call(EditSession.prototype);\n\n\nconfig.defineOptions(EditSession.prototype, \"session\", {\n wrap: {\n set: function(value) {\n if (!value || value == \"off\")\n value = false;\n else if (value == \"free\")\n value = true;\n else if (value == \"printMargin\")\n value = -1;\n else if (typeof value == \"string\")\n value = parseInt(value, 10) || false;\n\n if (this.$wrap == value)\n return;\n this.$wrap = value;\n if (!value) {\n this.setUseWrapMode(false);\n } else {\n var col = typeof value == \"number\" ? value : null;\n this.setWrapLimitRange(col, col);\n this.setUseWrapMode(true);\n }\n },\n get: function() {\n if (this.getUseWrapMode()) {\n if (this.$wrap == -1)\n return \"printMargin\";\n if (!this.getWrapLimitRange().min)\n return \"free\";\n return this.$wrap;\n }\n return \"off\";\n },\n handlesSet: true\n }, \n wrapMethod: {\n set: function(val) {\n val = val == \"auto\"\n ? this.$mode.type != \"text\"\n : val != \"text\";\n if (val != this.$wrapAsCode) {\n this.$wrapAsCode = val;\n if (this.$useWrapMode) {\n this.$modified = true;\n this.$resetRowCache(0);\n this.$updateWrapData(0, this.getLength() - 1);\n }\n }\n },\n initialValue: \"auto\"\n },\n indentedSoftWrap: { initialValue: true },\n firstLineNumber: {\n set: function() {this._signal(\"changeBreakpoint\");},\n initialValue: 1\n },\n useWorker: {\n set: function(useWorker) {\n this.$useWorker = useWorker;\n\n this.$stopWorker();\n if (useWorker)\n this.$startWorker();\n },\n initialValue: true\n },\n useSoftTabs: {initialValue: true},\n tabSize: {\n set: function(tabSize) {\n if (isNaN(tabSize) || this.$tabSize === tabSize) return;\n\n this.$modified = true;\n this.$rowLengthCache = [];\n this.$tabSize = tabSize;\n this._signal(\"changeTabSize\");\n },\n initialValue: 4,\n handlesSet: true\n },\n overwrite: {\n set: function(val) {this._signal(\"changeOverwrite\");},\n initialValue: false\n },\n newLineMode: {\n set: function(val) {this.doc.setNewLineMode(val)},\n get: function() {return this.doc.getNewLineMode()},\n handlesSet: true\n },\n mode: {\n set: function(val) { this.setMode(val) },\n get: function() { return this.$modeId }\n }\n});\n\nexports.EditSession = EditSession;\n});\n\nace.define(\"ace/search\",[\"require\",\"exports\",\"module\",\"ace/lib/lang\",\"ace/lib/oop\",\"ace/range\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar lang = acequire(\"./lib/lang\");\nvar oop = acequire(\"./lib/oop\");\nvar Range = acequire(\"./range\").Range;\n\nvar Search = function() {\n this.$options = {};\n};\n\n(function() {\n this.set = function(options) {\n oop.mixin(this.$options, options);\n return this;\n };\n this.getOptions = function() {\n return lang.copyObject(this.$options);\n };\n this.setOptions = function(options) {\n this.$options = options;\n };\n this.find = function(session) {\n var options = this.$options;\n var iterator = this.$matchIterator(session, options);\n if (!iterator)\n return false;\n\n var firstRange = null;\n iterator.forEach(function(range, row, offset) {\n if (!range.start) {\n var column = range.offset + (offset || 0);\n firstRange = new Range(row, column, row, column + range.length);\n if (!range.length && options.start && options.start.start\n && options.skipCurrent != false && firstRange.isEqual(options.start)\n ) {\n firstRange = null;\n return false;\n }\n } else\n firstRange = range;\n return true;\n });\n\n return firstRange;\n };\n this.findAll = function(session) {\n var options = this.$options;\n if (!options.needle)\n return [];\n this.$assembleRegExp(options);\n\n var range = options.range;\n var lines = range\n ? session.getLines(range.start.row, range.end.row)\n : session.doc.getAllLines();\n\n var ranges = [];\n var re = options.re;\n if (options.$isMultiLine) {\n var len = re.length;\n var maxRow = lines.length - len;\n var prevRange;\n outer: for (var row = re.offset || 0; row <= maxRow; row++) {\n for (var j = 0; j < len; j++)\n if (lines[row + j].search(re[j]) == -1)\n continue outer;\n \n var startLine = lines[row];\n var line = lines[row + len - 1];\n var startIndex = startLine.length - startLine.match(re[0])[0].length;\n var endIndex = line.match(re[len - 1])[0].length;\n \n if (prevRange && prevRange.end.row === row &&\n prevRange.end.column > startIndex\n ) {\n continue;\n }\n ranges.push(prevRange = new Range(\n row, startIndex, row + len - 1, endIndex\n ));\n if (len > 2)\n row = row + len - 2;\n }\n } else {\n for (var i = 0; i < lines.length; i++) {\n var matches = lang.getMatchOffsets(lines[i], re);\n for (var j = 0; j < matches.length; j++) {\n var match = matches[j];\n ranges.push(new Range(i, match.offset, i, match.offset + match.length));\n }\n }\n }\n\n if (range) {\n var startColumn = range.start.column;\n var endColumn = range.start.column;\n var i = 0, j = ranges.length - 1;\n while (i < j && ranges[i].start.column < startColumn && ranges[i].start.row == range.start.row)\n i++;\n\n while (i < j && ranges[j].end.column > endColumn && ranges[j].end.row == range.end.row)\n j--;\n \n ranges = ranges.slice(i, j + 1);\n for (i = 0, j = ranges.length; i < j; i++) {\n ranges[i].start.row += range.start.row;\n ranges[i].end.row += range.start.row;\n }\n }\n\n return ranges;\n };\n this.replace = function(input, replacement) {\n var options = this.$options;\n\n var re = this.$assembleRegExp(options);\n if (options.$isMultiLine)\n return replacement;\n\n if (!re)\n return;\n\n var match = re.exec(input);\n if (!match || match[0].length != input.length)\n return null;\n \n replacement = input.replace(re, replacement);\n if (options.preserveCase) {\n replacement = replacement.split(\"\");\n for (var i = Math.min(input.length, input.length); i--; ) {\n var ch = input[i];\n if (ch && ch.toLowerCase() != ch)\n replacement[i] = replacement[i].toUpperCase();\n else\n replacement[i] = replacement[i].toLowerCase();\n }\n replacement = replacement.join(\"\");\n }\n \n return replacement;\n };\n\n this.$matchIterator = function(session, options) {\n var re = this.$assembleRegExp(options);\n if (!re)\n return false;\n\n var callback;\n if (options.$isMultiLine) {\n var len = re.length;\n var matchIterator = function(line, row, offset) {\n var startIndex = line.search(re[0]);\n if (startIndex == -1)\n return;\n for (var i = 1; i < len; i++) {\n line = session.getLine(row + i);\n if (line.search(re[i]) == -1)\n return;\n }\n\n var endIndex = line.match(re[len - 1])[0].length;\n\n var range = new Range(row, startIndex, row + len - 1, endIndex);\n if (re.offset == 1) {\n range.start.row--;\n range.start.column = Number.MAX_VALUE;\n } else if (offset)\n range.start.column += offset;\n\n if (callback(range))\n return true;\n };\n } else if (options.backwards) {\n var matchIterator = function(line, row, startIndex) {\n var matches = lang.getMatchOffsets(line, re);\n for (var i = matches.length-1; i >= 0; i--)\n if (callback(matches[i], row, startIndex))\n return true;\n };\n } else {\n var matchIterator = function(line, row, startIndex) {\n var matches = lang.getMatchOffsets(line, re);\n for (var i = 0; i < matches.length; i++)\n if (callback(matches[i], row, startIndex))\n return true;\n };\n }\n \n var lineIterator = this.$lineIterator(session, options);\n\n return {\n forEach: function(_callback) {\n callback = _callback;\n lineIterator.forEach(matchIterator);\n }\n };\n };\n\n this.$assembleRegExp = function(options, $disableFakeMultiline) {\n if (options.needle instanceof RegExp)\n return options.re = options.needle;\n\n var needle = options.needle;\n\n if (!options.needle)\n return options.re = false;\n\n if (!options.regExp)\n needle = lang.escapeRegExp(needle);\n\n if (options.wholeWord)\n needle = \"\\\\b\" + needle + \"\\\\b\";\n\n var modifier = options.caseSensitive ? \"gm\" : \"gmi\";\n\n options.$isMultiLine = !$disableFakeMultiline && /[\\n\\r]/.test(needle);\n if (options.$isMultiLine)\n return options.re = this.$assembleMultilineRegExp(needle, modifier);\n\n try {\n var re = new RegExp(needle, modifier);\n } catch(e) {\n re = false;\n }\n return options.re = re;\n };\n\n this.$assembleMultilineRegExp = function(needle, modifier) {\n var parts = needle.replace(/\\r\\n|\\r|\\n/g, \"$\\n^\").split(\"\\n\");\n var re = [];\n for (var i = 0; i < parts.length; i++) try {\n re.push(new RegExp(parts[i], modifier));\n } catch(e) {\n return false;\n }\n if (parts[0] == \"\") {\n re.shift();\n re.offset = 1;\n } else {\n re.offset = 0;\n }\n return re;\n };\n\n this.$lineIterator = function(session, options) {\n var backwards = options.backwards == true;\n var skipCurrent = options.skipCurrent != false;\n\n var range = options.range;\n var start = options.start;\n if (!start)\n start = range ? range[backwards ? \"end\" : \"start\"] : session.selection.getRange();\n \n if (start.start)\n start = start[skipCurrent != backwards ? \"end\" : \"start\"];\n\n var firstRow = range ? range.start.row : 0;\n var lastRow = range ? range.end.row : session.getLength() - 1;\n\n var forEach = backwards ? function(callback) {\n var row = start.row;\n\n var line = session.getLine(row).substring(0, start.column);\n if (callback(line, row))\n return;\n\n for (row--; row >= firstRow; row--)\n if (callback(session.getLine(row), row))\n return;\n\n if (options.wrap == false)\n return;\n\n for (row = lastRow, firstRow = start.row; row >= firstRow; row--)\n if (callback(session.getLine(row), row))\n return;\n } : function(callback) {\n var row = start.row;\n\n var line = session.getLine(row).substr(start.column);\n if (callback(line, row, start.column))\n return;\n\n for (row = row+1; row <= lastRow; row++)\n if (callback(session.getLine(row), row))\n return;\n\n if (options.wrap == false)\n return;\n\n for (row = firstRow, lastRow = start.row; row <= lastRow; row++)\n if (callback(session.getLine(row), row))\n return;\n };\n \n return {forEach: forEach};\n };\n\n}).call(Search.prototype);\n\nexports.Search = Search;\n});\n\nace.define(\"ace/keyboard/hash_handler\",[\"require\",\"exports\",\"module\",\"ace/lib/keys\",\"ace/lib/useragent\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar keyUtil = acequire(\"../lib/keys\");\nvar useragent = acequire(\"../lib/useragent\");\nvar KEY_MODS = keyUtil.KEY_MODS;\n\nfunction HashHandler(config, platform) {\n this.platform = platform || (useragent.isMac ? \"mac\" : \"win\");\n this.commands = {};\n this.commandKeyBinding = {};\n this.addCommands(config);\n this.$singleCommand = true;\n}\n\nfunction MultiHashHandler(config, platform) {\n HashHandler.call(this, config, platform);\n this.$singleCommand = false;\n}\n\nMultiHashHandler.prototype = HashHandler.prototype;\n\n(function() {\n \n\n this.addCommand = function(command) {\n if (this.commands[command.name])\n this.removeCommand(command);\n\n this.commands[command.name] = command;\n\n if (command.bindKey)\n this._buildKeyHash(command);\n };\n\n this.removeCommand = function(command, keepCommand) {\n var name = command && (typeof command === 'string' ? command : command.name);\n command = this.commands[name];\n if (!keepCommand)\n delete this.commands[name];\n var ckb = this.commandKeyBinding;\n for (var keyId in ckb) {\n var cmdGroup = ckb[keyId];\n if (cmdGroup == command) {\n delete ckb[keyId];\n } else if (Array.isArray(cmdGroup)) {\n var i = cmdGroup.indexOf(command);\n if (i != -1) {\n cmdGroup.splice(i, 1);\n if (cmdGroup.length == 1)\n ckb[keyId] = cmdGroup[0];\n }\n }\n }\n };\n\n this.bindKey = function(key, command, position) {\n if (typeof key == \"object\" && key) {\n if (position == undefined)\n position = key.position;\n key = key[this.platform];\n }\n if (!key)\n return;\n if (typeof command == \"function\")\n return this.addCommand({exec: command, bindKey: key, name: command.name || key});\n \n key.split(\"|\").forEach(function(keyPart) {\n var chain = \"\";\n if (keyPart.indexOf(\" \") != -1) {\n var parts = keyPart.split(/\\s+/);\n keyPart = parts.pop();\n parts.forEach(function(keyPart) {\n var binding = this.parseKeys(keyPart);\n var id = KEY_MODS[binding.hashId] + binding.key;\n chain += (chain ? \" \" : \"\") + id;\n this._addCommandToBinding(chain, \"chainKeys\");\n }, this);\n chain += \" \";\n }\n var binding = this.parseKeys(keyPart);\n var id = KEY_MODS[binding.hashId] + binding.key;\n this._addCommandToBinding(chain + id, command, position);\n }, this);\n };\n \n function getPosition(command) {\n return typeof command == \"object\" && command.bindKey\n && command.bindKey.position || 0;\n }\n this._addCommandToBinding = function(keyId, command, position) {\n var ckb = this.commandKeyBinding, i;\n if (!command) {\n delete ckb[keyId];\n } else if (!ckb[keyId] || this.$singleCommand) {\n ckb[keyId] = command;\n } else {\n if (!Array.isArray(ckb[keyId])) {\n ckb[keyId] = [ckb[keyId]];\n } else if ((i = ckb[keyId].indexOf(command)) != -1) {\n ckb[keyId].splice(i, 1);\n }\n\n if (typeof position != \"number\") {\n if (position || command.isDefault)\n position = -100;\n else\n position = getPosition(command);\n }\n var commands = ckb[keyId];\n for (i = 0; i < commands.length; i++) {\n var other = commands[i];\n var otherPos = getPosition(other);\n if (otherPos > position)\n break;\n }\n commands.splice(i, 0, command);\n }\n };\n\n this.addCommands = function(commands) {\n commands && Object.keys(commands).forEach(function(name) {\n var command = commands[name];\n if (!command)\n return;\n \n if (typeof command === \"string\")\n return this.bindKey(command, name);\n\n if (typeof command === \"function\")\n command = { exec: command };\n\n if (typeof command !== \"object\")\n return;\n\n if (!command.name)\n command.name = name;\n\n this.addCommand(command);\n }, this);\n };\n\n this.removeCommands = function(commands) {\n Object.keys(commands).forEach(function(name) {\n this.removeCommand(commands[name]);\n }, this);\n };\n\n this.bindKeys = function(keyList) {\n Object.keys(keyList).forEach(function(key) {\n this.bindKey(key, keyList[key]);\n }, this);\n };\n\n this._buildKeyHash = function(command) {\n this.bindKey(command.bindKey, command);\n };\n this.parseKeys = function(keys) {\n var parts = keys.toLowerCase().split(/[\\-\\+]([\\-\\+])?/).filter(function(x){return x});\n var key = parts.pop();\n\n var keyCode = keyUtil[key];\n if (keyUtil.FUNCTION_KEYS[keyCode])\n key = keyUtil.FUNCTION_KEYS[keyCode].toLowerCase();\n else if (!parts.length)\n return {key: key, hashId: -1};\n else if (parts.length == 1 && parts[0] == \"shift\")\n return {key: key.toUpperCase(), hashId: -1};\n\n var hashId = 0;\n for (var i = parts.length; i--;) {\n var modifier = keyUtil.KEY_MODS[parts[i]];\n if (modifier == null) {\n if (typeof console != \"undefined\")\n console.error(\"invalid modifier \" + parts[i] + \" in \" + keys);\n return false;\n }\n hashId |= modifier;\n }\n return {key: key, hashId: hashId};\n };\n\n this.findKeyCommand = function findKeyCommand(hashId, keyString) {\n var key = KEY_MODS[hashId] + keyString;\n return this.commandKeyBinding[key];\n };\n\n this.handleKeyboard = function(data, hashId, keyString, keyCode) {\n if (keyCode < 0) return;\n var key = KEY_MODS[hashId] + keyString;\n var command = this.commandKeyBinding[key];\n if (data.$keyChain) {\n data.$keyChain += \" \" + key;\n command = this.commandKeyBinding[data.$keyChain] || command;\n }\n \n if (command) {\n if (command == \"chainKeys\" || command[command.length - 1] == \"chainKeys\") {\n data.$keyChain = data.$keyChain || key;\n return {command: \"null\"};\n }\n }\n \n if (data.$keyChain) {\n if ((!hashId || hashId == 4) && keyString.length == 1)\n data.$keyChain = data.$keyChain.slice(0, -key.length - 1); // wait for input\n else if (hashId == -1 || keyCode > 0)\n data.$keyChain = \"\"; // reset keyChain\n }\n return {command: command};\n };\n \n this.getStatusText = function(editor, data) {\n return data.$keyChain || \"\";\n };\n\n}).call(HashHandler.prototype);\n\nexports.HashHandler = HashHandler;\nexports.MultiHashHandler = MultiHashHandler;\n});\n\nace.define(\"ace/commands/command_manager\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/keyboard/hash_handler\",\"ace/lib/event_emitter\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar oop = acequire(\"../lib/oop\");\nvar MultiHashHandler = acequire(\"../keyboard/hash_handler\").MultiHashHandler;\nvar EventEmitter = acequire(\"../lib/event_emitter\").EventEmitter;\n\nvar CommandManager = function(platform, commands) {\n MultiHashHandler.call(this, commands, platform);\n this.byName = this.commands;\n this.setDefaultHandler(\"exec\", function(e) {\n return e.command.exec(e.editor, e.args || {});\n });\n};\n\noop.inherits(CommandManager, MultiHashHandler);\n\n(function() {\n\n oop.implement(this, EventEmitter);\n\n this.exec = function(command, editor, args) {\n if (Array.isArray(command)) {\n for (var i = command.length; i--; ) {\n if (this.exec(command[i], editor, args)) return true;\n }\n return false;\n }\n \n if (typeof command === \"string\")\n command = this.commands[command];\n\n if (!command)\n return false;\n\n if (editor && editor.$readOnly && !command.readOnly)\n return false;\n\n var e = {editor: editor, command: command, args: args};\n e.returnValue = this._emit(\"exec\", e);\n this._signal(\"afterExec\", e);\n\n return e.returnValue === false ? false : true;\n };\n\n this.toggleRecording = function(editor) {\n if (this.$inReplay)\n return;\n\n editor && editor._emit(\"changeStatus\");\n if (this.recording) {\n this.macro.pop();\n this.removeEventListener(\"exec\", this.$addCommandToMacro);\n\n if (!this.macro.length)\n this.macro = this.oldMacro;\n\n return this.recording = false;\n }\n if (!this.$addCommandToMacro) {\n this.$addCommandToMacro = function(e) {\n this.macro.push([e.command, e.args]);\n }.bind(this);\n }\n\n this.oldMacro = this.macro;\n this.macro = [];\n this.on(\"exec\", this.$addCommandToMacro);\n return this.recording = true;\n };\n\n this.replay = function(editor) {\n if (this.$inReplay || !this.macro)\n return;\n\n if (this.recording)\n return this.toggleRecording(editor);\n\n try {\n this.$inReplay = true;\n this.macro.forEach(function(x) {\n if (typeof x == \"string\")\n this.exec(x, editor);\n else\n this.exec(x[0], editor, x[1]);\n }, this);\n } finally {\n this.$inReplay = false;\n }\n };\n\n this.trimMacro = function(m) {\n return m.map(function(x){\n if (typeof x[0] != \"string\")\n x[0] = x[0].name;\n if (!x[1])\n x = x[0];\n return x;\n });\n };\n\n}).call(CommandManager.prototype);\n\nexports.CommandManager = CommandManager;\n\n});\n\nace.define(\"ace/commands/default_commands\",[\"require\",\"exports\",\"module\",\"ace/lib/lang\",\"ace/config\",\"ace/range\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar lang = acequire(\"../lib/lang\");\nvar config = acequire(\"../config\");\nvar Range = acequire(\"../range\").Range;\n\nfunction bindKey(win, mac) {\n return {win: win, mac: mac};\n}\nexports.commands = [{\n name: \"showSettingsMenu\",\n bindKey: bindKey(\"Ctrl-,\", \"Command-,\"),\n exec: function(editor) {\n config.loadModule(\"ace/ext/settings_menu\", function(module) {\n module.init(editor);\n editor.showSettingsMenu();\n });\n },\n readOnly: true\n}, {\n name: \"goToNextError\",\n bindKey: bindKey(\"Alt-E\", \"Ctrl-E\"),\n exec: function(editor) {\n config.loadModule(\"ace/ext/error_marker\", function(module) {\n module.showErrorMarker(editor, 1);\n });\n },\n scrollIntoView: \"animate\",\n readOnly: true\n}, {\n name: \"goToPreviousError\",\n bindKey: bindKey(\"Alt-Shift-E\", \"Ctrl-Shift-E\"),\n exec: function(editor) {\n config.loadModule(\"ace/ext/error_marker\", function(module) {\n module.showErrorMarker(editor, -1);\n });\n },\n scrollIntoView: \"animate\",\n readOnly: true\n}, {\n name: \"selectall\",\n bindKey: bindKey(\"Ctrl-A\", \"Command-A\"),\n exec: function(editor) { editor.selectAll(); },\n readOnly: true\n}, {\n name: \"centerselection\",\n bindKey: bindKey(null, \"Ctrl-L\"),\n exec: function(editor) { editor.centerSelection(); },\n readOnly: true\n}, {\n name: \"gotoline\",\n bindKey: bindKey(\"Ctrl-L\", \"Command-L\"),\n exec: function(editor) {\n var line = parseInt(prompt(\"Enter line number:\"), 10);\n if (!isNaN(line)) {\n editor.gotoLine(line);\n }\n },\n readOnly: true\n}, {\n name: \"fold\",\n bindKey: bindKey(\"Alt-L|Ctrl-F1\", \"Command-Alt-L|Command-F1\"),\n exec: function(editor) { editor.session.toggleFold(false); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"center\",\n readOnly: true\n}, {\n name: \"unfold\",\n bindKey: bindKey(\"Alt-Shift-L|Ctrl-Shift-F1\", \"Command-Alt-Shift-L|Command-Shift-F1\"),\n exec: function(editor) { editor.session.toggleFold(true); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"center\",\n readOnly: true\n}, {\n name: \"toggleFoldWidget\",\n bindKey: bindKey(\"F2\", \"F2\"),\n exec: function(editor) { editor.session.toggleFoldWidget(); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"center\",\n readOnly: true\n}, {\n name: \"toggleParentFoldWidget\",\n bindKey: bindKey(\"Alt-F2\", \"Alt-F2\"),\n exec: function(editor) { editor.session.toggleFoldWidget(true); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"center\",\n readOnly: true\n}, {\n name: \"foldall\",\n bindKey: bindKey(null, \"Ctrl-Command-Option-0\"),\n exec: function(editor) { editor.session.foldAll(); },\n scrollIntoView: \"center\",\n readOnly: true\n}, {\n name: \"foldOther\",\n bindKey: bindKey(\"Alt-0\", \"Command-Option-0\"),\n exec: function(editor) { \n editor.session.foldAll();\n editor.session.unfold(editor.selection.getAllRanges());\n },\n scrollIntoView: \"center\",\n readOnly: true\n}, {\n name: \"unfoldall\",\n bindKey: bindKey(\"Alt-Shift-0\", \"Command-Option-Shift-0\"),\n exec: function(editor) { editor.session.unfold(); },\n scrollIntoView: \"center\",\n readOnly: true\n}, {\n name: \"findnext\",\n bindKey: bindKey(\"Ctrl-K\", \"Command-G\"),\n exec: function(editor) { editor.findNext(); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"center\",\n readOnly: true\n}, {\n name: \"findprevious\",\n bindKey: bindKey(\"Ctrl-Shift-K\", \"Command-Shift-G\"),\n exec: function(editor) { editor.findPrevious(); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"center\",\n readOnly: true\n}, {\n name: \"selectOrFindNext\",\n bindKey: bindKey(\"Alt-K\", \"Ctrl-G\"),\n exec: function(editor) {\n if (editor.selection.isEmpty())\n editor.selection.selectWord();\n else\n editor.findNext(); \n },\n readOnly: true\n}, {\n name: \"selectOrFindPrevious\",\n bindKey: bindKey(\"Alt-Shift-K\", \"Ctrl-Shift-G\"),\n exec: function(editor) { \n if (editor.selection.isEmpty())\n editor.selection.selectWord();\n else\n editor.findPrevious();\n },\n readOnly: true\n}, {\n name: \"find\",\n bindKey: bindKey(\"Ctrl-F\", \"Command-F\"),\n exec: function(editor) {\n config.loadModule(\"ace/ext/searchbox\", function(e) {e.Search(editor)});\n },\n readOnly: true\n}, {\n name: \"overwrite\",\n bindKey: \"Insert\",\n exec: function(editor) { editor.toggleOverwrite(); },\n readOnly: true\n}, {\n name: \"selecttostart\",\n bindKey: bindKey(\"Ctrl-Shift-Home\", \"Command-Shift-Up\"),\n exec: function(editor) { editor.getSelection().selectFileStart(); },\n multiSelectAction: \"forEach\",\n readOnly: true,\n scrollIntoView: \"animate\",\n aceCommandGroup: \"fileJump\"\n}, {\n name: \"gotostart\",\n bindKey: bindKey(\"Ctrl-Home\", \"Command-Home|Command-Up\"),\n exec: function(editor) { editor.navigateFileStart(); },\n multiSelectAction: \"forEach\",\n readOnly: true,\n scrollIntoView: \"animate\",\n aceCommandGroup: \"fileJump\"\n}, {\n name: \"selectup\",\n bindKey: bindKey(\"Shift-Up\", \"Shift-Up\"),\n exec: function(editor) { editor.getSelection().selectUp(); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"cursor\",\n readOnly: true\n}, {\n name: \"golineup\",\n bindKey: bindKey(\"Up\", \"Up|Ctrl-P\"),\n exec: function(editor, args) { editor.navigateUp(args.times); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"cursor\",\n readOnly: true\n}, {\n name: \"selecttoend\",\n bindKey: bindKey(\"Ctrl-Shift-End\", \"Command-Shift-Down\"),\n exec: function(editor) { editor.getSelection().selectFileEnd(); },\n multiSelectAction: \"forEach\",\n readOnly: true,\n scrollIntoView: \"animate\",\n aceCommandGroup: \"fileJump\"\n}, {\n name: \"gotoend\",\n bindKey: bindKey(\"Ctrl-End\", \"Command-End|Command-Down\"),\n exec: function(editor) { editor.navigateFileEnd(); },\n multiSelectAction: \"forEach\",\n readOnly: true,\n scrollIntoView: \"animate\",\n aceCommandGroup: \"fileJump\"\n}, {\n name: \"selectdown\",\n bindKey: bindKey(\"Shift-Down\", \"Shift-Down\"),\n exec: function(editor) { editor.getSelection().selectDown(); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"cursor\",\n readOnly: true\n}, {\n name: \"golinedown\",\n bindKey: bindKey(\"Down\", \"Down|Ctrl-N\"),\n exec: function(editor, args) { editor.navigateDown(args.times); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"cursor\",\n readOnly: true\n}, {\n name: \"selectwordleft\",\n bindKey: bindKey(\"Ctrl-Shift-Left\", \"Option-Shift-Left\"),\n exec: function(editor) { editor.getSelection().selectWordLeft(); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"cursor\",\n readOnly: true\n}, {\n name: \"gotowordleft\",\n bindKey: bindKey(\"Ctrl-Left\", \"Option-Left\"),\n exec: function(editor) { editor.navigateWordLeft(); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"cursor\",\n readOnly: true\n}, {\n name: \"selecttolinestart\",\n bindKey: bindKey(\"Alt-Shift-Left\", \"Command-Shift-Left\"),\n exec: function(editor) { editor.getSelection().selectLineStart(); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"cursor\",\n readOnly: true\n}, {\n name: \"gotolinestart\",\n bindKey: bindKey(\"Alt-Left|Home\", \"Command-Left|Home|Ctrl-A\"),\n exec: function(editor) { editor.navigateLineStart(); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"cursor\",\n readOnly: true\n}, {\n name: \"selectleft\",\n bindKey: bindKey(\"Shift-Left\", \"Shift-Left\"),\n exec: function(editor) { editor.getSelection().selectLeft(); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"cursor\",\n readOnly: true\n}, {\n name: \"gotoleft\",\n bindKey: bindKey(\"Left\", \"Left|Ctrl-B\"),\n exec: function(editor, args) { editor.navigateLeft(args.times); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"cursor\",\n readOnly: true\n}, {\n name: \"selectwordright\",\n bindKey: bindKey(\"Ctrl-Shift-Right\", \"Option-Shift-Right\"),\n exec: function(editor) { editor.getSelection().selectWordRight(); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"cursor\",\n readOnly: true\n}, {\n name: \"gotowordright\",\n bindKey: bindKey(\"Ctrl-Right\", \"Option-Right\"),\n exec: function(editor) { editor.navigateWordRight(); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"cursor\",\n readOnly: true\n}, {\n name: \"selecttolineend\",\n bindKey: bindKey(\"Alt-Shift-Right\", \"Command-Shift-Right\"),\n exec: function(editor) { editor.getSelection().selectLineEnd(); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"cursor\",\n readOnly: true\n}, {\n name: \"gotolineend\",\n bindKey: bindKey(\"Alt-Right|End\", \"Command-Right|End|Ctrl-E\"),\n exec: function(editor) { editor.navigateLineEnd(); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"cursor\",\n readOnly: true\n}, {\n name: \"selectright\",\n bindKey: bindKey(\"Shift-Right\", \"Shift-Right\"),\n exec: function(editor) { editor.getSelection().selectRight(); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"cursor\",\n readOnly: true\n}, {\n name: \"gotoright\",\n bindKey: bindKey(\"Right\", \"Right|Ctrl-F\"),\n exec: function(editor, args) { editor.navigateRight(args.times); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"cursor\",\n readOnly: true\n}, {\n name: \"selectpagedown\",\n bindKey: \"Shift-PageDown\",\n exec: function(editor) { editor.selectPageDown(); },\n readOnly: true\n}, {\n name: \"pagedown\",\n bindKey: bindKey(null, \"Option-PageDown\"),\n exec: function(editor) { editor.scrollPageDown(); },\n readOnly: true\n}, {\n name: \"gotopagedown\",\n bindKey: bindKey(\"PageDown\", \"PageDown|Ctrl-V\"),\n exec: function(editor) { editor.gotoPageDown(); },\n readOnly: true\n}, {\n name: \"selectpageup\",\n bindKey: \"Shift-PageUp\",\n exec: function(editor) { editor.selectPageUp(); },\n readOnly: true\n}, {\n name: \"pageup\",\n bindKey: bindKey(null, \"Option-PageUp\"),\n exec: function(editor) { editor.scrollPageUp(); },\n readOnly: true\n}, {\n name: \"gotopageup\",\n bindKey: \"PageUp\",\n exec: function(editor) { editor.gotoPageUp(); },\n readOnly: true\n}, {\n name: \"scrollup\",\n bindKey: bindKey(\"Ctrl-Up\", null),\n exec: function(e) { e.renderer.scrollBy(0, -2 * e.renderer.layerConfig.lineHeight); },\n readOnly: true\n}, {\n name: \"scrolldown\",\n bindKey: bindKey(\"Ctrl-Down\", null),\n exec: function(e) { e.renderer.scrollBy(0, 2 * e.renderer.layerConfig.lineHeight); },\n readOnly: true\n}, {\n name: \"selectlinestart\",\n bindKey: \"Shift-Home\",\n exec: function(editor) { editor.getSelection().selectLineStart(); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"cursor\",\n readOnly: true\n}, {\n name: \"selectlineend\",\n bindKey: \"Shift-End\",\n exec: function(editor) { editor.getSelection().selectLineEnd(); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"cursor\",\n readOnly: true\n}, {\n name: \"togglerecording\",\n bindKey: bindKey(\"Ctrl-Alt-E\", \"Command-Option-E\"),\n exec: function(editor) { editor.commands.toggleRecording(editor); },\n readOnly: true\n}, {\n name: \"replaymacro\",\n bindKey: bindKey(\"Ctrl-Shift-E\", \"Command-Shift-E\"),\n exec: function(editor) { editor.commands.replay(editor); },\n readOnly: true\n}, {\n name: \"jumptomatching\",\n bindKey: bindKey(\"Ctrl-P\", \"Ctrl-P\"),\n exec: function(editor) { editor.jumpToMatching(); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"animate\",\n readOnly: true\n}, {\n name: \"selecttomatching\",\n bindKey: bindKey(\"Ctrl-Shift-P\", \"Ctrl-Shift-P\"),\n exec: function(editor) { editor.jumpToMatching(true); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"animate\",\n readOnly: true\n}, {\n name: \"expandToMatching\",\n bindKey: bindKey(\"Ctrl-Shift-M\", \"Ctrl-Shift-M\"),\n exec: function(editor) { editor.jumpToMatching(true, true); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"animate\",\n readOnly: true\n}, {\n name: \"passKeysToBrowser\",\n bindKey: bindKey(null, null),\n exec: function() {},\n passEvent: true,\n readOnly: true\n}, {\n name: \"copy\",\n exec: function(editor) {\n },\n readOnly: true\n},\n{\n name: \"cut\",\n exec: function(editor) {\n var range = editor.getSelectionRange();\n editor._emit(\"cut\", range);\n\n if (!editor.selection.isEmpty()) {\n editor.session.remove(range);\n editor.clearSelection();\n }\n },\n scrollIntoView: \"cursor\",\n multiSelectAction: \"forEach\"\n}, {\n name: \"paste\",\n exec: function(editor, args) {\n editor.$handlePaste(args);\n },\n scrollIntoView: \"cursor\"\n}, {\n name: \"removeline\",\n bindKey: bindKey(\"Ctrl-D\", \"Command-D\"),\n exec: function(editor) { editor.removeLines(); },\n scrollIntoView: \"cursor\",\n multiSelectAction: \"forEachLine\"\n}, {\n name: \"duplicateSelection\",\n bindKey: bindKey(\"Ctrl-Shift-D\", \"Command-Shift-D\"),\n exec: function(editor) { editor.duplicateSelection(); },\n scrollIntoView: \"cursor\",\n multiSelectAction: \"forEach\"\n}, {\n name: \"sortlines\",\n bindKey: bindKey(\"Ctrl-Alt-S\", \"Command-Alt-S\"),\n exec: function(editor) { editor.sortLines(); },\n scrollIntoView: \"selection\",\n multiSelectAction: \"forEachLine\"\n}, {\n name: \"togglecomment\",\n bindKey: bindKey(\"Ctrl-/\", \"Command-/\"),\n exec: function(editor) { editor.toggleCommentLines(); },\n multiSelectAction: \"forEachLine\",\n scrollIntoView: \"selectionPart\"\n}, {\n name: \"toggleBlockComment\",\n bindKey: bindKey(\"Ctrl-Shift-/\", \"Command-Shift-/\"),\n exec: function(editor) { editor.toggleBlockComment(); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"selectionPart\"\n}, {\n name: \"modifyNumberUp\",\n bindKey: bindKey(\"Ctrl-Shift-Up\", \"Alt-Shift-Up\"),\n exec: function(editor) { editor.modifyNumber(1); },\n scrollIntoView: \"cursor\",\n multiSelectAction: \"forEach\"\n}, {\n name: \"modifyNumberDown\",\n bindKey: bindKey(\"Ctrl-Shift-Down\", \"Alt-Shift-Down\"),\n exec: function(editor) { editor.modifyNumber(-1); },\n scrollIntoView: \"cursor\",\n multiSelectAction: \"forEach\"\n}, {\n name: \"replace\",\n bindKey: bindKey(\"Ctrl-H\", \"Command-Option-F\"),\n exec: function(editor) {\n config.loadModule(\"ace/ext/searchbox\", function(e) {e.Search(editor, true)});\n }\n}, {\n name: \"undo\",\n bindKey: bindKey(\"Ctrl-Z\", \"Command-Z\"),\n exec: function(editor) { editor.undo(); }\n}, {\n name: \"redo\",\n bindKey: bindKey(\"Ctrl-Shift-Z|Ctrl-Y\", \"Command-Shift-Z|Command-Y\"),\n exec: function(editor) { editor.redo(); }\n}, {\n name: \"copylinesup\",\n bindKey: bindKey(\"Alt-Shift-Up\", \"Command-Option-Up\"),\n exec: function(editor) { editor.copyLinesUp(); },\n scrollIntoView: \"cursor\"\n}, {\n name: \"movelinesup\",\n bindKey: bindKey(\"Alt-Up\", \"Option-Up\"),\n exec: function(editor) { editor.moveLinesUp(); },\n scrollIntoView: \"cursor\"\n}, {\n name: \"copylinesdown\",\n bindKey: bindKey(\"Alt-Shift-Down\", \"Command-Option-Down\"),\n exec: function(editor) { editor.copyLinesDown(); },\n scrollIntoView: \"cursor\"\n}, {\n name: \"movelinesdown\",\n bindKey: bindKey(\"Alt-Down\", \"Option-Down\"),\n exec: function(editor) { editor.moveLinesDown(); },\n scrollIntoView: \"cursor\"\n}, {\n name: \"del\",\n bindKey: bindKey(\"Delete\", \"Delete|Ctrl-D|Shift-Delete\"),\n exec: function(editor) { editor.remove(\"right\"); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"cursor\"\n}, {\n name: \"backspace\",\n bindKey: bindKey(\n \"Shift-Backspace|Backspace\",\n \"Ctrl-Backspace|Shift-Backspace|Backspace|Ctrl-H\"\n ),\n exec: function(editor) { editor.remove(\"left\"); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"cursor\"\n}, {\n name: \"cut_or_delete\",\n bindKey: bindKey(\"Shift-Delete\", null),\n exec: function(editor) { \n if (editor.selection.isEmpty()) {\n editor.remove(\"left\");\n } else {\n return false;\n }\n },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"cursor\"\n}, {\n name: \"removetolinestart\",\n bindKey: bindKey(\"Alt-Backspace\", \"Command-Backspace\"),\n exec: function(editor) { editor.removeToLineStart(); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"cursor\"\n}, {\n name: \"removetolineend\",\n bindKey: bindKey(\"Alt-Delete\", \"Ctrl-K\"),\n exec: function(editor) { editor.removeToLineEnd(); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"cursor\"\n}, {\n name: \"removewordleft\",\n bindKey: bindKey(\"Ctrl-Backspace\", \"Alt-Backspace|Ctrl-Alt-Backspace\"),\n exec: function(editor) { editor.removeWordLeft(); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"cursor\"\n}, {\n name: \"removewordright\",\n bindKey: bindKey(\"Ctrl-Delete\", \"Alt-Delete\"),\n exec: function(editor) { editor.removeWordRight(); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"cursor\"\n}, {\n name: \"outdent\",\n bindKey: bindKey(\"Shift-Tab\", \"Shift-Tab\"),\n exec: function(editor) { editor.blockOutdent(); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"selectionPart\"\n}, {\n name: \"indent\",\n bindKey: bindKey(\"Tab\", \"Tab\"),\n exec: function(editor) { editor.indent(); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"selectionPart\"\n}, {\n name: \"blockoutdent\",\n bindKey: bindKey(\"Ctrl-[\", \"Ctrl-[\"),\n exec: function(editor) { editor.blockOutdent(); },\n multiSelectAction: \"forEachLine\",\n scrollIntoView: \"selectionPart\"\n}, {\n name: \"blockindent\",\n bindKey: bindKey(\"Ctrl-]\", \"Ctrl-]\"),\n exec: function(editor) { editor.blockIndent(); },\n multiSelectAction: \"forEachLine\",\n scrollIntoView: \"selectionPart\"\n}, {\n name: \"insertstring\",\n exec: function(editor, str) { editor.insert(str); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"cursor\"\n}, {\n name: \"inserttext\",\n exec: function(editor, args) {\n editor.insert(lang.stringRepeat(args.text || \"\", args.times || 1));\n },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"cursor\"\n}, {\n name: \"splitline\",\n bindKey: bindKey(null, \"Ctrl-O\"),\n exec: function(editor) { editor.splitLine(); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"cursor\"\n}, {\n name: \"transposeletters\",\n bindKey: bindKey(\"Ctrl-T\", \"Ctrl-T\"),\n exec: function(editor) { editor.transposeLetters(); },\n multiSelectAction: function(editor) {editor.transposeSelections(1); },\n scrollIntoView: \"cursor\"\n}, {\n name: \"touppercase\",\n bindKey: bindKey(\"Ctrl-U\", \"Ctrl-U\"),\n exec: function(editor) { editor.toUpperCase(); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"cursor\"\n}, {\n name: \"tolowercase\",\n bindKey: bindKey(\"Ctrl-Shift-U\", \"Ctrl-Shift-U\"),\n exec: function(editor) { editor.toLowerCase(); },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"cursor\"\n}, {\n name: \"expandtoline\",\n bindKey: bindKey(\"Ctrl-Shift-L\", \"Command-Shift-L\"),\n exec: function(editor) {\n var range = editor.selection.getRange();\n\n range.start.column = range.end.column = 0;\n range.end.row++;\n editor.selection.setRange(range, false);\n },\n multiSelectAction: \"forEach\",\n scrollIntoView: \"cursor\",\n readOnly: true\n}, {\n name: \"joinlines\",\n bindKey: bindKey(null, null),\n exec: function(editor) {\n var isBackwards = editor.selection.isBackwards();\n var selectionStart = isBackwards ? editor.selection.getSelectionLead() : editor.selection.getSelectionAnchor();\n var selectionEnd = isBackwards ? editor.selection.getSelectionAnchor() : editor.selection.getSelectionLead();\n var firstLineEndCol = editor.session.doc.getLine(selectionStart.row).length;\n var selectedText = editor.session.doc.getTextRange(editor.selection.getRange());\n var selectedCount = selectedText.replace(/\\n\\s*/, \" \").length;\n var insertLine = editor.session.doc.getLine(selectionStart.row);\n\n for (var i = selectionStart.row + 1; i <= selectionEnd.row + 1; i++) {\n var curLine = lang.stringTrimLeft(lang.stringTrimRight(editor.session.doc.getLine(i)));\n if (curLine.length !== 0) {\n curLine = \" \" + curLine;\n }\n insertLine += curLine;\n }\n\n if (selectionEnd.row + 1 < (editor.session.doc.getLength() - 1)) {\n insertLine += editor.session.doc.getNewLineCharacter();\n }\n\n editor.clearSelection();\n editor.session.doc.replace(new Range(selectionStart.row, 0, selectionEnd.row + 2, 0), insertLine);\n\n if (selectedCount > 0) {\n editor.selection.moveCursorTo(selectionStart.row, selectionStart.column);\n editor.selection.selectTo(selectionStart.row, selectionStart.column + selectedCount);\n } else {\n firstLineEndCol = editor.session.doc.getLine(selectionStart.row).length > firstLineEndCol ? (firstLineEndCol + 1) : firstLineEndCol;\n editor.selection.moveCursorTo(selectionStart.row, firstLineEndCol);\n }\n },\n multiSelectAction: \"forEach\",\n readOnly: true\n}, {\n name: \"invertSelection\",\n bindKey: bindKey(null, null),\n exec: function(editor) {\n var endRow = editor.session.doc.getLength() - 1;\n var endCol = editor.session.doc.getLine(endRow).length;\n var ranges = editor.selection.rangeList.ranges;\n var newRanges = [];\n if (ranges.length < 1) {\n ranges = [editor.selection.getRange()];\n }\n\n for (var i = 0; i < ranges.length; i++) {\n if (i == (ranges.length - 1)) {\n if (!(ranges[i].end.row === endRow && ranges[i].end.column === endCol)) {\n newRanges.push(new Range(ranges[i].end.row, ranges[i].end.column, endRow, endCol));\n }\n }\n\n if (i === 0) {\n if (!(ranges[i].start.row === 0 && ranges[i].start.column === 0)) {\n newRanges.push(new Range(0, 0, ranges[i].start.row, ranges[i].start.column));\n }\n } else {\n newRanges.push(new Range(ranges[i-1].end.row, ranges[i-1].end.column, ranges[i].start.row, ranges[i].start.column));\n }\n }\n\n editor.exitMultiSelectMode();\n editor.clearSelection();\n\n for(var i = 0; i < newRanges.length; i++) {\n editor.selection.addRange(newRanges[i], false);\n }\n },\n readOnly: true,\n scrollIntoView: \"none\"\n}];\n\n});\n\nace.define(\"ace/editor\",[\"require\",\"exports\",\"module\",\"ace/lib/fixoldbrowsers\",\"ace/lib/oop\",\"ace/lib/dom\",\"ace/lib/lang\",\"ace/lib/useragent\",\"ace/keyboard/textinput\",\"ace/mouse/mouse_handler\",\"ace/mouse/fold_handler\",\"ace/keyboard/keybinding\",\"ace/edit_session\",\"ace/search\",\"ace/range\",\"ace/lib/event_emitter\",\"ace/commands/command_manager\",\"ace/commands/default_commands\",\"ace/config\",\"ace/token_iterator\"], function(acequire, exports, module) {\n\"use strict\";\n\nacequire(\"./lib/fixoldbrowsers\");\n\nvar oop = acequire(\"./lib/oop\");\nvar dom = acequire(\"./lib/dom\");\nvar lang = acequire(\"./lib/lang\");\nvar useragent = acequire(\"./lib/useragent\");\nvar TextInput = acequire(\"./keyboard/textinput\").TextInput;\nvar MouseHandler = acequire(\"./mouse/mouse_handler\").MouseHandler;\nvar FoldHandler = acequire(\"./mouse/fold_handler\").FoldHandler;\nvar KeyBinding = acequire(\"./keyboard/keybinding\").KeyBinding;\nvar EditSession = acequire(\"./edit_session\").EditSession;\nvar Search = acequire(\"./search\").Search;\nvar Range = acequire(\"./range\").Range;\nvar EventEmitter = acequire(\"./lib/event_emitter\").EventEmitter;\nvar CommandManager = acequire(\"./commands/command_manager\").CommandManager;\nvar defaultCommands = acequire(\"./commands/default_commands\").commands;\nvar config = acequire(\"./config\");\nvar TokenIterator = acequire(\"./token_iterator\").TokenIterator;\nvar Editor = function(renderer, session) {\n var container = renderer.getContainerElement();\n this.container = container;\n this.renderer = renderer;\n\n this.commands = new CommandManager(useragent.isMac ? \"mac\" : \"win\", defaultCommands);\n this.textInput = new TextInput(renderer.getTextAreaContainer(), this);\n this.renderer.textarea = this.textInput.getElement();\n this.keyBinding = new KeyBinding(this);\n this.$mouseHandler = new MouseHandler(this);\n new FoldHandler(this);\n\n this.$blockScrolling = 0;\n this.$search = new Search().set({\n wrap: true\n });\n\n this.$historyTracker = this.$historyTracker.bind(this);\n this.commands.on(\"exec\", this.$historyTracker);\n\n this.$initOperationListeners();\n \n this._$emitInputEvent = lang.delayedCall(function() {\n this._signal(\"input\", {});\n if (this.session && this.session.bgTokenizer)\n this.session.bgTokenizer.scheduleStart();\n }.bind(this));\n \n this.on(\"change\", function(_, _self) {\n _self._$emitInputEvent.schedule(31);\n });\n\n this.setSession(session || new EditSession(\"\"));\n config.resetOptions(this);\n config._signal(\"editor\", this);\n};\n\n(function(){\n\n oop.implement(this, EventEmitter);\n\n this.$initOperationListeners = function() {\n function last(a) {return a[a.length - 1]}\n\n this.selections = [];\n this.commands.on(\"exec\", this.startOperation.bind(this), true);\n this.commands.on(\"afterExec\", this.endOperation.bind(this), true);\n\n this.$opResetTimer = lang.delayedCall(this.endOperation.bind(this));\n\n this.on(\"change\", function() {\n this.curOp || this.startOperation();\n this.curOp.docChanged = true;\n }.bind(this), true);\n\n this.on(\"changeSelection\", function() {\n this.curOp || this.startOperation();\n this.curOp.selectionChanged = true;\n }.bind(this), true);\n };\n\n this.curOp = null;\n this.prevOp = {};\n this.startOperation = function(commadEvent) {\n if (this.curOp) {\n if (!commadEvent || this.curOp.command)\n return;\n this.prevOp = this.curOp;\n }\n if (!commadEvent) {\n this.previousCommand = null;\n commadEvent = {};\n }\n\n this.$opResetTimer.schedule();\n this.curOp = {\n command: commadEvent.command || {},\n args: commadEvent.args,\n scrollTop: this.renderer.scrollTop\n };\n if (this.curOp.command.name && this.curOp.command.scrollIntoView !== undefined)\n this.$blockScrolling++;\n };\n\n this.endOperation = function(e) {\n if (this.curOp) {\n if (e && e.returnValue === false)\n return this.curOp = null;\n this._signal(\"beforeEndOperation\");\n var command = this.curOp.command;\n if (command.name && this.$blockScrolling > 0)\n this.$blockScrolling--;\n var scrollIntoView = command && command.scrollIntoView;\n if (scrollIntoView) {\n switch (scrollIntoView) {\n case \"center-animate\":\n scrollIntoView = \"animate\";\n case \"center\":\n this.renderer.scrollCursorIntoView(null, 0.5);\n break;\n case \"animate\":\n case \"cursor\":\n this.renderer.scrollCursorIntoView();\n break;\n case \"selectionPart\":\n var range = this.selection.getRange();\n var config = this.renderer.layerConfig;\n if (range.start.row >= config.lastRow || range.end.row <= config.firstRow) {\n this.renderer.scrollSelectionIntoView(this.selection.anchor, this.selection.lead);\n }\n break;\n default:\n break;\n }\n if (scrollIntoView == \"animate\")\n this.renderer.animateScrolling(this.curOp.scrollTop);\n }\n \n this.prevOp = this.curOp;\n this.curOp = null;\n }\n };\n this.$mergeableCommands = [\"backspace\", \"del\", \"insertstring\"];\n this.$historyTracker = function(e) {\n if (!this.$mergeUndoDeltas)\n return;\n\n var prev = this.prevOp;\n var mergeableCommands = this.$mergeableCommands;\n var shouldMerge = prev.command && (e.command.name == prev.command.name);\n if (e.command.name == \"insertstring\") {\n var text = e.args;\n if (this.mergeNextCommand === undefined)\n this.mergeNextCommand = true;\n\n shouldMerge = shouldMerge\n && this.mergeNextCommand // previous command allows to coalesce with\n && (!/\\s/.test(text) || /\\s/.test(prev.args)); // previous insertion was of same type\n\n this.mergeNextCommand = true;\n } else {\n shouldMerge = shouldMerge\n && mergeableCommands.indexOf(e.command.name) !== -1; // the command is mergeable\n }\n\n if (\n this.$mergeUndoDeltas != \"always\"\n && Date.now() - this.sequenceStartTime > 2000\n ) {\n shouldMerge = false; // the sequence is too long\n }\n\n if (shouldMerge)\n this.session.mergeUndoDeltas = true;\n else if (mergeableCommands.indexOf(e.command.name) !== -1)\n this.sequenceStartTime = Date.now();\n };\n this.setKeyboardHandler = function(keyboardHandler, cb) {\n if (keyboardHandler && typeof keyboardHandler === \"string\") {\n this.$keybindingId = keyboardHandler;\n var _self = this;\n config.loadModule([\"keybinding\", keyboardHandler], function(module) {\n if (_self.$keybindingId == keyboardHandler)\n _self.keyBinding.setKeyboardHandler(module && module.handler);\n cb && cb();\n });\n } else {\n this.$keybindingId = null;\n this.keyBinding.setKeyboardHandler(keyboardHandler);\n cb && cb();\n }\n };\n this.getKeyboardHandler = function() {\n return this.keyBinding.getKeyboardHandler();\n };\n this.setSession = function(session) {\n if (this.session == session)\n return;\n if (this.curOp) this.endOperation();\n this.curOp = {};\n\n var oldSession = this.session;\n if (oldSession) {\n this.session.off(\"change\", this.$onDocumentChange);\n this.session.off(\"changeMode\", this.$onChangeMode);\n this.session.off(\"tokenizerUpdate\", this.$onTokenizerUpdate);\n this.session.off(\"changeTabSize\", this.$onChangeTabSize);\n this.session.off(\"changeWrapLimit\", this.$onChangeWrapLimit);\n this.session.off(\"changeWrapMode\", this.$onChangeWrapMode);\n this.session.off(\"changeFold\", this.$onChangeFold);\n this.session.off(\"changeFrontMarker\", this.$onChangeFrontMarker);\n this.session.off(\"changeBackMarker\", this.$onChangeBackMarker);\n this.session.off(\"changeBreakpoint\", this.$onChangeBreakpoint);\n this.session.off(\"changeAnnotation\", this.$onChangeAnnotation);\n this.session.off(\"changeOverwrite\", this.$onCursorChange);\n this.session.off(\"changeScrollTop\", this.$onScrollTopChange);\n this.session.off(\"changeScrollLeft\", this.$onScrollLeftChange);\n\n var selection = this.session.getSelection();\n selection.off(\"changeCursor\", this.$onCursorChange);\n selection.off(\"changeSelection\", this.$onSelectionChange);\n }\n\n this.session = session;\n if (session) {\n this.$onDocumentChange = this.onDocumentChange.bind(this);\n session.on(\"change\", this.$onDocumentChange);\n this.renderer.setSession(session);\n \n this.$onChangeMode = this.onChangeMode.bind(this);\n session.on(\"changeMode\", this.$onChangeMode);\n \n this.$onTokenizerUpdate = this.onTokenizerUpdate.bind(this);\n session.on(\"tokenizerUpdate\", this.$onTokenizerUpdate);\n \n this.$onChangeTabSize = this.renderer.onChangeTabSize.bind(this.renderer);\n session.on(\"changeTabSize\", this.$onChangeTabSize);\n \n this.$onChangeWrapLimit = this.onChangeWrapLimit.bind(this);\n session.on(\"changeWrapLimit\", this.$onChangeWrapLimit);\n \n this.$onChangeWrapMode = this.onChangeWrapMode.bind(this);\n session.on(\"changeWrapMode\", this.$onChangeWrapMode);\n \n this.$onChangeFold = this.onChangeFold.bind(this);\n session.on(\"changeFold\", this.$onChangeFold);\n \n this.$onChangeFrontMarker = this.onChangeFrontMarker.bind(this);\n this.session.on(\"changeFrontMarker\", this.$onChangeFrontMarker);\n \n this.$onChangeBackMarker = this.onChangeBackMarker.bind(this);\n this.session.on(\"changeBackMarker\", this.$onChangeBackMarker);\n \n this.$onChangeBreakpoint = this.onChangeBreakpoint.bind(this);\n this.session.on(\"changeBreakpoint\", this.$onChangeBreakpoint);\n \n this.$onChangeAnnotation = this.onChangeAnnotation.bind(this);\n this.session.on(\"changeAnnotation\", this.$onChangeAnnotation);\n \n this.$onCursorChange = this.onCursorChange.bind(this);\n this.session.on(\"changeOverwrite\", this.$onCursorChange);\n \n this.$onScrollTopChange = this.onScrollTopChange.bind(this);\n this.session.on(\"changeScrollTop\", this.$onScrollTopChange);\n \n this.$onScrollLeftChange = this.onScrollLeftChange.bind(this);\n this.session.on(\"changeScrollLeft\", this.$onScrollLeftChange);\n \n this.selection = session.getSelection();\n this.selection.on(\"changeCursor\", this.$onCursorChange);\n \n this.$onSelectionChange = this.onSelectionChange.bind(this);\n this.selection.on(\"changeSelection\", this.$onSelectionChange);\n \n this.onChangeMode();\n \n this.$blockScrolling += 1;\n this.onCursorChange();\n this.$blockScrolling -= 1;\n \n this.onScrollTopChange();\n this.onScrollLeftChange();\n this.onSelectionChange();\n this.onChangeFrontMarker();\n this.onChangeBackMarker();\n this.onChangeBreakpoint();\n this.onChangeAnnotation();\n this.session.getUseWrapMode() && this.renderer.adjustWrapLimit();\n this.renderer.updateFull();\n } else {\n this.selection = null;\n this.renderer.setSession(session);\n }\n\n this._signal(\"changeSession\", {\n session: session,\n oldSession: oldSession\n });\n \n this.curOp = null;\n \n oldSession && oldSession._signal(\"changeEditor\", {oldEditor: this});\n session && session._signal(\"changeEditor\", {editor: this});\n };\n this.getSession = function() {\n return this.session;\n };\n this.setValue = function(val, cursorPos) {\n this.session.doc.setValue(val);\n\n if (!cursorPos)\n this.selectAll();\n else if (cursorPos == 1)\n this.navigateFileEnd();\n else if (cursorPos == -1)\n this.navigateFileStart();\n\n return val;\n };\n this.getValue = function() {\n return this.session.getValue();\n };\n this.getSelection = function() {\n return this.selection;\n };\n this.resize = function(force) {\n this.renderer.onResize(force);\n };\n this.setTheme = function(theme, cb) {\n this.renderer.setTheme(theme, cb);\n };\n this.getTheme = function() {\n return this.renderer.getTheme();\n };\n this.setStyle = function(style) {\n this.renderer.setStyle(style);\n };\n this.unsetStyle = function(style) {\n this.renderer.unsetStyle(style);\n };\n this.getFontSize = function () {\n return this.getOption(\"fontSize\") ||\n dom.computedStyle(this.container, \"fontSize\");\n };\n this.setFontSize = function(size) {\n this.setOption(\"fontSize\", size);\n };\n\n this.$highlightBrackets = function() {\n if (this.session.$bracketHighlight) {\n this.session.removeMarker(this.session.$bracketHighlight);\n this.session.$bracketHighlight = null;\n }\n\n if (this.$highlightPending) {\n return;\n }\n var self = this;\n this.$highlightPending = true;\n setTimeout(function() {\n self.$highlightPending = false;\n var session = self.session;\n if (!session || !session.bgTokenizer) return;\n var pos = session.findMatchingBracket(self.getCursorPosition());\n if (pos) {\n var range = new Range(pos.row, pos.column, pos.row, pos.column + 1);\n } else if (session.$mode.getMatching) {\n var range = session.$mode.getMatching(self.session);\n }\n if (range)\n session.$bracketHighlight = session.addMarker(range, \"ace_bracket\", \"text\");\n }, 50);\n };\n this.$highlightTags = function() {\n if (this.$highlightTagPending)\n return;\n var self = this;\n this.$highlightTagPending = true;\n setTimeout(function() {\n self.$highlightTagPending = false;\n \n var session = self.session;\n if (!session || !session.bgTokenizer) return;\n \n var pos = self.getCursorPosition();\n var iterator = new TokenIterator(self.session, pos.row, pos.column);\n var token = iterator.getCurrentToken();\n \n if (!token || !/\\b(?:tag-open|tag-name)/.test(token.type)) {\n session.removeMarker(session.$tagHighlight);\n session.$tagHighlight = null;\n return;\n }\n \n if (token.type.indexOf(\"tag-open\") != -1) {\n token = iterator.stepForward();\n if (!token)\n return;\n }\n \n var tag = token.value;\n var depth = 0;\n var prevToken = iterator.stepBackward();\n \n if (prevToken.value == '<'){\n do {\n prevToken = token;\n token = iterator.stepForward();\n \n if (token && token.value === tag && token.type.indexOf('tag-name') !== -1) {\n if (prevToken.value === '<'){\n depth++;\n } else if (prevToken.value === '= 0);\n } else {\n do {\n token = prevToken;\n prevToken = iterator.stepBackward();\n \n if (token && token.value === tag && token.type.indexOf('tag-name') !== -1) {\n if (prevToken.value === '<') {\n depth++;\n } else if (prevToken.value === ' 1))\n highlight = false;\n }\n\n if (session.$highlightLineMarker && !highlight) {\n session.removeMarker(session.$highlightLineMarker.id);\n session.$highlightLineMarker = null;\n } else if (!session.$highlightLineMarker && highlight) {\n var range = new Range(highlight.row, highlight.column, highlight.row, Infinity);\n range.id = session.addMarker(range, \"ace_active-line\", \"screenLine\");\n session.$highlightLineMarker = range;\n } else if (highlight) {\n session.$highlightLineMarker.start.row = highlight.row;\n session.$highlightLineMarker.end.row = highlight.row;\n session.$highlightLineMarker.start.column = highlight.column;\n session._signal(\"changeBackMarker\");\n }\n };\n\n this.onSelectionChange = function(e) {\n var session = this.session;\n\n if (session.$selectionMarker) {\n session.removeMarker(session.$selectionMarker);\n }\n session.$selectionMarker = null;\n\n if (!this.selection.isEmpty()) {\n var range = this.selection.getRange();\n var style = this.getSelectionStyle();\n session.$selectionMarker = session.addMarker(range, \"ace_selection\", style);\n } else {\n this.$updateHighlightActiveLine();\n }\n\n var re = this.$highlightSelectedWord && this.$getSelectionHighLightRegexp();\n this.session.highlight(re);\n\n this._signal(\"changeSelection\");\n };\n\n this.$getSelectionHighLightRegexp = function() {\n var session = this.session;\n\n var selection = this.getSelectionRange();\n if (selection.isEmpty() || selection.isMultiLine())\n return;\n\n var startOuter = selection.start.column - 1;\n var endOuter = selection.end.column + 1;\n var line = session.getLine(selection.start.row);\n var lineCols = line.length;\n var needle = line.substring(Math.max(startOuter, 0),\n Math.min(endOuter, lineCols));\n if ((startOuter >= 0 && /^[\\w\\d]/.test(needle)) ||\n (endOuter <= lineCols && /[\\w\\d]$/.test(needle)))\n return;\n\n needle = line.substring(selection.start.column, selection.end.column);\n if (!/^[\\w\\d]+$/.test(needle))\n return;\n\n var re = this.$search.$assembleRegExp({\n wholeWord: true,\n caseSensitive: true,\n needle: needle\n });\n\n return re;\n };\n\n\n this.onChangeFrontMarker = function() {\n this.renderer.updateFrontMarkers();\n };\n\n this.onChangeBackMarker = function() {\n this.renderer.updateBackMarkers();\n };\n\n\n this.onChangeBreakpoint = function() {\n this.renderer.updateBreakpoints();\n };\n\n this.onChangeAnnotation = function() {\n this.renderer.setAnnotations(this.session.getAnnotations());\n };\n\n\n this.onChangeMode = function(e) {\n this.renderer.updateText();\n this._emit(\"changeMode\", e);\n };\n\n\n this.onChangeWrapLimit = function() {\n this.renderer.updateFull();\n };\n\n this.onChangeWrapMode = function() {\n this.renderer.onResize(true);\n };\n\n\n this.onChangeFold = function() {\n this.$updateHighlightActiveLine();\n this.renderer.updateFull();\n };\n this.getSelectedText = function() {\n return this.session.getTextRange(this.getSelectionRange());\n };\n this.getCopyText = function() {\n var text = this.getSelectedText();\n this._signal(\"copy\", text);\n return text;\n };\n this.onCopy = function() {\n this.commands.exec(\"copy\", this);\n };\n this.onCut = function() {\n this.commands.exec(\"cut\", this);\n };\n this.onPaste = function(text, event) {\n var e = {text: text, event: event};\n this.commands.exec(\"paste\", this, e);\n };\n \n this.$handlePaste = function(e) {\n if (typeof e == \"string\") \n e = {text: e};\n this._signal(\"paste\", e);\n var text = e.text;\n if (!this.inMultiSelectMode || this.inVirtualSelectionMode) {\n this.insert(text);\n } else {\n var lines = text.split(/\\r\\n|\\r|\\n/);\n var ranges = this.selection.rangeList.ranges;\n \n if (lines.length > ranges.length || lines.length < 2 || !lines[1])\n return this.commands.exec(\"insertstring\", this, text);\n \n for (var i = ranges.length; i--;) {\n var range = ranges[i];\n if (!range.isEmpty())\n this.session.remove(range);\n \n this.session.insert(range.start, lines[i]);\n }\n }\n };\n\n this.execCommand = function(command, args) {\n return this.commands.exec(command, this, args);\n };\n this.insert = function(text, pasted) {\n var session = this.session;\n var mode = session.getMode();\n var cursor = this.getCursorPosition();\n\n if (this.getBehavioursEnabled() && !pasted) {\n var transform = mode.transformAction(session.getState(cursor.row), 'insertion', this, session, text);\n if (transform) {\n if (text !== transform.text) {\n this.session.mergeUndoDeltas = false;\n this.$mergeNextCommand = false;\n }\n text = transform.text;\n\n }\n }\n \n if (text == \"\\t\")\n text = this.session.getTabString();\n if (!this.selection.isEmpty()) {\n var range = this.getSelectionRange();\n cursor = this.session.remove(range);\n this.clearSelection();\n }\n else if (this.session.getOverwrite()) {\n var range = new Range.fromPoints(cursor, cursor);\n range.end.column += text.length;\n this.session.remove(range);\n }\n\n if (text == \"\\n\" || text == \"\\r\\n\") {\n var line = session.getLine(cursor.row);\n if (cursor.column > line.search(/\\S|$/)) {\n var d = line.substr(cursor.column).search(/\\S|$/);\n session.doc.removeInLine(cursor.row, cursor.column, cursor.column + d);\n }\n }\n this.clearSelection();\n\n var start = cursor.column;\n var lineState = session.getState(cursor.row);\n var line = session.getLine(cursor.row);\n var shouldOutdent = mode.checkOutdent(lineState, line, text);\n var end = session.insert(cursor, text);\n\n if (transform && transform.selection) {\n if (transform.selection.length == 2) { // Transform relative to the current column\n this.selection.setSelectionRange(\n new Range(cursor.row, start + transform.selection[0],\n cursor.row, start + transform.selection[1]));\n } else { // Transform relative to the current row.\n this.selection.setSelectionRange(\n new Range(cursor.row + transform.selection[0],\n transform.selection[1],\n cursor.row + transform.selection[2],\n transform.selection[3]));\n }\n }\n\n if (session.getDocument().isNewLine(text)) {\n var lineIndent = mode.getNextLineIndent(lineState, line.slice(0, cursor.column), session.getTabString());\n\n session.insert({row: cursor.row+1, column: 0}, lineIndent);\n }\n if (shouldOutdent)\n mode.autoOutdent(lineState, session, cursor.row);\n };\n\n this.onTextInput = function(text) {\n this.keyBinding.onTextInput(text);\n };\n\n this.onCommandKey = function(e, hashId, keyCode) {\n this.keyBinding.onCommandKey(e, hashId, keyCode);\n };\n this.setOverwrite = function(overwrite) {\n this.session.setOverwrite(overwrite);\n };\n this.getOverwrite = function() {\n return this.session.getOverwrite();\n };\n this.toggleOverwrite = function() {\n this.session.toggleOverwrite();\n };\n this.setScrollSpeed = function(speed) {\n this.setOption(\"scrollSpeed\", speed);\n };\n this.getScrollSpeed = function() {\n return this.getOption(\"scrollSpeed\");\n };\n this.setDragDelay = function(dragDelay) {\n this.setOption(\"dragDelay\", dragDelay);\n };\n this.getDragDelay = function() {\n return this.getOption(\"dragDelay\");\n };\n this.setSelectionStyle = function(val) {\n this.setOption(\"selectionStyle\", val);\n };\n this.getSelectionStyle = function() {\n return this.getOption(\"selectionStyle\");\n };\n this.setHighlightActiveLine = function(shouldHighlight) {\n this.setOption(\"highlightActiveLine\", shouldHighlight);\n };\n this.getHighlightActiveLine = function() {\n return this.getOption(\"highlightActiveLine\");\n };\n this.setHighlightGutterLine = function(shouldHighlight) {\n this.setOption(\"highlightGutterLine\", shouldHighlight);\n };\n\n this.getHighlightGutterLine = function() {\n return this.getOption(\"highlightGutterLine\");\n };\n this.setHighlightSelectedWord = function(shouldHighlight) {\n this.setOption(\"highlightSelectedWord\", shouldHighlight);\n };\n this.getHighlightSelectedWord = function() {\n return this.$highlightSelectedWord;\n };\n\n this.setAnimatedScroll = function(shouldAnimate){\n this.renderer.setAnimatedScroll(shouldAnimate);\n };\n\n this.getAnimatedScroll = function(){\n return this.renderer.getAnimatedScroll();\n };\n this.setShowInvisibles = function(showInvisibles) {\n this.renderer.setShowInvisibles(showInvisibles);\n };\n this.getShowInvisibles = function() {\n return this.renderer.getShowInvisibles();\n };\n\n this.setDisplayIndentGuides = function(display) {\n this.renderer.setDisplayIndentGuides(display);\n };\n\n this.getDisplayIndentGuides = function() {\n return this.renderer.getDisplayIndentGuides();\n };\n this.setShowPrintMargin = function(showPrintMargin) {\n this.renderer.setShowPrintMargin(showPrintMargin);\n };\n this.getShowPrintMargin = function() {\n return this.renderer.getShowPrintMargin();\n };\n this.setPrintMarginColumn = function(showPrintMargin) {\n this.renderer.setPrintMarginColumn(showPrintMargin);\n };\n this.getPrintMarginColumn = function() {\n return this.renderer.getPrintMarginColumn();\n };\n this.setReadOnly = function(readOnly) {\n this.setOption(\"readOnly\", readOnly);\n };\n this.getReadOnly = function() {\n return this.getOption(\"readOnly\");\n };\n this.setBehavioursEnabled = function (enabled) {\n this.setOption(\"behavioursEnabled\", enabled);\n };\n this.getBehavioursEnabled = function () {\n return this.getOption(\"behavioursEnabled\");\n };\n this.setWrapBehavioursEnabled = function (enabled) {\n this.setOption(\"wrapBehavioursEnabled\", enabled);\n };\n this.getWrapBehavioursEnabled = function () {\n return this.getOption(\"wrapBehavioursEnabled\");\n };\n this.setShowFoldWidgets = function(show) {\n this.setOption(\"showFoldWidgets\", show);\n\n };\n this.getShowFoldWidgets = function() {\n return this.getOption(\"showFoldWidgets\");\n };\n\n this.setFadeFoldWidgets = function(fade) {\n this.setOption(\"fadeFoldWidgets\", fade);\n };\n\n this.getFadeFoldWidgets = function() {\n return this.getOption(\"fadeFoldWidgets\");\n };\n this.remove = function(dir) {\n if (this.selection.isEmpty()){\n if (dir == \"left\")\n this.selection.selectLeft();\n else\n this.selection.selectRight();\n }\n\n var range = this.getSelectionRange();\n if (this.getBehavioursEnabled()) {\n var session = this.session;\n var state = session.getState(range.start.row);\n var new_range = session.getMode().transformAction(state, 'deletion', this, session, range);\n\n if (range.end.column === 0) {\n var text = session.getTextRange(range);\n if (text[text.length - 1] == \"\\n\") {\n var line = session.getLine(range.end.row);\n if (/^\\s+$/.test(line)) {\n range.end.column = line.length;\n }\n }\n }\n if (new_range)\n range = new_range;\n }\n\n this.session.remove(range);\n this.clearSelection();\n };\n this.removeWordRight = function() {\n if (this.selection.isEmpty())\n this.selection.selectWordRight();\n\n this.session.remove(this.getSelectionRange());\n this.clearSelection();\n };\n this.removeWordLeft = function() {\n if (this.selection.isEmpty())\n this.selection.selectWordLeft();\n\n this.session.remove(this.getSelectionRange());\n this.clearSelection();\n };\n this.removeToLineStart = function() {\n if (this.selection.isEmpty())\n this.selection.selectLineStart();\n\n this.session.remove(this.getSelectionRange());\n this.clearSelection();\n };\n this.removeToLineEnd = function() {\n if (this.selection.isEmpty())\n this.selection.selectLineEnd();\n\n var range = this.getSelectionRange();\n if (range.start.column == range.end.column && range.start.row == range.end.row) {\n range.end.column = 0;\n range.end.row++;\n }\n\n this.session.remove(range);\n this.clearSelection();\n };\n this.splitLine = function() {\n if (!this.selection.isEmpty()) {\n this.session.remove(this.getSelectionRange());\n this.clearSelection();\n }\n\n var cursor = this.getCursorPosition();\n this.insert(\"\\n\");\n this.moveCursorToPosition(cursor);\n };\n this.transposeLetters = function() {\n if (!this.selection.isEmpty()) {\n return;\n }\n\n var cursor = this.getCursorPosition();\n var column = cursor.column;\n if (column === 0)\n return;\n\n var line = this.session.getLine(cursor.row);\n var swap, range;\n if (column < line.length) {\n swap = line.charAt(column) + line.charAt(column-1);\n range = new Range(cursor.row, column-1, cursor.row, column+1);\n }\n else {\n swap = line.charAt(column-1) + line.charAt(column-2);\n range = new Range(cursor.row, column-2, cursor.row, column);\n }\n this.session.replace(range, swap);\n };\n this.toLowerCase = function() {\n var originalRange = this.getSelectionRange();\n if (this.selection.isEmpty()) {\n this.selection.selectWord();\n }\n\n var range = this.getSelectionRange();\n var text = this.session.getTextRange(range);\n this.session.replace(range, text.toLowerCase());\n this.selection.setSelectionRange(originalRange);\n };\n this.toUpperCase = function() {\n var originalRange = this.getSelectionRange();\n if (this.selection.isEmpty()) {\n this.selection.selectWord();\n }\n\n var range = this.getSelectionRange();\n var text = this.session.getTextRange(range);\n this.session.replace(range, text.toUpperCase());\n this.selection.setSelectionRange(originalRange);\n };\n this.indent = function() {\n var session = this.session;\n var range = this.getSelectionRange();\n\n if (range.start.row < range.end.row) {\n var rows = this.$getSelectedRows();\n session.indentRows(rows.first, rows.last, \"\\t\");\n return;\n } else if (range.start.column < range.end.column) {\n var text = session.getTextRange(range);\n if (!/^\\s+$/.test(text)) {\n var rows = this.$getSelectedRows();\n session.indentRows(rows.first, rows.last, \"\\t\");\n return;\n }\n }\n \n var line = session.getLine(range.start.row);\n var position = range.start;\n var size = session.getTabSize();\n var column = session.documentToScreenColumn(position.row, position.column);\n\n if (this.session.getUseSoftTabs()) {\n var count = (size - column % size);\n var indentString = lang.stringRepeat(\" \", count);\n } else {\n var count = column % size;\n while (line[range.start.column] == \" \" && count) {\n range.start.column--;\n count--;\n }\n this.selection.setSelectionRange(range);\n indentString = \"\\t\";\n }\n return this.insert(indentString);\n };\n this.blockIndent = function() {\n var rows = this.$getSelectedRows();\n this.session.indentRows(rows.first, rows.last, \"\\t\");\n };\n this.blockOutdent = function() {\n var selection = this.session.getSelection();\n this.session.outdentRows(selection.getRange());\n };\n this.sortLines = function() {\n var rows = this.$getSelectedRows();\n var session = this.session;\n\n var lines = [];\n for (i = rows.first; i <= rows.last; i++)\n lines.push(session.getLine(i));\n\n lines.sort(function(a, b) {\n if (a.toLowerCase() < b.toLowerCase()) return -1;\n if (a.toLowerCase() > b.toLowerCase()) return 1;\n return 0;\n });\n\n var deleteRange = new Range(0, 0, 0, 0);\n for (var i = rows.first; i <= rows.last; i++) {\n var line = session.getLine(i);\n deleteRange.start.row = i;\n deleteRange.end.row = i;\n deleteRange.end.column = line.length;\n session.replace(deleteRange, lines[i-rows.first]);\n }\n };\n this.toggleCommentLines = function() {\n var state = this.session.getState(this.getCursorPosition().row);\n var rows = this.$getSelectedRows();\n this.session.getMode().toggleCommentLines(state, this.session, rows.first, rows.last);\n };\n\n this.toggleBlockComment = function() {\n var cursor = this.getCursorPosition();\n var state = this.session.getState(cursor.row);\n var range = this.getSelectionRange();\n this.session.getMode().toggleBlockComment(state, this.session, range, cursor);\n };\n this.getNumberAt = function(row, column) {\n var _numberRx = /[\\-]?[0-9]+(?:\\.[0-9]+)?/g;\n _numberRx.lastIndex = 0;\n\n var s = this.session.getLine(row);\n while (_numberRx.lastIndex < column) {\n var m = _numberRx.exec(s);\n if(m.index <= column && m.index+m[0].length >= column){\n var number = {\n value: m[0],\n start: m.index,\n end: m.index+m[0].length\n };\n return number;\n }\n }\n return null;\n };\n this.modifyNumber = function(amount) {\n var row = this.selection.getCursor().row;\n var column = this.selection.getCursor().column;\n var charRange = new Range(row, column-1, row, column);\n\n var c = this.session.getTextRange(charRange);\n if (!isNaN(parseFloat(c)) && isFinite(c)) {\n var nr = this.getNumberAt(row, column);\n if (nr) {\n var fp = nr.value.indexOf(\".\") >= 0 ? nr.start + nr.value.indexOf(\".\") + 1 : nr.end;\n var decimals = nr.start + nr.value.length - fp;\n\n var t = parseFloat(nr.value);\n t *= Math.pow(10, decimals);\n\n\n if(fp !== nr.end && column < fp){\n amount *= Math.pow(10, nr.end - column - 1);\n } else {\n amount *= Math.pow(10, nr.end - column);\n }\n\n t += amount;\n t /= Math.pow(10, decimals);\n var nnr = t.toFixed(decimals);\n var replaceRange = new Range(row, nr.start, row, nr.end);\n this.session.replace(replaceRange, nnr);\n this.moveCursorTo(row, Math.max(nr.start +1, column + nnr.length - nr.value.length));\n\n }\n }\n };\n this.removeLines = function() {\n var rows = this.$getSelectedRows();\n this.session.removeFullLines(rows.first, rows.last);\n this.clearSelection();\n };\n\n this.duplicateSelection = function() {\n var sel = this.selection;\n var doc = this.session;\n var range = sel.getRange();\n var reverse = sel.isBackwards();\n if (range.isEmpty()) {\n var row = range.start.row;\n doc.duplicateLines(row, row);\n } else {\n var point = reverse ? range.start : range.end;\n var endPoint = doc.insert(point, doc.getTextRange(range), false);\n range.start = point;\n range.end = endPoint;\n\n sel.setSelectionRange(range, reverse);\n }\n };\n this.moveLinesDown = function() {\n this.$moveLines(1, false);\n };\n this.moveLinesUp = function() {\n this.$moveLines(-1, false);\n };\n this.moveText = function(range, toPosition, copy) {\n return this.session.moveText(range, toPosition, copy);\n };\n this.copyLinesUp = function() {\n this.$moveLines(-1, true);\n };\n this.copyLinesDown = function() {\n this.$moveLines(1, true);\n };\n this.$moveLines = function(dir, copy) {\n var rows, moved;\n var selection = this.selection;\n if (!selection.inMultiSelectMode || this.inVirtualSelectionMode) {\n var range = selection.toOrientedRange();\n rows = this.$getSelectedRows(range);\n moved = this.session.$moveLines(rows.first, rows.last, copy ? 0 : dir);\n if (copy && dir == -1) moved = 0;\n range.moveBy(moved, 0);\n selection.fromOrientedRange(range);\n } else {\n var ranges = selection.rangeList.ranges;\n selection.rangeList.detach(this.session);\n this.inVirtualSelectionMode = true;\n \n var diff = 0;\n var totalDiff = 0;\n var l = ranges.length;\n for (var i = 0; i < l; i++) {\n var rangeIndex = i;\n ranges[i].moveBy(diff, 0);\n rows = this.$getSelectedRows(ranges[i]);\n var first = rows.first;\n var last = rows.last;\n while (++i < l) {\n if (totalDiff) ranges[i].moveBy(totalDiff, 0);\n var subRows = this.$getSelectedRows(ranges[i]);\n if (copy && subRows.first != last)\n break;\n else if (!copy && subRows.first > last + 1)\n break;\n last = subRows.last;\n }\n i--;\n diff = this.session.$moveLines(first, last, copy ? 0 : dir);\n if (copy && dir == -1) rangeIndex = i + 1;\n while (rangeIndex <= i) {\n ranges[rangeIndex].moveBy(diff, 0);\n rangeIndex++;\n }\n if (!copy) diff = 0;\n totalDiff += diff;\n }\n \n selection.fromOrientedRange(selection.ranges[0]);\n selection.rangeList.attach(this.session);\n this.inVirtualSelectionMode = false;\n }\n };\n this.$getSelectedRows = function(range) {\n range = (range || this.getSelectionRange()).collapseRows();\n\n return {\n first: this.session.getRowFoldStart(range.start.row),\n last: this.session.getRowFoldEnd(range.end.row)\n };\n };\n\n this.onCompositionStart = function(text) {\n this.renderer.showComposition(this.getCursorPosition());\n };\n\n this.onCompositionUpdate = function(text) {\n this.renderer.setCompositionText(text);\n };\n\n this.onCompositionEnd = function() {\n this.renderer.hideComposition();\n };\n this.getFirstVisibleRow = function() {\n return this.renderer.getFirstVisibleRow();\n };\n this.getLastVisibleRow = function() {\n return this.renderer.getLastVisibleRow();\n };\n this.isRowVisible = function(row) {\n return (row >= this.getFirstVisibleRow() && row <= this.getLastVisibleRow());\n };\n this.isRowFullyVisible = function(row) {\n return (row >= this.renderer.getFirstFullyVisibleRow() && row <= this.renderer.getLastFullyVisibleRow());\n };\n this.$getVisibleRowCount = function() {\n return this.renderer.getScrollBottomRow() - this.renderer.getScrollTopRow() + 1;\n };\n\n this.$moveByPage = function(dir, select) {\n var renderer = this.renderer;\n var config = this.renderer.layerConfig;\n var rows = dir * Math.floor(config.height / config.lineHeight);\n\n this.$blockScrolling++;\n if (select === true) {\n this.selection.$moveSelection(function(){\n this.moveCursorBy(rows, 0);\n });\n } else if (select === false) {\n this.selection.moveCursorBy(rows, 0);\n this.selection.clearSelection();\n }\n this.$blockScrolling--;\n\n var scrollTop = renderer.scrollTop;\n\n renderer.scrollBy(0, rows * config.lineHeight);\n if (select != null)\n renderer.scrollCursorIntoView(null, 0.5);\n\n renderer.animateScrolling(scrollTop);\n };\n this.selectPageDown = function() {\n this.$moveByPage(1, true);\n };\n this.selectPageUp = function() {\n this.$moveByPage(-1, true);\n };\n this.gotoPageDown = function() {\n this.$moveByPage(1, false);\n };\n this.gotoPageUp = function() {\n this.$moveByPage(-1, false);\n };\n this.scrollPageDown = function() {\n this.$moveByPage(1);\n };\n this.scrollPageUp = function() {\n this.$moveByPage(-1);\n };\n this.scrollToRow = function(row) {\n this.renderer.scrollToRow(row);\n };\n this.scrollToLine = function(line, center, animate, callback) {\n this.renderer.scrollToLine(line, center, animate, callback);\n };\n this.centerSelection = function() {\n var range = this.getSelectionRange();\n var pos = {\n row: Math.floor(range.start.row + (range.end.row - range.start.row) / 2),\n column: Math.floor(range.start.column + (range.end.column - range.start.column) / 2)\n };\n this.renderer.alignCursor(pos, 0.5);\n };\n this.getCursorPosition = function() {\n return this.selection.getCursor();\n };\n this.getCursorPositionScreen = function() {\n return this.session.documentToScreenPosition(this.getCursorPosition());\n };\n this.getSelectionRange = function() {\n return this.selection.getRange();\n };\n this.selectAll = function() {\n this.$blockScrolling += 1;\n this.selection.selectAll();\n this.$blockScrolling -= 1;\n };\n this.clearSelection = function() {\n this.selection.clearSelection();\n };\n this.moveCursorTo = function(row, column) {\n this.selection.moveCursorTo(row, column);\n };\n this.moveCursorToPosition = function(pos) {\n this.selection.moveCursorToPosition(pos);\n };\n this.jumpToMatching = function(select, expand) {\n var cursor = this.getCursorPosition();\n var iterator = new TokenIterator(this.session, cursor.row, cursor.column);\n var prevToken = iterator.getCurrentToken();\n var token = prevToken || iterator.stepForward();\n\n if (!token) return;\n var matchType;\n var found = false;\n var depth = {};\n var i = cursor.column - token.start;\n var bracketType;\n var brackets = {\n \")\": \"(\",\n \"(\": \"(\",\n \"]\": \"[\",\n \"[\": \"[\",\n \"{\": \"{\",\n \"}\": \"{\"\n };\n \n do {\n if (token.value.match(/[{}()\\[\\]]/g)) {\n for (; i < token.value.length && !found; i++) {\n if (!brackets[token.value[i]]) {\n continue;\n }\n\n bracketType = brackets[token.value[i]] + '.' + token.type.replace(\"rparen\", \"lparen\");\n\n if (isNaN(depth[bracketType])) {\n depth[bracketType] = 0;\n }\n\n switch (token.value[i]) {\n case '(':\n case '[':\n case '{':\n depth[bracketType]++;\n break;\n case ')':\n case ']':\n case '}':\n depth[bracketType]--;\n\n if (depth[bracketType] === -1) {\n matchType = 'bracket';\n found = true;\n }\n break;\n }\n }\n }\n else if (token && token.type.indexOf('tag-name') !== -1) {\n if (isNaN(depth[token.value])) {\n depth[token.value] = 0;\n }\n \n if (prevToken.value === '<') {\n depth[token.value]++;\n }\n else if (prevToken.value === '= 0; --i) {\n if(this.$tryReplace(ranges[i], replacement)) {\n replaced++;\n }\n }\n\n this.selection.setSelectionRange(selection);\n this.$blockScrolling -= 1;\n\n return replaced;\n };\n\n this.$tryReplace = function(range, replacement) {\n var input = this.session.getTextRange(range);\n replacement = this.$search.replace(input, replacement);\n if (replacement !== null) {\n range.end = this.session.replace(range, replacement);\n return range;\n } else {\n return null;\n }\n };\n this.getLastSearchOptions = function() {\n return this.$search.getOptions();\n };\n this.find = function(needle, options, animate) {\n if (!options)\n options = {};\n\n if (typeof needle == \"string\" || needle instanceof RegExp)\n options.needle = needle;\n else if (typeof needle == \"object\")\n oop.mixin(options, needle);\n\n var range = this.selection.getRange();\n if (options.needle == null) {\n needle = this.session.getTextRange(range)\n || this.$search.$options.needle;\n if (!needle) {\n range = this.session.getWordRange(range.start.row, range.start.column);\n needle = this.session.getTextRange(range);\n }\n this.$search.set({needle: needle});\n }\n\n this.$search.set(options);\n if (!options.start)\n this.$search.set({start: range});\n\n var newRange = this.$search.find(this.session);\n if (options.preventScroll)\n return newRange;\n if (newRange) {\n this.revealRange(newRange, animate);\n return newRange;\n }\n if (options.backwards)\n range.start = range.end;\n else\n range.end = range.start;\n this.selection.setRange(range);\n };\n this.findNext = function(options, animate) {\n this.find({skipCurrent: true, backwards: false}, options, animate);\n };\n this.findPrevious = function(options, animate) {\n this.find(options, {skipCurrent: true, backwards: true}, animate);\n };\n\n this.revealRange = function(range, animate) {\n this.$blockScrolling += 1;\n this.session.unfold(range);\n this.selection.setSelectionRange(range);\n this.$blockScrolling -= 1;\n\n var scrollTop = this.renderer.scrollTop;\n this.renderer.scrollSelectionIntoView(range.start, range.end, 0.5);\n if (animate !== false)\n this.renderer.animateScrolling(scrollTop);\n };\n this.undo = function() {\n this.$blockScrolling++;\n this.session.getUndoManager().undo();\n this.$blockScrolling--;\n this.renderer.scrollCursorIntoView(null, 0.5);\n };\n this.redo = function() {\n this.$blockScrolling++;\n this.session.getUndoManager().redo();\n this.$blockScrolling--;\n this.renderer.scrollCursorIntoView(null, 0.5);\n };\n this.destroy = function() {\n this.renderer.destroy();\n this._signal(\"destroy\", this);\n if (this.session) {\n this.session.destroy();\n }\n };\n this.setAutoScrollEditorIntoView = function(enable) {\n if (!enable)\n return;\n var rect;\n var self = this;\n var shouldScroll = false;\n if (!this.$scrollAnchor)\n this.$scrollAnchor = document.createElement(\"div\");\n var scrollAnchor = this.$scrollAnchor;\n scrollAnchor.style.cssText = \"position:absolute\";\n this.container.insertBefore(scrollAnchor, this.container.firstChild);\n var onChangeSelection = this.on(\"changeSelection\", function() {\n shouldScroll = true;\n });\n var onBeforeRender = this.renderer.on(\"beforeRender\", function() {\n if (shouldScroll)\n rect = self.renderer.container.getBoundingClientRect();\n });\n var onAfterRender = this.renderer.on(\"afterRender\", function() {\n if (shouldScroll && rect && (self.isFocused()\n || self.searchBox && self.searchBox.isFocused())\n ) {\n var renderer = self.renderer;\n var pos = renderer.$cursorLayer.$pixelPos;\n var config = renderer.layerConfig;\n var top = pos.top - config.offset;\n if (pos.top >= 0 && top + rect.top < 0) {\n shouldScroll = true;\n } else if (pos.top < config.height &&\n pos.top + rect.top + config.lineHeight > window.innerHeight) {\n shouldScroll = false;\n } else {\n shouldScroll = null;\n }\n if (shouldScroll != null) {\n scrollAnchor.style.top = top + \"px\";\n scrollAnchor.style.left = pos.left + \"px\";\n scrollAnchor.style.height = config.lineHeight + \"px\";\n scrollAnchor.scrollIntoView(shouldScroll);\n }\n shouldScroll = rect = null;\n }\n });\n this.setAutoScrollEditorIntoView = function(enable) {\n if (enable)\n return;\n delete this.setAutoScrollEditorIntoView;\n this.off(\"changeSelection\", onChangeSelection);\n this.renderer.off(\"afterRender\", onAfterRender);\n this.renderer.off(\"beforeRender\", onBeforeRender);\n };\n };\n\n\n this.$resetCursorStyle = function() {\n var style = this.$cursorStyle || \"ace\";\n var cursorLayer = this.renderer.$cursorLayer;\n if (!cursorLayer)\n return;\n cursorLayer.setSmoothBlinking(/smooth/.test(style));\n cursorLayer.isBlinking = !this.$readOnly && style != \"wide\";\n dom.setCssClass(cursorLayer.element, \"ace_slim-cursors\", /slim/.test(style));\n };\n\n}).call(Editor.prototype);\n\n\n\nconfig.defineOptions(Editor.prototype, \"editor\", {\n selectionStyle: {\n set: function(style) {\n this.onSelectionChange();\n this._signal(\"changeSelectionStyle\", {data: style});\n },\n initialValue: \"line\"\n },\n highlightActiveLine: {\n set: function() {this.$updateHighlightActiveLine();},\n initialValue: true\n },\n highlightSelectedWord: {\n set: function(shouldHighlight) {this.$onSelectionChange();},\n initialValue: true\n },\n readOnly: {\n set: function(readOnly) {\n this.$resetCursorStyle(); \n },\n initialValue: false\n },\n cursorStyle: {\n set: function(val) { this.$resetCursorStyle(); },\n values: [\"ace\", \"slim\", \"smooth\", \"wide\"],\n initialValue: \"ace\"\n },\n mergeUndoDeltas: {\n values: [false, true, \"always\"],\n initialValue: true\n },\n behavioursEnabled: {initialValue: true},\n wrapBehavioursEnabled: {initialValue: true},\n autoScrollEditorIntoView: {\n set: function(val) {this.setAutoScrollEditorIntoView(val)}\n },\n keyboardHandler: {\n set: function(val) { this.setKeyboardHandler(val); },\n get: function() { return this.keybindingId; },\n handlesSet: true\n },\n\n hScrollBarAlwaysVisible: \"renderer\",\n vScrollBarAlwaysVisible: \"renderer\",\n highlightGutterLine: \"renderer\",\n animatedScroll: \"renderer\",\n showInvisibles: \"renderer\",\n showPrintMargin: \"renderer\",\n printMarginColumn: \"renderer\",\n printMargin: \"renderer\",\n fadeFoldWidgets: \"renderer\",\n showFoldWidgets: \"renderer\",\n showLineNumbers: \"renderer\",\n showGutter: \"renderer\",\n displayIndentGuides: \"renderer\",\n fontSize: \"renderer\",\n fontFamily: \"renderer\",\n maxLines: \"renderer\",\n minLines: \"renderer\",\n scrollPastEnd: \"renderer\",\n fixedWidthGutter: \"renderer\",\n theme: \"renderer\",\n\n scrollSpeed: \"$mouseHandler\",\n dragDelay: \"$mouseHandler\",\n dragEnabled: \"$mouseHandler\",\n focusTimout: \"$mouseHandler\",\n tooltipFollowsMouse: \"$mouseHandler\",\n\n firstLineNumber: \"session\",\n overwrite: \"session\",\n newLineMode: \"session\",\n useWorker: \"session\",\n useSoftTabs: \"session\",\n tabSize: \"session\",\n wrap: \"session\",\n indentedSoftWrap: \"session\",\n foldStyle: \"session\",\n mode: \"session\"\n});\n\nexports.Editor = Editor;\n});\n\nace.define(\"ace/undomanager\",[\"require\",\"exports\",\"module\"], function(acequire, exports, module) {\n\"use strict\";\nvar UndoManager = function() {\n this.reset();\n};\n\n(function() {\n this.execute = function(options) {\n var deltaSets = options.args[0];\n this.$doc = options.args[1];\n if (options.merge && this.hasUndo()){\n this.dirtyCounter--;\n deltaSets = this.$undoStack.pop().concat(deltaSets);\n }\n this.$undoStack.push(deltaSets);\n this.$redoStack = [];\n if (this.dirtyCounter < 0) {\n this.dirtyCounter = NaN;\n }\n this.dirtyCounter++;\n };\n this.undo = function(dontSelect) {\n var deltaSets = this.$undoStack.pop();\n var undoSelectionRange = null;\n if (deltaSets) {\n undoSelectionRange = this.$doc.undoChanges(deltaSets, dontSelect);\n this.$redoStack.push(deltaSets);\n this.dirtyCounter--;\n }\n\n return undoSelectionRange;\n };\n this.redo = function(dontSelect) {\n var deltaSets = this.$redoStack.pop();\n var redoSelectionRange = null;\n if (deltaSets) {\n redoSelectionRange =\n this.$doc.redoChanges(this.$deserializeDeltas(deltaSets), dontSelect);\n this.$undoStack.push(deltaSets);\n this.dirtyCounter++;\n }\n return redoSelectionRange;\n };\n this.reset = function() {\n this.$undoStack = [];\n this.$redoStack = [];\n this.dirtyCounter = 0;\n };\n this.hasUndo = function() {\n return this.$undoStack.length > 0;\n };\n this.hasRedo = function() {\n return this.$redoStack.length > 0;\n };\n this.markClean = function() {\n this.dirtyCounter = 0;\n };\n this.isClean = function() {\n return this.dirtyCounter === 0;\n };\n this.$serializeDeltas = function(deltaSets) {\n return cloneDeltaSetsObj(deltaSets, $serializeDelta);\n };\n this.$deserializeDeltas = function(deltaSets) {\n return cloneDeltaSetsObj(deltaSets, $deserializeDelta);\n };\n \n function $serializeDelta(delta){\n return {\n action: delta.action,\n start: delta.start,\n end: delta.end,\n lines: delta.lines.length == 1 ? null : delta.lines,\n text: delta.lines.length == 1 ? delta.lines[0] : null\n };\n }\n \n function $deserializeDelta(delta) {\n return {\n action: delta.action,\n start: delta.start,\n end: delta.end,\n lines: delta.lines || [delta.text]\n };\n }\n \n function cloneDeltaSetsObj(deltaSets_old, fnGetModifiedDelta) {\n var deltaSets_new = new Array(deltaSets_old.length);\n for (var i = 0; i < deltaSets_old.length; i++) {\n var deltaSet_old = deltaSets_old[i];\n var deltaSet_new = { group: deltaSet_old.group, deltas: new Array(deltaSet_old.length)};\n \n for (var j = 0; j < deltaSet_old.deltas.length; j++) {\n var delta_old = deltaSet_old.deltas[j];\n deltaSet_new.deltas[j] = fnGetModifiedDelta(delta_old);\n }\n \n deltaSets_new[i] = deltaSet_new;\n }\n return deltaSets_new;\n }\n \n}).call(UndoManager.prototype);\n\nexports.UndoManager = UndoManager;\n});\n\nace.define(\"ace/layer/gutter\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\",\"ace/lib/oop\",\"ace/lib/lang\",\"ace/lib/event_emitter\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar dom = acequire(\"../lib/dom\");\nvar oop = acequire(\"../lib/oop\");\nvar lang = acequire(\"../lib/lang\");\nvar EventEmitter = acequire(\"../lib/event_emitter\").EventEmitter;\n\nvar Gutter = function(parentEl) {\n this.element = dom.createElement(\"div\");\n this.element.className = \"ace_layer ace_gutter-layer\";\n parentEl.appendChild(this.element);\n this.setShowFoldWidgets(this.$showFoldWidgets);\n \n this.gutterWidth = 0;\n\n this.$annotations = [];\n this.$updateAnnotations = this.$updateAnnotations.bind(this);\n\n this.$cells = [];\n};\n\n(function() {\n\n oop.implement(this, EventEmitter);\n\n this.setSession = function(session) {\n if (this.session)\n this.session.removeEventListener(\"change\", this.$updateAnnotations);\n this.session = session;\n if (session)\n session.on(\"change\", this.$updateAnnotations);\n };\n\n this.addGutterDecoration = function(row, className){\n if (window.console)\n console.warn && console.warn(\"deprecated use session.addGutterDecoration\");\n this.session.addGutterDecoration(row, className);\n };\n\n this.removeGutterDecoration = function(row, className){\n if (window.console)\n console.warn && console.warn(\"deprecated use session.removeGutterDecoration\");\n this.session.removeGutterDecoration(row, className);\n };\n\n this.setAnnotations = function(annotations) {\n this.$annotations = [];\n for (var i = 0; i < annotations.length; i++) {\n var annotation = annotations[i];\n var row = annotation.row;\n var rowInfo = this.$annotations[row];\n if (!rowInfo)\n rowInfo = this.$annotations[row] = {text: []};\n \n var annoText = annotation.text;\n annoText = annoText ? lang.escapeHTML(annoText) : annotation.html || \"\";\n\n if (rowInfo.text.indexOf(annoText) === -1)\n rowInfo.text.push(annoText);\n\n var type = annotation.type;\n if (type == \"error\")\n rowInfo.className = \" ace_error\";\n else if (type == \"warning\" && rowInfo.className != \" ace_error\")\n rowInfo.className = \" ace_warning\";\n else if (type == \"info\" && (!rowInfo.className))\n rowInfo.className = \" ace_info\";\n }\n };\n\n this.$updateAnnotations = function (delta) {\n if (!this.$annotations.length)\n return;\n var firstRow = delta.start.row;\n var len = delta.end.row - firstRow;\n if (len === 0) {\n } else if (delta.action == 'remove') {\n this.$annotations.splice(firstRow, len + 1, null);\n } else {\n var args = new Array(len + 1);\n args.unshift(firstRow, 1);\n this.$annotations.splice.apply(this.$annotations, args);\n }\n };\n\n this.update = function(config) {\n var session = this.session;\n var firstRow = config.firstRow;\n var lastRow = Math.min(config.lastRow + config.gutterOffset, // needed to compensate for hor scollbar\n session.getLength() - 1);\n var fold = session.getNextFoldLine(firstRow);\n var foldStart = fold ? fold.start.row : Infinity;\n var foldWidgets = this.$showFoldWidgets && session.foldWidgets;\n var breakpoints = session.$breakpoints;\n var decorations = session.$decorations;\n var firstLineNumber = session.$firstLineNumber;\n var lastLineNumber = 0;\n \n var gutterRenderer = session.gutterRenderer || this.$renderer;\n\n var cell = null;\n var index = -1;\n var row = firstRow;\n while (true) {\n if (row > foldStart) {\n row = fold.end.row + 1;\n fold = session.getNextFoldLine(row, fold);\n foldStart = fold ? fold.start.row : Infinity;\n }\n if (row > lastRow) {\n while (this.$cells.length > index + 1) {\n cell = this.$cells.pop();\n this.element.removeChild(cell.element);\n }\n break;\n }\n\n cell = this.$cells[++index];\n if (!cell) {\n cell = {element: null, textNode: null, foldWidget: null};\n cell.element = dom.createElement(\"div\");\n cell.textNode = document.createTextNode('');\n cell.element.appendChild(cell.textNode);\n this.element.appendChild(cell.element);\n this.$cells[index] = cell;\n }\n\n var className = \"ace_gutter-cell \";\n if (breakpoints[row])\n className += breakpoints[row];\n if (decorations[row])\n className += decorations[row];\n if (this.$annotations[row])\n className += this.$annotations[row].className;\n if (cell.element.className != className)\n cell.element.className = className;\n\n var height = session.getRowLength(row) * config.lineHeight + \"px\";\n if (height != cell.element.style.height)\n cell.element.style.height = height;\n\n if (foldWidgets) {\n var c = foldWidgets[row];\n if (c == null)\n c = foldWidgets[row] = session.getFoldWidget(row);\n }\n\n if (c) {\n if (!cell.foldWidget) {\n cell.foldWidget = dom.createElement(\"span\");\n cell.element.appendChild(cell.foldWidget);\n }\n var className = \"ace_fold-widget ace_\" + c;\n if (c == \"start\" && row == foldStart && row < fold.end.row)\n className += \" ace_closed\";\n else\n className += \" ace_open\";\n if (cell.foldWidget.className != className)\n cell.foldWidget.className = className;\n\n var height = config.lineHeight + \"px\";\n if (cell.foldWidget.style.height != height)\n cell.foldWidget.style.height = height;\n } else {\n if (cell.foldWidget) {\n cell.element.removeChild(cell.foldWidget);\n cell.foldWidget = null;\n }\n }\n \n var text = lastLineNumber = gutterRenderer\n ? gutterRenderer.getText(session, row)\n : row + firstLineNumber;\n if (text != cell.textNode.data)\n cell.textNode.data = text;\n\n row++;\n }\n\n this.element.style.height = config.minHeight + \"px\";\n\n if (this.$fixedWidth || session.$useWrapMode)\n lastLineNumber = session.getLength() + firstLineNumber;\n\n var gutterWidth = gutterRenderer \n ? gutterRenderer.getWidth(session, lastLineNumber, config)\n : lastLineNumber.toString().length * config.characterWidth;\n \n var padding = this.$padding || this.$computePadding();\n gutterWidth += padding.left + padding.right;\n if (gutterWidth !== this.gutterWidth && !isNaN(gutterWidth)) {\n this.gutterWidth = gutterWidth;\n this.element.style.width = Math.ceil(this.gutterWidth) + \"px\";\n this._emit(\"changeGutterWidth\", gutterWidth);\n }\n };\n\n this.$fixedWidth = false;\n \n this.$showLineNumbers = true;\n this.$renderer = \"\";\n this.setShowLineNumbers = function(show) {\n this.$renderer = !show && {\n getWidth: function() {return \"\"},\n getText: function() {return \"\"}\n };\n };\n \n this.getShowLineNumbers = function() {\n return this.$showLineNumbers;\n };\n \n this.$showFoldWidgets = true;\n this.setShowFoldWidgets = function(show) {\n if (show)\n dom.addCssClass(this.element, \"ace_folding-enabled\");\n else\n dom.removeCssClass(this.element, \"ace_folding-enabled\");\n\n this.$showFoldWidgets = show;\n this.$padding = null;\n };\n \n this.getShowFoldWidgets = function() {\n return this.$showFoldWidgets;\n };\n\n this.$computePadding = function() {\n if (!this.element.firstChild)\n return {left: 0, right: 0};\n var style = dom.computedStyle(this.element.firstChild);\n this.$padding = {};\n this.$padding.left = parseInt(style.paddingLeft) + 1 || 0;\n this.$padding.right = parseInt(style.paddingRight) || 0;\n return this.$padding;\n };\n\n this.getRegion = function(point) {\n var padding = this.$padding || this.$computePadding();\n var rect = this.element.getBoundingClientRect();\n if (point.x < padding.left + rect.left)\n return \"markers\";\n if (this.$showFoldWidgets && point.x > rect.right - padding.right)\n return \"foldWidgets\";\n };\n\n}).call(Gutter.prototype);\n\nexports.Gutter = Gutter;\n\n});\n\nace.define(\"ace/layer/marker\",[\"require\",\"exports\",\"module\",\"ace/range\",\"ace/lib/dom\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar Range = acequire(\"../range\").Range;\nvar dom = acequire(\"../lib/dom\");\n\nvar Marker = function(parentEl) {\n this.element = dom.createElement(\"div\");\n this.element.className = \"ace_layer ace_marker-layer\";\n parentEl.appendChild(this.element);\n};\n\n(function() {\n\n this.$padding = 0;\n\n this.setPadding = function(padding) {\n this.$padding = padding;\n };\n this.setSession = function(session) {\n this.session = session;\n };\n \n this.setMarkers = function(markers) {\n this.markers = markers;\n };\n\n this.update = function(config) {\n var config = config || this.config;\n if (!config)\n return;\n\n this.config = config;\n\n\n var html = [];\n for (var key in this.markers) {\n var marker = this.markers[key];\n\n if (!marker.range) {\n marker.update(html, this, this.session, config);\n continue;\n }\n\n var range = marker.range.clipRows(config.firstRow, config.lastRow);\n if (range.isEmpty()) continue;\n\n range = range.toScreenRange(this.session);\n if (marker.renderer) {\n var top = this.$getTop(range.start.row, config);\n var left = this.$padding + range.start.column * config.characterWidth;\n marker.renderer(html, range, left, top, config);\n } else if (marker.type == \"fullLine\") {\n this.drawFullLineMarker(html, range, marker.clazz, config);\n } else if (marker.type == \"screenLine\") {\n this.drawScreenLineMarker(html, range, marker.clazz, config);\n } else if (range.isMultiLine()) {\n if (marker.type == \"text\")\n this.drawTextMarker(html, range, marker.clazz, config);\n else\n this.drawMultiLineMarker(html, range, marker.clazz, config);\n } else {\n this.drawSingleLineMarker(html, range, marker.clazz + \" ace_start\" + \" ace_br15\", config);\n }\n }\n this.element.innerHTML = html.join(\"\");\n };\n\n this.$getTop = function(row, layerConfig) {\n return (row - layerConfig.firstRowScreen) * layerConfig.lineHeight;\n };\n\n function getBorderClass(tl, tr, br, bl) {\n return (tl ? 1 : 0) | (tr ? 2 : 0) | (br ? 4 : 0) | (bl ? 8 : 0);\n }\n this.drawTextMarker = function(stringBuilder, range, clazz, layerConfig, extraStyle) {\n var session = this.session;\n var start = range.start.row;\n var end = range.end.row;\n var row = start;\n var prev = 0; \n var curr = 0;\n var next = session.getScreenLastRowColumn(row);\n var lineRange = new Range(row, range.start.column, row, curr);\n for (; row <= end; row++) {\n lineRange.start.row = lineRange.end.row = row;\n lineRange.start.column = row == start ? range.start.column : session.getRowWrapIndent(row);\n lineRange.end.column = next;\n prev = curr;\n curr = next;\n next = row + 1 < end ? session.getScreenLastRowColumn(row + 1) : row == end ? 0 : range.end.column;\n this.drawSingleLineMarker(stringBuilder, lineRange, \n clazz + (row == start ? \" ace_start\" : \"\") + \" ace_br\"\n + getBorderClass(row == start || row == start + 1 && range.start.column, prev < curr, curr > next, row == end),\n layerConfig, row == end ? 0 : 1, extraStyle);\n }\n };\n this.drawMultiLineMarker = function(stringBuilder, range, clazz, config, extraStyle) {\n var padding = this.$padding;\n var height = config.lineHeight;\n var top = this.$getTop(range.start.row, config);\n var left = padding + range.start.column * config.characterWidth;\n extraStyle = extraStyle || \"\";\n\n stringBuilder.push(\n \"

\"\n );\n top = this.$getTop(range.end.row, config);\n var width = range.end.column * config.characterWidth;\n\n stringBuilder.push(\n \"
\"\n );\n height = (range.end.row - range.start.row - 1) * config.lineHeight;\n if (height <= 0)\n return;\n top = this.$getTop(range.start.row + 1, config);\n \n var radiusClass = (range.start.column ? 1 : 0) | (range.end.column ? 0 : 8);\n\n stringBuilder.push(\n \"
\"\n );\n };\n this.drawSingleLineMarker = function(stringBuilder, range, clazz, config, extraLength, extraStyle) {\n var height = config.lineHeight;\n var width = (range.end.column + (extraLength || 0) - range.start.column) * config.characterWidth;\n\n var top = this.$getTop(range.start.row, config);\n var left = this.$padding + range.start.column * config.characterWidth;\n\n stringBuilder.push(\n \"
\"\n );\n };\n\n this.drawFullLineMarker = function(stringBuilder, range, clazz, config, extraStyle) {\n var top = this.$getTop(range.start.row, config);\n var height = config.lineHeight;\n if (range.start.row != range.end.row)\n height += this.$getTop(range.end.row, config) - top;\n\n stringBuilder.push(\n \"
\"\n );\n };\n \n this.drawScreenLineMarker = function(stringBuilder, range, clazz, config, extraStyle) {\n var top = this.$getTop(range.start.row, config);\n var height = config.lineHeight;\n\n stringBuilder.push(\n \"
\"\n );\n };\n\n}).call(Marker.prototype);\n\nexports.Marker = Marker;\n\n});\n\nace.define(\"ace/layer/text\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/dom\",\"ace/lib/lang\",\"ace/lib/useragent\",\"ace/lib/event_emitter\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar oop = acequire(\"../lib/oop\");\nvar dom = acequire(\"../lib/dom\");\nvar lang = acequire(\"../lib/lang\");\nvar useragent = acequire(\"../lib/useragent\");\nvar EventEmitter = acequire(\"../lib/event_emitter\").EventEmitter;\n\nvar Text = function(parentEl) {\n this.element = dom.createElement(\"div\");\n this.element.className = \"ace_layer ace_text-layer\";\n parentEl.appendChild(this.element);\n this.$updateEolChar = this.$updateEolChar.bind(this);\n};\n\n(function() {\n\n oop.implement(this, EventEmitter);\n\n this.EOF_CHAR = \"\\xB6\";\n this.EOL_CHAR_LF = \"\\xAC\";\n this.EOL_CHAR_CRLF = \"\\xa4\";\n this.EOL_CHAR = this.EOL_CHAR_LF;\n this.TAB_CHAR = \"\\u2014\"; //\"\\u21E5\";\n this.SPACE_CHAR = \"\\xB7\";\n this.$padding = 0;\n\n this.$updateEolChar = function() {\n var EOL_CHAR = this.session.doc.getNewLineCharacter() == \"\\n\"\n ? this.EOL_CHAR_LF\n : this.EOL_CHAR_CRLF;\n if (this.EOL_CHAR != EOL_CHAR) {\n this.EOL_CHAR = EOL_CHAR;\n return true;\n }\n }\n\n this.setPadding = function(padding) {\n this.$padding = padding;\n this.element.style.padding = \"0 \" + padding + \"px\";\n };\n\n this.getLineHeight = function() {\n return this.$fontMetrics.$characterSize.height || 0;\n };\n\n this.getCharacterWidth = function() {\n return this.$fontMetrics.$characterSize.width || 0;\n };\n \n this.$setFontMetrics = function(measure) {\n this.$fontMetrics = measure;\n this.$fontMetrics.on(\"changeCharacterSize\", function(e) {\n this._signal(\"changeCharacterSize\", e);\n }.bind(this));\n this.$pollSizeChanges();\n }\n\n this.checkForSizeChanges = function() {\n this.$fontMetrics.checkForSizeChanges();\n };\n this.$pollSizeChanges = function() {\n return this.$pollSizeChangesTimer = this.$fontMetrics.$pollSizeChanges();\n };\n this.setSession = function(session) {\n this.session = session;\n if (session)\n this.$computeTabString();\n };\n\n this.showInvisibles = false;\n this.setShowInvisibles = function(showInvisibles) {\n if (this.showInvisibles == showInvisibles)\n return false;\n\n this.showInvisibles = showInvisibles;\n this.$computeTabString();\n return true;\n };\n\n this.displayIndentGuides = true;\n this.setDisplayIndentGuides = function(display) {\n if (this.displayIndentGuides == display)\n return false;\n\n this.displayIndentGuides = display;\n this.$computeTabString();\n return true;\n };\n\n this.$tabStrings = [];\n this.onChangeTabSize =\n this.$computeTabString = function() {\n var tabSize = this.session.getTabSize();\n this.tabSize = tabSize;\n var tabStr = this.$tabStrings = [0];\n for (var i = 1; i < tabSize + 1; i++) {\n if (this.showInvisibles) {\n tabStr.push(\"\"\n + lang.stringRepeat(this.TAB_CHAR, i)\n + \"\");\n } else {\n tabStr.push(lang.stringRepeat(\" \", i));\n }\n }\n if (this.displayIndentGuides) {\n this.$indentGuideRe = /\\s\\S| \\t|\\t |\\s$/;\n var className = \"ace_indent-guide\";\n var spaceClass = \"\";\n var tabClass = \"\";\n if (this.showInvisibles) {\n className += \" ace_invisible\";\n spaceClass = \" ace_invisible_space\";\n tabClass = \" ace_invisible_tab\";\n var spaceContent = lang.stringRepeat(this.SPACE_CHAR, this.tabSize);\n var tabContent = lang.stringRepeat(this.TAB_CHAR, this.tabSize);\n } else{\n var spaceContent = lang.stringRepeat(\" \", this.tabSize);\n var tabContent = spaceContent;\n }\n\n this.$tabStrings[\" \"] = \"\" + spaceContent + \"\";\n this.$tabStrings[\"\\t\"] = \"\" + tabContent + \"\";\n }\n };\n\n this.updateLines = function(config, firstRow, lastRow) {\n if (this.config.lastRow != config.lastRow ||\n this.config.firstRow != config.firstRow) {\n this.scrollLines(config);\n }\n this.config = config;\n\n var first = Math.max(firstRow, config.firstRow);\n var last = Math.min(lastRow, config.lastRow);\n\n var lineElements = this.element.childNodes;\n var lineElementsIdx = 0;\n\n for (var row = config.firstRow; row < first; row++) {\n var foldLine = this.session.getFoldLine(row);\n if (foldLine) {\n if (foldLine.containsRow(first)) {\n first = foldLine.start.row;\n break;\n } else {\n row = foldLine.end.row;\n }\n }\n lineElementsIdx ++;\n }\n\n var row = first;\n var foldLine = this.session.getNextFoldLine(row);\n var foldStart = foldLine ? foldLine.start.row : Infinity;\n\n while (true) {\n if (row > foldStart) {\n row = foldLine.end.row+1;\n foldLine = this.session.getNextFoldLine(row, foldLine);\n foldStart = foldLine ? foldLine.start.row :Infinity;\n }\n if (row > last)\n break;\n\n var lineElement = lineElements[lineElementsIdx++];\n if (lineElement) {\n var html = [];\n this.$renderLine(\n html, row, !this.$useLineGroups(), row == foldStart ? foldLine : false\n );\n lineElement.style.height = config.lineHeight * this.session.getRowLength(row) + \"px\";\n lineElement.innerHTML = html.join(\"\");\n }\n row++;\n }\n };\n\n this.scrollLines = function(config) {\n var oldConfig = this.config;\n this.config = config;\n\n if (!oldConfig || oldConfig.lastRow < config.firstRow)\n return this.update(config);\n\n if (config.lastRow < oldConfig.firstRow)\n return this.update(config);\n\n var el = this.element;\n if (oldConfig.firstRow < config.firstRow)\n for (var row=this.session.getFoldedRowCount(oldConfig.firstRow, config.firstRow - 1); row>0; row--)\n el.removeChild(el.firstChild);\n\n if (oldConfig.lastRow > config.lastRow)\n for (var row=this.session.getFoldedRowCount(config.lastRow + 1, oldConfig.lastRow); row>0; row--)\n el.removeChild(el.lastChild);\n\n if (config.firstRow < oldConfig.firstRow) {\n var fragment = this.$renderLinesFragment(config, config.firstRow, oldConfig.firstRow - 1);\n if (el.firstChild)\n el.insertBefore(fragment, el.firstChild);\n else\n el.appendChild(fragment);\n }\n\n if (config.lastRow > oldConfig.lastRow) {\n var fragment = this.$renderLinesFragment(config, oldConfig.lastRow + 1, config.lastRow);\n el.appendChild(fragment);\n }\n };\n\n this.$renderLinesFragment = function(config, firstRow, lastRow) {\n var fragment = this.element.ownerDocument.createDocumentFragment();\n var row = firstRow;\n var foldLine = this.session.getNextFoldLine(row);\n var foldStart = foldLine ? foldLine.start.row : Infinity;\n\n while (true) {\n if (row > foldStart) {\n row = foldLine.end.row+1;\n foldLine = this.session.getNextFoldLine(row, foldLine);\n foldStart = foldLine ? foldLine.start.row : Infinity;\n }\n if (row > lastRow)\n break;\n\n var container = dom.createElement(\"div\");\n\n var html = [];\n this.$renderLine(html, row, false, row == foldStart ? foldLine : false);\n container.innerHTML = html.join(\"\");\n if (this.$useLineGroups()) {\n container.className = 'ace_line_group';\n fragment.appendChild(container);\n container.style.height = config.lineHeight * this.session.getRowLength(row) + \"px\";\n\n } else {\n while(container.firstChild)\n fragment.appendChild(container.firstChild);\n }\n\n row++;\n }\n return fragment;\n };\n\n this.update = function(config) {\n this.config = config;\n\n var html = [];\n var firstRow = config.firstRow, lastRow = config.lastRow;\n\n var row = firstRow;\n var foldLine = this.session.getNextFoldLine(row);\n var foldStart = foldLine ? foldLine.start.row : Infinity;\n\n while (true) {\n if (row > foldStart) {\n row = foldLine.end.row+1;\n foldLine = this.session.getNextFoldLine(row, foldLine);\n foldStart = foldLine ? foldLine.start.row :Infinity;\n }\n if (row > lastRow)\n break;\n\n if (this.$useLineGroups())\n html.push(\"
\")\n\n this.$renderLine(html, row, false, row == foldStart ? foldLine : false);\n\n if (this.$useLineGroups())\n html.push(\"
\"); // end the line group\n\n row++;\n }\n this.element.innerHTML = html.join(\"\");\n };\n\n this.$textToken = {\n \"text\": true,\n \"rparen\": true,\n \"lparen\": true\n };\n\n this.$renderToken = function(stringBuilder, screenColumn, token, value) {\n var self = this;\n var replaceReg = /\\t|&|<|>|( +)|([\\x00-\\x1f\\x80-\\xa0\\xad\\u1680\\u180E\\u2000-\\u200f\\u2028\\u2029\\u202F\\u205F\\u3000\\uFEFF\\uFFF9-\\uFFFC])|[\\u1100-\\u115F\\u11A3-\\u11A7\\u11FA-\\u11FF\\u2329-\\u232A\\u2E80-\\u2E99\\u2E9B-\\u2EF3\\u2F00-\\u2FD5\\u2FF0-\\u2FFB\\u3000-\\u303E\\u3041-\\u3096\\u3099-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u3190-\\u31BA\\u31C0-\\u31E3\\u31F0-\\u321E\\u3220-\\u3247\\u3250-\\u32FE\\u3300-\\u4DBF\\u4E00-\\uA48C\\uA490-\\uA4C6\\uA960-\\uA97C\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFAFF\\uFE10-\\uFE19\\uFE30-\\uFE52\\uFE54-\\uFE66\\uFE68-\\uFE6B\\uFF01-\\uFF60\\uFFE0-\\uFFE6]/g;\n var replaceFunc = function(c, a, b, tabIdx, idx4) {\n if (a) {\n return self.showInvisibles\n ? \"\" + lang.stringRepeat(self.SPACE_CHAR, c.length) + \"\"\n : c;\n } else if (c == \"&\") {\n return \"&\";\n } else if (c == \"<\") {\n return \"<\";\n } else if (c == \">\") {\n return \">\";\n } else if (c == \"\\t\") {\n var tabSize = self.session.getScreenTabSize(screenColumn + tabIdx);\n screenColumn += tabSize - 1;\n return self.$tabStrings[tabSize];\n } else if (c == \"\\u3000\") {\n var classToUse = self.showInvisibles ? \"ace_cjk ace_invisible ace_invisible_space\" : \"ace_cjk\";\n var space = self.showInvisibles ? self.SPACE_CHAR : \"\";\n screenColumn += 1;\n return \"\" + space + \"\";\n } else if (b) {\n return \"\" + self.SPACE_CHAR + \"\";\n } else {\n screenColumn += 1;\n return \"\" + c + \"\";\n }\n };\n\n var output = value.replace(replaceReg, replaceFunc);\n\n if (!this.$textToken[token.type]) {\n var classes = \"ace_\" + token.type.replace(/\\./g, \" ace_\");\n var style = \"\";\n if (token.type == \"fold\")\n style = \" style='width:\" + (token.value.length * this.config.characterWidth) + \"px;' \";\n stringBuilder.push(\"\", output, \"\");\n }\n else {\n stringBuilder.push(output);\n }\n return screenColumn + value.length;\n };\n\n this.renderIndentGuide = function(stringBuilder, value, max) {\n var cols = value.search(this.$indentGuideRe);\n if (cols <= 0 || cols >= max)\n return value;\n if (value[0] == \" \") {\n cols -= cols % this.tabSize;\n stringBuilder.push(lang.stringRepeat(this.$tabStrings[\" \"], cols/this.tabSize));\n return value.substr(cols);\n } else if (value[0] == \"\\t\") {\n stringBuilder.push(lang.stringRepeat(this.$tabStrings[\"\\t\"], cols));\n return value.substr(cols);\n }\n return value;\n };\n\n this.$renderWrappedLine = function(stringBuilder, tokens, splits, onlyContents) {\n var chars = 0;\n var split = 0;\n var splitChars = splits[0];\n var screenColumn = 0;\n\n for (var i = 0; i < tokens.length; i++) {\n var token = tokens[i];\n var value = token.value;\n if (i == 0 && this.displayIndentGuides) {\n chars = value.length;\n value = this.renderIndentGuide(stringBuilder, value, splitChars);\n if (!value)\n continue;\n chars -= value.length;\n }\n\n if (chars + value.length < splitChars) {\n screenColumn = this.$renderToken(stringBuilder, screenColumn, token, value);\n chars += value.length;\n } else {\n while (chars + value.length >= splitChars) {\n screenColumn = this.$renderToken(\n stringBuilder, screenColumn,\n token, value.substring(0, splitChars - chars)\n );\n value = value.substring(splitChars - chars);\n chars = splitChars;\n\n if (!onlyContents) {\n stringBuilder.push(\"\",\n \"
\"\n );\n }\n\n stringBuilder.push(lang.stringRepeat(\"\\xa0\", splits.indent));\n\n split ++;\n screenColumn = 0;\n splitChars = splits[split] || Number.MAX_VALUE;\n }\n if (value.length != 0) {\n chars += value.length;\n screenColumn = this.$renderToken(\n stringBuilder, screenColumn, token, value\n );\n }\n }\n }\n };\n\n this.$renderSimpleLine = function(stringBuilder, tokens) {\n var screenColumn = 0;\n var token = tokens[0];\n var value = token.value;\n if (this.displayIndentGuides)\n value = this.renderIndentGuide(stringBuilder, value);\n if (value)\n screenColumn = this.$renderToken(stringBuilder, screenColumn, token, value);\n for (var i = 1; i < tokens.length; i++) {\n token = tokens[i];\n value = token.value;\n screenColumn = this.$renderToken(stringBuilder, screenColumn, token, value);\n }\n };\n this.$renderLine = function(stringBuilder, row, onlyContents, foldLine) {\n if (!foldLine && foldLine != false)\n foldLine = this.session.getFoldLine(row);\n\n if (foldLine)\n var tokens = this.$getFoldLineTokens(row, foldLine);\n else\n var tokens = this.session.getTokens(row);\n\n\n if (!onlyContents) {\n stringBuilder.push(\n \"
\"\n );\n }\n\n if (tokens.length) {\n var splits = this.session.getRowSplitData(row);\n if (splits && splits.length)\n this.$renderWrappedLine(stringBuilder, tokens, splits, onlyContents);\n else\n this.$renderSimpleLine(stringBuilder, tokens);\n }\n\n if (this.showInvisibles) {\n if (foldLine)\n row = foldLine.end.row\n\n stringBuilder.push(\n \"\",\n row == this.session.getLength() - 1 ? this.EOF_CHAR : this.EOL_CHAR,\n \"\"\n );\n }\n if (!onlyContents)\n stringBuilder.push(\"
\");\n };\n\n this.$getFoldLineTokens = function(row, foldLine) {\n var session = this.session;\n var renderTokens = [];\n\n function addTokens(tokens, from, to) {\n var idx = 0, col = 0;\n while ((col + tokens[idx].value.length) < from) {\n col += tokens[idx].value.length;\n idx++;\n\n if (idx == tokens.length)\n return;\n }\n if (col != from) {\n var value = tokens[idx].value.substring(from - col);\n if (value.length > (to - from))\n value = value.substring(0, to - from);\n\n renderTokens.push({\n type: tokens[idx].type,\n value: value\n });\n\n col = from + value.length;\n idx += 1;\n }\n\n while (col < to && idx < tokens.length) {\n var value = tokens[idx].value;\n if (value.length + col > to) {\n renderTokens.push({\n type: tokens[idx].type,\n value: value.substring(0, to - col)\n });\n } else\n renderTokens.push(tokens[idx]);\n col += value.length;\n idx += 1;\n }\n }\n\n var tokens = session.getTokens(row);\n foldLine.walk(function(placeholder, row, column, lastColumn, isNewRow) {\n if (placeholder != null) {\n renderTokens.push({\n type: \"fold\",\n value: placeholder\n });\n } else {\n if (isNewRow)\n tokens = session.getTokens(row);\n\n if (tokens.length)\n addTokens(tokens, lastColumn, column);\n }\n }, foldLine.end.row, this.session.getLine(foldLine.end.row).length);\n\n return renderTokens;\n };\n\n this.$useLineGroups = function() {\n return this.session.getUseWrapMode();\n };\n\n this.destroy = function() {\n clearInterval(this.$pollSizeChangesTimer);\n if (this.$measureNode)\n this.$measureNode.parentNode.removeChild(this.$measureNode);\n delete this.$measureNode;\n };\n\n}).call(Text.prototype);\n\nexports.Text = Text;\n\n});\n\nace.define(\"ace/layer/cursor\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar dom = acequire(\"../lib/dom\");\nvar isIE8;\n\nvar Cursor = function(parentEl) {\n this.element = dom.createElement(\"div\");\n this.element.className = \"ace_layer ace_cursor-layer\";\n parentEl.appendChild(this.element);\n \n if (isIE8 === undefined)\n isIE8 = !(\"opacity\" in this.element.style);\n\n this.isVisible = false;\n this.isBlinking = true;\n this.blinkInterval = 1000;\n this.smoothBlinking = false;\n\n this.cursors = [];\n this.cursor = this.addCursor();\n dom.addCssClass(this.element, \"ace_hidden-cursors\");\n this.$updateCursors = (isIE8\n ? this.$updateVisibility\n : this.$updateOpacity).bind(this);\n};\n\n(function() {\n \n this.$updateVisibility = function(val) {\n var cursors = this.cursors;\n for (var i = cursors.length; i--; )\n cursors[i].style.visibility = val ? \"\" : \"hidden\";\n };\n this.$updateOpacity = function(val) {\n var cursors = this.cursors;\n for (var i = cursors.length; i--; )\n cursors[i].style.opacity = val ? \"\" : \"0\";\n };\n \n\n this.$padding = 0;\n this.setPadding = function(padding) {\n this.$padding = padding;\n };\n\n this.setSession = function(session) {\n this.session = session;\n };\n\n this.setBlinking = function(blinking) {\n if (blinking != this.isBlinking){\n this.isBlinking = blinking;\n this.restartTimer();\n }\n };\n\n this.setBlinkInterval = function(blinkInterval) {\n if (blinkInterval != this.blinkInterval){\n this.blinkInterval = blinkInterval;\n this.restartTimer();\n }\n };\n\n this.setSmoothBlinking = function(smoothBlinking) {\n if (smoothBlinking != this.smoothBlinking && !isIE8) {\n this.smoothBlinking = smoothBlinking;\n dom.setCssClass(this.element, \"ace_smooth-blinking\", smoothBlinking);\n this.$updateCursors(true);\n this.$updateCursors = (this.$updateOpacity).bind(this);\n this.restartTimer();\n }\n };\n\n this.addCursor = function() {\n var el = dom.createElement(\"div\");\n el.className = \"ace_cursor\";\n this.element.appendChild(el);\n this.cursors.push(el);\n return el;\n };\n\n this.removeCursor = function() {\n if (this.cursors.length > 1) {\n var el = this.cursors.pop();\n el.parentNode.removeChild(el);\n return el;\n }\n };\n\n this.hideCursor = function() {\n this.isVisible = false;\n dom.addCssClass(this.element, \"ace_hidden-cursors\");\n this.restartTimer();\n };\n\n this.showCursor = function() {\n this.isVisible = true;\n dom.removeCssClass(this.element, \"ace_hidden-cursors\");\n this.restartTimer();\n };\n\n this.restartTimer = function() {\n var update = this.$updateCursors;\n clearInterval(this.intervalId);\n clearTimeout(this.timeoutId);\n if (this.smoothBlinking) {\n dom.removeCssClass(this.element, \"ace_smooth-blinking\");\n }\n \n update(true);\n\n if (!this.isBlinking || !this.blinkInterval || !this.isVisible)\n return;\n\n if (this.smoothBlinking) {\n setTimeout(function(){\n dom.addCssClass(this.element, \"ace_smooth-blinking\");\n }.bind(this));\n }\n \n var blink = function(){\n this.timeoutId = setTimeout(function() {\n update(false);\n }, 0.6 * this.blinkInterval);\n }.bind(this);\n\n this.intervalId = setInterval(function() {\n update(true);\n blink();\n }, this.blinkInterval);\n\n blink();\n };\n\n this.getPixelPosition = function(position, onScreen) {\n if (!this.config || !this.session)\n return {left : 0, top : 0};\n\n if (!position)\n position = this.session.selection.getCursor();\n var pos = this.session.documentToScreenPosition(position);\n var cursorLeft = this.$padding + pos.column * this.config.characterWidth;\n var cursorTop = (pos.row - (onScreen ? this.config.firstRowScreen : 0)) *\n this.config.lineHeight;\n\n return {left : cursorLeft, top : cursorTop};\n };\n\n this.update = function(config) {\n this.config = config;\n\n var selections = this.session.$selectionMarkers;\n var i = 0, cursorIndex = 0;\n\n if (selections === undefined || selections.length === 0){\n selections = [{cursor: null}];\n }\n\n for (var i = 0, n = selections.length; i < n; i++) {\n var pixelPos = this.getPixelPosition(selections[i].cursor, true);\n if ((pixelPos.top > config.height + config.offset ||\n pixelPos.top < 0) && i > 1) {\n continue;\n }\n\n var style = (this.cursors[cursorIndex++] || this.addCursor()).style;\n \n if (!this.drawCursor) {\n style.left = pixelPos.left + \"px\";\n style.top = pixelPos.top + \"px\";\n style.width = config.characterWidth + \"px\";\n style.height = config.lineHeight + \"px\";\n } else {\n this.drawCursor(style, pixelPos, config, selections[i], this.session);\n }\n }\n while (this.cursors.length > cursorIndex)\n this.removeCursor();\n\n var overwrite = this.session.getOverwrite();\n this.$setOverwrite(overwrite);\n this.$pixelPos = pixelPos;\n this.restartTimer();\n };\n \n this.drawCursor = null;\n\n this.$setOverwrite = function(overwrite) {\n if (overwrite != this.overwrite) {\n this.overwrite = overwrite;\n if (overwrite)\n dom.addCssClass(this.element, \"ace_overwrite-cursors\");\n else\n dom.removeCssClass(this.element, \"ace_overwrite-cursors\");\n }\n };\n\n this.destroy = function() {\n clearInterval(this.intervalId);\n clearTimeout(this.timeoutId);\n };\n\n}).call(Cursor.prototype);\n\nexports.Cursor = Cursor;\n\n});\n\nace.define(\"ace/scrollbar\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/dom\",\"ace/lib/event\",\"ace/lib/event_emitter\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar oop = acequire(\"./lib/oop\");\nvar dom = acequire(\"./lib/dom\");\nvar event = acequire(\"./lib/event\");\nvar EventEmitter = acequire(\"./lib/event_emitter\").EventEmitter;\nvar ScrollBar = function(parent) {\n this.element = dom.createElement(\"div\");\n this.element.className = \"ace_scrollbar ace_scrollbar\" + this.classSuffix;\n\n this.inner = dom.createElement(\"div\");\n this.inner.className = \"ace_scrollbar-inner\";\n this.element.appendChild(this.inner);\n\n parent.appendChild(this.element);\n\n this.setVisible(false);\n this.skipEvent = false;\n\n event.addListener(this.element, \"scroll\", this.onScroll.bind(this));\n event.addListener(this.element, \"mousedown\", event.preventDefault);\n};\n\n(function() {\n oop.implement(this, EventEmitter);\n\n this.setVisible = function(isVisible) {\n this.element.style.display = isVisible ? \"\" : \"none\";\n this.isVisible = isVisible;\n };\n}).call(ScrollBar.prototype);\nvar VScrollBar = function(parent, renderer) {\n ScrollBar.call(this, parent);\n this.scrollTop = 0;\n renderer.$scrollbarWidth = \n this.width = dom.scrollbarWidth(parent.ownerDocument);\n this.inner.style.width =\n this.element.style.width = (this.width || 15) + 5 + \"px\";\n};\n\noop.inherits(VScrollBar, ScrollBar);\n\n(function() {\n\n this.classSuffix = '-v';\n this.onScroll = function() {\n if (!this.skipEvent) {\n this.scrollTop = this.element.scrollTop;\n this._emit(\"scroll\", {data: this.scrollTop});\n }\n this.skipEvent = false;\n };\n this.getWidth = function() {\n return this.isVisible ? this.width : 0;\n };\n this.setHeight = function(height) {\n this.element.style.height = height + \"px\";\n };\n this.setInnerHeight = function(height) {\n this.inner.style.height = height + \"px\";\n };\n this.setScrollHeight = function(height) {\n this.inner.style.height = height + \"px\";\n };\n this.setScrollTop = function(scrollTop) {\n if (this.scrollTop != scrollTop) {\n this.skipEvent = true;\n this.scrollTop = this.element.scrollTop = scrollTop;\n }\n };\n\n}).call(VScrollBar.prototype);\nvar HScrollBar = function(parent, renderer) {\n ScrollBar.call(this, parent);\n this.scrollLeft = 0;\n this.height = renderer.$scrollbarWidth;\n this.inner.style.height =\n this.element.style.height = (this.height || 15) + 5 + \"px\";\n};\n\noop.inherits(HScrollBar, ScrollBar);\n\n(function() {\n\n this.classSuffix = '-h';\n this.onScroll = function() {\n if (!this.skipEvent) {\n this.scrollLeft = this.element.scrollLeft;\n this._emit(\"scroll\", {data: this.scrollLeft});\n }\n this.skipEvent = false;\n };\n this.getHeight = function() {\n return this.isVisible ? this.height : 0;\n };\n this.setWidth = function(width) {\n this.element.style.width = width + \"px\";\n };\n this.setInnerWidth = function(width) {\n this.inner.style.width = width + \"px\";\n };\n this.setScrollWidth = function(width) {\n this.inner.style.width = width + \"px\";\n };\n this.setScrollLeft = function(scrollLeft) {\n if (this.scrollLeft != scrollLeft) {\n this.skipEvent = true;\n this.scrollLeft = this.element.scrollLeft = scrollLeft;\n }\n };\n\n}).call(HScrollBar.prototype);\n\n\nexports.ScrollBar = VScrollBar; // backward compatibility\nexports.ScrollBarV = VScrollBar; // backward compatibility\nexports.ScrollBarH = HScrollBar; // backward compatibility\n\nexports.VScrollBar = VScrollBar;\nexports.HScrollBar = HScrollBar;\n});\n\nace.define(\"ace/renderloop\",[\"require\",\"exports\",\"module\",\"ace/lib/event\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar event = acequire(\"./lib/event\");\n\n\nvar RenderLoop = function(onRender, win) {\n this.onRender = onRender;\n this.pending = false;\n this.changes = 0;\n this.window = win || window;\n};\n\n(function() {\n\n\n this.schedule = function(change) {\n this.changes = this.changes | change;\n if (!this.pending && this.changes) {\n this.pending = true;\n var _self = this;\n event.nextFrame(function() {\n _self.pending = false;\n var changes;\n while (changes = _self.changes) {\n _self.changes = 0;\n _self.onRender(changes);\n }\n }, this.window);\n }\n };\n\n}).call(RenderLoop.prototype);\n\nexports.RenderLoop = RenderLoop;\n});\n\nace.define(\"ace/layer/font_metrics\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/dom\",\"ace/lib/lang\",\"ace/lib/useragent\",\"ace/lib/event_emitter\"], function(acequire, exports, module) {\n\nvar oop = acequire(\"../lib/oop\");\nvar dom = acequire(\"../lib/dom\");\nvar lang = acequire(\"../lib/lang\");\nvar useragent = acequire(\"../lib/useragent\");\nvar EventEmitter = acequire(\"../lib/event_emitter\").EventEmitter;\n\nvar CHAR_COUNT = 0;\n\nvar FontMetrics = exports.FontMetrics = function(parentEl) {\n this.el = dom.createElement(\"div\");\n this.$setMeasureNodeStyles(this.el.style, true);\n \n this.$main = dom.createElement(\"div\");\n this.$setMeasureNodeStyles(this.$main.style);\n \n this.$measureNode = dom.createElement(\"div\");\n this.$setMeasureNodeStyles(this.$measureNode.style);\n \n \n this.el.appendChild(this.$main);\n this.el.appendChild(this.$measureNode);\n parentEl.appendChild(this.el);\n \n if (!CHAR_COUNT)\n this.$testFractionalRect();\n this.$measureNode.innerHTML = lang.stringRepeat(\"X\", CHAR_COUNT);\n \n this.$characterSize = {width: 0, height: 0};\n this.checkForSizeChanges();\n};\n\n(function() {\n\n oop.implement(this, EventEmitter);\n \n this.$characterSize = {width: 0, height: 0};\n \n this.$testFractionalRect = function() {\n var el = dom.createElement(\"div\");\n this.$setMeasureNodeStyles(el.style);\n el.style.width = \"0.2px\";\n document.documentElement.appendChild(el);\n var w = el.getBoundingClientRect().width;\n if (w > 0 && w < 1)\n CHAR_COUNT = 50;\n else\n CHAR_COUNT = 100;\n el.parentNode.removeChild(el);\n };\n \n this.$setMeasureNodeStyles = function(style, isRoot) {\n style.width = style.height = \"auto\";\n style.left = style.top = \"0px\";\n style.visibility = \"hidden\";\n style.position = \"absolute\";\n style.whiteSpace = \"pre\";\n\n if (useragent.isIE < 8) {\n style[\"font-family\"] = \"inherit\";\n } else {\n style.font = \"inherit\";\n }\n style.overflow = isRoot ? \"hidden\" : \"visible\";\n };\n\n this.checkForSizeChanges = function() {\n var size = this.$measureSizes();\n if (size && (this.$characterSize.width !== size.width || this.$characterSize.height !== size.height)) {\n this.$measureNode.style.fontWeight = \"bold\";\n var boldSize = this.$measureSizes();\n this.$measureNode.style.fontWeight = \"\";\n this.$characterSize = size;\n this.charSizes = Object.create(null);\n this.allowBoldFonts = boldSize && boldSize.width === size.width && boldSize.height === size.height;\n this._emit(\"changeCharacterSize\", {data: size});\n }\n };\n\n this.$pollSizeChanges = function() {\n if (this.$pollSizeChangesTimer)\n return this.$pollSizeChangesTimer;\n var self = this;\n return this.$pollSizeChangesTimer = setInterval(function() {\n self.checkForSizeChanges();\n }, 500);\n };\n \n this.setPolling = function(val) {\n if (val) {\n this.$pollSizeChanges();\n } else if (this.$pollSizeChangesTimer) {\n clearInterval(this.$pollSizeChangesTimer);\n this.$pollSizeChangesTimer = 0;\n }\n };\n\n this.$measureSizes = function() {\n if (CHAR_COUNT === 50) {\n var rect = null;\n try { \n rect = this.$measureNode.getBoundingClientRect();\n } catch(e) {\n rect = {width: 0, height:0 };\n }\n var size = {\n height: rect.height,\n width: rect.width / CHAR_COUNT\n };\n } else {\n var size = {\n height: this.$measureNode.clientHeight,\n width: this.$measureNode.clientWidth / CHAR_COUNT\n };\n }\n if (size.width === 0 || size.height === 0)\n return null;\n return size;\n };\n\n this.$measureCharWidth = function(ch) {\n this.$main.innerHTML = lang.stringRepeat(ch, CHAR_COUNT);\n var rect = this.$main.getBoundingClientRect();\n return rect.width / CHAR_COUNT;\n };\n \n this.getCharacterWidth = function(ch) {\n var w = this.charSizes[ch];\n if (w === undefined) {\n w = this.charSizes[ch] = this.$measureCharWidth(ch) / this.$characterSize.width;\n }\n return w;\n };\n\n this.destroy = function() {\n clearInterval(this.$pollSizeChangesTimer);\n if (this.el && this.el.parentNode)\n this.el.parentNode.removeChild(this.el);\n };\n\n}).call(FontMetrics.prototype);\n\n});\n\nace.define(\"ace/virtual_renderer\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/dom\",\"ace/config\",\"ace/lib/useragent\",\"ace/layer/gutter\",\"ace/layer/marker\",\"ace/layer/text\",\"ace/layer/cursor\",\"ace/scrollbar\",\"ace/scrollbar\",\"ace/renderloop\",\"ace/layer/font_metrics\",\"ace/lib/event_emitter\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar oop = acequire(\"./lib/oop\");\nvar dom = acequire(\"./lib/dom\");\nvar config = acequire(\"./config\");\nvar useragent = acequire(\"./lib/useragent\");\nvar GutterLayer = acequire(\"./layer/gutter\").Gutter;\nvar MarkerLayer = acequire(\"./layer/marker\").Marker;\nvar TextLayer = acequire(\"./layer/text\").Text;\nvar CursorLayer = acequire(\"./layer/cursor\").Cursor;\nvar HScrollBar = acequire(\"./scrollbar\").HScrollBar;\nvar VScrollBar = acequire(\"./scrollbar\").VScrollBar;\nvar RenderLoop = acequire(\"./renderloop\").RenderLoop;\nvar FontMetrics = acequire(\"./layer/font_metrics\").FontMetrics;\nvar EventEmitter = acequire(\"./lib/event_emitter\").EventEmitter;\nvar editorCss = \".ace_editor {\\\nposition: relative;\\\noverflow: hidden;\\\nfont: 12px/normal 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace;\\\ndirection: ltr;\\\n}\\\n.ace_scroller {\\\nposition: absolute;\\\noverflow: hidden;\\\ntop: 0;\\\nbottom: 0;\\\nbackground-color: inherit;\\\n-ms-user-select: none;\\\n-moz-user-select: none;\\\n-webkit-user-select: none;\\\nuser-select: none;\\\ncursor: text;\\\n}\\\n.ace_content {\\\nposition: absolute;\\\n-moz-box-sizing: border-box;\\\n-webkit-box-sizing: border-box;\\\nbox-sizing: border-box;\\\nmin-width: 100%;\\\n}\\\n.ace_dragging .ace_scroller:before{\\\nposition: absolute;\\\ntop: 0;\\\nleft: 0;\\\nright: 0;\\\nbottom: 0;\\\ncontent: '';\\\nbackground: rgba(250, 250, 250, 0.01);\\\nz-index: 1000;\\\n}\\\n.ace_dragging.ace_dark .ace_scroller:before{\\\nbackground: rgba(0, 0, 0, 0.01);\\\n}\\\n.ace_selecting, .ace_selecting * {\\\ncursor: text !important;\\\n}\\\n.ace_gutter {\\\nposition: absolute;\\\noverflow : hidden;\\\nwidth: auto;\\\ntop: 0;\\\nbottom: 0;\\\nleft: 0;\\\ncursor: default;\\\nz-index: 4;\\\n-ms-user-select: none;\\\n-moz-user-select: none;\\\n-webkit-user-select: none;\\\nuser-select: none;\\\n}\\\n.ace_gutter-active-line {\\\nposition: absolute;\\\nleft: 0;\\\nright: 0;\\\n}\\\n.ace_scroller.ace_scroll-left {\\\nbox-shadow: 17px 0 16px -16px rgba(0, 0, 0, 0.4) inset;\\\n}\\\n.ace_gutter-cell {\\\npadding-left: 19px;\\\npadding-right: 6px;\\\nbackground-repeat: no-repeat;\\\n}\\\n.ace_gutter-cell.ace_error {\\\nbackground-image: url(\\\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABOFBMVEX/////////QRswFAb/Ui4wFAYwFAYwFAaWGAfDRymzOSH/PxswFAb/SiUwFAYwFAbUPRvjQiDllog5HhHdRybsTi3/Tyv9Tir+Syj/UC3////XurebMBIwFAb/RSHbPx/gUzfdwL3kzMivKBAwFAbbvbnhPx66NhowFAYwFAaZJg8wFAaxKBDZurf/RB6mMxb/SCMwFAYwFAbxQB3+RB4wFAb/Qhy4Oh+4QifbNRcwFAYwFAYwFAb/QRzdNhgwFAYwFAbav7v/Uy7oaE68MBK5LxLewr/r2NXewLswFAaxJw4wFAbkPRy2PyYwFAaxKhLm1tMwFAazPiQwFAaUGAb/QBrfOx3bvrv/VC/maE4wFAbRPBq6MRO8Qynew8Dp2tjfwb0wFAbx6eju5+by6uns4uH9/f36+vr/GkHjAAAAYnRSTlMAGt+64rnWu/bo8eAA4InH3+DwoN7j4eLi4xP99Nfg4+b+/u9B/eDs1MD1mO7+4PHg2MXa347g7vDizMLN4eG+Pv7i5evs/v79yu7S3/DV7/498Yv24eH+4ufQ3Ozu/v7+y13sRqwAAADLSURBVHjaZc/XDsFgGIBhtDrshlitmk2IrbHFqL2pvXf/+78DPokj7+Fz9qpU/9UXJIlhmPaTaQ6QPaz0mm+5gwkgovcV6GZzd5JtCQwgsxoHOvJO15kleRLAnMgHFIESUEPmawB9ngmelTtipwwfASilxOLyiV5UVUyVAfbG0cCPHig+GBkzAENHS0AstVF6bacZIOzgLmxsHbt2OecNgJC83JERmePUYq8ARGkJx6XtFsdddBQgZE2nPR6CICZhawjA4Fb/chv+399kfR+MMMDGOQAAAABJRU5ErkJggg==\\\");\\\nbackground-repeat: no-repeat;\\\nbackground-position: 2px center;\\\n}\\\n.ace_gutter-cell.ace_warning {\\\nbackground-image: url(\\\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAmVBMVEX///8AAAD///8AAAAAAABPSzb/5sAAAAB/blH/73z/ulkAAAAAAAD85pkAAAAAAAACAgP/vGz/rkDerGbGrV7/pkQICAf////e0IsAAAD/oED/qTvhrnUAAAD/yHD/njcAAADuv2r/nz//oTj/p064oGf/zHAAAAA9Nir/tFIAAAD/tlTiuWf/tkIAAACynXEAAAAAAAAtIRW7zBpBAAAAM3RSTlMAABR1m7RXO8Ln31Z36zT+neXe5OzooRDfn+TZ4p3h2hTf4t3k3ucyrN1K5+Xaks52Sfs9CXgrAAAAjklEQVR42o3PbQ+CIBQFYEwboPhSYgoYunIqqLn6/z8uYdH8Vmdnu9vz4WwXgN/xTPRD2+sgOcZjsge/whXZgUaYYvT8QnuJaUrjrHUQreGczuEafQCO/SJTufTbroWsPgsllVhq3wJEk2jUSzX3CUEDJC84707djRc5MTAQxoLgupWRwW6UB5fS++NV8AbOZgnsC7BpEAAAAABJRU5ErkJggg==\\\");\\\nbackground-position: 2px center;\\\n}\\\n.ace_gutter-cell.ace_info {\\\nbackground-image: url(\\\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAJ0Uk5TAAB2k804AAAAPklEQVQY02NgIB68QuO3tiLznjAwpKTgNyDbMegwisCHZUETUZV0ZqOquBpXj2rtnpSJT1AEnnRmL2OgGgAAIKkRQap2htgAAAAASUVORK5CYII=\\\");\\\nbackground-position: 2px center;\\\n}\\\n.ace_dark .ace_gutter-cell.ace_info {\\\nbackground-image: url(\\\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAJFBMVEUAAAChoaGAgIAqKiq+vr6tra1ZWVmUlJSbm5s8PDxubm56enrdgzg3AAAAAXRSTlMAQObYZgAAAClJREFUeNpjYMAPdsMYHegyJZFQBlsUlMFVCWUYKkAZMxZAGdxlDMQBAG+TBP4B6RyJAAAAAElFTkSuQmCC\\\");\\\n}\\\n.ace_scrollbar {\\\nposition: absolute;\\\nright: 0;\\\nbottom: 0;\\\nz-index: 6;\\\n}\\\n.ace_scrollbar-inner {\\\nposition: absolute;\\\ncursor: text;\\\nleft: 0;\\\ntop: 0;\\\n}\\\n.ace_scrollbar-v{\\\noverflow-x: hidden;\\\noverflow-y: scroll;\\\ntop: 0;\\\n}\\\n.ace_scrollbar-h {\\\noverflow-x: scroll;\\\noverflow-y: hidden;\\\nleft: 0;\\\n}\\\n.ace_print-margin {\\\nposition: absolute;\\\nheight: 100%;\\\n}\\\n.ace_text-input {\\\nposition: absolute;\\\nz-index: 0;\\\nwidth: 0.5em;\\\nheight: 1em;\\\nopacity: 0;\\\nbackground: transparent;\\\n-moz-appearance: none;\\\nappearance: none;\\\nborder: none;\\\nresize: none;\\\noutline: none;\\\noverflow: hidden;\\\nfont: inherit;\\\npadding: 0 1px;\\\nmargin: 0 -1px;\\\ntext-indent: -1em;\\\n-ms-user-select: text;\\\n-moz-user-select: text;\\\n-webkit-user-select: text;\\\nuser-select: text;\\\nwhite-space: pre!important;\\\n}\\\n.ace_text-input.ace_composition {\\\nbackground: inherit;\\\ncolor: inherit;\\\nz-index: 1000;\\\nopacity: 1;\\\ntext-indent: 0;\\\n}\\\n.ace_layer {\\\nz-index: 1;\\\nposition: absolute;\\\noverflow: hidden;\\\nword-wrap: normal;\\\nwhite-space: pre;\\\nheight: 100%;\\\nwidth: 100%;\\\n-moz-box-sizing: border-box;\\\n-webkit-box-sizing: border-box;\\\nbox-sizing: border-box;\\\npointer-events: none;\\\n}\\\n.ace_gutter-layer {\\\nposition: relative;\\\nwidth: auto;\\\ntext-align: right;\\\npointer-events: auto;\\\n}\\\n.ace_text-layer {\\\nfont: inherit !important;\\\n}\\\n.ace_cjk {\\\ndisplay: inline-block;\\\ntext-align: center;\\\n}\\\n.ace_cursor-layer {\\\nz-index: 4;\\\n}\\\n.ace_cursor {\\\nz-index: 4;\\\nposition: absolute;\\\n-moz-box-sizing: border-box;\\\n-webkit-box-sizing: border-box;\\\nbox-sizing: border-box;\\\nborder-left: 2px solid;\\\ntransform: translatez(0);\\\n}\\\n.ace_slim-cursors .ace_cursor {\\\nborder-left-width: 1px;\\\n}\\\n.ace_overwrite-cursors .ace_cursor {\\\nborder-left-width: 0;\\\nborder-bottom: 1px solid;\\\n}\\\n.ace_hidden-cursors .ace_cursor {\\\nopacity: 0.2;\\\n}\\\n.ace_smooth-blinking .ace_cursor {\\\n-webkit-transition: opacity 0.18s;\\\ntransition: opacity 0.18s;\\\n}\\\n.ace_editor.ace_multiselect .ace_cursor {\\\nborder-left-width: 1px;\\\n}\\\n.ace_marker-layer .ace_step, .ace_marker-layer .ace_stack {\\\nposition: absolute;\\\nz-index: 3;\\\n}\\\n.ace_marker-layer .ace_selection {\\\nposition: absolute;\\\nz-index: 5;\\\n}\\\n.ace_marker-layer .ace_bracket {\\\nposition: absolute;\\\nz-index: 6;\\\n}\\\n.ace_marker-layer .ace_active-line {\\\nposition: absolute;\\\nz-index: 2;\\\n}\\\n.ace_marker-layer .ace_selected-word {\\\nposition: absolute;\\\nz-index: 4;\\\n-moz-box-sizing: border-box;\\\n-webkit-box-sizing: border-box;\\\nbox-sizing: border-box;\\\n}\\\n.ace_line .ace_fold {\\\n-moz-box-sizing: border-box;\\\n-webkit-box-sizing: border-box;\\\nbox-sizing: border-box;\\\ndisplay: inline-block;\\\nheight: 11px;\\\nmargin-top: -2px;\\\nvertical-align: middle;\\\nbackground-image:\\\nurl(\\\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII=\\\"),\\\nurl(\\\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACJJREFUeNpi+P//fxgTAwPDBxDxD078RSX+YeEyDFMCIMAAI3INmXiwf2YAAAAASUVORK5CYII=\\\");\\\nbackground-repeat: no-repeat, repeat-x;\\\nbackground-position: center center, top left;\\\ncolor: transparent;\\\nborder: 1px solid black;\\\nborder-radius: 2px;\\\ncursor: pointer;\\\npointer-events: auto;\\\n}\\\n.ace_dark .ace_fold {\\\n}\\\n.ace_fold:hover{\\\nbackground-image:\\\nurl(\\\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII=\\\"),\\\nurl(\\\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACBJREFUeNpi+P//fz4TAwPDZxDxD5X4i5fLMEwJgAADAEPVDbjNw87ZAAAAAElFTkSuQmCC\\\");\\\n}\\\n.ace_tooltip {\\\nbackground-color: #FFF;\\\nbackground-image: -webkit-linear-gradient(top, transparent, rgba(0, 0, 0, 0.1));\\\nbackground-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1));\\\nborder: 1px solid gray;\\\nborder-radius: 1px;\\\nbox-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);\\\ncolor: black;\\\nmax-width: 100%;\\\npadding: 3px 4px;\\\nposition: fixed;\\\nz-index: 999999;\\\n-moz-box-sizing: border-box;\\\n-webkit-box-sizing: border-box;\\\nbox-sizing: border-box;\\\ncursor: default;\\\nwhite-space: pre;\\\nword-wrap: break-word;\\\nline-height: normal;\\\nfont-style: normal;\\\nfont-weight: normal;\\\nletter-spacing: normal;\\\npointer-events: none;\\\n}\\\n.ace_folding-enabled > .ace_gutter-cell {\\\npadding-right: 13px;\\\n}\\\n.ace_fold-widget {\\\n-moz-box-sizing: border-box;\\\n-webkit-box-sizing: border-box;\\\nbox-sizing: border-box;\\\nmargin: 0 -12px 0 1px;\\\ndisplay: none;\\\nwidth: 11px;\\\nvertical-align: top;\\\nbackground-image: url(\\\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42mWKsQ0AMAzC8ixLlrzQjzmBiEjp0A6WwBCSPgKAXoLkqSot7nN3yMwR7pZ32NzpKkVoDBUxKAAAAABJRU5ErkJggg==\\\");\\\nbackground-repeat: no-repeat;\\\nbackground-position: center;\\\nborder-radius: 3px;\\\nborder: 1px solid transparent;\\\ncursor: pointer;\\\n}\\\n.ace_folding-enabled .ace_fold-widget {\\\ndisplay: inline-block; \\\n}\\\n.ace_fold-widget.ace_end {\\\nbackground-image: url(\\\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42m3HwQkAMAhD0YzsRchFKI7sAikeWkrxwScEB0nh5e7KTPWimZki4tYfVbX+MNl4pyZXejUO1QAAAABJRU5ErkJggg==\\\");\\\n}\\\n.ace_fold-widget.ace_closed {\\\nbackground-image: url(\\\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAGCAYAAAAG5SQMAAAAOUlEQVR42jXKwQkAMAgDwKwqKD4EwQ26sSOkVWjgIIHAzPiCgaqiqnJHZnKICBERHN194O5b9vbLuAVRL+l0YWnZAAAAAElFTkSuQmCCXA==\\\");\\\n}\\\n.ace_fold-widget:hover {\\\nborder: 1px solid rgba(0, 0, 0, 0.3);\\\nbackground-color: rgba(255, 255, 255, 0.2);\\\nbox-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);\\\n}\\\n.ace_fold-widget:active {\\\nborder: 1px solid rgba(0, 0, 0, 0.4);\\\nbackground-color: rgba(0, 0, 0, 0.05);\\\nbox-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);\\\n}\\\n.ace_dark .ace_fold-widget {\\\nbackground-image: url(\\\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHklEQVQIW2P4//8/AzoGEQ7oGCaLLAhWiSwB146BAQCSTPYocqT0AAAAAElFTkSuQmCC\\\");\\\n}\\\n.ace_dark .ace_fold-widget.ace_end {\\\nbackground-image: url(\\\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAH0lEQVQIW2P4//8/AxQ7wNjIAjDMgC4AxjCVKBirIAAF0kz2rlhxpAAAAABJRU5ErkJggg==\\\");\\\n}\\\n.ace_dark .ace_fold-widget.ace_closed {\\\nbackground-image: url(\\\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAHElEQVQIW2P4//+/AxAzgDADlOOAznHAKgPWAwARji8UIDTfQQAAAABJRU5ErkJggg==\\\");\\\n}\\\n.ace_dark .ace_fold-widget:hover {\\\nbox-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);\\\nbackground-color: rgba(255, 255, 255, 0.1);\\\n}\\\n.ace_dark .ace_fold-widget:active {\\\nbox-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);\\\n}\\\n.ace_fold-widget.ace_invalid {\\\nbackground-color: #FFB4B4;\\\nborder-color: #DE5555;\\\n}\\\n.ace_fade-fold-widgets .ace_fold-widget {\\\n-webkit-transition: opacity 0.4s ease 0.05s;\\\ntransition: opacity 0.4s ease 0.05s;\\\nopacity: 0;\\\n}\\\n.ace_fade-fold-widgets:hover .ace_fold-widget {\\\n-webkit-transition: opacity 0.05s ease 0.05s;\\\ntransition: opacity 0.05s ease 0.05s;\\\nopacity:1;\\\n}\\\n.ace_underline {\\\ntext-decoration: underline;\\\n}\\\n.ace_bold {\\\nfont-weight: bold;\\\n}\\\n.ace_nobold .ace_bold {\\\nfont-weight: normal;\\\n}\\\n.ace_italic {\\\nfont-style: italic;\\\n}\\\n.ace_error-marker {\\\nbackground-color: rgba(255, 0, 0,0.2);\\\nposition: absolute;\\\nz-index: 9;\\\n}\\\n.ace_highlight-marker {\\\nbackground-color: rgba(255, 255, 0,0.2);\\\nposition: absolute;\\\nz-index: 8;\\\n}\\\n.ace_br1 {border-top-left-radius : 3px;}\\\n.ace_br2 {border-top-right-radius : 3px;}\\\n.ace_br3 {border-top-left-radius : 3px; border-top-right-radius: 3px;}\\\n.ace_br4 {border-bottom-right-radius: 3px;}\\\n.ace_br5 {border-top-left-radius : 3px; border-bottom-right-radius: 3px;}\\\n.ace_br6 {border-top-right-radius : 3px; border-bottom-right-radius: 3px;}\\\n.ace_br7 {border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px;}\\\n.ace_br8 {border-bottom-left-radius : 3px;}\\\n.ace_br9 {border-top-left-radius : 3px; border-bottom-left-radius: 3px;}\\\n.ace_br10{border-top-right-radius : 3px; border-bottom-left-radius: 3px;}\\\n.ace_br11{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-left-radius: 3px;}\\\n.ace_br12{border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}\\\n.ace_br13{border-top-left-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}\\\n.ace_br14{border-top-right-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}\\\n.ace_br15{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}\\\n\";\n\ndom.importCssString(editorCss, \"ace_editor.css\");\n\nvar VirtualRenderer = function(container, theme) {\n var _self = this;\n\n this.container = container || dom.createElement(\"div\");\n this.$keepTextAreaAtCursor = !useragent.isOldIE;\n\n dom.addCssClass(this.container, \"ace_editor\");\n\n this.setTheme(theme);\n\n this.$gutter = dom.createElement(\"div\");\n this.$gutter.className = \"ace_gutter\";\n this.container.appendChild(this.$gutter);\n\n this.scroller = dom.createElement(\"div\");\n this.scroller.className = \"ace_scroller\";\n this.container.appendChild(this.scroller);\n\n this.content = dom.createElement(\"div\");\n this.content.className = \"ace_content\";\n this.scroller.appendChild(this.content);\n\n this.$gutterLayer = new GutterLayer(this.$gutter);\n this.$gutterLayer.on(\"changeGutterWidth\", this.onGutterResize.bind(this));\n\n this.$markerBack = new MarkerLayer(this.content);\n\n var textLayer = this.$textLayer = new TextLayer(this.content);\n this.canvas = textLayer.element;\n\n this.$markerFront = new MarkerLayer(this.content);\n\n this.$cursorLayer = new CursorLayer(this.content);\n this.$horizScroll = false;\n this.$vScroll = false;\n\n this.scrollBar = \n this.scrollBarV = new VScrollBar(this.container, this);\n this.scrollBarH = new HScrollBar(this.container, this);\n this.scrollBarV.addEventListener(\"scroll\", function(e) {\n if (!_self.$scrollAnimation)\n _self.session.setScrollTop(e.data - _self.scrollMargin.top);\n });\n this.scrollBarH.addEventListener(\"scroll\", function(e) {\n if (!_self.$scrollAnimation)\n _self.session.setScrollLeft(e.data - _self.scrollMargin.left);\n });\n\n this.scrollTop = 0;\n this.scrollLeft = 0;\n\n this.cursorPos = {\n row : 0,\n column : 0\n };\n\n this.$fontMetrics = new FontMetrics(this.container);\n this.$textLayer.$setFontMetrics(this.$fontMetrics);\n this.$textLayer.addEventListener(\"changeCharacterSize\", function(e) {\n _self.updateCharacterSize();\n _self.onResize(true, _self.gutterWidth, _self.$size.width, _self.$size.height);\n _self._signal(\"changeCharacterSize\", e);\n });\n\n this.$size = {\n width: 0,\n height: 0,\n scrollerHeight: 0,\n scrollerWidth: 0,\n $dirty: true\n };\n\n this.layerConfig = {\n width : 1,\n padding : 0,\n firstRow : 0,\n firstRowScreen: 0,\n lastRow : 0,\n lineHeight : 0,\n characterWidth : 0,\n minHeight : 1,\n maxHeight : 1,\n offset : 0,\n height : 1,\n gutterOffset: 1\n };\n \n this.scrollMargin = {\n left: 0,\n right: 0,\n top: 0,\n bottom: 0,\n v: 0,\n h: 0\n };\n\n this.$loop = new RenderLoop(\n this.$renderChanges.bind(this),\n this.container.ownerDocument.defaultView\n );\n this.$loop.schedule(this.CHANGE_FULL);\n\n this.updateCharacterSize();\n this.setPadding(4);\n config.resetOptions(this);\n config._emit(\"renderer\", this);\n};\n\n(function() {\n\n this.CHANGE_CURSOR = 1;\n this.CHANGE_MARKER = 2;\n this.CHANGE_GUTTER = 4;\n this.CHANGE_SCROLL = 8;\n this.CHANGE_LINES = 16;\n this.CHANGE_TEXT = 32;\n this.CHANGE_SIZE = 64;\n this.CHANGE_MARKER_BACK = 128;\n this.CHANGE_MARKER_FRONT = 256;\n this.CHANGE_FULL = 512;\n this.CHANGE_H_SCROLL = 1024;\n\n oop.implement(this, EventEmitter);\n\n this.updateCharacterSize = function() {\n if (this.$textLayer.allowBoldFonts != this.$allowBoldFonts) {\n this.$allowBoldFonts = this.$textLayer.allowBoldFonts;\n this.setStyle(\"ace_nobold\", !this.$allowBoldFonts);\n }\n\n this.layerConfig.characterWidth =\n this.characterWidth = this.$textLayer.getCharacterWidth();\n this.layerConfig.lineHeight =\n this.lineHeight = this.$textLayer.getLineHeight();\n this.$updatePrintMargin();\n };\n this.setSession = function(session) {\n if (this.session)\n this.session.doc.off(\"changeNewLineMode\", this.onChangeNewLineMode);\n \n this.session = session;\n if (session && this.scrollMargin.top && session.getScrollTop() <= 0)\n session.setScrollTop(-this.scrollMargin.top);\n\n this.$cursorLayer.setSession(session);\n this.$markerBack.setSession(session);\n this.$markerFront.setSession(session);\n this.$gutterLayer.setSession(session);\n this.$textLayer.setSession(session);\n if (!session)\n return;\n \n this.$loop.schedule(this.CHANGE_FULL);\n this.session.$setFontMetrics(this.$fontMetrics);\n \n this.onChangeNewLineMode = this.onChangeNewLineMode.bind(this);\n this.onChangeNewLineMode()\n this.session.doc.on(\"changeNewLineMode\", this.onChangeNewLineMode);\n };\n this.updateLines = function(firstRow, lastRow, force) {\n if (lastRow === undefined)\n lastRow = Infinity;\n\n if (!this.$changedLines) {\n this.$changedLines = {\n firstRow: firstRow,\n lastRow: lastRow\n };\n }\n else {\n if (this.$changedLines.firstRow > firstRow)\n this.$changedLines.firstRow = firstRow;\n\n if (this.$changedLines.lastRow < lastRow)\n this.$changedLines.lastRow = lastRow;\n }\n if (this.$changedLines.lastRow < this.layerConfig.firstRow) {\n if (force)\n this.$changedLines.lastRow = this.layerConfig.lastRow;\n else\n return;\n }\n if (this.$changedLines.firstRow > this.layerConfig.lastRow)\n return;\n this.$loop.schedule(this.CHANGE_LINES);\n };\n\n this.onChangeNewLineMode = function() {\n this.$loop.schedule(this.CHANGE_TEXT);\n this.$textLayer.$updateEolChar();\n };\n \n this.onChangeTabSize = function() {\n this.$loop.schedule(this.CHANGE_TEXT | this.CHANGE_MARKER);\n this.$textLayer.onChangeTabSize();\n };\n this.updateText = function() {\n this.$loop.schedule(this.CHANGE_TEXT);\n };\n this.updateFull = function(force) {\n if (force)\n this.$renderChanges(this.CHANGE_FULL, true);\n else\n this.$loop.schedule(this.CHANGE_FULL);\n };\n this.updateFontSize = function() {\n this.$textLayer.checkForSizeChanges();\n };\n\n this.$changes = 0;\n this.$updateSizeAsync = function() {\n if (this.$loop.pending)\n this.$size.$dirty = true;\n else\n this.onResize();\n };\n this.onResize = function(force, gutterWidth, width, height) {\n if (this.resizing > 2)\n return;\n else if (this.resizing > 0)\n this.resizing++;\n else\n this.resizing = force ? 1 : 0;\n var el = this.container;\n if (!height)\n height = el.clientHeight || el.scrollHeight;\n if (!width)\n width = el.clientWidth || el.scrollWidth;\n var changes = this.$updateCachedSize(force, gutterWidth, width, height);\n\n \n if (!this.$size.scrollerHeight || (!width && !height))\n return this.resizing = 0;\n\n if (force)\n this.$gutterLayer.$padding = null;\n\n if (force)\n this.$renderChanges(changes | this.$changes, true);\n else\n this.$loop.schedule(changes | this.$changes);\n\n if (this.resizing)\n this.resizing = 0;\n this.scrollBarV.scrollLeft = this.scrollBarV.scrollTop = null;\n };\n \n this.$updateCachedSize = function(force, gutterWidth, width, height) {\n height -= (this.$extraHeight || 0);\n var changes = 0;\n var size = this.$size;\n var oldSize = {\n width: size.width,\n height: size.height,\n scrollerHeight: size.scrollerHeight,\n scrollerWidth: size.scrollerWidth\n };\n if (height && (force || size.height != height)) {\n size.height = height;\n changes |= this.CHANGE_SIZE;\n\n size.scrollerHeight = size.height;\n if (this.$horizScroll)\n size.scrollerHeight -= this.scrollBarH.getHeight();\n this.scrollBarV.element.style.bottom = this.scrollBarH.getHeight() + \"px\";\n\n changes = changes | this.CHANGE_SCROLL;\n }\n\n if (width && (force || size.width != width)) {\n changes |= this.CHANGE_SIZE;\n size.width = width;\n \n if (gutterWidth == null)\n gutterWidth = this.$showGutter ? this.$gutter.offsetWidth : 0;\n \n this.gutterWidth = gutterWidth;\n \n this.scrollBarH.element.style.left = \n this.scroller.style.left = gutterWidth + \"px\";\n size.scrollerWidth = Math.max(0, width - gutterWidth - this.scrollBarV.getWidth()); \n \n this.scrollBarH.element.style.right = \n this.scroller.style.right = this.scrollBarV.getWidth() + \"px\";\n this.scroller.style.bottom = this.scrollBarH.getHeight() + \"px\";\n\n if (this.session && this.session.getUseWrapMode() && this.adjustWrapLimit() || force)\n changes |= this.CHANGE_FULL;\n }\n \n size.$dirty = !width || !height;\n\n if (changes)\n this._signal(\"resize\", oldSize);\n\n return changes;\n };\n\n this.onGutterResize = function() {\n var gutterWidth = this.$showGutter ? this.$gutter.offsetWidth : 0;\n if (gutterWidth != this.gutterWidth)\n this.$changes |= this.$updateCachedSize(true, gutterWidth, this.$size.width, this.$size.height);\n\n if (this.session.getUseWrapMode() && this.adjustWrapLimit()) {\n this.$loop.schedule(this.CHANGE_FULL);\n } else if (this.$size.$dirty) {\n this.$loop.schedule(this.CHANGE_FULL);\n } else {\n this.$computeLayerConfig();\n this.$loop.schedule(this.CHANGE_MARKER);\n }\n };\n this.adjustWrapLimit = function() {\n var availableWidth = this.$size.scrollerWidth - this.$padding * 2;\n var limit = Math.floor(availableWidth / this.characterWidth);\n return this.session.adjustWrapLimit(limit, this.$showPrintMargin && this.$printMarginColumn);\n };\n this.setAnimatedScroll = function(shouldAnimate){\n this.setOption(\"animatedScroll\", shouldAnimate);\n };\n this.getAnimatedScroll = function() {\n return this.$animatedScroll;\n };\n this.setShowInvisibles = function(showInvisibles) {\n this.setOption(\"showInvisibles\", showInvisibles);\n };\n this.getShowInvisibles = function() {\n return this.getOption(\"showInvisibles\");\n };\n this.getDisplayIndentGuides = function() {\n return this.getOption(\"displayIndentGuides\");\n };\n\n this.setDisplayIndentGuides = function(display) {\n this.setOption(\"displayIndentGuides\", display);\n };\n this.setShowPrintMargin = function(showPrintMargin) {\n this.setOption(\"showPrintMargin\", showPrintMargin);\n };\n this.getShowPrintMargin = function() {\n return this.getOption(\"showPrintMargin\");\n };\n this.setPrintMarginColumn = function(showPrintMargin) {\n this.setOption(\"printMarginColumn\", showPrintMargin);\n };\n this.getPrintMarginColumn = function() {\n return this.getOption(\"printMarginColumn\");\n };\n this.getShowGutter = function(){\n return this.getOption(\"showGutter\");\n };\n this.setShowGutter = function(show){\n return this.setOption(\"showGutter\", show);\n };\n\n this.getFadeFoldWidgets = function(){\n return this.getOption(\"fadeFoldWidgets\")\n };\n\n this.setFadeFoldWidgets = function(show) {\n this.setOption(\"fadeFoldWidgets\", show);\n };\n\n this.setHighlightGutterLine = function(shouldHighlight) {\n this.setOption(\"highlightGutterLine\", shouldHighlight);\n };\n\n this.getHighlightGutterLine = function() {\n return this.getOption(\"highlightGutterLine\");\n };\n\n this.$updateGutterLineHighlight = function() {\n var pos = this.$cursorLayer.$pixelPos;\n var height = this.layerConfig.lineHeight;\n if (this.session.getUseWrapMode()) {\n var cursor = this.session.selection.getCursor();\n cursor.column = 0;\n pos = this.$cursorLayer.getPixelPosition(cursor, true);\n height *= this.session.getRowLength(cursor.row);\n }\n this.$gutterLineHighlight.style.top = pos.top - this.layerConfig.offset + \"px\";\n this.$gutterLineHighlight.style.height = height + \"px\";\n };\n\n this.$updatePrintMargin = function() {\n if (!this.$showPrintMargin && !this.$printMarginEl)\n return;\n\n if (!this.$printMarginEl) {\n var containerEl = dom.createElement(\"div\");\n containerEl.className = \"ace_layer ace_print-margin-layer\";\n this.$printMarginEl = dom.createElement(\"div\");\n this.$printMarginEl.className = \"ace_print-margin\";\n containerEl.appendChild(this.$printMarginEl);\n this.content.insertBefore(containerEl, this.content.firstChild);\n }\n\n var style = this.$printMarginEl.style;\n style.left = ((this.characterWidth * this.$printMarginColumn) + this.$padding) + \"px\";\n style.visibility = this.$showPrintMargin ? \"visible\" : \"hidden\";\n \n if (this.session && this.session.$wrap == -1)\n this.adjustWrapLimit();\n };\n this.getContainerElement = function() {\n return this.container;\n };\n this.getMouseEventTarget = function() {\n return this.scroller;\n };\n this.getTextAreaContainer = function() {\n return this.container;\n };\n this.$moveTextAreaToCursor = function() {\n if (!this.$keepTextAreaAtCursor)\n return;\n var config = this.layerConfig;\n var posTop = this.$cursorLayer.$pixelPos.top;\n var posLeft = this.$cursorLayer.$pixelPos.left;\n posTop -= config.offset;\n\n var style = this.textarea.style;\n var h = this.lineHeight;\n if (posTop < 0 || posTop > config.height - h) {\n style.top = style.left = \"0\";\n return;\n }\n\n var w = this.characterWidth;\n if (this.$composition) {\n var val = this.textarea.value.replace(/^\\x01+/, \"\");\n w *= (this.session.$getStringScreenWidth(val)[0]+2);\n h += 2;\n }\n posLeft -= this.scrollLeft;\n if (posLeft > this.$size.scrollerWidth - w)\n posLeft = this.$size.scrollerWidth - w;\n\n posLeft += this.gutterWidth;\n style.height = h + \"px\";\n style.width = w + \"px\";\n style.left = Math.min(posLeft, this.$size.scrollerWidth - w) + \"px\";\n style.top = Math.min(posTop, this.$size.height - h) + \"px\";\n };\n this.getFirstVisibleRow = function() {\n return this.layerConfig.firstRow;\n };\n this.getFirstFullyVisibleRow = function() {\n return this.layerConfig.firstRow + (this.layerConfig.offset === 0 ? 0 : 1);\n };\n this.getLastFullyVisibleRow = function() {\n var config = this.layerConfig;\n var lastRow = config.lastRow\n var top = this.session.documentToScreenRow(lastRow, 0) * config.lineHeight;\n if (top - this.session.getScrollTop() > config.height - config.lineHeight)\n return lastRow - 1;\n return lastRow;\n };\n this.getLastVisibleRow = function() {\n return this.layerConfig.lastRow;\n };\n\n this.$padding = null;\n this.setPadding = function(padding) {\n this.$padding = padding;\n this.$textLayer.setPadding(padding);\n this.$cursorLayer.setPadding(padding);\n this.$markerFront.setPadding(padding);\n this.$markerBack.setPadding(padding);\n this.$loop.schedule(this.CHANGE_FULL);\n this.$updatePrintMargin();\n };\n \n this.setScrollMargin = function(top, bottom, left, right) {\n var sm = this.scrollMargin;\n sm.top = top|0;\n sm.bottom = bottom|0;\n sm.right = right|0;\n sm.left = left|0;\n sm.v = sm.top + sm.bottom;\n sm.h = sm.left + sm.right;\n if (sm.top && this.scrollTop <= 0 && this.session)\n this.session.setScrollTop(-sm.top);\n this.updateFull();\n };\n this.getHScrollBarAlwaysVisible = function() {\n return this.$hScrollBarAlwaysVisible;\n };\n this.setHScrollBarAlwaysVisible = function(alwaysVisible) {\n this.setOption(\"hScrollBarAlwaysVisible\", alwaysVisible);\n };\n this.getVScrollBarAlwaysVisible = function() {\n return this.$vScrollBarAlwaysVisible;\n };\n this.setVScrollBarAlwaysVisible = function(alwaysVisible) {\n this.setOption(\"vScrollBarAlwaysVisible\", alwaysVisible);\n };\n\n this.$updateScrollBarV = function() {\n var scrollHeight = this.layerConfig.maxHeight;\n var scrollerHeight = this.$size.scrollerHeight;\n if (!this.$maxLines && this.$scrollPastEnd) {\n scrollHeight -= (scrollerHeight - this.lineHeight) * this.$scrollPastEnd;\n if (this.scrollTop > scrollHeight - scrollerHeight) {\n scrollHeight = this.scrollTop + scrollerHeight;\n this.scrollBarV.scrollTop = null;\n }\n }\n this.scrollBarV.setScrollHeight(scrollHeight + this.scrollMargin.v);\n this.scrollBarV.setScrollTop(this.scrollTop + this.scrollMargin.top);\n };\n this.$updateScrollBarH = function() {\n this.scrollBarH.setScrollWidth(this.layerConfig.width + 2 * this.$padding + this.scrollMargin.h);\n this.scrollBarH.setScrollLeft(this.scrollLeft + this.scrollMargin.left);\n };\n \n this.$frozen = false;\n this.freeze = function() {\n this.$frozen = true;\n };\n \n this.unfreeze = function() {\n this.$frozen = false;\n };\n\n this.$renderChanges = function(changes, force) {\n if (this.$changes) {\n changes |= this.$changes;\n this.$changes = 0;\n }\n if ((!this.session || !this.container.offsetWidth || this.$frozen) || (!changes && !force)) {\n this.$changes |= changes;\n return; \n } \n if (this.$size.$dirty) {\n this.$changes |= changes;\n return this.onResize(true);\n }\n if (!this.lineHeight) {\n this.$textLayer.checkForSizeChanges();\n }\n \n this._signal(\"beforeRender\");\n var config = this.layerConfig;\n if (changes & this.CHANGE_FULL ||\n changes & this.CHANGE_SIZE ||\n changes & this.CHANGE_TEXT ||\n changes & this.CHANGE_LINES ||\n changes & this.CHANGE_SCROLL ||\n changes & this.CHANGE_H_SCROLL\n ) {\n changes |= this.$computeLayerConfig();\n if (config.firstRow != this.layerConfig.firstRow && config.firstRowScreen == this.layerConfig.firstRowScreen) {\n var st = this.scrollTop + (config.firstRow - this.layerConfig.firstRow) * this.lineHeight;\n if (st > 0) {\n this.scrollTop = st;\n changes = changes | this.CHANGE_SCROLL;\n changes |= this.$computeLayerConfig();\n }\n }\n config = this.layerConfig;\n this.$updateScrollBarV();\n if (changes & this.CHANGE_H_SCROLL)\n this.$updateScrollBarH();\n this.$gutterLayer.element.style.marginTop = (-config.offset) + \"px\";\n this.content.style.marginTop = (-config.offset) + \"px\";\n this.content.style.width = config.width + 2 * this.$padding + \"px\";\n this.content.style.height = config.minHeight + \"px\";\n }\n if (changes & this.CHANGE_H_SCROLL) {\n this.content.style.marginLeft = -this.scrollLeft + \"px\";\n this.scroller.className = this.scrollLeft <= 0 ? \"ace_scroller\" : \"ace_scroller ace_scroll-left\";\n }\n if (changes & this.CHANGE_FULL) {\n this.$textLayer.update(config);\n if (this.$showGutter)\n this.$gutterLayer.update(config);\n this.$markerBack.update(config);\n this.$markerFront.update(config);\n this.$cursorLayer.update(config);\n this.$moveTextAreaToCursor();\n this.$highlightGutterLine && this.$updateGutterLineHighlight();\n this._signal(\"afterRender\");\n return;\n }\n if (changes & this.CHANGE_SCROLL) {\n if (changes & this.CHANGE_TEXT || changes & this.CHANGE_LINES)\n this.$textLayer.update(config);\n else\n this.$textLayer.scrollLines(config);\n\n if (this.$showGutter)\n this.$gutterLayer.update(config);\n this.$markerBack.update(config);\n this.$markerFront.update(config);\n this.$cursorLayer.update(config);\n this.$highlightGutterLine && this.$updateGutterLineHighlight();\n this.$moveTextAreaToCursor();\n this._signal(\"afterRender\");\n return;\n }\n\n if (changes & this.CHANGE_TEXT) {\n this.$textLayer.update(config);\n if (this.$showGutter)\n this.$gutterLayer.update(config);\n }\n else if (changes & this.CHANGE_LINES) {\n if (this.$updateLines() || (changes & this.CHANGE_GUTTER) && this.$showGutter)\n this.$gutterLayer.update(config);\n }\n else if (changes & this.CHANGE_TEXT || changes & this.CHANGE_GUTTER) {\n if (this.$showGutter)\n this.$gutterLayer.update(config);\n }\n\n if (changes & this.CHANGE_CURSOR) {\n this.$cursorLayer.update(config);\n this.$moveTextAreaToCursor();\n this.$highlightGutterLine && this.$updateGutterLineHighlight();\n }\n\n if (changes & (this.CHANGE_MARKER | this.CHANGE_MARKER_FRONT)) {\n this.$markerFront.update(config);\n }\n\n if (changes & (this.CHANGE_MARKER | this.CHANGE_MARKER_BACK)) {\n this.$markerBack.update(config);\n }\n\n this._signal(\"afterRender\");\n };\n\n \n this.$autosize = function() {\n var height = this.session.getScreenLength() * this.lineHeight;\n var maxHeight = this.$maxLines * this.lineHeight;\n var desiredHeight = Math.max(\n (this.$minLines||1) * this.lineHeight,\n Math.min(maxHeight, height)\n ) + this.scrollMargin.v + (this.$extraHeight || 0);\n if (this.$horizScroll)\n desiredHeight += this.scrollBarH.getHeight();\n var vScroll = height > maxHeight;\n \n if (desiredHeight != this.desiredHeight ||\n this.$size.height != this.desiredHeight || vScroll != this.$vScroll) {\n if (vScroll != this.$vScroll) {\n this.$vScroll = vScroll;\n this.scrollBarV.setVisible(vScroll);\n }\n \n var w = this.container.clientWidth;\n this.container.style.height = desiredHeight + \"px\";\n this.$updateCachedSize(true, this.$gutterWidth, w, desiredHeight);\n this.desiredHeight = desiredHeight;\n \n this._signal(\"autosize\");\n }\n };\n \n this.$computeLayerConfig = function() {\n var session = this.session;\n var size = this.$size;\n \n var hideScrollbars = size.height <= 2 * this.lineHeight;\n var screenLines = this.session.getScreenLength();\n var maxHeight = screenLines * this.lineHeight;\n\n var longestLine = this.$getLongestLine();\n \n var horizScroll = !hideScrollbars && (this.$hScrollBarAlwaysVisible ||\n size.scrollerWidth - longestLine - 2 * this.$padding < 0);\n\n var hScrollChanged = this.$horizScroll !== horizScroll;\n if (hScrollChanged) {\n this.$horizScroll = horizScroll;\n this.scrollBarH.setVisible(horizScroll);\n }\n var vScrollBefore = this.$vScroll; // autosize can change vscroll value in which case we need to update longestLine\n if (this.$maxLines && this.lineHeight > 1)\n this.$autosize();\n\n var offset = this.scrollTop % this.lineHeight;\n var minHeight = size.scrollerHeight + this.lineHeight;\n \n var scrollPastEnd = !this.$maxLines && this.$scrollPastEnd\n ? (size.scrollerHeight - this.lineHeight) * this.$scrollPastEnd\n : 0;\n maxHeight += scrollPastEnd;\n \n var sm = this.scrollMargin;\n this.session.setScrollTop(Math.max(-sm.top,\n Math.min(this.scrollTop, maxHeight - size.scrollerHeight + sm.bottom)));\n\n this.session.setScrollLeft(Math.max(-sm.left, Math.min(this.scrollLeft, \n longestLine + 2 * this.$padding - size.scrollerWidth + sm.right)));\n \n var vScroll = !hideScrollbars && (this.$vScrollBarAlwaysVisible ||\n size.scrollerHeight - maxHeight + scrollPastEnd < 0 || this.scrollTop > sm.top);\n var vScrollChanged = vScrollBefore !== vScroll;\n if (vScrollChanged) {\n this.$vScroll = vScroll;\n this.scrollBarV.setVisible(vScroll);\n }\n\n var lineCount = Math.ceil(minHeight / this.lineHeight) - 1;\n var firstRow = Math.max(0, Math.round((this.scrollTop - offset) / this.lineHeight));\n var lastRow = firstRow + lineCount;\n var firstRowScreen, firstRowHeight;\n var lineHeight = this.lineHeight;\n firstRow = session.screenToDocumentRow(firstRow, 0);\n var foldLine = session.getFoldLine(firstRow);\n if (foldLine) {\n firstRow = foldLine.start.row;\n }\n\n firstRowScreen = session.documentToScreenRow(firstRow, 0);\n firstRowHeight = session.getRowLength(firstRow) * lineHeight;\n\n lastRow = Math.min(session.screenToDocumentRow(lastRow, 0), session.getLength() - 1);\n minHeight = size.scrollerHeight + session.getRowLength(lastRow) * lineHeight +\n firstRowHeight;\n\n offset = this.scrollTop - firstRowScreen * lineHeight;\n\n var changes = 0;\n if (this.layerConfig.width != longestLine) \n changes = this.CHANGE_H_SCROLL;\n if (hScrollChanged || vScrollChanged) {\n changes = this.$updateCachedSize(true, this.gutterWidth, size.width, size.height);\n this._signal(\"scrollbarVisibilityChanged\");\n if (vScrollChanged)\n longestLine = this.$getLongestLine();\n }\n \n this.layerConfig = {\n width : longestLine,\n padding : this.$padding,\n firstRow : firstRow,\n firstRowScreen: firstRowScreen,\n lastRow : lastRow,\n lineHeight : lineHeight,\n characterWidth : this.characterWidth,\n minHeight : minHeight,\n maxHeight : maxHeight,\n offset : offset,\n gutterOffset : Math.max(0, Math.ceil((offset + size.height - size.scrollerHeight) / lineHeight)),\n height : this.$size.scrollerHeight\n };\n\n return changes;\n };\n\n this.$updateLines = function() {\n var firstRow = this.$changedLines.firstRow;\n var lastRow = this.$changedLines.lastRow;\n this.$changedLines = null;\n\n var layerConfig = this.layerConfig;\n\n if (firstRow > layerConfig.lastRow + 1) { return; }\n if (lastRow < layerConfig.firstRow) { return; }\n if (lastRow === Infinity) {\n if (this.$showGutter)\n this.$gutterLayer.update(layerConfig);\n this.$textLayer.update(layerConfig);\n return;\n }\n this.$textLayer.updateLines(layerConfig, firstRow, lastRow);\n return true;\n };\n\n this.$getLongestLine = function() {\n var charCount = this.session.getScreenWidth();\n if (this.showInvisibles && !this.session.$useWrapMode)\n charCount += 1;\n\n return Math.max(this.$size.scrollerWidth - 2 * this.$padding, Math.round(charCount * this.characterWidth));\n };\n this.updateFrontMarkers = function() {\n this.$markerFront.setMarkers(this.session.getMarkers(true));\n this.$loop.schedule(this.CHANGE_MARKER_FRONT);\n };\n this.updateBackMarkers = function() {\n this.$markerBack.setMarkers(this.session.getMarkers());\n this.$loop.schedule(this.CHANGE_MARKER_BACK);\n };\n this.addGutterDecoration = function(row, className){\n this.$gutterLayer.addGutterDecoration(row, className);\n };\n this.removeGutterDecoration = function(row, className){\n this.$gutterLayer.removeGutterDecoration(row, className);\n };\n this.updateBreakpoints = function(rows) {\n this.$loop.schedule(this.CHANGE_GUTTER);\n };\n this.setAnnotations = function(annotations) {\n this.$gutterLayer.setAnnotations(annotations);\n this.$loop.schedule(this.CHANGE_GUTTER);\n };\n this.updateCursor = function() {\n this.$loop.schedule(this.CHANGE_CURSOR);\n };\n this.hideCursor = function() {\n this.$cursorLayer.hideCursor();\n };\n this.showCursor = function() {\n this.$cursorLayer.showCursor();\n };\n\n this.scrollSelectionIntoView = function(anchor, lead, offset) {\n this.scrollCursorIntoView(anchor, offset);\n this.scrollCursorIntoView(lead, offset);\n };\n this.scrollCursorIntoView = function(cursor, offset, $viewMargin) {\n if (this.$size.scrollerHeight === 0)\n return;\n\n var pos = this.$cursorLayer.getPixelPosition(cursor);\n\n var left = pos.left;\n var top = pos.top;\n \n var topMargin = $viewMargin && $viewMargin.top || 0;\n var bottomMargin = $viewMargin && $viewMargin.bottom || 0;\n \n var scrollTop = this.$scrollAnimation ? this.session.getScrollTop() : this.scrollTop;\n \n if (scrollTop + topMargin > top) {\n if (offset && scrollTop + topMargin > top + this.lineHeight)\n top -= offset * this.$size.scrollerHeight;\n if (top === 0)\n top = -this.scrollMargin.top;\n this.session.setScrollTop(top);\n } else if (scrollTop + this.$size.scrollerHeight - bottomMargin < top + this.lineHeight) {\n if (offset && scrollTop + this.$size.scrollerHeight - bottomMargin < top - this.lineHeight)\n top += offset * this.$size.scrollerHeight;\n this.session.setScrollTop(top + this.lineHeight - this.$size.scrollerHeight);\n }\n\n var scrollLeft = this.scrollLeft;\n\n if (scrollLeft > left) {\n if (left < this.$padding + 2 * this.layerConfig.characterWidth)\n left = -this.scrollMargin.left;\n this.session.setScrollLeft(left);\n } else if (scrollLeft + this.$size.scrollerWidth < left + this.characterWidth) {\n this.session.setScrollLeft(Math.round(left + this.characterWidth - this.$size.scrollerWidth));\n } else if (scrollLeft <= this.$padding && left - scrollLeft < this.characterWidth) {\n this.session.setScrollLeft(0);\n }\n };\n this.getScrollTop = function() {\n return this.session.getScrollTop();\n };\n this.getScrollLeft = function() {\n return this.session.getScrollLeft();\n };\n this.getScrollTopRow = function() {\n return this.scrollTop / this.lineHeight;\n };\n this.getScrollBottomRow = function() {\n return Math.max(0, Math.floor((this.scrollTop + this.$size.scrollerHeight) / this.lineHeight) - 1);\n };\n this.scrollToRow = function(row) {\n this.session.setScrollTop(row * this.lineHeight);\n };\n\n this.alignCursor = function(cursor, alignment) {\n if (typeof cursor == \"number\")\n cursor = {row: cursor, column: 0};\n\n var pos = this.$cursorLayer.getPixelPosition(cursor);\n var h = this.$size.scrollerHeight - this.lineHeight;\n var offset = pos.top - h * (alignment || 0);\n\n this.session.setScrollTop(offset);\n return offset;\n };\n\n this.STEPS = 8;\n this.$calcSteps = function(fromValue, toValue){\n var i = 0;\n var l = this.STEPS;\n var steps = [];\n\n var func = function(t, x_min, dx) {\n return dx * (Math.pow(t - 1, 3) + 1) + x_min;\n };\n\n for (i = 0; i < l; ++i)\n steps.push(func(i / this.STEPS, fromValue, toValue - fromValue));\n\n return steps;\n };\n this.scrollToLine = function(line, center, animate, callback) {\n var pos = this.$cursorLayer.getPixelPosition({row: line, column: 0});\n var offset = pos.top;\n if (center)\n offset -= this.$size.scrollerHeight / 2;\n\n var initialScroll = this.scrollTop;\n this.session.setScrollTop(offset);\n if (animate !== false)\n this.animateScrolling(initialScroll, callback);\n };\n\n this.animateScrolling = function(fromValue, callback) {\n var toValue = this.scrollTop;\n if (!this.$animatedScroll)\n return;\n var _self = this;\n \n if (fromValue == toValue)\n return;\n \n if (this.$scrollAnimation) {\n var oldSteps = this.$scrollAnimation.steps;\n if (oldSteps.length) {\n fromValue = oldSteps[0];\n if (fromValue == toValue)\n return;\n }\n }\n \n var steps = _self.$calcSteps(fromValue, toValue);\n this.$scrollAnimation = {from: fromValue, to: toValue, steps: steps};\n\n clearInterval(this.$timer);\n\n _self.session.setScrollTop(steps.shift());\n _self.session.$scrollTop = toValue;\n this.$timer = setInterval(function() {\n if (steps.length) {\n _self.session.setScrollTop(steps.shift());\n _self.session.$scrollTop = toValue;\n } else if (toValue != null) {\n _self.session.$scrollTop = -1;\n _self.session.setScrollTop(toValue);\n toValue = null;\n } else {\n _self.$timer = clearInterval(_self.$timer);\n _self.$scrollAnimation = null;\n callback && callback();\n }\n }, 10);\n };\n this.scrollToY = function(scrollTop) {\n if (this.scrollTop !== scrollTop) {\n this.$loop.schedule(this.CHANGE_SCROLL);\n this.scrollTop = scrollTop;\n }\n };\n this.scrollToX = function(scrollLeft) {\n if (this.scrollLeft !== scrollLeft)\n this.scrollLeft = scrollLeft;\n this.$loop.schedule(this.CHANGE_H_SCROLL);\n };\n this.scrollTo = function(x, y) {\n this.session.setScrollTop(y);\n this.session.setScrollLeft(y);\n };\n this.scrollBy = function(deltaX, deltaY) {\n deltaY && this.session.setScrollTop(this.session.getScrollTop() + deltaY);\n deltaX && this.session.setScrollLeft(this.session.getScrollLeft() + deltaX);\n };\n this.isScrollableBy = function(deltaX, deltaY) {\n if (deltaY < 0 && this.session.getScrollTop() >= 1 - this.scrollMargin.top)\n return true;\n if (deltaY > 0 && this.session.getScrollTop() + this.$size.scrollerHeight\n - this.layerConfig.maxHeight < -1 + this.scrollMargin.bottom)\n return true;\n if (deltaX < 0 && this.session.getScrollLeft() >= 1 - this.scrollMargin.left)\n return true;\n if (deltaX > 0 && this.session.getScrollLeft() + this.$size.scrollerWidth\n - this.layerConfig.width < -1 + this.scrollMargin.right)\n return true;\n };\n\n this.pixelToScreenCoordinates = function(x, y) {\n var canvasPos = this.scroller.getBoundingClientRect();\n\n var offset = (x + this.scrollLeft - canvasPos.left - this.$padding) / this.characterWidth;\n var row = Math.floor((y + this.scrollTop - canvasPos.top) / this.lineHeight);\n var col = Math.round(offset);\n\n return {row: row, column: col, side: offset - col > 0 ? 1 : -1};\n };\n\n this.screenToTextCoordinates = function(x, y) {\n var canvasPos = this.scroller.getBoundingClientRect();\n\n var col = Math.round(\n (x + this.scrollLeft - canvasPos.left - this.$padding) / this.characterWidth\n );\n\n var row = (y + this.scrollTop - canvasPos.top) / this.lineHeight;\n\n return this.session.screenToDocumentPosition(row, Math.max(col, 0));\n };\n this.textToScreenCoordinates = function(row, column) {\n var canvasPos = this.scroller.getBoundingClientRect();\n var pos = this.session.documentToScreenPosition(row, column);\n\n var x = this.$padding + Math.round(pos.column * this.characterWidth);\n var y = pos.row * this.lineHeight;\n\n return {\n pageX: canvasPos.left + x - this.scrollLeft,\n pageY: canvasPos.top + y - this.scrollTop\n };\n };\n this.visualizeFocus = function() {\n dom.addCssClass(this.container, \"ace_focus\");\n };\n this.visualizeBlur = function() {\n dom.removeCssClass(this.container, \"ace_focus\");\n };\n this.showComposition = function(position) {\n if (!this.$composition)\n this.$composition = {\n keepTextAreaAtCursor: this.$keepTextAreaAtCursor,\n cssText: this.textarea.style.cssText\n };\n\n this.$keepTextAreaAtCursor = true;\n dom.addCssClass(this.textarea, \"ace_composition\");\n this.textarea.style.cssText = \"\";\n this.$moveTextAreaToCursor();\n };\n this.setCompositionText = function(text) {\n this.$moveTextAreaToCursor();\n };\n this.hideComposition = function() {\n if (!this.$composition)\n return;\n\n dom.removeCssClass(this.textarea, \"ace_composition\");\n this.$keepTextAreaAtCursor = this.$composition.keepTextAreaAtCursor;\n this.textarea.style.cssText = this.$composition.cssText;\n this.$composition = null;\n };\n this.setTheme = function(theme, cb) {\n var _self = this;\n this.$themeId = theme;\n _self._dispatchEvent('themeChange',{theme:theme});\n\n if (!theme || typeof theme == \"string\") {\n var moduleName = theme || this.$options.theme.initialValue;\n config.loadModule([\"theme\", moduleName], afterLoad);\n } else {\n afterLoad(theme);\n }\n\n function afterLoad(module) {\n if (_self.$themeId != theme)\n return cb && cb();\n if (!module.cssClass)\n return;\n dom.importCssString(\n module.cssText,\n module.cssClass,\n _self.container.ownerDocument\n );\n\n if (_self.theme)\n dom.removeCssClass(_self.container, _self.theme.cssClass);\n\n var padding = \"padding\" in module ? module.padding \n : \"padding\" in (_self.theme || {}) ? 4 : _self.$padding;\n if (_self.$padding && padding != _self.$padding)\n _self.setPadding(padding);\n _self.$theme = module.cssClass;\n\n _self.theme = module;\n dom.addCssClass(_self.container, module.cssClass);\n dom.setCssClass(_self.container, \"ace_dark\", module.isDark);\n if (_self.$size) {\n _self.$size.width = 0;\n _self.$updateSizeAsync();\n }\n\n _self._dispatchEvent('themeLoaded', {theme:module});\n cb && cb();\n }\n };\n this.getTheme = function() {\n return this.$themeId;\n };\n this.setStyle = function(style, include) {\n dom.setCssClass(this.container, style, include !== false);\n };\n this.unsetStyle = function(style) {\n dom.removeCssClass(this.container, style);\n };\n \n this.setCursorStyle = function(style) {\n if (this.scroller.style.cursor != style)\n this.scroller.style.cursor = style;\n };\n this.setMouseCursor = function(cursorStyle) {\n this.scroller.style.cursor = cursorStyle;\n };\n this.destroy = function() {\n this.$textLayer.destroy();\n this.$cursorLayer.destroy();\n };\n\n}).call(VirtualRenderer.prototype);\n\n\nconfig.defineOptions(VirtualRenderer.prototype, \"renderer\", {\n animatedScroll: {initialValue: false},\n showInvisibles: {\n set: function(value) {\n if (this.$textLayer.setShowInvisibles(value))\n this.$loop.schedule(this.CHANGE_TEXT);\n },\n initialValue: false\n },\n showPrintMargin: {\n set: function() { this.$updatePrintMargin(); },\n initialValue: true\n },\n printMarginColumn: {\n set: function() { this.$updatePrintMargin(); },\n initialValue: 80\n },\n printMargin: {\n set: function(val) {\n if (typeof val == \"number\")\n this.$printMarginColumn = val;\n this.$showPrintMargin = !!val;\n this.$updatePrintMargin();\n },\n get: function() {\n return this.$showPrintMargin && this.$printMarginColumn; \n }\n },\n showGutter: {\n set: function(show){\n this.$gutter.style.display = show ? \"block\" : \"none\";\n this.$loop.schedule(this.CHANGE_FULL);\n this.onGutterResize();\n },\n initialValue: true\n },\n fadeFoldWidgets: {\n set: function(show) {\n dom.setCssClass(this.$gutter, \"ace_fade-fold-widgets\", show);\n },\n initialValue: false\n },\n showFoldWidgets: {\n set: function(show) {this.$gutterLayer.setShowFoldWidgets(show)},\n initialValue: true\n },\n showLineNumbers: {\n set: function(show) {\n this.$gutterLayer.setShowLineNumbers(show);\n this.$loop.schedule(this.CHANGE_GUTTER);\n },\n initialValue: true\n },\n displayIndentGuides: {\n set: function(show) {\n if (this.$textLayer.setDisplayIndentGuides(show))\n this.$loop.schedule(this.CHANGE_TEXT);\n },\n initialValue: true\n },\n highlightGutterLine: {\n set: function(shouldHighlight) {\n if (!this.$gutterLineHighlight) {\n this.$gutterLineHighlight = dom.createElement(\"div\");\n this.$gutterLineHighlight.className = \"ace_gutter-active-line\";\n this.$gutter.appendChild(this.$gutterLineHighlight);\n return;\n }\n\n this.$gutterLineHighlight.style.display = shouldHighlight ? \"\" : \"none\";\n if (this.$cursorLayer.$pixelPos)\n this.$updateGutterLineHighlight();\n },\n initialValue: false,\n value: true\n },\n hScrollBarAlwaysVisible: {\n set: function(val) {\n if (!this.$hScrollBarAlwaysVisible || !this.$horizScroll)\n this.$loop.schedule(this.CHANGE_SCROLL);\n },\n initialValue: false\n },\n vScrollBarAlwaysVisible: {\n set: function(val) {\n if (!this.$vScrollBarAlwaysVisible || !this.$vScroll)\n this.$loop.schedule(this.CHANGE_SCROLL);\n },\n initialValue: false\n },\n fontSize: {\n set: function(size) {\n if (typeof size == \"number\")\n size = size + \"px\";\n this.container.style.fontSize = size;\n this.updateFontSize();\n },\n initialValue: 12\n },\n fontFamily: {\n set: function(name) {\n this.container.style.fontFamily = name;\n this.updateFontSize();\n }\n },\n maxLines: {\n set: function(val) {\n this.updateFull();\n }\n },\n minLines: {\n set: function(val) {\n this.updateFull();\n }\n },\n scrollPastEnd: {\n set: function(val) {\n val = +val || 0;\n if (this.$scrollPastEnd == val)\n return;\n this.$scrollPastEnd = val;\n this.$loop.schedule(this.CHANGE_SCROLL);\n },\n initialValue: 0,\n handlesSet: true\n },\n fixedWidthGutter: {\n set: function(val) {\n this.$gutterLayer.$fixedWidth = !!val;\n this.$loop.schedule(this.CHANGE_GUTTER);\n }\n },\n theme: {\n set: function(val) { this.setTheme(val) },\n get: function() { return this.$themeId || this.theme; },\n initialValue: \"./theme/textmate\",\n handlesSet: true\n }\n});\n\nexports.VirtualRenderer = VirtualRenderer;\n});\n\nace.define(\"ace/worker/worker_client\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/net\",\"ace/lib/event_emitter\",\"ace/config\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar oop = acequire(\"../lib/oop\");\nvar net = acequire(\"../lib/net\");\nvar EventEmitter = acequire(\"../lib/event_emitter\").EventEmitter;\nvar config = acequire(\"../config\");\n\nvar WorkerClient = function(topLevelNamespaces, mod, classname, workerUrl) {\n this.$sendDeltaQueue = this.$sendDeltaQueue.bind(this);\n this.changeListener = this.changeListener.bind(this);\n this.onMessage = this.onMessage.bind(this);\n if (acequire.nameToUrl && !acequire.toUrl)\n acequire.toUrl = acequire.nameToUrl;\n \n if (config.get(\"packaged\") || !acequire.toUrl) {\n workerUrl = workerUrl || config.moduleUrl(mod.id, \"worker\")\n } else {\n var normalizePath = this.$normalizePath;\n workerUrl = workerUrl || normalizePath(acequire.toUrl(\"ace/worker/worker.js\", null, \"_\"));\n\n var tlns = {};\n topLevelNamespaces.forEach(function(ns) {\n tlns[ns] = normalizePath(acequire.toUrl(ns, null, \"_\").replace(/(\\.js)?(\\?.*)?$/, \"\"));\n });\n }\n\n try {\n var workerSrc = mod.src;\n var Blob = require('w3c-blob');\n var blob = new Blob([ workerSrc ], { type: 'application/javascript' });\n var blobUrl = (window.URL || window.webkitURL).createObjectURL(blob);\n\n this.$worker = new Worker(blobUrl);\n\n } catch(e) {\n if (e instanceof window.DOMException) {\n var blob = this.$workerBlob(workerUrl);\n var URL = window.URL || window.webkitURL;\n var blobURL = URL.createObjectURL(blob);\n\n this.$worker = new Worker(blobURL);\n URL.revokeObjectURL(blobURL);\n } else {\n throw e;\n }\n }\n this.$worker.postMessage({\n init : true,\n tlns : tlns,\n module : mod.id,\n classname : classname\n });\n\n this.callbackId = 1;\n this.callbacks = {};\n\n this.$worker.onmessage = this.onMessage;\n};\n\n(function(){\n\n oop.implement(this, EventEmitter);\n\n this.onMessage = function(e) {\n var msg = e.data;\n switch(msg.type) {\n case \"event\":\n this._signal(msg.name, {data: msg.data});\n break;\n case \"call\":\n var callback = this.callbacks[msg.id];\n if (callback) {\n callback(msg.data);\n delete this.callbacks[msg.id];\n }\n break;\n case \"error\":\n this.reportError(msg.data);\n break;\n case \"log\":\n window.console && console.log && console.log.apply(console, msg.data);\n break;\n }\n };\n \n this.reportError = function(err) {\n window.console && console.error && console.error(err);\n };\n\n this.$normalizePath = function(path) {\n return net.qualifyURL(path);\n };\n\n this.terminate = function() {\n this._signal(\"terminate\", {});\n this.deltaQueue = null;\n this.$worker.terminate();\n this.$worker = null;\n if (this.$doc)\n this.$doc.off(\"change\", this.changeListener);\n this.$doc = null;\n };\n\n this.send = function(cmd, args) {\n this.$worker.postMessage({command: cmd, args: args});\n };\n\n this.call = function(cmd, args, callback) {\n if (callback) {\n var id = this.callbackId++;\n this.callbacks[id] = callback;\n args.push(id);\n }\n this.send(cmd, args);\n };\n\n this.emit = function(event, data) {\n try {\n this.$worker.postMessage({event: event, data: {data: data.data}});\n }\n catch(ex) {\n console.error(ex.stack);\n }\n };\n\n this.attachToDocument = function(doc) {\n if(this.$doc)\n this.terminate();\n\n this.$doc = doc;\n this.call(\"setValue\", [doc.getValue()]);\n doc.on(\"change\", this.changeListener);\n };\n\n this.changeListener = function(delta) {\n if (!this.deltaQueue) {\n this.deltaQueue = [];\n setTimeout(this.$sendDeltaQueue, 0);\n }\n if (delta.action == \"insert\")\n this.deltaQueue.push(delta.start, delta.lines);\n else\n this.deltaQueue.push(delta.start, delta.end);\n };\n\n this.$sendDeltaQueue = function() {\n var q = this.deltaQueue;\n if (!q) return;\n this.deltaQueue = null;\n if (q.length > 50 && q.length > this.$doc.getLength() >> 1) {\n this.call(\"setValue\", [this.$doc.getValue()]);\n } else\n this.emit(\"change\", {data: q});\n };\n\n this.$workerBlob = function(workerUrl) {\n var script = \"importScripts('\" + net.qualifyURL(workerUrl) + \"');\";\n try {\n return new Blob([script], {\"type\": \"application/javascript\"});\n } catch (e) { // Backwards-compatibility\n var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;\n var blobBuilder = new BlobBuilder();\n blobBuilder.append(script);\n return blobBuilder.getBlob(\"application/javascript\");\n }\n };\n\n}).call(WorkerClient.prototype);\n\n\nvar UIWorkerClient = function(topLevelNamespaces, mod, classname) {\n this.$sendDeltaQueue = this.$sendDeltaQueue.bind(this);\n this.changeListener = this.changeListener.bind(this);\n this.callbackId = 1;\n this.callbacks = {};\n this.messageBuffer = [];\n\n var main = null;\n var emitSync = false;\n var sender = Object.create(EventEmitter);\n var _self = this;\n\n this.$worker = {};\n this.$worker.terminate = function() {};\n this.$worker.postMessage = function(e) {\n _self.messageBuffer.push(e);\n if (main) {\n if (emitSync)\n setTimeout(processNext);\n else\n processNext();\n }\n };\n this.setEmitSync = function(val) { emitSync = val };\n\n var processNext = function() {\n var msg = _self.messageBuffer.shift();\n if (msg.command)\n main[msg.command].apply(main, msg.args);\n else if (msg.event)\n sender._signal(msg.event, msg.data);\n };\n\n sender.postMessage = function(msg) {\n _self.onMessage({data: msg});\n };\n sender.callback = function(data, callbackId) {\n this.postMessage({type: \"call\", id: callbackId, data: data});\n };\n sender.emit = function(name, data) {\n this.postMessage({type: \"event\", name: name, data: data});\n };\n\n config.loadModule([\"worker\", mod], function(Main) {\n main = new Main[classname](sender);\n while (_self.messageBuffer.length)\n processNext();\n });\n};\n\nUIWorkerClient.prototype = WorkerClient.prototype;\n\nexports.UIWorkerClient = UIWorkerClient;\nexports.WorkerClient = WorkerClient;\n\n});\n\nace.define(\"ace/placeholder\",[\"require\",\"exports\",\"module\",\"ace/range\",\"ace/lib/event_emitter\",\"ace/lib/oop\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar Range = acequire(\"./range\").Range;\nvar EventEmitter = acequire(\"./lib/event_emitter\").EventEmitter;\nvar oop = acequire(\"./lib/oop\");\n\nvar PlaceHolder = function(session, length, pos, others, mainClass, othersClass) {\n var _self = this;\n this.length = length;\n this.session = session;\n this.doc = session.getDocument();\n this.mainClass = mainClass;\n this.othersClass = othersClass;\n this.$onUpdate = this.onUpdate.bind(this);\n this.doc.on(\"change\", this.$onUpdate);\n this.$others = others;\n \n this.$onCursorChange = function() {\n setTimeout(function() {\n _self.onCursorChange();\n });\n };\n \n this.$pos = pos;\n var undoStack = session.getUndoManager().$undoStack || session.getUndoManager().$undostack || {length: -1};\n this.$undoStackDepth = undoStack.length;\n this.setup();\n\n session.selection.on(\"changeCursor\", this.$onCursorChange);\n};\n\n(function() {\n\n oop.implement(this, EventEmitter);\n this.setup = function() {\n var _self = this;\n var doc = this.doc;\n var session = this.session;\n \n this.selectionBefore = session.selection.toJSON();\n if (session.selection.inMultiSelectMode)\n session.selection.toSingleRange();\n\n this.pos = doc.createAnchor(this.$pos.row, this.$pos.column);\n var pos = this.pos;\n pos.$insertRight = true;\n pos.detach();\n pos.markerId = session.addMarker(new Range(pos.row, pos.column, pos.row, pos.column + this.length), this.mainClass, null, false);\n this.others = [];\n this.$others.forEach(function(other) {\n var anchor = doc.createAnchor(other.row, other.column);\n anchor.$insertRight = true;\n anchor.detach();\n _self.others.push(anchor);\n });\n session.setUndoSelect(false);\n };\n this.showOtherMarkers = function() {\n if (this.othersActive) return;\n var session = this.session;\n var _self = this;\n this.othersActive = true;\n this.others.forEach(function(anchor) {\n anchor.markerId = session.addMarker(new Range(anchor.row, anchor.column, anchor.row, anchor.column+_self.length), _self.othersClass, null, false);\n });\n };\n this.hideOtherMarkers = function() {\n if (!this.othersActive) return;\n this.othersActive = false;\n for (var i = 0; i < this.others.length; i++) {\n this.session.removeMarker(this.others[i].markerId);\n }\n };\n this.onUpdate = function(delta) {\n if (this.$updating)\n return this.updateAnchors(delta);\n \n var range = delta;\n if (range.start.row !== range.end.row) return;\n if (range.start.row !== this.pos.row) return;\n this.$updating = true;\n var lengthDiff = delta.action === \"insert\" ? range.end.column - range.start.column : range.start.column - range.end.column;\n var inMainRange = range.start.column >= this.pos.column && range.start.column <= this.pos.column + this.length + 1;\n var distanceFromStart = range.start.column - this.pos.column;\n \n this.updateAnchors(delta);\n \n if (inMainRange)\n this.length += lengthDiff;\n\n if (inMainRange && !this.session.$fromUndo) {\n if (delta.action === 'insert') {\n for (var i = this.others.length - 1; i >= 0; i--) {\n var otherPos = this.others[i];\n var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart};\n this.doc.insertMergedLines(newPos, delta.lines);\n }\n } else if (delta.action === 'remove') {\n for (var i = this.others.length - 1; i >= 0; i--) {\n var otherPos = this.others[i];\n var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart};\n this.doc.remove(new Range(newPos.row, newPos.column, newPos.row, newPos.column - lengthDiff));\n }\n }\n }\n \n this.$updating = false;\n this.updateMarkers();\n };\n \n this.updateAnchors = function(delta) {\n this.pos.onChange(delta);\n for (var i = this.others.length; i--;)\n this.others[i].onChange(delta);\n this.updateMarkers();\n };\n \n this.updateMarkers = function() {\n if (this.$updating)\n return;\n var _self = this;\n var session = this.session;\n var updateMarker = function(pos, className) {\n session.removeMarker(pos.markerId);\n pos.markerId = session.addMarker(new Range(pos.row, pos.column, pos.row, pos.column+_self.length), className, null, false);\n };\n updateMarker(this.pos, this.mainClass);\n for (var i = this.others.length; i--;)\n updateMarker(this.others[i], this.othersClass);\n };\n\n this.onCursorChange = function(event) {\n if (this.$updating || !this.session) return;\n var pos = this.session.selection.getCursor();\n if (pos.row === this.pos.row && pos.column >= this.pos.column && pos.column <= this.pos.column + this.length) {\n this.showOtherMarkers();\n this._emit(\"cursorEnter\", event);\n } else {\n this.hideOtherMarkers();\n this._emit(\"cursorLeave\", event);\n }\n }; \n this.detach = function() {\n this.session.removeMarker(this.pos && this.pos.markerId);\n this.hideOtherMarkers();\n this.doc.removeEventListener(\"change\", this.$onUpdate);\n this.session.selection.removeEventListener(\"changeCursor\", this.$onCursorChange);\n this.session.setUndoSelect(true);\n this.session = null;\n };\n this.cancel = function() {\n if (this.$undoStackDepth === -1)\n return;\n var undoManager = this.session.getUndoManager();\n var undosRequired = (undoManager.$undoStack || undoManager.$undostack).length - this.$undoStackDepth;\n for (var i = 0; i < undosRequired; i++) {\n undoManager.undo(true);\n }\n if (this.selectionBefore)\n this.session.selection.fromJSON(this.selectionBefore);\n };\n}).call(PlaceHolder.prototype);\n\n\nexports.PlaceHolder = PlaceHolder;\n});\n\nace.define(\"ace/mouse/multi_select_handler\",[\"require\",\"exports\",\"module\",\"ace/lib/event\",\"ace/lib/useragent\"], function(acequire, exports, module) {\n\nvar event = acequire(\"../lib/event\");\nvar useragent = acequire(\"../lib/useragent\");\nfunction isSamePoint(p1, p2) {\n return p1.row == p2.row && p1.column == p2.column;\n}\n\nfunction onMouseDown(e) {\n var ev = e.domEvent;\n var alt = ev.altKey;\n var shift = ev.shiftKey;\n var ctrl = ev.ctrlKey;\n var accel = e.getAccelKey();\n var button = e.getButton();\n \n if (ctrl && useragent.isMac)\n button = ev.button;\n\n if (e.editor.inMultiSelectMode && button == 2) {\n e.editor.textInput.onContextMenu(e.domEvent);\n return;\n }\n \n if (!ctrl && !alt && !accel) {\n if (button === 0 && e.editor.inMultiSelectMode)\n e.editor.exitMultiSelectMode();\n return;\n }\n \n if (button !== 0)\n return;\n\n var editor = e.editor;\n var selection = editor.selection;\n var isMultiSelect = editor.inMultiSelectMode;\n var pos = e.getDocumentPosition();\n var cursor = selection.getCursor();\n var inSelection = e.inSelection() || (selection.isEmpty() && isSamePoint(pos, cursor));\n\n var mouseX = e.x, mouseY = e.y;\n var onMouseSelection = function(e) {\n mouseX = e.clientX;\n mouseY = e.clientY;\n };\n \n var session = editor.session;\n var screenAnchor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY);\n var screenCursor = screenAnchor;\n \n var selectionMode;\n if (editor.$mouseHandler.$enableJumpToDef) {\n if (ctrl && alt || accel && alt)\n selectionMode = shift ? \"block\" : \"add\";\n else if (alt && editor.$blockSelectEnabled)\n selectionMode = \"block\";\n } else {\n if (accel && !alt) {\n selectionMode = \"add\";\n if (!isMultiSelect && shift)\n return;\n } else if (alt && editor.$blockSelectEnabled) {\n selectionMode = \"block\";\n }\n }\n \n if (selectionMode && useragent.isMac && ev.ctrlKey) {\n editor.$mouseHandler.cancelContextMenu();\n }\n\n if (selectionMode == \"add\") {\n if (!isMultiSelect && inSelection)\n return; // dragging\n\n if (!isMultiSelect) {\n var range = selection.toOrientedRange();\n editor.addSelectionMarker(range);\n }\n\n var oldRange = selection.rangeList.rangeAtPoint(pos);\n \n \n editor.$blockScrolling++;\n editor.inVirtualSelectionMode = true;\n \n if (shift) {\n oldRange = null;\n range = selection.ranges[0] || range;\n editor.removeSelectionMarker(range);\n }\n editor.once(\"mouseup\", function() {\n var tmpSel = selection.toOrientedRange();\n\n if (oldRange && tmpSel.isEmpty() && isSamePoint(oldRange.cursor, tmpSel.cursor))\n selection.substractPoint(tmpSel.cursor);\n else {\n if (shift) {\n selection.substractPoint(range.cursor);\n } else if (range) {\n editor.removeSelectionMarker(range);\n selection.addRange(range);\n }\n selection.addRange(tmpSel);\n }\n editor.$blockScrolling--;\n editor.inVirtualSelectionMode = false;\n });\n\n } else if (selectionMode == \"block\") {\n e.stop();\n editor.inVirtualSelectionMode = true; \n var initialRange;\n var rectSel = [];\n var blockSelect = function() {\n var newCursor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY);\n var cursor = session.screenToDocumentPosition(newCursor.row, newCursor.column);\n\n if (isSamePoint(screenCursor, newCursor) && isSamePoint(cursor, selection.lead))\n return;\n screenCursor = newCursor;\n \n editor.$blockScrolling++;\n editor.selection.moveToPosition(cursor);\n editor.renderer.scrollCursorIntoView();\n\n editor.removeSelectionMarkers(rectSel);\n rectSel = selection.rectangularRangeBlock(screenCursor, screenAnchor);\n if (editor.$mouseHandler.$clickSelection && rectSel.length == 1 && rectSel[0].isEmpty())\n rectSel[0] = editor.$mouseHandler.$clickSelection.clone();\n rectSel.forEach(editor.addSelectionMarker, editor);\n editor.updateSelectionMarkers();\n editor.$blockScrolling--;\n };\n editor.$blockScrolling++;\n if (isMultiSelect && !accel) {\n selection.toSingleRange();\n } else if (!isMultiSelect && accel) {\n initialRange = selection.toOrientedRange();\n editor.addSelectionMarker(initialRange);\n }\n \n if (shift)\n screenAnchor = session.documentToScreenPosition(selection.lead); \n else\n selection.moveToPosition(pos);\n editor.$blockScrolling--;\n \n screenCursor = {row: -1, column: -1};\n\n var onMouseSelectionEnd = function(e) {\n clearInterval(timerId);\n editor.removeSelectionMarkers(rectSel);\n if (!rectSel.length)\n rectSel = [selection.toOrientedRange()];\n editor.$blockScrolling++;\n if (initialRange) {\n editor.removeSelectionMarker(initialRange);\n selection.toSingleRange(initialRange);\n }\n for (var i = 0; i < rectSel.length; i++)\n selection.addRange(rectSel[i]);\n editor.inVirtualSelectionMode = false;\n editor.$mouseHandler.$clickSelection = null;\n editor.$blockScrolling--;\n };\n\n var onSelectionInterval = blockSelect;\n\n event.capture(editor.container, onMouseSelection, onMouseSelectionEnd);\n var timerId = setInterval(function() {onSelectionInterval();}, 20);\n\n return e.preventDefault();\n }\n}\n\n\nexports.onMouseDown = onMouseDown;\n\n});\n\nace.define(\"ace/commands/multi_select_commands\",[\"require\",\"exports\",\"module\",\"ace/keyboard/hash_handler\"], function(acequire, exports, module) {\nexports.defaultCommands = [{\n name: \"addCursorAbove\",\n exec: function(editor) { editor.selectMoreLines(-1); },\n bindKey: {win: \"Ctrl-Alt-Up\", mac: \"Ctrl-Alt-Up\"},\n scrollIntoView: \"cursor\",\n readOnly: true\n}, {\n name: \"addCursorBelow\",\n exec: function(editor) { editor.selectMoreLines(1); },\n bindKey: {win: \"Ctrl-Alt-Down\", mac: \"Ctrl-Alt-Down\"},\n scrollIntoView: \"cursor\",\n readOnly: true\n}, {\n name: \"addCursorAboveSkipCurrent\",\n exec: function(editor) { editor.selectMoreLines(-1, true); },\n bindKey: {win: \"Ctrl-Alt-Shift-Up\", mac: \"Ctrl-Alt-Shift-Up\"},\n scrollIntoView: \"cursor\",\n readOnly: true\n}, {\n name: \"addCursorBelowSkipCurrent\",\n exec: function(editor) { editor.selectMoreLines(1, true); },\n bindKey: {win: \"Ctrl-Alt-Shift-Down\", mac: \"Ctrl-Alt-Shift-Down\"},\n scrollIntoView: \"cursor\",\n readOnly: true\n}, {\n name: \"selectMoreBefore\",\n exec: function(editor) { editor.selectMore(-1); },\n bindKey: {win: \"Ctrl-Alt-Left\", mac: \"Ctrl-Alt-Left\"},\n scrollIntoView: \"cursor\",\n readOnly: true\n}, {\n name: \"selectMoreAfter\",\n exec: function(editor) { editor.selectMore(1); },\n bindKey: {win: \"Ctrl-Alt-Right\", mac: \"Ctrl-Alt-Right\"},\n scrollIntoView: \"cursor\",\n readOnly: true\n}, {\n name: \"selectNextBefore\",\n exec: function(editor) { editor.selectMore(-1, true); },\n bindKey: {win: \"Ctrl-Alt-Shift-Left\", mac: \"Ctrl-Alt-Shift-Left\"},\n scrollIntoView: \"cursor\",\n readOnly: true\n}, {\n name: \"selectNextAfter\",\n exec: function(editor) { editor.selectMore(1, true); },\n bindKey: {win: \"Ctrl-Alt-Shift-Right\", mac: \"Ctrl-Alt-Shift-Right\"},\n scrollIntoView: \"cursor\",\n readOnly: true\n}, {\n name: \"splitIntoLines\",\n exec: function(editor) { editor.multiSelect.splitIntoLines(); },\n bindKey: {win: \"Ctrl-Alt-L\", mac: \"Ctrl-Alt-L\"},\n readOnly: true\n}, {\n name: \"alignCursors\",\n exec: function(editor) { editor.alignCursors(); },\n bindKey: {win: \"Ctrl-Alt-A\", mac: \"Ctrl-Alt-A\"},\n scrollIntoView: \"cursor\"\n}, {\n name: \"findAll\",\n exec: function(editor) { editor.findAll(); },\n bindKey: {win: \"Ctrl-Alt-K\", mac: \"Ctrl-Alt-G\"},\n scrollIntoView: \"cursor\",\n readOnly: true\n}];\nexports.multiSelectCommands = [{\n name: \"singleSelection\",\n bindKey: \"esc\",\n exec: function(editor) { editor.exitMultiSelectMode(); },\n scrollIntoView: \"cursor\",\n readOnly: true,\n isAvailable: function(editor) {return editor && editor.inMultiSelectMode}\n}];\n\nvar HashHandler = acequire(\"../keyboard/hash_handler\").HashHandler;\nexports.keyboardHandler = new HashHandler(exports.multiSelectCommands);\n\n});\n\nace.define(\"ace/multi_select\",[\"require\",\"exports\",\"module\",\"ace/range_list\",\"ace/range\",\"ace/selection\",\"ace/mouse/multi_select_handler\",\"ace/lib/event\",\"ace/lib/lang\",\"ace/commands/multi_select_commands\",\"ace/search\",\"ace/edit_session\",\"ace/editor\",\"ace/config\"], function(acequire, exports, module) {\n\nvar RangeList = acequire(\"./range_list\").RangeList;\nvar Range = acequire(\"./range\").Range;\nvar Selection = acequire(\"./selection\").Selection;\nvar onMouseDown = acequire(\"./mouse/multi_select_handler\").onMouseDown;\nvar event = acequire(\"./lib/event\");\nvar lang = acequire(\"./lib/lang\");\nvar commands = acequire(\"./commands/multi_select_commands\");\nexports.commands = commands.defaultCommands.concat(commands.multiSelectCommands);\nvar Search = acequire(\"./search\").Search;\nvar search = new Search();\n\nfunction find(session, needle, dir) {\n search.$options.wrap = true;\n search.$options.needle = needle;\n search.$options.backwards = dir == -1;\n return search.find(session);\n}\nvar EditSession = acequire(\"./edit_session\").EditSession;\n(function() {\n this.getSelectionMarkers = function() {\n return this.$selectionMarkers;\n };\n}).call(EditSession.prototype);\n(function() {\n this.ranges = null;\n this.rangeList = null;\n this.addRange = function(range, $blockChangeEvents) {\n if (!range)\n return;\n\n if (!this.inMultiSelectMode && this.rangeCount === 0) {\n var oldRange = this.toOrientedRange();\n this.rangeList.add(oldRange);\n this.rangeList.add(range);\n if (this.rangeList.ranges.length != 2) {\n this.rangeList.removeAll();\n return $blockChangeEvents || this.fromOrientedRange(range);\n }\n this.rangeList.removeAll();\n this.rangeList.add(oldRange);\n this.$onAddRange(oldRange);\n }\n\n if (!range.cursor)\n range.cursor = range.end;\n\n var removed = this.rangeList.add(range);\n\n this.$onAddRange(range);\n\n if (removed.length)\n this.$onRemoveRange(removed);\n\n if (this.rangeCount > 1 && !this.inMultiSelectMode) {\n this._signal(\"multiSelect\");\n this.inMultiSelectMode = true;\n this.session.$undoSelect = false;\n this.rangeList.attach(this.session);\n }\n\n return $blockChangeEvents || this.fromOrientedRange(range);\n };\n\n this.toSingleRange = function(range) {\n range = range || this.ranges[0];\n var removed = this.rangeList.removeAll();\n if (removed.length)\n this.$onRemoveRange(removed);\n\n range && this.fromOrientedRange(range);\n };\n this.substractPoint = function(pos) {\n var removed = this.rangeList.substractPoint(pos);\n if (removed) {\n this.$onRemoveRange(removed);\n return removed[0];\n }\n };\n this.mergeOverlappingRanges = function() {\n var removed = this.rangeList.merge();\n if (removed.length)\n this.$onRemoveRange(removed);\n else if(this.ranges[0])\n this.fromOrientedRange(this.ranges[0]);\n };\n\n this.$onAddRange = function(range) {\n this.rangeCount = this.rangeList.ranges.length;\n this.ranges.unshift(range);\n this._signal(\"addRange\", {range: range});\n };\n\n this.$onRemoveRange = function(removed) {\n this.rangeCount = this.rangeList.ranges.length;\n if (this.rangeCount == 1 && this.inMultiSelectMode) {\n var lastRange = this.rangeList.ranges.pop();\n removed.push(lastRange);\n this.rangeCount = 0;\n }\n\n for (var i = removed.length; i--; ) {\n var index = this.ranges.indexOf(removed[i]);\n this.ranges.splice(index, 1);\n }\n\n this._signal(\"removeRange\", {ranges: removed});\n\n if (this.rangeCount === 0 && this.inMultiSelectMode) {\n this.inMultiSelectMode = false;\n this._signal(\"singleSelect\");\n this.session.$undoSelect = true;\n this.rangeList.detach(this.session);\n }\n\n lastRange = lastRange || this.ranges[0];\n if (lastRange && !lastRange.isEqual(this.getRange()))\n this.fromOrientedRange(lastRange);\n };\n this.$initRangeList = function() {\n if (this.rangeList)\n return;\n\n this.rangeList = new RangeList();\n this.ranges = [];\n this.rangeCount = 0;\n };\n this.getAllRanges = function() {\n return this.rangeCount ? this.rangeList.ranges.concat() : [this.getRange()];\n };\n\n this.splitIntoLines = function () {\n if (this.rangeCount > 1) {\n var ranges = this.rangeList.ranges;\n var lastRange = ranges[ranges.length - 1];\n var range = Range.fromPoints(ranges[0].start, lastRange.end);\n\n this.toSingleRange();\n this.setSelectionRange(range, lastRange.cursor == lastRange.start);\n } else {\n var range = this.getRange();\n var isBackwards = this.isBackwards();\n var startRow = range.start.row;\n var endRow = range.end.row;\n if (startRow == endRow) {\n if (isBackwards)\n var start = range.end, end = range.start;\n else\n var start = range.start, end = range.end;\n \n this.addRange(Range.fromPoints(end, end));\n this.addRange(Range.fromPoints(start, start));\n return;\n }\n\n var rectSel = [];\n var r = this.getLineRange(startRow, true);\n r.start.column = range.start.column;\n rectSel.push(r);\n\n for (var i = startRow + 1; i < endRow; i++)\n rectSel.push(this.getLineRange(i, true));\n\n r = this.getLineRange(endRow, true);\n r.end.column = range.end.column;\n rectSel.push(r);\n\n rectSel.forEach(this.addRange, this);\n }\n };\n this.toggleBlockSelection = function () {\n if (this.rangeCount > 1) {\n var ranges = this.rangeList.ranges;\n var lastRange = ranges[ranges.length - 1];\n var range = Range.fromPoints(ranges[0].start, lastRange.end);\n\n this.toSingleRange();\n this.setSelectionRange(range, lastRange.cursor == lastRange.start);\n } else {\n var cursor = this.session.documentToScreenPosition(this.selectionLead);\n var anchor = this.session.documentToScreenPosition(this.selectionAnchor);\n\n var rectSel = this.rectangularRangeBlock(cursor, anchor);\n rectSel.forEach(this.addRange, this);\n }\n };\n this.rectangularRangeBlock = function(screenCursor, screenAnchor, includeEmptyLines) {\n var rectSel = [];\n\n var xBackwards = screenCursor.column < screenAnchor.column;\n if (xBackwards) {\n var startColumn = screenCursor.column;\n var endColumn = screenAnchor.column;\n } else {\n var startColumn = screenAnchor.column;\n var endColumn = screenCursor.column;\n }\n\n var yBackwards = screenCursor.row < screenAnchor.row;\n if (yBackwards) {\n var startRow = screenCursor.row;\n var endRow = screenAnchor.row;\n } else {\n var startRow = screenAnchor.row;\n var endRow = screenCursor.row;\n }\n\n if (startColumn < 0)\n startColumn = 0;\n if (startRow < 0)\n startRow = 0;\n\n if (startRow == endRow)\n includeEmptyLines = true;\n\n for (var row = startRow; row <= endRow; row++) {\n var range = Range.fromPoints(\n this.session.screenToDocumentPosition(row, startColumn),\n this.session.screenToDocumentPosition(row, endColumn)\n );\n if (range.isEmpty()) {\n if (docEnd && isSamePoint(range.end, docEnd))\n break;\n var docEnd = range.end;\n }\n range.cursor = xBackwards ? range.start : range.end;\n rectSel.push(range);\n }\n\n if (yBackwards)\n rectSel.reverse();\n\n if (!includeEmptyLines) {\n var end = rectSel.length - 1;\n while (rectSel[end].isEmpty() && end > 0)\n end--;\n if (end > 0) {\n var start = 0;\n while (rectSel[start].isEmpty())\n start++;\n }\n for (var i = end; i >= start; i--) {\n if (rectSel[i].isEmpty())\n rectSel.splice(i, 1);\n }\n }\n\n return rectSel;\n };\n}).call(Selection.prototype);\nvar Editor = acequire(\"./editor\").Editor;\n(function() {\n this.updateSelectionMarkers = function() {\n this.renderer.updateCursor();\n this.renderer.updateBackMarkers();\n };\n this.addSelectionMarker = function(orientedRange) {\n if (!orientedRange.cursor)\n orientedRange.cursor = orientedRange.end;\n\n var style = this.getSelectionStyle();\n orientedRange.marker = this.session.addMarker(orientedRange, \"ace_selection\", style);\n\n this.session.$selectionMarkers.push(orientedRange);\n this.session.selectionMarkerCount = this.session.$selectionMarkers.length;\n return orientedRange;\n };\n this.removeSelectionMarker = function(range) {\n if (!range.marker)\n return;\n this.session.removeMarker(range.marker);\n var index = this.session.$selectionMarkers.indexOf(range);\n if (index != -1)\n this.session.$selectionMarkers.splice(index, 1);\n this.session.selectionMarkerCount = this.session.$selectionMarkers.length;\n };\n\n this.removeSelectionMarkers = function(ranges) {\n var markerList = this.session.$selectionMarkers;\n for (var i = ranges.length; i--; ) {\n var range = ranges[i];\n if (!range.marker)\n continue;\n this.session.removeMarker(range.marker);\n var index = markerList.indexOf(range);\n if (index != -1)\n markerList.splice(index, 1);\n }\n this.session.selectionMarkerCount = markerList.length;\n };\n\n this.$onAddRange = function(e) {\n this.addSelectionMarker(e.range);\n this.renderer.updateCursor();\n this.renderer.updateBackMarkers();\n };\n\n this.$onRemoveRange = function(e) {\n this.removeSelectionMarkers(e.ranges);\n this.renderer.updateCursor();\n this.renderer.updateBackMarkers();\n };\n\n this.$onMultiSelect = function(e) {\n if (this.inMultiSelectMode)\n return;\n this.inMultiSelectMode = true;\n\n this.setStyle(\"ace_multiselect\");\n this.keyBinding.addKeyboardHandler(commands.keyboardHandler);\n this.commands.setDefaultHandler(\"exec\", this.$onMultiSelectExec);\n\n this.renderer.updateCursor();\n this.renderer.updateBackMarkers();\n };\n\n this.$onSingleSelect = function(e) {\n if (this.session.multiSelect.inVirtualMode)\n return;\n this.inMultiSelectMode = false;\n\n this.unsetStyle(\"ace_multiselect\");\n this.keyBinding.removeKeyboardHandler(commands.keyboardHandler);\n\n this.commands.removeDefaultHandler(\"exec\", this.$onMultiSelectExec);\n this.renderer.updateCursor();\n this.renderer.updateBackMarkers();\n this._emit(\"changeSelection\");\n };\n\n this.$onMultiSelectExec = function(e) {\n var command = e.command;\n var editor = e.editor;\n if (!editor.multiSelect)\n return;\n if (!command.multiSelectAction) {\n var result = command.exec(editor, e.args || {});\n editor.multiSelect.addRange(editor.multiSelect.toOrientedRange());\n editor.multiSelect.mergeOverlappingRanges();\n } else if (command.multiSelectAction == \"forEach\") {\n result = editor.forEachSelection(command, e.args);\n } else if (command.multiSelectAction == \"forEachLine\") {\n result = editor.forEachSelection(command, e.args, true);\n } else if (command.multiSelectAction == \"single\") {\n editor.exitMultiSelectMode();\n result = command.exec(editor, e.args || {});\n } else {\n result = command.multiSelectAction(editor, e.args || {});\n }\n return result;\n }; \n this.forEachSelection = function(cmd, args, options) {\n if (this.inVirtualSelectionMode)\n return;\n var keepOrder = options && options.keepOrder;\n var $byLines = options == true || options && options.$byLines\n var session = this.session;\n var selection = this.selection;\n var rangeList = selection.rangeList;\n var ranges = (keepOrder ? selection : rangeList).ranges;\n var result;\n \n if (!ranges.length)\n return cmd.exec ? cmd.exec(this, args || {}) : cmd(this, args || {});\n \n var reg = selection._eventRegistry;\n selection._eventRegistry = {};\n\n var tmpSel = new Selection(session);\n this.inVirtualSelectionMode = true;\n for (var i = ranges.length; i--;) {\n if ($byLines) {\n while (i > 0 && ranges[i].start.row == ranges[i - 1].end.row)\n i--;\n }\n tmpSel.fromOrientedRange(ranges[i]);\n tmpSel.index = i;\n this.selection = session.selection = tmpSel;\n var cmdResult = cmd.exec ? cmd.exec(this, args || {}) : cmd(this, args || {});\n if (!result && cmdResult !== undefined)\n result = cmdResult;\n tmpSel.toOrientedRange(ranges[i]);\n }\n tmpSel.detach();\n\n this.selection = session.selection = selection;\n this.inVirtualSelectionMode = false;\n selection._eventRegistry = reg;\n selection.mergeOverlappingRanges();\n \n var anim = this.renderer.$scrollAnimation;\n this.onCursorChange();\n this.onSelectionChange();\n if (anim && anim.from == anim.to)\n this.renderer.animateScrolling(anim.from);\n \n return result;\n };\n this.exitMultiSelectMode = function() {\n if (!this.inMultiSelectMode || this.inVirtualSelectionMode)\n return;\n this.multiSelect.toSingleRange();\n };\n\n this.getSelectedText = function() {\n var text = \"\";\n if (this.inMultiSelectMode && !this.inVirtualSelectionMode) {\n var ranges = this.multiSelect.rangeList.ranges;\n var buf = [];\n for (var i = 0; i < ranges.length; i++) {\n buf.push(this.session.getTextRange(ranges[i]));\n }\n var nl = this.session.getDocument().getNewLineCharacter();\n text = buf.join(nl);\n if (text.length == (buf.length - 1) * nl.length)\n text = \"\";\n } else if (!this.selection.isEmpty()) {\n text = this.session.getTextRange(this.getSelectionRange());\n }\n return text;\n };\n \n this.$checkMultiselectChange = function(e, anchor) {\n if (this.inMultiSelectMode && !this.inVirtualSelectionMode) {\n var range = this.multiSelect.ranges[0];\n if (this.multiSelect.isEmpty() && anchor == this.multiSelect.anchor)\n return;\n var pos = anchor == this.multiSelect.anchor\n ? range.cursor == range.start ? range.end : range.start\n : range.cursor;\n if (pos.row != anchor.row \n || this.session.$clipPositionToDocument(pos.row, pos.column).column != anchor.column)\n this.multiSelect.toSingleRange(this.multiSelect.toOrientedRange());\n }\n };\n this.findAll = function(needle, options, additive) {\n options = options || {};\n options.needle = needle || options.needle;\n if (options.needle == undefined) {\n var range = this.selection.isEmpty()\n ? this.selection.getWordRange()\n : this.selection.getRange();\n options.needle = this.session.getTextRange(range);\n } \n this.$search.set(options);\n \n var ranges = this.$search.findAll(this.session);\n if (!ranges.length)\n return 0;\n\n this.$blockScrolling += 1;\n var selection = this.multiSelect;\n\n if (!additive)\n selection.toSingleRange(ranges[0]);\n\n for (var i = ranges.length; i--; )\n selection.addRange(ranges[i], true);\n if (range && selection.rangeList.rangeAtPoint(range.start))\n selection.addRange(range, true);\n \n this.$blockScrolling -= 1;\n\n return ranges.length;\n };\n this.selectMoreLines = function(dir, skip) {\n var range = this.selection.toOrientedRange();\n var isBackwards = range.cursor == range.end;\n\n var screenLead = this.session.documentToScreenPosition(range.cursor);\n if (this.selection.$desiredColumn)\n screenLead.column = this.selection.$desiredColumn;\n\n var lead = this.session.screenToDocumentPosition(screenLead.row + dir, screenLead.column);\n\n if (!range.isEmpty()) {\n var screenAnchor = this.session.documentToScreenPosition(isBackwards ? range.end : range.start);\n var anchor = this.session.screenToDocumentPosition(screenAnchor.row + dir, screenAnchor.column);\n } else {\n var anchor = lead;\n }\n\n if (isBackwards) {\n var newRange = Range.fromPoints(lead, anchor);\n newRange.cursor = newRange.start;\n } else {\n var newRange = Range.fromPoints(anchor, lead);\n newRange.cursor = newRange.end;\n }\n\n newRange.desiredColumn = screenLead.column;\n if (!this.selection.inMultiSelectMode) {\n this.selection.addRange(range);\n } else {\n if (skip)\n var toRemove = range.cursor;\n }\n\n this.selection.addRange(newRange);\n if (toRemove)\n this.selection.substractPoint(toRemove);\n };\n this.transposeSelections = function(dir) {\n var session = this.session;\n var sel = session.multiSelect;\n var all = sel.ranges;\n\n for (var i = all.length; i--; ) {\n var range = all[i];\n if (range.isEmpty()) {\n var tmp = session.getWordRange(range.start.row, range.start.column);\n range.start.row = tmp.start.row;\n range.start.column = tmp.start.column;\n range.end.row = tmp.end.row;\n range.end.column = tmp.end.column;\n }\n }\n sel.mergeOverlappingRanges();\n\n var words = [];\n for (var i = all.length; i--; ) {\n var range = all[i];\n words.unshift(session.getTextRange(range));\n }\n\n if (dir < 0)\n words.unshift(words.pop());\n else\n words.push(words.shift());\n\n for (var i = all.length; i--; ) {\n var range = all[i];\n var tmp = range.clone();\n session.replace(range, words[i]);\n range.start.row = tmp.start.row;\n range.start.column = tmp.start.column;\n }\n };\n this.selectMore = function(dir, skip, stopAtFirst) {\n var session = this.session;\n var sel = session.multiSelect;\n\n var range = sel.toOrientedRange();\n if (range.isEmpty()) {\n range = session.getWordRange(range.start.row, range.start.column);\n range.cursor = dir == -1 ? range.start : range.end;\n this.multiSelect.addRange(range);\n if (stopAtFirst)\n return;\n }\n var needle = session.getTextRange(range);\n\n var newRange = find(session, needle, dir);\n if (newRange) {\n newRange.cursor = dir == -1 ? newRange.start : newRange.end;\n this.$blockScrolling += 1;\n this.session.unfold(newRange);\n this.multiSelect.addRange(newRange);\n this.$blockScrolling -= 1;\n this.renderer.scrollCursorIntoView(null, 0.5);\n }\n if (skip)\n this.multiSelect.substractPoint(range.cursor);\n };\n this.alignCursors = function() {\n var session = this.session;\n var sel = session.multiSelect;\n var ranges = sel.ranges;\n var row = -1;\n var sameRowRanges = ranges.filter(function(r) {\n if (r.cursor.row == row)\n return true;\n row = r.cursor.row;\n });\n \n if (!ranges.length || sameRowRanges.length == ranges.length - 1) {\n var range = this.selection.getRange();\n var fr = range.start.row, lr = range.end.row;\n var guessRange = fr == lr;\n if (guessRange) {\n var max = this.session.getLength();\n var line;\n do {\n line = this.session.getLine(lr);\n } while (/[=:]/.test(line) && ++lr < max);\n do {\n line = this.session.getLine(fr);\n } while (/[=:]/.test(line) && --fr > 0);\n \n if (fr < 0) fr = 0;\n if (lr >= max) lr = max - 1;\n }\n var lines = this.session.removeFullLines(fr, lr);\n lines = this.$reAlignText(lines, guessRange);\n this.session.insert({row: fr, column: 0}, lines.join(\"\\n\") + \"\\n\");\n if (!guessRange) {\n range.start.column = 0;\n range.end.column = lines[lines.length - 1].length;\n }\n this.selection.setRange(range);\n } else {\n sameRowRanges.forEach(function(r) {\n sel.substractPoint(r.cursor);\n });\n\n var maxCol = 0;\n var minSpace = Infinity;\n var spaceOffsets = ranges.map(function(r) {\n var p = r.cursor;\n var line = session.getLine(p.row);\n var spaceOffset = line.substr(p.column).search(/\\S/g);\n if (spaceOffset == -1)\n spaceOffset = 0;\n\n if (p.column > maxCol)\n maxCol = p.column;\n if (spaceOffset < minSpace)\n minSpace = spaceOffset;\n return spaceOffset;\n });\n ranges.forEach(function(r, i) {\n var p = r.cursor;\n var l = maxCol - p.column;\n var d = spaceOffsets[i] - minSpace;\n if (l > d)\n session.insert(p, lang.stringRepeat(\" \", l - d));\n else\n session.remove(new Range(p.row, p.column, p.row, p.column - l + d));\n\n r.start.column = r.end.column = maxCol;\n r.start.row = r.end.row = p.row;\n r.cursor = r.end;\n });\n sel.fromOrientedRange(ranges[0]);\n this.renderer.updateCursor();\n this.renderer.updateBackMarkers();\n }\n };\n\n this.$reAlignText = function(lines, forceLeft) {\n var isLeftAligned = true, isRightAligned = true;\n var startW, textW, endW;\n\n return lines.map(function(line) {\n var m = line.match(/(\\s*)(.*?)(\\s*)([=:].*)/);\n if (!m)\n return [line];\n\n if (startW == null) {\n startW = m[1].length;\n textW = m[2].length;\n endW = m[3].length;\n return m;\n }\n\n if (startW + textW + endW != m[1].length + m[2].length + m[3].length)\n isRightAligned = false;\n if (startW != m[1].length)\n isLeftAligned = false;\n\n if (startW > m[1].length)\n startW = m[1].length;\n if (textW < m[2].length)\n textW = m[2].length;\n if (endW > m[3].length)\n endW = m[3].length;\n\n return m;\n }).map(forceLeft ? alignLeft :\n isLeftAligned ? isRightAligned ? alignRight : alignLeft : unAlign);\n\n function spaces(n) {\n return lang.stringRepeat(\" \", n);\n }\n\n function alignLeft(m) {\n return !m[2] ? m[0] : spaces(startW) + m[2]\n + spaces(textW - m[2].length + endW)\n + m[4].replace(/^([=:])\\s+/, \"$1 \");\n }\n function alignRight(m) {\n return !m[2] ? m[0] : spaces(startW + textW - m[2].length) + m[2]\n + spaces(endW, \" \")\n + m[4].replace(/^([=:])\\s+/, \"$1 \");\n }\n function unAlign(m) {\n return !m[2] ? m[0] : spaces(startW) + m[2]\n + spaces(endW)\n + m[4].replace(/^([=:])\\s+/, \"$1 \");\n }\n };\n}).call(Editor.prototype);\n\n\nfunction isSamePoint(p1, p2) {\n return p1.row == p2.row && p1.column == p2.column;\n}\nexports.onSessionChange = function(e) {\n var session = e.session;\n if (session && !session.multiSelect) {\n session.$selectionMarkers = [];\n session.selection.$initRangeList();\n session.multiSelect = session.selection;\n }\n this.multiSelect = session && session.multiSelect;\n\n var oldSession = e.oldSession;\n if (oldSession) {\n oldSession.multiSelect.off(\"addRange\", this.$onAddRange);\n oldSession.multiSelect.off(\"removeRange\", this.$onRemoveRange);\n oldSession.multiSelect.off(\"multiSelect\", this.$onMultiSelect);\n oldSession.multiSelect.off(\"singleSelect\", this.$onSingleSelect);\n oldSession.multiSelect.lead.off(\"change\", this.$checkMultiselectChange);\n oldSession.multiSelect.anchor.off(\"change\", this.$checkMultiselectChange);\n }\n\n if (session) {\n session.multiSelect.on(\"addRange\", this.$onAddRange);\n session.multiSelect.on(\"removeRange\", this.$onRemoveRange);\n session.multiSelect.on(\"multiSelect\", this.$onMultiSelect);\n session.multiSelect.on(\"singleSelect\", this.$onSingleSelect);\n session.multiSelect.lead.on(\"change\", this.$checkMultiselectChange);\n session.multiSelect.anchor.on(\"change\", this.$checkMultiselectChange);\n }\n\n if (session && this.inMultiSelectMode != session.selection.inMultiSelectMode) {\n if (session.selection.inMultiSelectMode)\n this.$onMultiSelect();\n else\n this.$onSingleSelect();\n }\n};\nfunction MultiSelect(editor) {\n if (editor.$multiselectOnSessionChange)\n return;\n editor.$onAddRange = editor.$onAddRange.bind(editor);\n editor.$onRemoveRange = editor.$onRemoveRange.bind(editor);\n editor.$onMultiSelect = editor.$onMultiSelect.bind(editor);\n editor.$onSingleSelect = editor.$onSingleSelect.bind(editor);\n editor.$multiselectOnSessionChange = exports.onSessionChange.bind(editor);\n editor.$checkMultiselectChange = editor.$checkMultiselectChange.bind(editor);\n\n editor.$multiselectOnSessionChange(editor);\n editor.on(\"changeSession\", editor.$multiselectOnSessionChange);\n\n editor.on(\"mousedown\", onMouseDown);\n editor.commands.addCommands(commands.defaultCommands);\n\n addAltCursorListeners(editor);\n}\n\nfunction addAltCursorListeners(editor){\n var el = editor.textInput.getElement();\n var altCursor = false;\n event.addListener(el, \"keydown\", function(e) {\n var altDown = e.keyCode == 18 && !(e.ctrlKey || e.shiftKey || e.metaKey);\n if (editor.$blockSelectEnabled && altDown) {\n if (!altCursor) {\n editor.renderer.setMouseCursor(\"crosshair\");\n altCursor = true;\n }\n } else if (altCursor) {\n reset();\n }\n });\n\n event.addListener(el, \"keyup\", reset);\n event.addListener(el, \"blur\", reset);\n function reset(e) {\n if (altCursor) {\n editor.renderer.setMouseCursor(\"\");\n altCursor = false;\n }\n }\n}\n\nexports.MultiSelect = MultiSelect;\n\n\nacequire(\"./config\").defineOptions(Editor.prototype, \"editor\", {\n enableMultiselect: {\n set: function(val) {\n MultiSelect(this);\n if (val) {\n this.on(\"changeSession\", this.$multiselectOnSessionChange);\n this.on(\"mousedown\", onMouseDown);\n } else {\n this.off(\"changeSession\", this.$multiselectOnSessionChange);\n this.off(\"mousedown\", onMouseDown);\n }\n },\n value: true\n },\n enableBlockSelect: {\n set: function(val) {\n this.$blockSelectEnabled = val;\n },\n value: true\n }\n});\n\n\n\n});\n\nace.define(\"ace/mode/folding/fold_mode\",[\"require\",\"exports\",\"module\",\"ace/range\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar Range = acequire(\"../../range\").Range;\n\nvar FoldMode = exports.FoldMode = function() {};\n\n(function() {\n\n this.foldingStartMarker = null;\n this.foldingStopMarker = null;\n this.getFoldWidget = function(session, foldStyle, row) {\n var line = session.getLine(row);\n if (this.foldingStartMarker.test(line))\n return \"start\";\n if (foldStyle == \"markbeginend\"\n && this.foldingStopMarker\n && this.foldingStopMarker.test(line))\n return \"end\";\n return \"\";\n };\n\n this.getFoldWidgetRange = function(session, foldStyle, row) {\n return null;\n };\n\n this.indentationBlock = function(session, row, column) {\n var re = /\\S/;\n var line = session.getLine(row);\n var startLevel = line.search(re);\n if (startLevel == -1)\n return;\n\n var startColumn = column || line.length;\n var maxRow = session.getLength();\n var startRow = row;\n var endRow = row;\n\n while (++row < maxRow) {\n var level = session.getLine(row).search(re);\n\n if (level == -1)\n continue;\n\n if (level <= startLevel)\n break;\n\n endRow = row;\n }\n\n if (endRow > startRow) {\n var endColumn = session.getLine(endRow).length;\n return new Range(startRow, startColumn, endRow, endColumn);\n }\n };\n\n this.openingBracketBlock = function(session, bracket, row, column, typeRe) {\n var start = {row: row, column: column + 1};\n var end = session.$findClosingBracket(bracket, start, typeRe);\n if (!end)\n return;\n\n var fw = session.foldWidgets[end.row];\n if (fw == null)\n fw = session.getFoldWidget(end.row);\n\n if (fw == \"start\" && end.row > start.row) {\n end.row --;\n end.column = session.getLine(end.row).length;\n }\n return Range.fromPoints(start, end);\n };\n\n this.closingBracketBlock = function(session, bracket, row, column, typeRe) {\n var end = {row: row, column: column};\n var start = session.$findOpeningBracket(bracket, end);\n\n if (!start)\n return;\n\n start.column++;\n end.column--;\n\n return Range.fromPoints(start, end);\n };\n}).call(FoldMode.prototype);\n\n});\n\nace.define(\"ace/theme/textmate\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\"], function(acequire, exports, module) {\n\"use strict\";\n\nexports.isDark = false;\nexports.cssClass = \"ace-tm\";\nexports.cssText = \".ace-tm .ace_gutter {\\\nbackground: #f0f0f0;\\\ncolor: #333;\\\n}\\\n.ace-tm .ace_print-margin {\\\nwidth: 1px;\\\nbackground: #e8e8e8;\\\n}\\\n.ace-tm .ace_fold {\\\nbackground-color: #6B72E6;\\\n}\\\n.ace-tm {\\\nbackground-color: #FFFFFF;\\\ncolor: black;\\\n}\\\n.ace-tm .ace_cursor {\\\ncolor: black;\\\n}\\\n.ace-tm .ace_invisible {\\\ncolor: rgb(191, 191, 191);\\\n}\\\n.ace-tm .ace_storage,\\\n.ace-tm .ace_keyword {\\\ncolor: blue;\\\n}\\\n.ace-tm .ace_constant {\\\ncolor: rgb(197, 6, 11);\\\n}\\\n.ace-tm .ace_constant.ace_buildin {\\\ncolor: rgb(88, 72, 246);\\\n}\\\n.ace-tm .ace_constant.ace_language {\\\ncolor: rgb(88, 92, 246);\\\n}\\\n.ace-tm .ace_constant.ace_library {\\\ncolor: rgb(6, 150, 14);\\\n}\\\n.ace-tm .ace_invalid {\\\nbackground-color: rgba(255, 0, 0, 0.1);\\\ncolor: red;\\\n}\\\n.ace-tm .ace_support.ace_function {\\\ncolor: rgb(60, 76, 114);\\\n}\\\n.ace-tm .ace_support.ace_constant {\\\ncolor: rgb(6, 150, 14);\\\n}\\\n.ace-tm .ace_support.ace_type,\\\n.ace-tm .ace_support.ace_class {\\\ncolor: rgb(109, 121, 222);\\\n}\\\n.ace-tm .ace_keyword.ace_operator {\\\ncolor: rgb(104, 118, 135);\\\n}\\\n.ace-tm .ace_string {\\\ncolor: rgb(3, 106, 7);\\\n}\\\n.ace-tm .ace_comment {\\\ncolor: rgb(76, 136, 107);\\\n}\\\n.ace-tm .ace_comment.ace_doc {\\\ncolor: rgb(0, 102, 255);\\\n}\\\n.ace-tm .ace_comment.ace_doc.ace_tag {\\\ncolor: rgb(128, 159, 191);\\\n}\\\n.ace-tm .ace_constant.ace_numeric {\\\ncolor: rgb(0, 0, 205);\\\n}\\\n.ace-tm .ace_variable {\\\ncolor: rgb(49, 132, 149);\\\n}\\\n.ace-tm .ace_xml-pe {\\\ncolor: rgb(104, 104, 91);\\\n}\\\n.ace-tm .ace_entity.ace_name.ace_function {\\\ncolor: #0000A2;\\\n}\\\n.ace-tm .ace_heading {\\\ncolor: rgb(12, 7, 255);\\\n}\\\n.ace-tm .ace_list {\\\ncolor:rgb(185, 6, 144);\\\n}\\\n.ace-tm .ace_meta.ace_tag {\\\ncolor:rgb(0, 22, 142);\\\n}\\\n.ace-tm .ace_string.ace_regex {\\\ncolor: rgb(255, 0, 0)\\\n}\\\n.ace-tm .ace_marker-layer .ace_selection {\\\nbackground: rgb(181, 213, 255);\\\n}\\\n.ace-tm.ace_multiselect .ace_selection.ace_start {\\\nbox-shadow: 0 0 3px 0px white;\\\n}\\\n.ace-tm .ace_marker-layer .ace_step {\\\nbackground: rgb(252, 255, 0);\\\n}\\\n.ace-tm .ace_marker-layer .ace_stack {\\\nbackground: rgb(164, 229, 101);\\\n}\\\n.ace-tm .ace_marker-layer .ace_bracket {\\\nmargin: -1px 0 0 -1px;\\\nborder: 1px solid rgb(192, 192, 192);\\\n}\\\n.ace-tm .ace_marker-layer .ace_active-line {\\\nbackground: rgba(0, 0, 0, 0.07);\\\n}\\\n.ace-tm .ace_gutter-active-line {\\\nbackground-color : #dcdcdc;\\\n}\\\n.ace-tm .ace_marker-layer .ace_selected-word {\\\nbackground: rgb(250, 250, 255);\\\nborder: 1px solid rgb(200, 200, 250);\\\n}\\\n.ace-tm .ace_indent-guide {\\\nbackground: url(\\\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\\\") right repeat-y;\\\n}\\\n\";\n\nvar dom = acequire(\"../lib/dom\");\ndom.importCssString(exports.cssText, exports.cssClass);\n});\n\nace.define(\"ace/line_widgets\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/dom\",\"ace/range\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar oop = acequire(\"./lib/oop\");\nvar dom = acequire(\"./lib/dom\");\nvar Range = acequire(\"./range\").Range;\n\n\nfunction LineWidgets(session) {\n this.session = session;\n this.session.widgetManager = this;\n this.session.getRowLength = this.getRowLength;\n this.session.$getWidgetScreenLength = this.$getWidgetScreenLength;\n this.updateOnChange = this.updateOnChange.bind(this);\n this.renderWidgets = this.renderWidgets.bind(this);\n this.measureWidgets = this.measureWidgets.bind(this);\n this.session._changedWidgets = [];\n this.$onChangeEditor = this.$onChangeEditor.bind(this);\n \n this.session.on(\"change\", this.updateOnChange);\n this.session.on(\"changeFold\", this.updateOnFold);\n this.session.on(\"changeEditor\", this.$onChangeEditor);\n}\n\n(function() {\n this.getRowLength = function(row) {\n var h;\n if (this.lineWidgets)\n h = this.lineWidgets[row] && this.lineWidgets[row].rowCount || 0;\n else \n h = 0;\n if (!this.$useWrapMode || !this.$wrapData[row]) {\n return 1 + h;\n } else {\n return this.$wrapData[row].length + 1 + h;\n }\n };\n\n this.$getWidgetScreenLength = function() {\n var screenRows = 0;\n this.lineWidgets.forEach(function(w){\n if (w && w.rowCount && !w.hidden)\n screenRows += w.rowCount;\n });\n return screenRows;\n }; \n \n this.$onChangeEditor = function(e) {\n this.attach(e.editor);\n };\n \n this.attach = function(editor) {\n if (editor && editor.widgetManager && editor.widgetManager != this)\n editor.widgetManager.detach();\n\n if (this.editor == editor)\n return;\n\n this.detach();\n this.editor = editor;\n \n if (editor) {\n editor.widgetManager = this;\n editor.renderer.on(\"beforeRender\", this.measureWidgets);\n editor.renderer.on(\"afterRender\", this.renderWidgets);\n }\n };\n this.detach = function(e) {\n var editor = this.editor;\n if (!editor)\n return;\n \n this.editor = null;\n editor.widgetManager = null;\n \n editor.renderer.off(\"beforeRender\", this.measureWidgets);\n editor.renderer.off(\"afterRender\", this.renderWidgets);\n var lineWidgets = this.session.lineWidgets;\n lineWidgets && lineWidgets.forEach(function(w) {\n if (w && w.el && w.el.parentNode) {\n w._inDocument = false;\n w.el.parentNode.removeChild(w.el);\n }\n });\n };\n\n this.updateOnFold = function(e, session) {\n var lineWidgets = session.lineWidgets;\n if (!lineWidgets || !e.action)\n return;\n var fold = e.data;\n var start = fold.start.row;\n var end = fold.end.row;\n var hide = e.action == \"add\";\n for (var i = start + 1; i < end; i++) {\n if (lineWidgets[i])\n lineWidgets[i].hidden = hide;\n }\n if (lineWidgets[end]) {\n if (hide) {\n if (!lineWidgets[start])\n lineWidgets[start] = lineWidgets[end];\n else\n lineWidgets[end].hidden = hide;\n } else {\n if (lineWidgets[start] == lineWidgets[end])\n lineWidgets[start] = undefined;\n lineWidgets[end].hidden = hide;\n }\n }\n };\n \n this.updateOnChange = function(delta) {\n var lineWidgets = this.session.lineWidgets;\n if (!lineWidgets) return;\n \n var startRow = delta.start.row;\n var len = delta.end.row - startRow;\n\n if (len === 0) {\n } else if (delta.action == 'remove') {\n var removed = lineWidgets.splice(startRow + 1, len);\n removed.forEach(function(w) {\n w && this.removeLineWidget(w);\n }, this);\n this.$updateRows();\n } else {\n var args = new Array(len);\n args.unshift(startRow, 0);\n lineWidgets.splice.apply(lineWidgets, args);\n this.$updateRows();\n }\n };\n \n this.$updateRows = function() {\n var lineWidgets = this.session.lineWidgets;\n if (!lineWidgets) return;\n var noWidgets = true;\n lineWidgets.forEach(function(w, i) {\n if (w) {\n noWidgets = false;\n w.row = i;\n while (w.$oldWidget) {\n w.$oldWidget.row = i;\n w = w.$oldWidget;\n }\n }\n });\n if (noWidgets)\n this.session.lineWidgets = null;\n };\n\n this.addLineWidget = function(w) {\n if (!this.session.lineWidgets)\n this.session.lineWidgets = new Array(this.session.getLength());\n \n var old = this.session.lineWidgets[w.row];\n if (old) {\n w.$oldWidget = old;\n if (old.el && old.el.parentNode) {\n old.el.parentNode.removeChild(old.el);\n old._inDocument = false;\n }\n }\n \n this.session.lineWidgets[w.row] = w;\n \n w.session = this.session;\n \n var renderer = this.editor.renderer;\n if (w.html && !w.el) {\n w.el = dom.createElement(\"div\");\n w.el.innerHTML = w.html;\n }\n if (w.el) {\n dom.addCssClass(w.el, \"ace_lineWidgetContainer\");\n w.el.style.position = \"absolute\";\n w.el.style.zIndex = 5;\n renderer.container.appendChild(w.el);\n w._inDocument = true;\n }\n \n if (!w.coverGutter) {\n w.el.style.zIndex = 3;\n }\n if (!w.pixelHeight) {\n w.pixelHeight = w.el.offsetHeight;\n }\n if (w.rowCount == null) {\n w.rowCount = w.pixelHeight / renderer.layerConfig.lineHeight;\n }\n \n var fold = this.session.getFoldAt(w.row, 0);\n w.$fold = fold;\n if (fold) {\n var lineWidgets = this.session.lineWidgets;\n if (w.row == fold.end.row && !lineWidgets[fold.start.row])\n lineWidgets[fold.start.row] = w;\n else\n w.hidden = true;\n }\n \n this.session._emit(\"changeFold\", {data:{start:{row: w.row}}});\n \n this.$updateRows();\n this.renderWidgets(null, renderer);\n this.onWidgetChanged(w);\n return w;\n };\n \n this.removeLineWidget = function(w) {\n w._inDocument = false;\n w.session = null;\n if (w.el && w.el.parentNode)\n w.el.parentNode.removeChild(w.el);\n if (w.editor && w.editor.destroy) try {\n w.editor.destroy();\n } catch(e){}\n if (this.session.lineWidgets) {\n var w1 = this.session.lineWidgets[w.row]\n if (w1 == w) {\n this.session.lineWidgets[w.row] = w.$oldWidget;\n if (w.$oldWidget)\n this.onWidgetChanged(w.$oldWidget);\n } else {\n while (w1) {\n if (w1.$oldWidget == w) {\n w1.$oldWidget = w.$oldWidget;\n break;\n }\n w1 = w1.$oldWidget;\n }\n }\n }\n this.session._emit(\"changeFold\", {data:{start:{row: w.row}}});\n this.$updateRows();\n };\n \n this.getWidgetsAtRow = function(row) {\n var lineWidgets = this.session.lineWidgets;\n var w = lineWidgets && lineWidgets[row];\n var list = [];\n while (w) {\n list.push(w);\n w = w.$oldWidget;\n }\n return list;\n };\n \n this.onWidgetChanged = function(w) {\n this.session._changedWidgets.push(w);\n this.editor && this.editor.renderer.updateFull();\n };\n \n this.measureWidgets = function(e, renderer) {\n var changedWidgets = this.session._changedWidgets;\n var config = renderer.layerConfig;\n \n if (!changedWidgets || !changedWidgets.length) return;\n var min = Infinity;\n for (var i = 0; i < changedWidgets.length; i++) {\n var w = changedWidgets[i];\n if (!w || !w.el) continue;\n if (w.session != this.session) continue;\n if (!w._inDocument) {\n if (this.session.lineWidgets[w.row] != w)\n continue;\n w._inDocument = true;\n renderer.container.appendChild(w.el);\n }\n \n w.h = w.el.offsetHeight;\n \n if (!w.fixedWidth) {\n w.w = w.el.offsetWidth;\n w.screenWidth = Math.ceil(w.w / config.characterWidth);\n }\n \n var rowCount = w.h / config.lineHeight;\n if (w.coverLine) {\n rowCount -= this.session.getRowLineCount(w.row);\n if (rowCount < 0)\n rowCount = 0;\n }\n if (w.rowCount != rowCount) {\n w.rowCount = rowCount;\n if (w.row < min)\n min = w.row;\n }\n }\n if (min != Infinity) {\n this.session._emit(\"changeFold\", {data:{start:{row: min}}});\n this.session.lineWidgetWidth = null;\n }\n this.session._changedWidgets = [];\n };\n \n this.renderWidgets = function(e, renderer) {\n var config = renderer.layerConfig;\n var lineWidgets = this.session.lineWidgets;\n if (!lineWidgets)\n return;\n var first = Math.min(this.firstRow, config.firstRow);\n var last = Math.max(this.lastRow, config.lastRow, lineWidgets.length);\n \n while (first > 0 && !lineWidgets[first])\n first--;\n \n this.firstRow = config.firstRow;\n this.lastRow = config.lastRow;\n\n renderer.$cursorLayer.config = config;\n for (var i = first; i <= last; i++) {\n var w = lineWidgets[i];\n if (!w || !w.el) continue;\n if (w.hidden) {\n w.el.style.top = -100 - (w.pixelHeight || 0) + \"px\";\n continue;\n }\n if (!w._inDocument) {\n w._inDocument = true;\n renderer.container.appendChild(w.el);\n }\n var top = renderer.$cursorLayer.getPixelPosition({row: i, column:0}, true).top;\n if (!w.coverLine)\n top += config.lineHeight * this.session.getRowLineCount(w.row);\n w.el.style.top = top - config.offset + \"px\";\n \n var left = w.coverGutter ? 0 : renderer.gutterWidth;\n if (!w.fixedWidth)\n left -= renderer.scrollLeft;\n w.el.style.left = left + \"px\";\n \n if (w.fullWidth && w.screenWidth) {\n w.el.style.minWidth = config.width + 2 * config.padding + \"px\";\n }\n \n if (w.fixedWidth) {\n w.el.style.right = renderer.scrollBar.getWidth() + \"px\";\n } else {\n w.el.style.right = \"\";\n }\n }\n };\n \n}).call(LineWidgets.prototype);\n\n\nexports.LineWidgets = LineWidgets;\n\n});\n\nace.define(\"ace/ext/error_marker\",[\"require\",\"exports\",\"module\",\"ace/line_widgets\",\"ace/lib/dom\",\"ace/range\"], function(acequire, exports, module) {\n\"use strict\";\nvar LineWidgets = acequire(\"../line_widgets\").LineWidgets;\nvar dom = acequire(\"../lib/dom\");\nvar Range = acequire(\"../range\").Range;\n\nfunction binarySearch(array, needle, comparator) {\n var first = 0;\n var last = array.length - 1;\n\n while (first <= last) {\n var mid = (first + last) >> 1;\n var c = comparator(needle, array[mid]);\n if (c > 0)\n first = mid + 1;\n else if (c < 0)\n last = mid - 1;\n else\n return mid;\n }\n return -(first + 1);\n}\n\nfunction findAnnotations(session, row, dir) {\n var annotations = session.getAnnotations().sort(Range.comparePoints);\n if (!annotations.length)\n return;\n \n var i = binarySearch(annotations, {row: row, column: -1}, Range.comparePoints);\n if (i < 0)\n i = -i - 1;\n \n if (i >= annotations.length)\n i = dir > 0 ? 0 : annotations.length - 1;\n else if (i === 0 && dir < 0)\n i = annotations.length - 1;\n \n var annotation = annotations[i];\n if (!annotation || !dir)\n return;\n\n if (annotation.row === row) {\n do {\n annotation = annotations[i += dir];\n } while (annotation && annotation.row === row);\n if (!annotation)\n return annotations.slice();\n }\n \n \n var matched = [];\n row = annotation.row;\n do {\n matched[dir < 0 ? \"unshift\" : \"push\"](annotation);\n annotation = annotations[i += dir];\n } while (annotation && annotation.row == row);\n return matched.length && matched;\n}\n\nexports.showErrorMarker = function(editor, dir) {\n var session = editor.session;\n if (!session.widgetManager) {\n session.widgetManager = new LineWidgets(session);\n session.widgetManager.attach(editor);\n }\n \n var pos = editor.getCursorPosition();\n var row = pos.row;\n var oldWidget = session.widgetManager.getWidgetsAtRow(row).filter(function(w) {\n return w.type == \"errorMarker\";\n })[0];\n if (oldWidget) {\n oldWidget.destroy();\n } else {\n row -= dir;\n }\n var annotations = findAnnotations(session, row, dir);\n var gutterAnno;\n if (annotations) {\n var annotation = annotations[0];\n pos.column = (annotation.pos && typeof annotation.column != \"number\"\n ? annotation.pos.sc\n : annotation.column) || 0;\n pos.row = annotation.row;\n gutterAnno = editor.renderer.$gutterLayer.$annotations[pos.row];\n } else if (oldWidget) {\n return;\n } else {\n gutterAnno = {\n text: [\"Looks good!\"],\n className: \"ace_ok\"\n };\n }\n editor.session.unfold(pos.row);\n editor.selection.moveToPosition(pos);\n \n var w = {\n row: pos.row, \n fixedWidth: true,\n coverGutter: true,\n el: dom.createElement(\"div\"),\n type: \"errorMarker\"\n };\n var el = w.el.appendChild(dom.createElement(\"div\"));\n var arrow = w.el.appendChild(dom.createElement(\"div\"));\n arrow.className = \"error_widget_arrow \" + gutterAnno.className;\n \n var left = editor.renderer.$cursorLayer\n .getPixelPosition(pos).left;\n arrow.style.left = left + editor.renderer.gutterWidth - 5 + \"px\";\n \n w.el.className = \"error_widget_wrapper\";\n el.className = \"error_widget \" + gutterAnno.className;\n el.innerHTML = gutterAnno.text.join(\"
\");\n \n el.appendChild(dom.createElement(\"div\"));\n \n var kb = function(_, hashId, keyString) {\n if (hashId === 0 && (keyString === \"esc\" || keyString === \"return\")) {\n w.destroy();\n return {command: \"null\"};\n }\n };\n \n w.destroy = function() {\n if (editor.$mouseHandler.isMousePressed)\n return;\n editor.keyBinding.removeKeyboardHandler(kb);\n session.widgetManager.removeLineWidget(w);\n editor.off(\"changeSelection\", w.destroy);\n editor.off(\"changeSession\", w.destroy);\n editor.off(\"mouseup\", w.destroy);\n editor.off(\"change\", w.destroy);\n };\n \n editor.keyBinding.addKeyboardHandler(kb);\n editor.on(\"changeSelection\", w.destroy);\n editor.on(\"changeSession\", w.destroy);\n editor.on(\"mouseup\", w.destroy);\n editor.on(\"change\", w.destroy);\n \n editor.session.widgetManager.addLineWidget(w);\n \n w.el.onmousedown = editor.focus.bind(editor);\n \n editor.renderer.scrollCursorIntoView(null, 0.5, {bottom: w.el.offsetHeight});\n};\n\n\ndom.importCssString(\"\\\n .error_widget_wrapper {\\\n background: inherit;\\\n color: inherit;\\\n border:none\\\n }\\\n .error_widget {\\\n border-top: solid 2px;\\\n border-bottom: solid 2px;\\\n margin: 5px 0;\\\n padding: 10px 40px;\\\n white-space: pre-wrap;\\\n }\\\n .error_widget.ace_error, .error_widget_arrow.ace_error{\\\n border-color: #ff5a5a\\\n }\\\n .error_widget.ace_warning, .error_widget_arrow.ace_warning{\\\n border-color: #F1D817\\\n }\\\n .error_widget.ace_info, .error_widget_arrow.ace_info{\\\n border-color: #5a5a5a\\\n }\\\n .error_widget.ace_ok, .error_widget_arrow.ace_ok{\\\n border-color: #5aaa5a\\\n }\\\n .error_widget_arrow {\\\n position: absolute;\\\n border: solid 5px;\\\n border-top-color: transparent!important;\\\n border-right-color: transparent!important;\\\n border-left-color: transparent!important;\\\n top: -5px;\\\n }\\\n\", \"\");\n\n});\n\nace.define(\"ace/ace\",[\"require\",\"exports\",\"module\",\"ace/lib/fixoldbrowsers\",\"ace/lib/dom\",\"ace/lib/event\",\"ace/editor\",\"ace/edit_session\",\"ace/undomanager\",\"ace/virtual_renderer\",\"ace/worker/worker_client\",\"ace/keyboard/hash_handler\",\"ace/placeholder\",\"ace/multi_select\",\"ace/mode/folding/fold_mode\",\"ace/theme/textmate\",\"ace/ext/error_marker\",\"ace/config\"], function(acequire, exports, module) {\n\"use strict\";\n\nacequire(\"./lib/fixoldbrowsers\");\n\nvar dom = acequire(\"./lib/dom\");\nvar event = acequire(\"./lib/event\");\n\nvar Editor = acequire(\"./editor\").Editor;\nvar EditSession = acequire(\"./edit_session\").EditSession;\nvar UndoManager = acequire(\"./undomanager\").UndoManager;\nvar Renderer = acequire(\"./virtual_renderer\").VirtualRenderer;\nacequire(\"./worker/worker_client\");\nacequire(\"./keyboard/hash_handler\");\nacequire(\"./placeholder\");\nacequire(\"./multi_select\");\nacequire(\"./mode/folding/fold_mode\");\nacequire(\"./theme/textmate\");\nacequire(\"./ext/error_marker\");\n\nexports.config = acequire(\"./config\");\nexports.acequire = acequire;\nexports.edit = function(el) {\n if (typeof el == \"string\") {\n var _id = el;\n el = document.getElementById(_id);\n if (!el)\n throw new Error(\"ace.edit can't find div #\" + _id);\n }\n\n if (el && el.env && el.env.editor instanceof Editor)\n return el.env.editor;\n\n var value = \"\";\n if (el && /input|textarea/i.test(el.tagName)) {\n var oldNode = el;\n value = oldNode.value;\n el = dom.createElement(\"pre\");\n oldNode.parentNode.replaceChild(el, oldNode);\n } else if (el) {\n value = dom.getInnerText(el);\n el.innerHTML = \"\";\n }\n\n var doc = exports.createEditSession(value);\n\n var editor = new Editor(new Renderer(el));\n editor.setSession(doc);\n\n var env = {\n document: doc,\n editor: editor,\n onResize: editor.resize.bind(editor, null)\n };\n if (oldNode) env.textarea = oldNode;\n event.addListener(window, \"resize\", env.onResize);\n editor.on(\"destroy\", function() {\n event.removeListener(window, \"resize\", env.onResize);\n env.editor.container.env = null; // prevent memory leak on old ie\n });\n editor.container.env = editor.env = env;\n return editor;\n};\nexports.createEditSession = function(text, mode) {\n var doc = new EditSession(text, mode);\n doc.setUndoManager(new UndoManager());\n return doc;\n}\nexports.EditSession = EditSession;\nexports.UndoManager = UndoManager;\nexports.version = \"1.2.3\";\n});\n (function() {\n ace.acequire([\"ace/ace\"], function(a) {\n a && a.config.init(true);\n if (!window.ace)\n window.ace = a;\n for (var key in a) if (a.hasOwnProperty(key))\n window.ace[key] = a[key];\n });\n })();\n \nmodule.exports = window.ace.acequire(\"ace/ace\");\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/brace/index.js\n ** module id = 127\n ** module chunks = 0\n **/","module.exports = function() { throw new Error(\"define cannot be used indirect\"); };\r\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** (webpack)/buildin/amd-define.js\n ** module id = 128\n ** module chunks = 0\n **/","module.exports = get_blob()\n\nfunction get_blob() {\n if(global.Blob) {\n try {\n new Blob(['asdf'], {type: 'text/plain'})\n return Blob\n } catch(err) {}\n }\n\n var Builder = global.WebKitBlobBuilder ||\n global.MozBlobBuilder ||\n global.MSBlobBuilder\n\n return function(parts, bag) {\n var builder = new Builder\n , endings = bag.endings\n , type = bag.type\n\n if(endings) for(var i = 0, len = parts.length; i < len; ++i) {\n builder.append(parts[i], endings)\n } else for(var i = 0, len = parts.length; i < len; ++i) {\n builder.append(parts[i])\n }\n\n return type ? builder.getBlob(type) : builder.getBlob()\n }\n}\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/w3c-blob/browser.js\n ** module id = 129\n ** module chunks = 0\n **/","ace.define(\"ace/mode/json_highlight_rules\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/mode/text_highlight_rules\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar oop = acequire(\"../lib/oop\");\nvar TextHighlightRules = acequire(\"./text_highlight_rules\").TextHighlightRules;\n\nvar JsonHighlightRules = function() {\n this.$rules = {\n \"start\" : [\n {\n token : \"variable\", // single line\n regex : '[\"](?:(?:\\\\\\\\.)|(?:[^\"\\\\\\\\]))*?[\"]\\\\s*(?=:)'\n }, {\n token : \"string\", // single line\n regex : '\"',\n next : \"string\"\n }, {\n token : \"constant.numeric\", // hex\n regex : \"0[xX][0-9a-fA-F]+\\\\b\"\n }, {\n token : \"constant.numeric\", // float\n regex : \"[+-]?\\\\d+(?:(?:\\\\.\\\\d*)?(?:[eE][+-]?\\\\d+)?)?\\\\b\"\n }, {\n token : \"constant.language.boolean\",\n regex : \"(?:true|false)\\\\b\"\n }, {\n token : \"invalid.illegal\", // single quoted strings are not allowed\n regex : \"['](?:(?:\\\\\\\\.)|(?:[^'\\\\\\\\]))*?[']\"\n }, {\n token : \"invalid.illegal\", // comments are not allowed\n regex : \"\\\\/\\\\/.*$\"\n }, {\n token : \"paren.lparen\",\n regex : \"[[({]\"\n }, {\n token : \"paren.rparen\",\n regex : \"[\\\\])}]\"\n }, {\n token : \"text\",\n regex : \"\\\\s+\"\n }\n ],\n \"string\" : [\n {\n token : \"constant.language.escape\",\n regex : /\\\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|[\"\\\\\\/bfnrt])/\n }, {\n token : \"string\",\n regex : '[^\"\\\\\\\\]+'\n }, {\n token : \"string\",\n regex : '\"',\n next : \"start\"\n }, {\n token : \"string\",\n regex : \"\",\n next : \"start\"\n }\n ]\n };\n \n};\n\noop.inherits(JsonHighlightRules, TextHighlightRules);\n\nexports.JsonHighlightRules = JsonHighlightRules;\n});\n\nace.define(\"ace/mode/matching_brace_outdent\",[\"require\",\"exports\",\"module\",\"ace/range\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar Range = acequire(\"../range\").Range;\n\nvar MatchingBraceOutdent = function() {};\n\n(function() {\n\n this.checkOutdent = function(line, input) {\n if (! /^\\s+$/.test(line))\n return false;\n\n return /^\\s*\\}/.test(input);\n };\n\n this.autoOutdent = function(doc, row) {\n var line = doc.getLine(row);\n var match = line.match(/^(\\s*\\})/);\n\n if (!match) return 0;\n\n var column = match[1].length;\n var openBracePos = doc.findMatchingBracket({row: row, column: column});\n\n if (!openBracePos || openBracePos.row == row) return 0;\n\n var indent = this.$getIndent(doc.getLine(openBracePos.row));\n doc.replace(new Range(row, 0, row, column-1), indent);\n };\n\n this.$getIndent = function(line) {\n return line.match(/^\\s*/)[0];\n };\n\n}).call(MatchingBraceOutdent.prototype);\n\nexports.MatchingBraceOutdent = MatchingBraceOutdent;\n});\n\nace.define(\"ace/mode/behaviour/cstyle\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/mode/behaviour\",\"ace/token_iterator\",\"ace/lib/lang\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar oop = acequire(\"../../lib/oop\");\nvar Behaviour = acequire(\"../behaviour\").Behaviour;\nvar TokenIterator = acequire(\"../../token_iterator\").TokenIterator;\nvar lang = acequire(\"../../lib/lang\");\n\nvar SAFE_INSERT_IN_TOKENS =\n [\"text\", \"paren.rparen\", \"punctuation.operator\"];\nvar SAFE_INSERT_BEFORE_TOKENS =\n [\"text\", \"paren.rparen\", \"punctuation.operator\", \"comment\"];\n\nvar context;\nvar contextCache = {};\nvar initContext = function(editor) {\n var id = -1;\n if (editor.multiSelect) {\n id = editor.selection.index;\n if (contextCache.rangeCount != editor.multiSelect.rangeCount)\n contextCache = {rangeCount: editor.multiSelect.rangeCount};\n }\n if (contextCache[id])\n return context = contextCache[id];\n context = contextCache[id] = {\n autoInsertedBrackets: 0,\n autoInsertedRow: -1,\n autoInsertedLineEnd: \"\",\n maybeInsertedBrackets: 0,\n maybeInsertedRow: -1,\n maybeInsertedLineStart: \"\",\n maybeInsertedLineEnd: \"\"\n };\n};\n\nvar getWrapped = function(selection, selected, opening, closing) {\n var rowDiff = selection.end.row - selection.start.row;\n return {\n text: opening + selected + closing,\n selection: [\n 0,\n selection.start.column + 1,\n rowDiff,\n selection.end.column + (rowDiff ? 0 : 1)\n ]\n };\n};\n\nvar CstyleBehaviour = function() {\n this.add(\"braces\", \"insertion\", function(state, action, editor, session, text) {\n var cursor = editor.getCursorPosition();\n var line = session.doc.getLine(cursor.row);\n if (text == '{') {\n initContext(editor);\n var selection = editor.getSelectionRange();\n var selected = session.doc.getTextRange(selection);\n if (selected !== \"\" && selected !== \"{\" && editor.getWrapBehavioursEnabled()) {\n return getWrapped(selection, selected, '{', '}');\n } else if (CstyleBehaviour.isSaneInsertion(editor, session)) {\n if (/[\\]\\}\\)]/.test(line[cursor.column]) || editor.inMultiSelectMode) {\n CstyleBehaviour.recordAutoInsert(editor, session, \"}\");\n return {\n text: '{}',\n selection: [1, 1]\n };\n } else {\n CstyleBehaviour.recordMaybeInsert(editor, session, \"{\");\n return {\n text: '{',\n selection: [1, 1]\n };\n }\n }\n } else if (text == '}') {\n initContext(editor);\n var rightChar = line.substring(cursor.column, cursor.column + 1);\n if (rightChar == '}') {\n var matching = session.$findOpeningBracket('}', {column: cursor.column + 1, row: cursor.row});\n if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) {\n CstyleBehaviour.popAutoInsertedClosing();\n return {\n text: '',\n selection: [1, 1]\n };\n }\n }\n } else if (text == \"\\n\" || text == \"\\r\\n\") {\n initContext(editor);\n var closing = \"\";\n if (CstyleBehaviour.isMaybeInsertedClosing(cursor, line)) {\n closing = lang.stringRepeat(\"}\", context.maybeInsertedBrackets);\n CstyleBehaviour.clearMaybeInsertedClosing();\n }\n var rightChar = line.substring(cursor.column, cursor.column + 1);\n if (rightChar === '}') {\n var openBracePos = session.findMatchingBracket({row: cursor.row, column: cursor.column+1}, '}');\n if (!openBracePos)\n return null;\n var next_indent = this.$getIndent(session.getLine(openBracePos.row));\n } else if (closing) {\n var next_indent = this.$getIndent(line);\n } else {\n CstyleBehaviour.clearMaybeInsertedClosing();\n return;\n }\n var indent = next_indent + session.getTabString();\n\n return {\n text: '\\n' + indent + '\\n' + next_indent + closing,\n selection: [1, indent.length, 1, indent.length]\n };\n } else {\n CstyleBehaviour.clearMaybeInsertedClosing();\n }\n });\n\n this.add(\"braces\", \"deletion\", function(state, action, editor, session, range) {\n var selected = session.doc.getTextRange(range);\n if (!range.isMultiLine() && selected == '{') {\n initContext(editor);\n var line = session.doc.getLine(range.start.row);\n var rightChar = line.substring(range.end.column, range.end.column + 1);\n if (rightChar == '}') {\n range.end.column++;\n return range;\n } else {\n context.maybeInsertedBrackets--;\n }\n }\n });\n\n this.add(\"parens\", \"insertion\", function(state, action, editor, session, text) {\n if (text == '(') {\n initContext(editor);\n var selection = editor.getSelectionRange();\n var selected = session.doc.getTextRange(selection);\n if (selected !== \"\" && editor.getWrapBehavioursEnabled()) {\n return getWrapped(selection, selected, '(', ')');\n } else if (CstyleBehaviour.isSaneInsertion(editor, session)) {\n CstyleBehaviour.recordAutoInsert(editor, session, \")\");\n return {\n text: '()',\n selection: [1, 1]\n };\n }\n } else if (text == ')') {\n initContext(editor);\n var cursor = editor.getCursorPosition();\n var line = session.doc.getLine(cursor.row);\n var rightChar = line.substring(cursor.column, cursor.column + 1);\n if (rightChar == ')') {\n var matching = session.$findOpeningBracket(')', {column: cursor.column + 1, row: cursor.row});\n if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) {\n CstyleBehaviour.popAutoInsertedClosing();\n return {\n text: '',\n selection: [1, 1]\n };\n }\n }\n }\n });\n\n this.add(\"parens\", \"deletion\", function(state, action, editor, session, range) {\n var selected = session.doc.getTextRange(range);\n if (!range.isMultiLine() && selected == '(') {\n initContext(editor);\n var line = session.doc.getLine(range.start.row);\n var rightChar = line.substring(range.start.column + 1, range.start.column + 2);\n if (rightChar == ')') {\n range.end.column++;\n return range;\n }\n }\n });\n\n this.add(\"brackets\", \"insertion\", function(state, action, editor, session, text) {\n if (text == '[') {\n initContext(editor);\n var selection = editor.getSelectionRange();\n var selected = session.doc.getTextRange(selection);\n if (selected !== \"\" && editor.getWrapBehavioursEnabled()) {\n return getWrapped(selection, selected, '[', ']');\n } else if (CstyleBehaviour.isSaneInsertion(editor, session)) {\n CstyleBehaviour.recordAutoInsert(editor, session, \"]\");\n return {\n text: '[]',\n selection: [1, 1]\n };\n }\n } else if (text == ']') {\n initContext(editor);\n var cursor = editor.getCursorPosition();\n var line = session.doc.getLine(cursor.row);\n var rightChar = line.substring(cursor.column, cursor.column + 1);\n if (rightChar == ']') {\n var matching = session.$findOpeningBracket(']', {column: cursor.column + 1, row: cursor.row});\n if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) {\n CstyleBehaviour.popAutoInsertedClosing();\n return {\n text: '',\n selection: [1, 1]\n };\n }\n }\n }\n });\n\n this.add(\"brackets\", \"deletion\", function(state, action, editor, session, range) {\n var selected = session.doc.getTextRange(range);\n if (!range.isMultiLine() && selected == '[') {\n initContext(editor);\n var line = session.doc.getLine(range.start.row);\n var rightChar = line.substring(range.start.column + 1, range.start.column + 2);\n if (rightChar == ']') {\n range.end.column++;\n return range;\n }\n }\n });\n\n this.add(\"string_dquotes\", \"insertion\", function(state, action, editor, session, text) {\n if (text == '\"' || text == \"'\") {\n initContext(editor);\n var quote = text;\n var selection = editor.getSelectionRange();\n var selected = session.doc.getTextRange(selection);\n if (selected !== \"\" && selected !== \"'\" && selected != '\"' && editor.getWrapBehavioursEnabled()) {\n return getWrapped(selection, selected, quote, quote);\n } else if (!selected) {\n var cursor = editor.getCursorPosition();\n var line = session.doc.getLine(cursor.row);\n var leftChar = line.substring(cursor.column-1, cursor.column);\n var rightChar = line.substring(cursor.column, cursor.column + 1);\n \n var token = session.getTokenAt(cursor.row, cursor.column);\n var rightToken = session.getTokenAt(cursor.row, cursor.column + 1);\n if (leftChar == \"\\\\\" && token && /escape/.test(token.type))\n return null;\n \n var stringBefore = token && /string|escape/.test(token.type);\n var stringAfter = !rightToken || /string|escape/.test(rightToken.type);\n \n var pair;\n if (rightChar == quote) {\n pair = stringBefore !== stringAfter;\n } else {\n if (stringBefore && !stringAfter)\n return null; // wrap string with different quote\n if (stringBefore && stringAfter)\n return null; // do not pair quotes inside strings\n var wordRe = session.$mode.tokenRe;\n wordRe.lastIndex = 0;\n var isWordBefore = wordRe.test(leftChar);\n wordRe.lastIndex = 0;\n var isWordAfter = wordRe.test(leftChar);\n if (isWordBefore || isWordAfter)\n return null; // before or after alphanumeric\n if (rightChar && !/[\\s;,.})\\]\\\\]/.test(rightChar))\n return null; // there is rightChar and it isn't closing\n pair = true;\n }\n return {\n text: pair ? quote + quote : \"\",\n selection: [1,1]\n };\n }\n }\n });\n\n this.add(\"string_dquotes\", \"deletion\", function(state, action, editor, session, range) {\n var selected = session.doc.getTextRange(range);\n if (!range.isMultiLine() && (selected == '\"' || selected == \"'\")) {\n initContext(editor);\n var line = session.doc.getLine(range.start.row);\n var rightChar = line.substring(range.start.column + 1, range.start.column + 2);\n if (rightChar == selected) {\n range.end.column++;\n return range;\n }\n }\n });\n\n};\n\n \nCstyleBehaviour.isSaneInsertion = function(editor, session) {\n var cursor = editor.getCursorPosition();\n var iterator = new TokenIterator(session, cursor.row, cursor.column);\n if (!this.$matchTokenType(iterator.getCurrentToken() || \"text\", SAFE_INSERT_IN_TOKENS)) {\n var iterator2 = new TokenIterator(session, cursor.row, cursor.column + 1);\n if (!this.$matchTokenType(iterator2.getCurrentToken() || \"text\", SAFE_INSERT_IN_TOKENS))\n return false;\n }\n iterator.stepForward();\n return iterator.getCurrentTokenRow() !== cursor.row ||\n this.$matchTokenType(iterator.getCurrentToken() || \"text\", SAFE_INSERT_BEFORE_TOKENS);\n};\n\nCstyleBehaviour.$matchTokenType = function(token, types) {\n return types.indexOf(token.type || token) > -1;\n};\n\nCstyleBehaviour.recordAutoInsert = function(editor, session, bracket) {\n var cursor = editor.getCursorPosition();\n var line = session.doc.getLine(cursor.row);\n if (!this.isAutoInsertedClosing(cursor, line, context.autoInsertedLineEnd[0]))\n context.autoInsertedBrackets = 0;\n context.autoInsertedRow = cursor.row;\n context.autoInsertedLineEnd = bracket + line.substr(cursor.column);\n context.autoInsertedBrackets++;\n};\n\nCstyleBehaviour.recordMaybeInsert = function(editor, session, bracket) {\n var cursor = editor.getCursorPosition();\n var line = session.doc.getLine(cursor.row);\n if (!this.isMaybeInsertedClosing(cursor, line))\n context.maybeInsertedBrackets = 0;\n context.maybeInsertedRow = cursor.row;\n context.maybeInsertedLineStart = line.substr(0, cursor.column) + bracket;\n context.maybeInsertedLineEnd = line.substr(cursor.column);\n context.maybeInsertedBrackets++;\n};\n\nCstyleBehaviour.isAutoInsertedClosing = function(cursor, line, bracket) {\n return context.autoInsertedBrackets > 0 &&\n cursor.row === context.autoInsertedRow &&\n bracket === context.autoInsertedLineEnd[0] &&\n line.substr(cursor.column) === context.autoInsertedLineEnd;\n};\n\nCstyleBehaviour.isMaybeInsertedClosing = function(cursor, line) {\n return context.maybeInsertedBrackets > 0 &&\n cursor.row === context.maybeInsertedRow &&\n line.substr(cursor.column) === context.maybeInsertedLineEnd &&\n line.substr(0, cursor.column) == context.maybeInsertedLineStart;\n};\n\nCstyleBehaviour.popAutoInsertedClosing = function() {\n context.autoInsertedLineEnd = context.autoInsertedLineEnd.substr(1);\n context.autoInsertedBrackets--;\n};\n\nCstyleBehaviour.clearMaybeInsertedClosing = function() {\n if (context) {\n context.maybeInsertedBrackets = 0;\n context.maybeInsertedRow = -1;\n }\n};\n\n\n\noop.inherits(CstyleBehaviour, Behaviour);\n\nexports.CstyleBehaviour = CstyleBehaviour;\n});\n\nace.define(\"ace/mode/folding/cstyle\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/range\",\"ace/mode/folding/fold_mode\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar oop = acequire(\"../../lib/oop\");\nvar Range = acequire(\"../../range\").Range;\nvar BaseFoldMode = acequire(\"./fold_mode\").FoldMode;\n\nvar FoldMode = exports.FoldMode = function(commentRegex) {\n if (commentRegex) {\n this.foldingStartMarker = new RegExp(\n this.foldingStartMarker.source.replace(/\\|[^|]*?$/, \"|\" + commentRegex.start)\n );\n this.foldingStopMarker = new RegExp(\n this.foldingStopMarker.source.replace(/\\|[^|]*?$/, \"|\" + commentRegex.end)\n );\n }\n};\noop.inherits(FoldMode, BaseFoldMode);\n\n(function() {\n \n this.foldingStartMarker = /(\\{|\\[)[^\\}\\]]*$|^\\s*(\\/\\*)/;\n this.foldingStopMarker = /^[^\\[\\{]*(\\}|\\])|^[\\s\\*]*(\\*\\/)/;\n this.singleLineBlockCommentRe= /^\\s*(\\/\\*).*\\*\\/\\s*$/;\n this.tripleStarBlockCommentRe = /^\\s*(\\/\\*\\*\\*).*\\*\\/\\s*$/;\n this.startRegionRe = /^\\s*(\\/\\*|\\/\\/)#?region\\b/;\n this._getFoldWidgetBase = this.getFoldWidget;\n this.getFoldWidget = function(session, foldStyle, row) {\n var line = session.getLine(row);\n \n if (this.singleLineBlockCommentRe.test(line)) {\n if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))\n return \"\";\n }\n \n var fw = this._getFoldWidgetBase(session, foldStyle, row);\n \n if (!fw && this.startRegionRe.test(line))\n return \"start\"; // lineCommentRegionStart\n \n return fw;\n };\n\n this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {\n var line = session.getLine(row);\n \n if (this.startRegionRe.test(line))\n return this.getCommentRegionBlock(session, line, row);\n \n var match = line.match(this.foldingStartMarker);\n if (match) {\n var i = match.index;\n\n if (match[1])\n return this.openingBracketBlock(session, match[1], row, i);\n \n var range = session.getCommentFoldRange(row, i + match[0].length, 1);\n \n if (range && !range.isMultiLine()) {\n if (forceMultiline) {\n range = this.getSectionRange(session, row);\n } else if (foldStyle != \"all\")\n range = null;\n }\n \n return range;\n }\n\n if (foldStyle === \"markbegin\")\n return;\n\n var match = line.match(this.foldingStopMarker);\n if (match) {\n var i = match.index + match[0].length;\n\n if (match[1])\n return this.closingBracketBlock(session, match[1], row, i);\n\n return session.getCommentFoldRange(row, i, -1);\n }\n };\n \n this.getSectionRange = function(session, row) {\n var line = session.getLine(row);\n var startIndent = line.search(/\\S/);\n var startRow = row;\n var startColumn = line.length;\n row = row + 1;\n var endRow = row;\n var maxRow = session.getLength();\n while (++row < maxRow) {\n line = session.getLine(row);\n var indent = line.search(/\\S/);\n if (indent === -1)\n continue;\n if (startIndent > indent)\n break;\n var subRange = this.getFoldWidgetRange(session, \"all\", row);\n \n if (subRange) {\n if (subRange.start.row <= startRow) {\n break;\n } else if (subRange.isMultiLine()) {\n row = subRange.end.row;\n } else if (startIndent == indent) {\n break;\n }\n }\n endRow = row;\n }\n \n return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);\n };\n this.getCommentRegionBlock = function(session, line, row) {\n var startColumn = line.search(/\\s*$/);\n var maxRow = session.getLength();\n var startRow = row;\n \n var re = /^\\s*(?:\\/\\*|\\/\\/|--)#?(end)?region\\b/;\n var depth = 1;\n while (++row < maxRow) {\n line = session.getLine(row);\n var m = re.exec(line);\n if (!m) continue;\n if (m[1]) depth--;\n else depth++;\n\n if (!depth) break;\n }\n\n var endRow = row;\n if (endRow > startRow) {\n return new Range(startRow, startColumn, endRow, line.length);\n }\n };\n\n}).call(FoldMode.prototype);\n\n});\n\nace.define(\"ace/mode/json\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/mode/text\",\"ace/mode/json_highlight_rules\",\"ace/mode/matching_brace_outdent\",\"ace/mode/behaviour/cstyle\",\"ace/mode/folding/cstyle\",\"ace/worker/worker_client\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar oop = acequire(\"../lib/oop\");\nvar TextMode = acequire(\"./text\").Mode;\nvar HighlightRules = acequire(\"./json_highlight_rules\").JsonHighlightRules;\nvar MatchingBraceOutdent = acequire(\"./matching_brace_outdent\").MatchingBraceOutdent;\nvar CstyleBehaviour = acequire(\"./behaviour/cstyle\").CstyleBehaviour;\nvar CStyleFoldMode = acequire(\"./folding/cstyle\").FoldMode;\nvar WorkerClient = acequire(\"../worker/worker_client\").WorkerClient;\n\nvar Mode = function() {\n this.HighlightRules = HighlightRules;\n this.$outdent = new MatchingBraceOutdent();\n this.$behaviour = new CstyleBehaviour();\n this.foldingRules = new CStyleFoldMode();\n};\noop.inherits(Mode, TextMode);\n\n(function() {\n\n this.getNextLineIndent = function(state, line, tab) {\n var indent = this.$getIndent(line);\n\n if (state == \"start\") {\n var match = line.match(/^.*[\\{\\(\\[]\\s*$/);\n if (match) {\n indent += tab;\n }\n }\n\n return indent;\n };\n\n this.checkOutdent = function(state, line, input) {\n return this.$outdent.checkOutdent(line, input);\n };\n\n this.autoOutdent = function(state, doc, row) {\n this.$outdent.autoOutdent(doc, row);\n };\n\n this.createWorker = function(session) {\n var worker = new WorkerClient([\"ace\"], require(\"../worker/json\"), \"JsonWorker\");\n worker.attachToDocument(session.getDocument());\n\n worker.on(\"annotate\", function(e) {\n session.setAnnotations(e.data);\n });\n\n worker.on(\"terminate\", function() {\n session.clearAnnotations();\n });\n\n return worker;\n };\n\n\n this.$id = \"ace/mode/json\";\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n});\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/brace/mode/json.js\n ** module id = 130\n ** module chunks = 0\n **/","module.exports.id = 'ace/mode/json_worker';\nmodule.exports.src = \"\\\"no use strict\\\";(function(window){function resolveModuleId(id,paths){for(var testPath=id,tail=\\\"\\\";testPath;){var alias=paths[testPath];if(\\\"string\\\"==typeof alias)return alias+tail;if(alias)return alias.location.replace(/\\\\/*$/,\\\"/\\\")+(tail||alias.main||alias.name);if(alias===!1)return\\\"\\\";var i=testPath.lastIndexOf(\\\"/\\\");if(-1===i)break;tail=testPath.substr(i)+tail,testPath=testPath.slice(0,i)}return id}if(!(void 0!==window.window&&window.document||window.acequire&&window.define)){window.console||(window.console=function(){var msgs=Array.prototype.slice.call(arguments,0);postMessage({type:\\\"log\\\",data:msgs})},window.console.error=window.console.warn=window.console.log=window.console.trace=window.console),window.window=window,window.ace=window,window.onerror=function(message,file,line,col,err){postMessage({type:\\\"error\\\",data:{message:message,data:err.data,file:file,line:line,col:col,stack:err.stack}})},window.normalizeModule=function(parentId,moduleName){if(-1!==moduleName.indexOf(\\\"!\\\")){var chunks=moduleName.split(\\\"!\\\");return window.normalizeModule(parentId,chunks[0])+\\\"!\\\"+window.normalizeModule(parentId,chunks[1])}if(\\\".\\\"==moduleName.charAt(0)){var base=parentId.split(\\\"/\\\").slice(0,-1).join(\\\"/\\\");for(moduleName=(base?base+\\\"/\\\":\\\"\\\")+moduleName;-1!==moduleName.indexOf(\\\".\\\")&&previous!=moduleName;){var previous=moduleName;moduleName=moduleName.replace(/^\\\\.\\\\//,\\\"\\\").replace(/\\\\/\\\\.\\\\//,\\\"/\\\").replace(/[^\\\\/]+\\\\/\\\\.\\\\.\\\\//,\\\"\\\")}}return moduleName},window.acequire=function acequire(parentId,id){if(id||(id=parentId,parentId=null),!id.charAt)throw Error(\\\"worker.js acequire() accepts only (parentId, id) as arguments\\\");id=window.normalizeModule(parentId,id);var module=window.acequire.modules[id];if(module)return module.initialized||(module.initialized=!0,module.exports=module.factory().exports),module.exports;if(!window.acequire.tlns)return console.log(\\\"unable to load \\\"+id);var path=resolveModuleId(id,window.acequire.tlns);return\\\".js\\\"!=path.slice(-3)&&(path+=\\\".js\\\"),window.acequire.id=id,window.acequire.modules[id]={},importScripts(path),window.acequire(parentId,id)},window.acequire.modules={},window.acequire.tlns={},window.define=function(id,deps,factory){if(2==arguments.length?(factory=deps,\\\"string\\\"!=typeof id&&(deps=id,id=window.acequire.id)):1==arguments.length&&(factory=id,deps=[],id=window.acequire.id),\\\"function\\\"!=typeof factory)return window.acequire.modules[id]={exports:factory,initialized:!0},void 0;deps.length||(deps=[\\\"require\\\",\\\"exports\\\",\\\"module\\\"]);var req=function(childId){return window.acequire(id,childId)};window.acequire.modules[id]={exports:{},factory:function(){var module=this,returnExports=factory.apply(this,deps.map(function(dep){switch(dep){case\\\"require\\\":return req;case\\\"exports\\\":return module.exports;case\\\"module\\\":return module;default:return req(dep)}}));return returnExports&&(module.exports=returnExports),module}}},window.define.amd={},acequire.tlns={},window.initBaseUrls=function(topLevelNamespaces){for(var i in topLevelNamespaces)acequire.tlns[i]=topLevelNamespaces[i]},window.initSender=function(){var EventEmitter=window.acequire(\\\"ace/lib/event_emitter\\\").EventEmitter,oop=window.acequire(\\\"ace/lib/oop\\\"),Sender=function(){};return function(){oop.implement(this,EventEmitter),this.callback=function(data,callbackId){postMessage({type:\\\"call\\\",id:callbackId,data:data})},this.emit=function(name,data){postMessage({type:\\\"event\\\",name:name,data:data})}}.call(Sender.prototype),new Sender};var main=window.main=null,sender=window.sender=null;window.onmessage=function(e){var msg=e.data;if(msg.event&&sender)sender._signal(msg.event,msg.data);else if(msg.command)if(main[msg.command])main[msg.command].apply(main,msg.args);else{if(!window[msg.command])throw Error(\\\"Unknown command:\\\"+msg.command);window[msg.command].apply(window,msg.args)}else if(msg.init){window.initBaseUrls(msg.tlns),acequire(\\\"ace/lib/es5-shim\\\"),sender=window.sender=window.initSender();var clazz=acequire(msg.module)[msg.classname];main=window.main=new clazz(sender)}}}})(this),ace.define(\\\"ace/lib/oop\\\",[\\\"require\\\",\\\"exports\\\",\\\"module\\\"],function(acequire,exports){\\\"use strict\\\";exports.inherits=function(ctor,superCtor){ctor.super_=superCtor,ctor.prototype=Object.create(superCtor.prototype,{constructor:{value:ctor,enumerable:!1,writable:!0,configurable:!0}})},exports.mixin=function(obj,mixin){for(var key in mixin)obj[key]=mixin[key];return obj},exports.implement=function(proto,mixin){exports.mixin(proto,mixin)}}),ace.define(\\\"ace/range\\\",[\\\"require\\\",\\\"exports\\\",\\\"module\\\"],function(acequire,exports){\\\"use strict\\\";var comparePoints=function(p1,p2){return p1.row-p2.row||p1.column-p2.column},Range=function(startRow,startColumn,endRow,endColumn){this.start={row:startRow,column:startColumn},this.end={row:endRow,column:endColumn}};(function(){this.isEqual=function(range){return this.start.row===range.start.row&&this.end.row===range.end.row&&this.start.column===range.start.column&&this.end.column===range.end.column},this.toString=function(){return\\\"Range: [\\\"+this.start.row+\\\"/\\\"+this.start.column+\\\"] -> [\\\"+this.end.row+\\\"/\\\"+this.end.column+\\\"]\\\"},this.contains=function(row,column){return 0==this.compare(row,column)},this.compareRange=function(range){var cmp,end=range.end,start=range.start;return cmp=this.compare(end.row,end.column),1==cmp?(cmp=this.compare(start.row,start.column),1==cmp?2:0==cmp?1:0):-1==cmp?-2:(cmp=this.compare(start.row,start.column),-1==cmp?-1:1==cmp?42:0)},this.comparePoint=function(p){return this.compare(p.row,p.column)},this.containsRange=function(range){return 0==this.comparePoint(range.start)&&0==this.comparePoint(range.end)},this.intersects=function(range){var cmp=this.compareRange(range);return-1==cmp||0==cmp||1==cmp},this.isEnd=function(row,column){return this.end.row==row&&this.end.column==column},this.isStart=function(row,column){return this.start.row==row&&this.start.column==column},this.setStart=function(row,column){\\\"object\\\"==typeof row?(this.start.column=row.column,this.start.row=row.row):(this.start.row=row,this.start.column=column)},this.setEnd=function(row,column){\\\"object\\\"==typeof row?(this.end.column=row.column,this.end.row=row.row):(this.end.row=row,this.end.column=column)},this.inside=function(row,column){return 0==this.compare(row,column)?this.isEnd(row,column)||this.isStart(row,column)?!1:!0:!1},this.insideStart=function(row,column){return 0==this.compare(row,column)?this.isEnd(row,column)?!1:!0:!1},this.insideEnd=function(row,column){return 0==this.compare(row,column)?this.isStart(row,column)?!1:!0:!1},this.compare=function(row,column){return this.isMultiLine()||row!==this.start.row?this.start.row>row?-1:row>this.end.row?1:this.start.row===row?column>=this.start.column?0:-1:this.end.row===row?this.end.column>=column?0:1:0:this.start.column>column?-1:column>this.end.column?1:0},this.compareStart=function(row,column){return this.start.row==row&&this.start.column==column?-1:this.compare(row,column)},this.compareEnd=function(row,column){return this.end.row==row&&this.end.column==column?1:this.compare(row,column)},this.compareInside=function(row,column){return this.end.row==row&&this.end.column==column?1:this.start.row==row&&this.start.column==column?-1:this.compare(row,column)},this.clipRows=function(firstRow,lastRow){if(this.end.row>lastRow)var end={row:lastRow+1,column:0};else if(firstRow>this.end.row)var end={row:firstRow,column:0};if(this.start.row>lastRow)var start={row:lastRow+1,column:0};else if(firstRow>this.start.row)var start={row:firstRow,column:0};return Range.fromPoints(start||this.start,end||this.end)},this.extend=function(row,column){var cmp=this.compare(row,column);if(0==cmp)return this;if(-1==cmp)var start={row:row,column:column};else var end={row:row,column:column};return Range.fromPoints(start||this.start,end||this.end)},this.isEmpty=function(){return this.start.row===this.end.row&&this.start.column===this.end.column},this.isMultiLine=function(){return this.start.row!==this.end.row},this.clone=function(){return Range.fromPoints(this.start,this.end)},this.collapseRows=function(){return 0==this.end.column?new Range(this.start.row,0,Math.max(this.start.row,this.end.row-1),0):new Range(this.start.row,0,this.end.row,0)},this.toScreenRange=function(session){var screenPosStart=session.documentToScreenPosition(this.start),screenPosEnd=session.documentToScreenPosition(this.end);return new Range(screenPosStart.row,screenPosStart.column,screenPosEnd.row,screenPosEnd.column)},this.moveBy=function(row,column){this.start.row+=row,this.start.column+=column,this.end.row+=row,this.end.column+=column}}).call(Range.prototype),Range.fromPoints=function(start,end){return new Range(start.row,start.column,end.row,end.column)},Range.comparePoints=comparePoints,Range.comparePoints=function(p1,p2){return p1.row-p2.row||p1.column-p2.column},exports.Range=Range}),ace.define(\\\"ace/apply_delta\\\",[\\\"require\\\",\\\"exports\\\",\\\"module\\\"],function(acequire,exports){\\\"use strict\\\";exports.applyDelta=function(docLines,delta){var row=delta.start.row,startColumn=delta.start.column,line=docLines[row]||\\\"\\\";switch(delta.action){case\\\"insert\\\":var lines=delta.lines;if(1===lines.length)docLines[row]=line.substring(0,startColumn)+delta.lines[0]+line.substring(startColumn);else{var args=[row,1].concat(delta.lines);docLines.splice.apply(docLines,args),docLines[row]=line.substring(0,startColumn)+docLines[row],docLines[row+delta.lines.length-1]+=line.substring(startColumn)}break;case\\\"remove\\\":var endColumn=delta.end.column,endRow=delta.end.row;row===endRow?docLines[row]=line.substring(0,startColumn)+line.substring(endColumn):docLines.splice(row,endRow-row+1,line.substring(0,startColumn)+docLines[endRow].substring(endColumn))}}}),ace.define(\\\"ace/lib/event_emitter\\\",[\\\"require\\\",\\\"exports\\\",\\\"module\\\"],function(acequire,exports){\\\"use strict\\\";var EventEmitter={},stopPropagation=function(){this.propagationStopped=!0},preventDefault=function(){this.defaultPrevented=!0};EventEmitter._emit=EventEmitter._dispatchEvent=function(eventName,e){this._eventRegistry||(this._eventRegistry={}),this._defaultHandlers||(this._defaultHandlers={});var listeners=this._eventRegistry[eventName]||[],defaultHandler=this._defaultHandlers[eventName];if(listeners.length||defaultHandler){\\\"object\\\"==typeof e&&e||(e={}),e.type||(e.type=eventName),e.stopPropagation||(e.stopPropagation=stopPropagation),e.preventDefault||(e.preventDefault=preventDefault),listeners=listeners.slice();for(var i=0;listeners.length>i&&(listeners[i](e,this),!e.propagationStopped);i++);return defaultHandler&&!e.defaultPrevented?defaultHandler(e,this):void 0}},EventEmitter._signal=function(eventName,e){var listeners=(this._eventRegistry||{})[eventName];if(listeners){listeners=listeners.slice();for(var i=0;listeners.length>i;i++)listeners[i](e,this)}},EventEmitter.once=function(eventName,callback){var _self=this;callback&&this.addEventListener(eventName,function newCallback(){_self.removeEventListener(eventName,newCallback),callback.apply(null,arguments)})},EventEmitter.setDefaultHandler=function(eventName,callback){var handlers=this._defaultHandlers;if(handlers||(handlers=this._defaultHandlers={_disabled_:{}}),handlers[eventName]){var old=handlers[eventName],disabled=handlers._disabled_[eventName];disabled||(handlers._disabled_[eventName]=disabled=[]),disabled.push(old);var i=disabled.indexOf(callback);-1!=i&&disabled.splice(i,1)}handlers[eventName]=callback},EventEmitter.removeDefaultHandler=function(eventName,callback){var handlers=this._defaultHandlers;if(handlers){var disabled=handlers._disabled_[eventName];if(handlers[eventName]==callback)handlers[eventName],disabled&&this.setDefaultHandler(eventName,disabled.pop());else if(disabled){var i=disabled.indexOf(callback);-1!=i&&disabled.splice(i,1)}}},EventEmitter.on=EventEmitter.addEventListener=function(eventName,callback,capturing){this._eventRegistry=this._eventRegistry||{};var listeners=this._eventRegistry[eventName];return listeners||(listeners=this._eventRegistry[eventName]=[]),-1==listeners.indexOf(callback)&&listeners[capturing?\\\"unshift\\\":\\\"push\\\"](callback),callback},EventEmitter.off=EventEmitter.removeListener=EventEmitter.removeEventListener=function(eventName,callback){this._eventRegistry=this._eventRegistry||{};var listeners=this._eventRegistry[eventName];if(listeners){var index=listeners.indexOf(callback);-1!==index&&listeners.splice(index,1)}},EventEmitter.removeAllListeners=function(eventName){this._eventRegistry&&(this._eventRegistry[eventName]=[])},exports.EventEmitter=EventEmitter}),ace.define(\\\"ace/anchor\\\",[\\\"require\\\",\\\"exports\\\",\\\"module\\\",\\\"ace/lib/oop\\\",\\\"ace/lib/event_emitter\\\"],function(acequire,exports){\\\"use strict\\\";var oop=acequire(\\\"./lib/oop\\\"),EventEmitter=acequire(\\\"./lib/event_emitter\\\").EventEmitter,Anchor=exports.Anchor=function(doc,row,column){this.$onChange=this.onChange.bind(this),this.attach(doc),column===void 0?this.setPosition(row.row,row.column):this.setPosition(row,column)};(function(){function $pointsInOrder(point1,point2,equalPointsInOrder){var bColIsAfter=equalPointsInOrder?point1.column<=point2.column:point1.columnthis.row)){var point=$getTransformedPoint(delta,{row:this.row,column:this.column},this.$insertRight);this.setPosition(point.row,point.column,!0)}},this.setPosition=function(row,column,noClip){var pos;if(pos=noClip?{row:row,column:column}:this.$clipPositionToDocument(row,column),this.row!=pos.row||this.column!=pos.column){var old={row:this.row,column:this.column};this.row=pos.row,this.column=pos.column,this._signal(\\\"change\\\",{old:old,value:pos})}},this.detach=function(){this.document.removeEventListener(\\\"change\\\",this.$onChange)},this.attach=function(doc){this.document=doc||this.document,this.document.on(\\\"change\\\",this.$onChange)},this.$clipPositionToDocument=function(row,column){var pos={};return row>=this.document.getLength()?(pos.row=Math.max(0,this.document.getLength()-1),pos.column=this.document.getLine(pos.row).length):0>row?(pos.row=0,pos.column=0):(pos.row=row,pos.column=Math.min(this.document.getLine(pos.row).length,Math.max(0,column))),0>column&&(pos.column=0),pos}}).call(Anchor.prototype)}),ace.define(\\\"ace/document\\\",[\\\"require\\\",\\\"exports\\\",\\\"module\\\",\\\"ace/lib/oop\\\",\\\"ace/apply_delta\\\",\\\"ace/lib/event_emitter\\\",\\\"ace/range\\\",\\\"ace/anchor\\\"],function(acequire,exports){\\\"use strict\\\";var oop=acequire(\\\"./lib/oop\\\"),applyDelta=acequire(\\\"./apply_delta\\\").applyDelta,EventEmitter=acequire(\\\"./lib/event_emitter\\\").EventEmitter,Range=acequire(\\\"./range\\\").Range,Anchor=acequire(\\\"./anchor\\\").Anchor,Document=function(textOrLines){this.$lines=[\\\"\\\"],0===textOrLines.length?this.$lines=[\\\"\\\"]:Array.isArray(textOrLines)?this.insertMergedLines({row:0,column:0},textOrLines):this.insert({row:0,column:0},textOrLines)};(function(){oop.implement(this,EventEmitter),this.setValue=function(text){var len=this.getLength()-1;this.remove(new Range(0,0,len,this.getLine(len).length)),this.insert({row:0,column:0},text)},this.getValue=function(){return this.getAllLines().join(this.getNewLineCharacter())},this.createAnchor=function(row,column){return new Anchor(this,row,column)},this.$split=0===\\\"aaa\\\".split(/a/).length?function(text){return text.replace(/\\\\r\\\\n|\\\\r/g,\\\"\\\\n\\\").split(\\\"\\\\n\\\")}:function(text){return text.split(/\\\\r\\\\n|\\\\r|\\\\n/)},this.$detectNewLine=function(text){var match=text.match(/^.*?(\\\\r\\\\n|\\\\r|\\\\n)/m);this.$autoNewLine=match?match[1]:\\\"\\\\n\\\",this._signal(\\\"changeNewLineMode\\\")},this.getNewLineCharacter=function(){switch(this.$newLineMode){case\\\"windows\\\":return\\\"\\\\r\\\\n\\\";case\\\"unix\\\":return\\\"\\\\n\\\";default:return this.$autoNewLine||\\\"\\\\n\\\"}},this.$autoNewLine=\\\"\\\",this.$newLineMode=\\\"auto\\\",this.setNewLineMode=function(newLineMode){this.$newLineMode!==newLineMode&&(this.$newLineMode=newLineMode,this._signal(\\\"changeNewLineMode\\\"))},this.getNewLineMode=function(){return this.$newLineMode},this.isNewLine=function(text){return\\\"\\\\r\\\\n\\\"==text||\\\"\\\\r\\\"==text||\\\"\\\\n\\\"==text},this.getLine=function(row){return this.$lines[row]||\\\"\\\"},this.getLines=function(firstRow,lastRow){return this.$lines.slice(firstRow,lastRow+1)},this.getAllLines=function(){return this.getLines(0,this.getLength())},this.getLength=function(){return this.$lines.length},this.getTextRange=function(range){return this.getLinesForRange(range).join(this.getNewLineCharacter())},this.getLinesForRange=function(range){var lines;if(range.start.row===range.end.row)lines=[this.getLine(range.start.row).substring(range.start.column,range.end.column)];else{lines=this.getLines(range.start.row,range.end.row),lines[0]=(lines[0]||\\\"\\\").substring(range.start.column);var l=lines.length-1;range.end.row-range.start.row==l&&(lines[l]=lines[l].substring(0,range.end.column))}return lines},this.insertLines=function(row,lines){return console.warn(\\\"Use of document.insertLines is deprecated. Use the insertFullLines method instead.\\\"),this.insertFullLines(row,lines)},this.removeLines=function(firstRow,lastRow){return console.warn(\\\"Use of document.removeLines is deprecated. Use the removeFullLines method instead.\\\"),this.removeFullLines(firstRow,lastRow)},this.insertNewLine=function(position){return console.warn(\\\"Use of document.insertNewLine is deprecated. Use insertMergedLines(position, ['', '']) instead.\\\"),this.insertMergedLines(position,[\\\"\\\",\\\"\\\"])},this.insert=function(position,text){return 1>=this.getLength()&&this.$detectNewLine(text),this.insertMergedLines(position,this.$split(text))},this.insertInLine=function(position,text){var start=this.clippedPos(position.row,position.column),end=this.pos(position.row,position.column+text.length);return this.applyDelta({start:start,end:end,action:\\\"insert\\\",lines:[text]},!0),this.clonePos(end)},this.clippedPos=function(row,column){var length=this.getLength();void 0===row?row=length:0>row?row=0:row>=length&&(row=length-1,column=void 0);var line=this.getLine(row);return void 0==column&&(column=line.length),column=Math.min(Math.max(column,0),line.length),{row:row,column:column}},this.clonePos=function(pos){return{row:pos.row,column:pos.column}},this.pos=function(row,column){return{row:row,column:column}},this.$clipPosition=function(position){var length=this.getLength();return position.row>=length?(position.row=Math.max(0,length-1),position.column=this.getLine(length-1).length):(position.row=Math.max(0,position.row),position.column=Math.min(Math.max(position.column,0),this.getLine(position.row).length)),position},this.insertFullLines=function(row,lines){row=Math.min(Math.max(row,0),this.getLength());var column=0;this.getLength()>row?(lines=lines.concat([\\\"\\\"]),column=0):(lines=[\\\"\\\"].concat(lines),row--,column=this.$lines[row].length),this.insertMergedLines({row:row,column:column},lines)},this.insertMergedLines=function(position,lines){var start=this.clippedPos(position.row,position.column),end={row:start.row+lines.length-1,column:(1==lines.length?start.column:0)+lines[lines.length-1].length};return this.applyDelta({start:start,end:end,action:\\\"insert\\\",lines:lines}),this.clonePos(end)},this.remove=function(range){var start=this.clippedPos(range.start.row,range.start.column),end=this.clippedPos(range.end.row,range.end.column);return this.applyDelta({start:start,end:end,action:\\\"remove\\\",lines:this.getLinesForRange({start:start,end:end})}),this.clonePos(start)},this.removeInLine=function(row,startColumn,endColumn){var start=this.clippedPos(row,startColumn),end=this.clippedPos(row,endColumn);return this.applyDelta({start:start,end:end,action:\\\"remove\\\",lines:this.getLinesForRange({start:start,end:end})},!0),this.clonePos(start)},this.removeFullLines=function(firstRow,lastRow){firstRow=Math.min(Math.max(0,firstRow),this.getLength()-1),lastRow=Math.min(Math.max(0,lastRow),this.getLength()-1);var deleteFirstNewLine=lastRow==this.getLength()-1&&firstRow>0,deleteLastNewLine=this.getLength()-1>lastRow,startRow=deleteFirstNewLine?firstRow-1:firstRow,startCol=deleteFirstNewLine?this.getLine(startRow).length:0,endRow=deleteLastNewLine?lastRow+1:lastRow,endCol=deleteLastNewLine?0:this.getLine(endRow).length,range=new Range(startRow,startCol,endRow,endCol),deletedLines=this.$lines.slice(firstRow,lastRow+1);return this.applyDelta({start:range.start,end:range.end,action:\\\"remove\\\",lines:this.getLinesForRange(range)}),deletedLines},this.removeNewLine=function(row){this.getLength()-1>row&&row>=0&&this.applyDelta({start:this.pos(row,this.getLine(row).length),end:this.pos(row+1,0),action:\\\"remove\\\",lines:[\\\"\\\",\\\"\\\"]})},this.replace=function(range,text){if(range instanceof Range||(range=Range.fromPoints(range.start,range.end)),0===text.length&&range.isEmpty())return range.start;if(text==this.getTextRange(range))return range.end;this.remove(range);var end;return end=text?this.insert(range.start,text):range.start},this.applyDeltas=function(deltas){for(var i=0;deltas.length>i;i++)this.applyDelta(deltas[i])},this.revertDeltas=function(deltas){for(var i=deltas.length-1;i>=0;i--)this.revertDelta(deltas[i])},this.applyDelta=function(delta,doNotValidate){var isInsert=\\\"insert\\\"==delta.action;(isInsert?1>=delta.lines.length&&!delta.lines[0]:!Range.comparePoints(delta.start,delta.end))||(isInsert&&delta.lines.length>2e4&&this.$splitAndapplyLargeDelta(delta,2e4),applyDelta(this.$lines,delta,doNotValidate),this._signal(\\\"change\\\",delta))},this.$splitAndapplyLargeDelta=function(delta,MAX){for(var lines=delta.lines,l=lines.length,row=delta.start.row,column=delta.start.column,from=0,to=0;;){from=to,to+=MAX-1;var chunk=lines.slice(from,to);if(to>l){delta.lines=chunk,delta.start.row=row+from,delta.start.column=column;break}chunk.push(\\\"\\\"),this.applyDelta({start:this.pos(row+from,column),end:this.pos(row+to,column=0),action:delta.action,lines:chunk},!0)}},this.revertDelta=function(delta){this.applyDelta({start:this.clonePos(delta.start),end:this.clonePos(delta.end),action:\\\"insert\\\"==delta.action?\\\"remove\\\":\\\"insert\\\",lines:delta.lines.slice()})},this.indexToPosition=function(index,startRow){for(var lines=this.$lines||this.getAllLines(),newlineLength=this.getNewLineCharacter().length,i=startRow||0,l=lines.length;l>i;i++)if(index-=lines[i].length+newlineLength,0>index)return{row:i,column:index+lines[i].length+newlineLength};return{row:l-1,column:lines[l-1].length}},this.positionToIndex=function(pos,startRow){for(var lines=this.$lines||this.getAllLines(),newlineLength=this.getNewLineCharacter().length,index=0,row=Math.min(pos.row,lines.length),i=startRow||0;row>i;++i)index+=lines[i].length+newlineLength;return index+pos.column}}).call(Document.prototype),exports.Document=Document}),ace.define(\\\"ace/lib/lang\\\",[\\\"require\\\",\\\"exports\\\",\\\"module\\\"],function(acequire,exports){\\\"use strict\\\";exports.last=function(a){return a[a.length-1]},exports.stringReverse=function(string){return string.split(\\\"\\\").reverse().join(\\\"\\\")},exports.stringRepeat=function(string,count){for(var result=\\\"\\\";count>0;)1&count&&(result+=string),(count>>=1)&&(string+=string);return result};var trimBeginRegexp=/^\\\\s\\\\s*/,trimEndRegexp=/\\\\s\\\\s*$/;exports.stringTrimLeft=function(string){return string.replace(trimBeginRegexp,\\\"\\\")},exports.stringTrimRight=function(string){return string.replace(trimEndRegexp,\\\"\\\")},exports.copyObject=function(obj){var copy={};for(var key in obj)copy[key]=obj[key];return copy},exports.copyArray=function(array){for(var copy=[],i=0,l=array.length;l>i;i++)copy[i]=array[i]&&\\\"object\\\"==typeof array[i]?this.copyObject(array[i]):array[i];return copy},exports.deepCopy=function deepCopy(obj){if(\\\"object\\\"!=typeof obj||!obj)return obj;var copy;if(Array.isArray(obj)){copy=[];for(var key=0;obj.length>key;key++)copy[key]=deepCopy(obj[key]);return copy}var cons=obj.constructor;if(cons===RegExp)return obj;copy=cons();for(var key in obj)copy[key]=deepCopy(obj[key]);return copy},exports.arrayToMap=function(arr){for(var map={},i=0;arr.length>i;i++)map[arr[i]]=1;return map},exports.createMap=function(props){var map=Object.create(null);for(var i in props)map[i]=props[i];return map},exports.arrayRemove=function(array,value){for(var i=0;array.length>=i;i++)value===array[i]&&array.splice(i,1)},exports.escapeRegExp=function(str){return str.replace(/([.*+?^${}()|[\\\\]\\\\/\\\\\\\\])/g,\\\"\\\\\\\\$1\\\")},exports.escapeHTML=function(str){return str.replace(/&/g,\\\"&\\\").replace(/\\\"/g,\\\""\\\").replace(/'/g,\\\"'\\\").replace(/i;i+=2){if(Array.isArray(data[i+1]))var d={action:\\\"insert\\\",start:data[i],lines:data[i+1]};else var d={action:\\\"remove\\\",start:data[i],end:data[i+1]};doc.applyDelta(d,!0)}return _self.$timeout?deferredUpdate.schedule(_self.$timeout):(_self.onUpdate(),void 0)})};(function(){this.$timeout=500,this.setTimeout=function(timeout){this.$timeout=timeout},this.setValue=function(value){this.doc.setValue(value),this.deferredUpdate.schedule(this.$timeout)},this.getValue=function(callbackId){this.sender.callback(this.doc.getValue(),callbackId)},this.onUpdate=function(){},this.isPending=function(){return this.deferredUpdate.isPending()}}).call(Mirror.prototype)}),ace.define(\\\"ace/mode/json/json_parse\\\",[\\\"require\\\",\\\"exports\\\",\\\"module\\\"],function(){\\\"use strict\\\";var at,ch,text,value,escapee={'\\\"':'\\\"',\\\"\\\\\\\\\\\":\\\"\\\\\\\\\\\",\\\"/\\\":\\\"/\\\",b:\\\"\\\\b\\\",f:\\\"\\\\f\\\",n:\\\"\\\\n\\\",r:\\\"\\\\r\\\",t:\\\"\\t\\\"},error=function(m){throw{name:\\\"SyntaxError\\\",message:m,at:at,text:text}},next=function(c){return c&&c!==ch&&error(\\\"Expected '\\\"+c+\\\"' instead of '\\\"+ch+\\\"'\\\"),ch=text.charAt(at),at+=1,ch},number=function(){var number,string=\\\"\\\";for(\\\"-\\\"===ch&&(string=\\\"-\\\",next(\\\"-\\\"));ch>=\\\"0\\\"&&\\\"9\\\">=ch;)string+=ch,next();if(\\\".\\\"===ch)for(string+=\\\".\\\";next()&&ch>=\\\"0\\\"&&\\\"9\\\">=ch;)string+=ch;if(\\\"e\\\"===ch||\\\"E\\\"===ch)for(string+=ch,next(),(\\\"-\\\"===ch||\\\"+\\\"===ch)&&(string+=ch,next());ch>=\\\"0\\\"&&\\\"9\\\">=ch;)string+=ch,next();return number=+string,isNaN(number)?(error(\\\"Bad number\\\"),void 0):number},string=function(){var hex,i,uffff,string=\\\"\\\";if('\\\"'===ch)for(;next();){if('\\\"'===ch)return next(),string;if(\\\"\\\\\\\\\\\"===ch)if(next(),\\\"u\\\"===ch){for(uffff=0,i=0;4>i&&(hex=parseInt(next(),16),isFinite(hex));i+=1)uffff=16*uffff+hex;string+=String.fromCharCode(uffff)}else{if(\\\"string\\\"!=typeof escapee[ch])break;string+=escapee[ch]}else string+=ch}error(\\\"Bad string\\\")},white=function(){for(;ch&&\\\" \\\">=ch;)next()},word=function(){switch(ch){case\\\"t\\\":return next(\\\"t\\\"),next(\\\"r\\\"),next(\\\"u\\\"),next(\\\"e\\\"),!0;case\\\"f\\\":return next(\\\"f\\\"),next(\\\"a\\\"),next(\\\"l\\\"),next(\\\"s\\\"),next(\\\"e\\\"),!1;case\\\"n\\\":return next(\\\"n\\\"),next(\\\"u\\\"),next(\\\"l\\\"),next(\\\"l\\\"),null}error(\\\"Unexpected '\\\"+ch+\\\"'\\\")},array=function(){var array=[];if(\\\"[\\\"===ch){if(next(\\\"[\\\"),white(),\\\"]\\\"===ch)return next(\\\"]\\\"),array;for(;ch;){if(array.push(value()),white(),\\\"]\\\"===ch)return next(\\\"]\\\"),array;next(\\\",\\\"),white()}}error(\\\"Bad array\\\")},object=function(){var key,object={};if(\\\"{\\\"===ch){if(next(\\\"{\\\"),white(),\\\"}\\\"===ch)return next(\\\"}\\\"),object;for(;ch;){if(key=string(),white(),next(\\\":\\\"),Object.hasOwnProperty.call(object,key)&&error('Duplicate key \\\"'+key+'\\\"'),object[key]=value(),white(),\\\"}\\\"===ch)return next(\\\"}\\\"),object;next(\\\",\\\"),white()}}error(\\\"Bad object\\\")};return value=function(){switch(white(),ch){case\\\"{\\\":return object();case\\\"[\\\":return array();case'\\\"':return string();case\\\"-\\\":return number();default:return ch>=\\\"0\\\"&&\\\"9\\\">=ch?number():word()}},function(source,reviver){var result;return text=source,at=0,ch=\\\" \\\",result=value(),white(),ch&&error(\\\"Syntax error\\\"),\\\"function\\\"==typeof reviver?function walk(holder,key){var k,v,value=holder[key];if(value&&\\\"object\\\"==typeof value)for(k in value)Object.hasOwnProperty.call(value,k)&&(v=walk(value,k),void 0!==v?value[k]=v:delete value[k]);return reviver.call(holder,key,value)}({\\\"\\\":result},\\\"\\\"):result}}),ace.define(\\\"ace/mode/json_worker\\\",[\\\"require\\\",\\\"exports\\\",\\\"module\\\",\\\"ace/lib/oop\\\",\\\"ace/worker/mirror\\\",\\\"ace/mode/json/json_parse\\\"],function(acequire,exports){\\\"use strict\\\";var oop=acequire(\\\"../lib/oop\\\"),Mirror=acequire(\\\"../worker/mirror\\\").Mirror,parse=acequire(\\\"./json/json_parse\\\"),JsonWorker=exports.JsonWorker=function(sender){Mirror.call(this,sender),this.setTimeout(200)};oop.inherits(JsonWorker,Mirror),function(){this.onUpdate=function(){var value=this.doc.getValue(),errors=[];try{value&&parse(value)}catch(e){var pos=this.doc.indexToPosition(e.at-1);errors.push({row:pos.row,column:pos.column,text:e.message,type:\\\"error\\\"})}this.sender.emit(\\\"annotate\\\",errors)}}.call(JsonWorker.prototype)}),ace.define(\\\"ace/lib/es5-shim\\\",[\\\"require\\\",\\\"exports\\\",\\\"module\\\"],function(){function Empty(){}function doesDefinePropertyWork(object){try{return Object.defineProperty(object,\\\"sentinel\\\",{}),\\\"sentinel\\\"in object}catch(exception){}}function toInteger(n){return n=+n,n!==n?n=0:0!==n&&n!==1/0&&n!==-(1/0)&&(n=(n>0||-1)*Math.floor(Math.abs(n))),n}Function.prototype.bind||(Function.prototype.bind=function(that){var target=this;if(\\\"function\\\"!=typeof target)throw new TypeError(\\\"Function.prototype.bind called on incompatible \\\"+target);var args=slice.call(arguments,1),bound=function(){if(this instanceof bound){var result=target.apply(this,args.concat(slice.call(arguments)));return Object(result)===result?result:this}return target.apply(that,args.concat(slice.call(arguments)))};return target.prototype&&(Empty.prototype=target.prototype,bound.prototype=new Empty,Empty.prototype=null),bound});var defineGetter,defineSetter,lookupGetter,lookupSetter,supportsAccessors,call=Function.prototype.call,prototypeOfArray=Array.prototype,prototypeOfObject=Object.prototype,slice=prototypeOfArray.slice,_toString=call.bind(prototypeOfObject.toString),owns=call.bind(prototypeOfObject.hasOwnProperty);if((supportsAccessors=owns(prototypeOfObject,\\\"__defineGetter__\\\"))&&(defineGetter=call.bind(prototypeOfObject.__defineGetter__),defineSetter=call.bind(prototypeOfObject.__defineSetter__),lookupGetter=call.bind(prototypeOfObject.__lookupGetter__),lookupSetter=call.bind(prototypeOfObject.__lookupSetter__)),2!=[1,2].splice(0).length)if(function(){function makeArray(l){var a=Array(l+2);return a[0]=a[1]=0,a}var lengthBefore,array=[];return array.splice.apply(array,makeArray(20)),array.splice.apply(array,makeArray(26)),lengthBefore=array.length,array.splice(5,0,\\\"XXX\\\"),lengthBefore+1==array.length,lengthBefore+1==array.length?!0:void 0\\n}()){var array_splice=Array.prototype.splice;Array.prototype.splice=function(start,deleteCount){return arguments.length?array_splice.apply(this,[void 0===start?0:start,void 0===deleteCount?this.length-start:deleteCount].concat(slice.call(arguments,2))):[]}}else Array.prototype.splice=function(pos,removeCount){var length=this.length;pos>0?pos>length&&(pos=length):void 0==pos?pos=0:0>pos&&(pos=Math.max(length+pos,0)),length>pos+removeCount||(removeCount=length-pos);var removed=this.slice(pos,pos+removeCount),insert=slice.call(arguments,2),add=insert.length;if(pos===length)add&&this.push.apply(this,insert);else{var remove=Math.min(removeCount,length-pos),tailOldPos=pos+remove,tailNewPos=tailOldPos+add-remove,tailCount=length-tailOldPos,lengthAfterRemove=length-remove;if(tailOldPos>tailNewPos)for(var i=0;tailCount>i;++i)this[tailNewPos+i]=this[tailOldPos+i];else if(tailNewPos>tailOldPos)for(i=tailCount;i--;)this[tailNewPos+i]=this[tailOldPos+i];if(add&&pos===lengthAfterRemove)this.length=lengthAfterRemove,this.push.apply(this,insert);else for(this.length=lengthAfterRemove+add,i=0;add>i;++i)this[pos+i]=insert[i]}return removed};Array.isArray||(Array.isArray=function(obj){return\\\"[object Array]\\\"==_toString(obj)});var boxedString=Object(\\\"a\\\"),splitString=\\\"a\\\"!=boxedString[0]||!(0 in boxedString);if(Array.prototype.forEach||(Array.prototype.forEach=function(fun){var object=toObject(this),self=splitString&&\\\"[object String]\\\"==_toString(this)?this.split(\\\"\\\"):object,thisp=arguments[1],i=-1,length=self.length>>>0;if(\\\"[object Function]\\\"!=_toString(fun))throw new TypeError;for(;length>++i;)i in self&&fun.call(thisp,self[i],i,object)}),Array.prototype.map||(Array.prototype.map=function(fun){var object=toObject(this),self=splitString&&\\\"[object String]\\\"==_toString(this)?this.split(\\\"\\\"):object,length=self.length>>>0,result=Array(length),thisp=arguments[1];if(\\\"[object Function]\\\"!=_toString(fun))throw new TypeError(fun+\\\" is not a function\\\");for(var i=0;length>i;i++)i in self&&(result[i]=fun.call(thisp,self[i],i,object));return result}),Array.prototype.filter||(Array.prototype.filter=function(fun){var value,object=toObject(this),self=splitString&&\\\"[object String]\\\"==_toString(this)?this.split(\\\"\\\"):object,length=self.length>>>0,result=[],thisp=arguments[1];if(\\\"[object Function]\\\"!=_toString(fun))throw new TypeError(fun+\\\" is not a function\\\");for(var i=0;length>i;i++)i in self&&(value=self[i],fun.call(thisp,value,i,object)&&result.push(value));return result}),Array.prototype.every||(Array.prototype.every=function(fun){var object=toObject(this),self=splitString&&\\\"[object String]\\\"==_toString(this)?this.split(\\\"\\\"):object,length=self.length>>>0,thisp=arguments[1];if(\\\"[object Function]\\\"!=_toString(fun))throw new TypeError(fun+\\\" is not a function\\\");for(var i=0;length>i;i++)if(i in self&&!fun.call(thisp,self[i],i,object))return!1;return!0}),Array.prototype.some||(Array.prototype.some=function(fun){var object=toObject(this),self=splitString&&\\\"[object String]\\\"==_toString(this)?this.split(\\\"\\\"):object,length=self.length>>>0,thisp=arguments[1];if(\\\"[object Function]\\\"!=_toString(fun))throw new TypeError(fun+\\\" is not a function\\\");for(var i=0;length>i;i++)if(i in self&&fun.call(thisp,self[i],i,object))return!0;return!1}),Array.prototype.reduce||(Array.prototype.reduce=function(fun){var object=toObject(this),self=splitString&&\\\"[object String]\\\"==_toString(this)?this.split(\\\"\\\"):object,length=self.length>>>0;if(\\\"[object Function]\\\"!=_toString(fun))throw new TypeError(fun+\\\" is not a function\\\");if(!length&&1==arguments.length)throw new TypeError(\\\"reduce of empty array with no initial value\\\");var result,i=0;if(arguments.length>=2)result=arguments[1];else for(;;){if(i in self){result=self[i++];break}if(++i>=length)throw new TypeError(\\\"reduce of empty array with no initial value\\\")}for(;length>i;i++)i in self&&(result=fun.call(void 0,result,self[i],i,object));return result}),Array.prototype.reduceRight||(Array.prototype.reduceRight=function(fun){var object=toObject(this),self=splitString&&\\\"[object String]\\\"==_toString(this)?this.split(\\\"\\\"):object,length=self.length>>>0;if(\\\"[object Function]\\\"!=_toString(fun))throw new TypeError(fun+\\\" is not a function\\\");if(!length&&1==arguments.length)throw new TypeError(\\\"reduceRight of empty array with no initial value\\\");var result,i=length-1;if(arguments.length>=2)result=arguments[1];else for(;;){if(i in self){result=self[i--];break}if(0>--i)throw new TypeError(\\\"reduceRight of empty array with no initial value\\\")}do i in this&&(result=fun.call(void 0,result,self[i],i,object));while(i--);return result}),Array.prototype.indexOf&&-1==[0,1].indexOf(1,2)||(Array.prototype.indexOf=function(sought){var self=splitString&&\\\"[object String]\\\"==_toString(this)?this.split(\\\"\\\"):toObject(this),length=self.length>>>0;if(!length)return-1;var i=0;for(arguments.length>1&&(i=toInteger(arguments[1])),i=i>=0?i:Math.max(0,length+i);length>i;i++)if(i in self&&self[i]===sought)return i;return-1}),Array.prototype.lastIndexOf&&-1==[0,1].lastIndexOf(0,-3)||(Array.prototype.lastIndexOf=function(sought){var self=splitString&&\\\"[object String]\\\"==_toString(this)?this.split(\\\"\\\"):toObject(this),length=self.length>>>0;if(!length)return-1;var i=length-1;for(arguments.length>1&&(i=Math.min(i,toInteger(arguments[1]))),i=i>=0?i:length-Math.abs(i);i>=0;i--)if(i in self&&sought===self[i])return i;return-1}),Object.getPrototypeOf||(Object.getPrototypeOf=function(object){return object.__proto__||(object.constructor?object.constructor.prototype:prototypeOfObject)}),!Object.getOwnPropertyDescriptor){var ERR_NON_OBJECT=\\\"Object.getOwnPropertyDescriptor called on a non-object: \\\";Object.getOwnPropertyDescriptor=function(object,property){if(\\\"object\\\"!=typeof object&&\\\"function\\\"!=typeof object||null===object)throw new TypeError(ERR_NON_OBJECT+object);if(owns(object,property)){var descriptor,getter,setter;if(descriptor={enumerable:!0,configurable:!0},supportsAccessors){var prototype=object.__proto__;object.__proto__=prototypeOfObject;var getter=lookupGetter(object,property),setter=lookupSetter(object,property);if(object.__proto__=prototype,getter||setter)return getter&&(descriptor.get=getter),setter&&(descriptor.set=setter),descriptor}return descriptor.value=object[property],descriptor}}}if(Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(object){return Object.keys(object)}),!Object.create){var createEmpty;createEmpty=null===Object.prototype.__proto__?function(){return{__proto__:null}}:function(){var empty={};for(var i in empty)empty[i]=null;return empty.constructor=empty.hasOwnProperty=empty.propertyIsEnumerable=empty.isPrototypeOf=empty.toLocaleString=empty.toString=empty.valueOf=empty.__proto__=null,empty},Object.create=function(prototype,properties){var object;if(null===prototype)object=createEmpty();else{if(\\\"object\\\"!=typeof prototype)throw new TypeError(\\\"typeof prototype[\\\"+typeof prototype+\\\"] != 'object'\\\");var Type=function(){};Type.prototype=prototype,object=new Type,object.__proto__=prototype}return void 0!==properties&&Object.defineProperties(object,properties),object}}if(Object.defineProperty){var definePropertyWorksOnObject=doesDefinePropertyWork({}),definePropertyWorksOnDom=\\\"undefined\\\"==typeof document||doesDefinePropertyWork(document.createElement(\\\"div\\\"));if(!definePropertyWorksOnObject||!definePropertyWorksOnDom)var definePropertyFallback=Object.defineProperty}if(!Object.defineProperty||definePropertyFallback){var ERR_NON_OBJECT_DESCRIPTOR=\\\"Property description must be an object: \\\",ERR_NON_OBJECT_TARGET=\\\"Object.defineProperty called on non-object: \\\",ERR_ACCESSORS_NOT_SUPPORTED=\\\"getters & setters can not be defined on this javascript engine\\\";Object.defineProperty=function(object,property,descriptor){if(\\\"object\\\"!=typeof object&&\\\"function\\\"!=typeof object||null===object)throw new TypeError(ERR_NON_OBJECT_TARGET+object);if(\\\"object\\\"!=typeof descriptor&&\\\"function\\\"!=typeof descriptor||null===descriptor)throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR+descriptor);if(definePropertyFallback)try{return definePropertyFallback.call(Object,object,property,descriptor)}catch(exception){}if(owns(descriptor,\\\"value\\\"))if(supportsAccessors&&(lookupGetter(object,property)||lookupSetter(object,property))){var prototype=object.__proto__;object.__proto__=prototypeOfObject,delete object[property],object[property]=descriptor.value,object.__proto__=prototype}else object[property]=descriptor.value;else{if(!supportsAccessors)throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);owns(descriptor,\\\"get\\\")&&defineGetter(object,property,descriptor.get),owns(descriptor,\\\"set\\\")&&defineSetter(object,property,descriptor.set)}return object}}Object.defineProperties||(Object.defineProperties=function(object,properties){for(var property in properties)owns(properties,property)&&Object.defineProperty(object,property,properties[property]);return object}),Object.seal||(Object.seal=function(object){return object}),Object.freeze||(Object.freeze=function(object){return object});try{Object.freeze(function(){})}catch(exception){Object.freeze=function(freezeObject){return function(object){return\\\"function\\\"==typeof object?object:freezeObject(object)}}(Object.freeze)}if(Object.preventExtensions||(Object.preventExtensions=function(object){return object}),Object.isSealed||(Object.isSealed=function(){return!1}),Object.isFrozen||(Object.isFrozen=function(){return!1}),Object.isExtensible||(Object.isExtensible=function(object){if(Object(object)===object)throw new TypeError;for(var name=\\\"\\\";owns(object,name);)name+=\\\"?\\\";object[name]=!0;var returnValue=owns(object,name);return delete object[name],returnValue}),!Object.keys){var hasDontEnumBug=!0,dontEnums=[\\\"toString\\\",\\\"toLocaleString\\\",\\\"valueOf\\\",\\\"hasOwnProperty\\\",\\\"isPrototypeOf\\\",\\\"propertyIsEnumerable\\\",\\\"constructor\\\"],dontEnumsLength=dontEnums.length;for(var key in{toString:null})hasDontEnumBug=!1;Object.keys=function(object){if(\\\"object\\\"!=typeof object&&\\\"function\\\"!=typeof object||null===object)throw new TypeError(\\\"Object.keys called on a non-object\\\");var keys=[];for(var name in object)owns(object,name)&&keys.push(name);if(hasDontEnumBug)for(var i=0,ii=dontEnumsLength;ii>i;i++){var dontEnum=dontEnums[i];owns(object,dontEnum)&&keys.push(dontEnum)}return keys}}Date.now||(Date.now=function(){return(new Date).getTime()});var ws=\\\"\\t\\\\n\\u000b\\\\f\\\\r   ᠎              \\\\u2028\\\\u2029\\\";if(!String.prototype.trim||ws.trim()){ws=\\\"[\\\"+ws+\\\"]\\\";var trimBeginRegexp=RegExp(\\\"^\\\"+ws+ws+\\\"*\\\"),trimEndRegexp=RegExp(ws+ws+\\\"*$\\\");String.prototype.trim=function(){return(this+\\\"\\\").replace(trimBeginRegexp,\\\"\\\").replace(trimEndRegexp,\\\"\\\")}}var toObject=function(o){if(null==o)throw new TypeError(\\\"can't convert \\\"+o+\\\" to object\\\");return Object(o)}});\";\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/brace/worker/json.js\n ** module id = 131\n ** module chunks = 0\n **/","ace.define(\"ace/ext/searchbox\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\",\"ace/lib/lang\",\"ace/lib/event\",\"ace/keyboard/hash_handler\",\"ace/lib/keys\"], function(acequire, exports, module) {\n\"use strict\";\n\nvar dom = acequire(\"../lib/dom\");\nvar lang = acequire(\"../lib/lang\");\nvar event = acequire(\"../lib/event\");\nvar searchboxCss = \"\\\n.ace_search {\\\nbackground-color: #ddd;\\\nborder: 1px solid #cbcbcb;\\\nborder-top: 0 none;\\\nmax-width: 325px;\\\noverflow: hidden;\\\nmargin: 0;\\\npadding: 4px;\\\npadding-right: 6px;\\\npadding-bottom: 0;\\\nposition: absolute;\\\ntop: 0px;\\\nz-index: 99;\\\nwhite-space: normal;\\\n}\\\n.ace_search.left {\\\nborder-left: 0 none;\\\nborder-radius: 0px 0px 5px 0px;\\\nleft: 0;\\\n}\\\n.ace_search.right {\\\nborder-radius: 0px 0px 0px 5px;\\\nborder-right: 0 none;\\\nright: 0;\\\n}\\\n.ace_search_form, .ace_replace_form {\\\nborder-radius: 3px;\\\nborder: 1px solid #cbcbcb;\\\nfloat: left;\\\nmargin-bottom: 4px;\\\noverflow: hidden;\\\n}\\\n.ace_search_form.ace_nomatch {\\\noutline: 1px solid red;\\\n}\\\n.ace_search_field {\\\nbackground-color: white;\\\nborder-right: 1px solid #cbcbcb;\\\nborder: 0 none;\\\n-webkit-box-sizing: border-box;\\\n-moz-box-sizing: border-box;\\\nbox-sizing: border-box;\\\nfloat: left;\\\nheight: 22px;\\\noutline: 0;\\\npadding: 0 7px;\\\nwidth: 214px;\\\nmargin: 0;\\\n}\\\n.ace_searchbtn,\\\n.ace_replacebtn {\\\nbackground: #fff;\\\nborder: 0 none;\\\nborder-left: 1px solid #dcdcdc;\\\ncursor: pointer;\\\nfloat: left;\\\nheight: 22px;\\\nmargin: 0;\\\nposition: relative;\\\n}\\\n.ace_searchbtn:last-child,\\\n.ace_replacebtn:last-child {\\\nborder-top-right-radius: 3px;\\\nborder-bottom-right-radius: 3px;\\\n}\\\n.ace_searchbtn:disabled {\\\nbackground: none;\\\ncursor: default;\\\n}\\\n.ace_searchbtn {\\\nbackground-position: 50% 50%;\\\nbackground-repeat: no-repeat;\\\nwidth: 27px;\\\n}\\\n.ace_searchbtn.prev {\\\nbackground-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADFJREFUeNpiSU1NZUAC/6E0I0yACYskCpsJiySKIiY0SUZk40FyTEgCjGgKwTRAgAEAQJUIPCE+qfkAAAAASUVORK5CYII=); \\\n}\\\n.ace_searchbtn.next {\\\nbackground-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADRJREFUeNpiTE1NZQCC/0DMyIAKwGJMUAYDEo3M/s+EpvM/mkKwCQxYjIeLMaELoLMBAgwAU7UJObTKsvAAAAAASUVORK5CYII=); \\\n}\\\n.ace_searchbtn_close {\\\nbackground: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAcCAYAAABRVo5BAAAAZ0lEQVR42u2SUQrAMAhDvazn8OjZBilCkYVVxiis8H4CT0VrAJb4WHT3C5xU2a2IQZXJjiQIRMdkEoJ5Q2yMqpfDIo+XY4k6h+YXOyKqTIj5REaxloNAd0xiKmAtsTHqW8sR2W5f7gCu5nWFUpVjZwAAAABJRU5ErkJggg==) no-repeat 50% 0;\\\nborder-radius: 50%;\\\nborder: 0 none;\\\ncolor: #656565;\\\ncursor: pointer;\\\nfloat: right;\\\nfont: 16px/16px Arial;\\\nheight: 14px;\\\nmargin: 5px 1px 9px 5px;\\\npadding: 0;\\\ntext-align: center;\\\nwidth: 14px;\\\n}\\\n.ace_searchbtn_close:hover {\\\nbackground-color: #656565;\\\nbackground-position: 50% 100%;\\\ncolor: white;\\\n}\\\n.ace_replacebtn.prev {\\\nwidth: 54px\\\n}\\\n.ace_replacebtn.next {\\\nwidth: 27px\\\n}\\\n.ace_button {\\\nmargin-left: 2px;\\\ncursor: pointer;\\\n-webkit-user-select: none;\\\n-moz-user-select: none;\\\n-o-user-select: none;\\\n-ms-user-select: none;\\\nuser-select: none;\\\noverflow: hidden;\\\nopacity: 0.7;\\\nborder: 1px solid rgba(100,100,100,0.23);\\\npadding: 1px;\\\n-moz-box-sizing: border-box;\\\nbox-sizing: border-box;\\\ncolor: black;\\\n}\\\n.ace_button:hover {\\\nbackground-color: #eee;\\\nopacity:1;\\\n}\\\n.ace_button:active {\\\nbackground-color: #ddd;\\\n}\\\n.ace_button.checked {\\\nborder-color: #3399ff;\\\nopacity:1;\\\n}\\\n.ace_search_options{\\\nmargin-bottom: 3px;\\\ntext-align: right;\\\n-webkit-user-select: none;\\\n-moz-user-select: none;\\\n-o-user-select: none;\\\n-ms-user-select: none;\\\nuser-select: none;\\\n}\";\nvar HashHandler = acequire(\"../keyboard/hash_handler\").HashHandler;\nvar keyUtil = acequire(\"../lib/keys\");\n\ndom.importCssString(searchboxCss, \"ace_searchbox\");\n\nvar html = ''.replace(/>\\s+/g, \">\");\n\nvar SearchBox = function(editor, range, showReplaceForm) {\n var div = dom.createElement(\"div\");\n div.innerHTML = html;\n this.element = div.firstChild;\n\n this.$init();\n this.setEditor(editor);\n};\n\n(function() {\n this.setEditor = function(editor) {\n editor.searchBox = this;\n editor.container.appendChild(this.element);\n this.editor = editor;\n };\n\n this.$initElements = function(sb) {\n this.searchBox = sb.querySelector(\".ace_search_form\");\n this.replaceBox = sb.querySelector(\".ace_replace_form\");\n this.searchOptions = sb.querySelector(\".ace_search_options\");\n this.regExpOption = sb.querySelector(\"[action=toggleRegexpMode]\");\n this.caseSensitiveOption = sb.querySelector(\"[action=toggleCaseSensitive]\");\n this.wholeWordOption = sb.querySelector(\"[action=toggleWholeWords]\");\n this.searchInput = this.searchBox.querySelector(\".ace_search_field\");\n this.replaceInput = this.replaceBox.querySelector(\".ace_search_field\");\n };\n \n this.$init = function() {\n var sb = this.element;\n \n this.$initElements(sb);\n \n var _this = this;\n event.addListener(sb, \"mousedown\", function(e) {\n setTimeout(function(){\n _this.activeInput.focus();\n }, 0);\n event.stopPropagation(e);\n });\n event.addListener(sb, \"click\", function(e) {\n var t = e.target || e.srcElement;\n var action = t.getAttribute(\"action\");\n if (action && _this[action])\n _this[action]();\n else if (_this.$searchBarKb.commands[action])\n _this.$searchBarKb.commands[action].exec(_this);\n event.stopPropagation(e);\n });\n\n event.addCommandKeyListener(sb, function(e, hashId, keyCode) {\n var keyString = keyUtil.keyCodeToString(keyCode);\n var command = _this.$searchBarKb.findKeyCommand(hashId, keyString);\n if (command && command.exec) {\n command.exec(_this);\n event.stopEvent(e);\n }\n });\n\n this.$onChange = lang.delayedCall(function() {\n _this.find(false, false);\n });\n\n event.addListener(this.searchInput, \"input\", function() {\n _this.$onChange.schedule(20);\n });\n event.addListener(this.searchInput, \"focus\", function() {\n _this.activeInput = _this.searchInput;\n _this.searchInput.value && _this.highlight();\n });\n event.addListener(this.replaceInput, \"focus\", function() {\n _this.activeInput = _this.replaceInput;\n _this.searchInput.value && _this.highlight();\n });\n };\n this.$closeSearchBarKb = new HashHandler([{\n bindKey: \"Esc\",\n name: \"closeSearchBar\",\n exec: function(editor) {\n editor.searchBox.hide();\n }\n }]);\n this.$searchBarKb = new HashHandler();\n this.$searchBarKb.bindKeys({\n \"Ctrl-f|Command-f\": function(sb) {\n var isReplace = sb.isReplace = !sb.isReplace;\n sb.replaceBox.style.display = isReplace ? \"\" : \"none\";\n sb.searchInput.focus();\n },\n \"Ctrl-H|Command-Option-F\": function(sb) {\n sb.replaceBox.style.display = \"\";\n sb.replaceInput.focus();\n },\n \"Ctrl-G|Command-G\": function(sb) {\n sb.findNext();\n },\n \"Ctrl-Shift-G|Command-Shift-G\": function(sb) {\n sb.findPrev();\n },\n \"esc\": function(sb) {\n setTimeout(function() { sb.hide();});\n },\n \"Return\": function(sb) {\n if (sb.activeInput == sb.replaceInput)\n sb.replace();\n sb.findNext();\n },\n \"Shift-Return\": function(sb) {\n if (sb.activeInput == sb.replaceInput)\n sb.replace();\n sb.findPrev();\n },\n \"Alt-Return\": function(sb) {\n if (sb.activeInput == sb.replaceInput)\n sb.replaceAll();\n sb.findAll();\n },\n \"Tab\": function(sb) {\n (sb.activeInput == sb.replaceInput ? sb.searchInput : sb.replaceInput).focus();\n }\n });\n\n this.$searchBarKb.addCommands([{\n name: \"toggleRegexpMode\",\n bindKey: {win: \"Alt-R|Alt-/\", mac: \"Ctrl-Alt-R|Ctrl-Alt-/\"},\n exec: function(sb) {\n sb.regExpOption.checked = !sb.regExpOption.checked;\n sb.$syncOptions();\n }\n }, {\n name: \"toggleCaseSensitive\",\n bindKey: {win: \"Alt-C|Alt-I\", mac: \"Ctrl-Alt-R|Ctrl-Alt-I\"},\n exec: function(sb) {\n sb.caseSensitiveOption.checked = !sb.caseSensitiveOption.checked;\n sb.$syncOptions();\n }\n }, {\n name: \"toggleWholeWords\",\n bindKey: {win: \"Alt-B|Alt-W\", mac: \"Ctrl-Alt-B|Ctrl-Alt-W\"},\n exec: function(sb) {\n sb.wholeWordOption.checked = !sb.wholeWordOption.checked;\n sb.$syncOptions();\n }\n }]);\n\n this.$syncOptions = function() {\n dom.setCssClass(this.regExpOption, \"checked\", this.regExpOption.checked);\n dom.setCssClass(this.wholeWordOption, \"checked\", this.wholeWordOption.checked);\n dom.setCssClass(this.caseSensitiveOption, \"checked\", this.caseSensitiveOption.checked);\n this.find(false, false);\n };\n\n this.highlight = function(re) {\n this.editor.session.highlight(re || this.editor.$search.$options.re);\n this.editor.renderer.updateBackMarkers()\n };\n this.find = function(skipCurrent, backwards, preventScroll) {\n var range = this.editor.find(this.searchInput.value, {\n skipCurrent: skipCurrent,\n backwards: backwards,\n wrap: true,\n regExp: this.regExpOption.checked,\n caseSensitive: this.caseSensitiveOption.checked,\n wholeWord: this.wholeWordOption.checked,\n preventScroll: preventScroll\n });\n var noMatch = !range && this.searchInput.value;\n dom.setCssClass(this.searchBox, \"ace_nomatch\", noMatch);\n this.editor._emit(\"findSearchBox\", { match: !noMatch });\n this.highlight();\n };\n this.findNext = function() {\n this.find(true, false);\n };\n this.findPrev = function() {\n this.find(true, true);\n };\n this.findAll = function(){\n var range = this.editor.findAll(this.searchInput.value, { \n regExp: this.regExpOption.checked,\n caseSensitive: this.caseSensitiveOption.checked,\n wholeWord: this.wholeWordOption.checked\n });\n var noMatch = !range && this.searchInput.value;\n dom.setCssClass(this.searchBox, \"ace_nomatch\", noMatch);\n this.editor._emit(\"findSearchBox\", { match: !noMatch });\n this.highlight();\n this.hide();\n };\n this.replace = function() {\n if (!this.editor.getReadOnly())\n this.editor.replace(this.replaceInput.value);\n }; \n this.replaceAndFindNext = function() {\n if (!this.editor.getReadOnly()) {\n this.editor.replace(this.replaceInput.value);\n this.findNext()\n }\n };\n this.replaceAll = function() {\n if (!this.editor.getReadOnly())\n this.editor.replaceAll(this.replaceInput.value);\n };\n\n this.hide = function() {\n this.element.style.display = \"none\";\n this.editor.keyBinding.removeKeyboardHandler(this.$closeSearchBarKb);\n this.editor.focus();\n };\n this.show = function(value, isReplace) {\n this.element.style.display = \"\";\n this.replaceBox.style.display = isReplace ? \"\" : \"none\";\n\n this.isReplace = isReplace;\n\n if (value)\n this.searchInput.value = value;\n \n this.find(false, false, true);\n \n this.searchInput.focus();\n this.searchInput.select();\n\n this.editor.keyBinding.addKeyboardHandler(this.$closeSearchBarKb);\n };\n\n this.isFocused = function() {\n var el = document.activeElement;\n return el == this.searchInput || el == this.replaceInput;\n }\n}).call(SearchBox.prototype);\n\nexports.SearchBox = SearchBox;\n\nexports.Search = function(editor, isReplace) {\n var sb = editor.searchBox || new SearchBox(editor);\n sb.show(editor.session.getTextRange(), isReplace);\n};\n\n});\n (function() {\n ace.acequire([\"ace/ext/searchbox\"], function() {});\n })();\n \n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/brace/ext/searchbox.js\n ** module id = 132\n ** module chunks = 0\n **/","/* ***** BEGIN LICENSE BLOCK *****\n * Distributed under the BSD license:\n *\n * Copyright (c) 2010, Ajax.org B.V.\n * All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n * * Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * * Neither the name of Ajax.org B.V. nor the\n * names of its contributors may be used to endorse or promote products\n * derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * ***** END LICENSE BLOCK ***** */\n\nace.define('ace/theme/jsoneditor', ['require', 'exports', 'module', 'ace/lib/dom'], function(acequire, exports, module) {\n\nexports.isDark = false;\nexports.cssClass = \"ace-jsoneditor\";\nexports.cssText = \".ace-jsoneditor .ace_gutter {\\\nbackground: #ebebeb;\\\ncolor: #333\\\n}\\\n\\\n.ace-jsoneditor.ace_editor {\\\nfont-family: droid sans mono, consolas, monospace, courier new, courier, sans-serif;\\\nline-height: 1.3;\\\n}\\\n.ace-jsoneditor .ace_print-margin {\\\nwidth: 1px;\\\nbackground: #e8e8e8\\\n}\\\n.ace-jsoneditor .ace_scroller {\\\nbackground-color: #FFFFFF\\\n}\\\n.ace-jsoneditor .ace_text-layer {\\\ncolor: gray\\\n}\\\n.ace-jsoneditor .ace_variable {\\\ncolor: #1a1a1a\\\n}\\\n.ace-jsoneditor .ace_cursor {\\\nborder-left: 2px solid #000000\\\n}\\\n.ace-jsoneditor .ace_overwrite-cursors .ace_cursor {\\\nborder-left: 0px;\\\nborder-bottom: 1px solid #000000\\\n}\\\n.ace-jsoneditor .ace_marker-layer .ace_selection {\\\nbackground: lightgray\\\n}\\\n.ace-jsoneditor.ace_multiselect .ace_selection.ace_start {\\\nbox-shadow: 0 0 3px 0px #FFFFFF;\\\nborder-radius: 2px\\\n}\\\n.ace-jsoneditor .ace_marker-layer .ace_step {\\\nbackground: rgb(255, 255, 0)\\\n}\\\n.ace-jsoneditor .ace_marker-layer .ace_bracket {\\\nmargin: -1px 0 0 -1px;\\\nborder: 1px solid #BFBFBF\\\n}\\\n.ace-jsoneditor .ace_marker-layer .ace_active-line {\\\nbackground: #FFFBD1\\\n}\\\n.ace-jsoneditor .ace_gutter-active-line {\\\nbackground-color : #dcdcdc\\\n}\\\n.ace-jsoneditor .ace_marker-layer .ace_selected-word {\\\nborder: 1px solid lightgray\\\n}\\\n.ace-jsoneditor .ace_invisible {\\\ncolor: #BFBFBF\\\n}\\\n.ace-jsoneditor .ace_keyword,\\\n.ace-jsoneditor .ace_meta,\\\n.ace-jsoneditor .ace_support.ace_constant.ace_property-value {\\\ncolor: #AF956F\\\n}\\\n.ace-jsoneditor .ace_keyword.ace_operator {\\\ncolor: #484848\\\n}\\\n.ace-jsoneditor .ace_keyword.ace_other.ace_unit {\\\ncolor: #96DC5F\\\n}\\\n.ace-jsoneditor .ace_constant.ace_language {\\\ncolor: darkorange\\\n}\\\n.ace-jsoneditor .ace_constant.ace_numeric {\\\ncolor: red\\\n}\\\n.ace-jsoneditor .ace_constant.ace_character.ace_entity {\\\ncolor: #BF78CC\\\n}\\\n.ace-jsoneditor .ace_invalid {\\\ncolor: #FFFFFF;\\\nbackground-color: #FF002A;\\\n}\\\n.ace-jsoneditor .ace_fold {\\\nbackground-color: #AF956F;\\\nborder-color: #000000\\\n}\\\n.ace-jsoneditor .ace_storage,\\\n.ace-jsoneditor .ace_support.ace_class,\\\n.ace-jsoneditor .ace_support.ace_function,\\\n.ace-jsoneditor .ace_support.ace_other,\\\n.ace-jsoneditor .ace_support.ace_type {\\\ncolor: #C52727\\\n}\\\n.ace-jsoneditor .ace_string {\\\ncolor: green\\\n}\\\n.ace-jsoneditor .ace_comment {\\\ncolor: #BCC8BA\\\n}\\\n.ace-jsoneditor .ace_entity.ace_name.ace_tag,\\\n.ace-jsoneditor .ace_entity.ace_other.ace_attribute-name {\\\ncolor: #606060\\\n}\\\n.ace-jsoneditor .ace_markup.ace_underline {\\\ntext-decoration: underline\\\n}\\\n.ace-jsoneditor .ace_indent-guide {\\\nbackground: url(\\\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\\\") right repeat-y\\\n}\";\n\nvar dom = acequire(\"../lib/dom\");\ndom.importCssString(exports.cssText, exports.cssClass);\n});\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/assets/ace/theme-jsoneditor.js\n **/","import { h, Component } from 'preact'\n\nimport { setIn, updateIn } from './utils/immutabilityHelpers'\nimport { expand, jsonToData, dataToJson, toDataPath, patchData } from './jsonData'\nimport {\n duplicate, insert, append, remove, changeType, changeValue, changeProperty, sort\n} from './actions'\nimport JSONNode from './JSONNode'\nimport JSONNodeView from './JSONNodeView'\nimport JSONNodeForm from './JSONNodeForm'\nimport ModeButton from './menu/ModeButton'\nimport { parseJSON } from './utils/jsonUtils'\n\nconst MAX_HISTORY_ITEMS = 1000 // maximum number of undo/redo items to be kept in memory\n\nexport default class TreeMode extends Component {\n constructor (props) {\n super(props)\n\n const expand = this.props.options.expand || TreeMode.expand\n const data = jsonToData(this.props.data || {}, expand, [])\n\n this.state = {\n nodeOptions: {\n name: null\n },\n\n data,\n\n history: [data],\n historyIndex: 0,\n\n events: {\n onChangeProperty: this.handleChangeProperty,\n onChangeValue: this.handleChangeValue,\n onChangeType: this.handleChangeType,\n onInsert: this.handleInsert,\n onAppend: this.handleAppend,\n onDuplicate: this.handleDuplicate,\n onRemove: this.handleRemove,\n onSort: this.handleSort,\n\n onExpand: this.handleExpand\n },\n\n search: null\n }\n }\n\n render (props, state) {\n const Node = (props.mode === 'view')\n ? JSONNodeView\n : (props.mode === 'form')\n ? JSONNodeForm\n : JSONNode\n\n return h('div', {\n class: `jsoneditor jsoneditor-mode-${props.mode}`,\n 'data-jsoneditor': 'true'\n }, [\n this.renderMenu(),\n\n h('div', {class: 'jsoneditor-contents jsoneditor-tree-contents', onClick: this.handleHideMenus}, [\n h('ul', {class: 'jsoneditor-list jsoneditor-root'}, [\n h(Node, {\n data: state.data,\n events: state.events,\n options: state.nodeOptions,\n parent: null,\n prop: null\n })\n ])\n ])\n ])\n }\n\n renderMenu () {\n let items = [\n h('button', {\n class: 'jsoneditor-expand-all',\n title: 'Expand all objects and arrays',\n onClick: this.handleExpandAll\n }),\n h('button', {\n class: 'jsoneditor-collapse-all',\n title: 'Collapse all objects and arrays',\n onClick: this.handleCollapseAll\n })\n ]\n\n if (this.props.mode !== 'view') {\n items = items.concat([\n h('div', {class: 'jsoneditor-vertical-menu-separator'}),\n\n h('div', {style: 'display:inline-block'}, [\n h('button', {\n class: 'jsoneditor-undo',\n title: 'Undo last action',\n disabled: !this.canUndo(),\n onClick: this.undo\n }),\n ]),\n h('button', {\n class: 'jsoneditor-redo',\n title: 'Redo',\n disabled: !this.canRedo(),\n onClick: this.redo\n })\n ])\n }\n\n if (this.props.options.modes ) {\n items = items.concat([\n h('div', {class: 'jsoneditor-vertical-menu-separator'}),\n\n h(ModeButton, {\n modes: this.props.options.modes,\n mode: this.props.mode,\n onChangeMode: this.props.onChangeMode,\n onError: this.handleError\n })\n ])\n }\n\n return h('div', {class: 'jsoneditor-menu'}, items)\n }\n\n /** @private */\n handleHideMenus = () => {\n JSONNode.hideActionMenu()\n }\n\n /** @private */\n handleChangeValue = (path, value) => {\n this.handlePatch(changeValue(this.state.data, path, value))\n }\n\n /** @private */\n handleChangeProperty = (parentPath, oldProp, newProp) => {\n this.handlePatch(changeProperty(this.state.data, parentPath, oldProp, newProp))\n }\n\n /** @private */\n handleChangeType = (path, type) => {\n this.handlePatch(changeType(this.state.data, path, type))\n }\n\n /** @private */\n handleInsert = (path, type) => {\n this.handlePatch(insert(this.state.data, path, type))\n }\n\n /** @private */\n handleAppend = (parentPath, type) => {\n this.handlePatch(append(this.state.data, parentPath, type))\n }\n\n /** @private */\n handleDuplicate = (path) => {\n this.handlePatch(duplicate(this.state.data, path))\n }\n\n /** @private */\n handleRemove = (path) => {\n this.handlePatch(remove(path))\n }\n\n /** @private */\n handleSort = (path, order = null) => {\n this.handlePatch(sort(this.state.data, path, order))\n }\n\n /** @private */\n handleExpand = (path, expanded, recurse) => {\n if (recurse) {\n const dataPath = toDataPath(this.state.data, path)\n\n this.setState({\n data: updateIn(this.state.data, dataPath, function (child) {\n return expand(child, (path) => true, expanded)\n })\n })\n }\n else {\n this.setState({\n data: expand(this.state.data, path, expanded)\n })\n }\n }\n\n /** @private */\n handleExpandAll = () => {\n const expanded = true\n\n this.setState({\n data: expand(this.state.data, TreeMode.expandAll, expanded)\n })\n }\n\n /** @private */\n handleCollapseAll = () => {\n const expanded = false\n\n this.setState({\n data: expand(this.state.data, TreeMode.expandAll, expanded)\n })\n }\n\n /**\n * Apply a JSONPatch to the current JSON document and emit a change event\n * @param {JSONPatch} actions\n * @private\n */\n handlePatch = (actions) => {\n // apply changes\n const result = this.patch(actions)\n\n this.emitOnChange (actions, result.revert)\n }\n\n /** @private */\n handleError = (err) => {\n if (this.props.options && this.props.options.onError) {\n this.props.options.onError(err)\n }\n else {\n console.error(err)\n }\n }\n\n /**\n * Emit an onChange event when there is a listener for it.\n * @param {JSONPatch} patch\n * @param {JSONPatch} revert\n * @private\n */\n emitOnChange (patch, revert) {\n if (this.props.options.onChange) {\n this.props.options.onChange(patch, revert)\n }\n }\n\n canUndo = () => {\n return this.state.historyIndex < this.state.history.length\n }\n\n canRedo = () => {\n return this.state.historyIndex > 0\n }\n\n undo = () => {\n if (this.canUndo()) {\n const history = this.state.history\n const historyIndex = this.state.historyIndex\n const historyItem = history[historyIndex]\n\n const result = patchData(this.state.data, historyItem.undo)\n\n this.setState({\n data: result.data,\n history,\n historyIndex: historyIndex + 1\n })\n\n this.emitOnChange (historyItem.undo, historyItem.redo)\n }\n }\n\n redo = () => {\n if (this.canRedo()) {\n const history = this.state.history\n const historyIndex = this.state.historyIndex - 1\n const historyItem = history[historyIndex]\n\n const result = patchData(this.state.data, historyItem.redo)\n\n this.setState({\n data: result.data,\n history,\n historyIndex\n })\n\n this.emitOnChange (historyItem.redo, historyItem.undo)\n }\n }\n\n /**\n * Apply a JSONPatch to the current JSON document\n * @param {JSONPatch} actions JSONPatch actions\n * @return {JSONPatchResult} Returns a JSONPatch result containing the\n * patch, a patch to revert the action, and\n * an error object which is null when successful\n */\n patch (actions) {\n const result = patchData(this.state.data, actions)\n const data = result.data\n\n const historyItem = {\n redo: actions,\n undo: result.revert\n }\n const history = [historyItem]\n .concat(this.state.history.slice(this.state.historyIndex))\n .slice(0, MAX_HISTORY_ITEMS)\n\n this.setState({\n data,\n history,\n historyIndex: 0\n })\n\n return {\n patch: actions,\n revert: result.revert,\n error: result.error\n }\n }\n\n /**\n * Set JSON object in editor\n * @param {Object | Array | string | number | boolean | null} json JSON data\n * @param {SetOptions} [options]\n */\n set (json, options = {}) {\n const name = options && options.name || null // the root name\n const data = jsonToData(json, options.expand || TreeMode.expand, [])\n\n this.setState({\n nodeOptions: setIn(this.state.nodeOptions, ['name'], name),\n\n data,\n // TODO: do we want to keep history when .set(json) is called?\n history: [],\n historyIndex: 0\n })\n }\n\n /**\n * Get JSON from the editor\n * @returns {Object | Array | string | number | boolean | null} json\n */\n get () {\n return dataToJson(this.state.data)\n }\n\n /**\n * Set a string containing a JSON document\n * @param {string} text\n */\n setText (text) {\n this.set(parseJSON(text))\n }\n\n /**\n * Get the JSON document as text\n * @return {string} text\n */\n getText () {\n const indentation = this.props.options.indentation || 2\n return JSON.stringify(this.get(), null, indentation)\n }\n\n /**\n * Expand one or multiple objects or arrays\n * @param {Path | function (path: Path) : boolean} callback\n */\n expand (callback) {\n this.setState({\n data: expand(this.state.data, callback, true)\n })\n }\n\n /**\n * Collapse one or multiple objects or arrays\n * @param {Path | function (path: Path) : boolean} callback\n */\n collapse (callback) {\n this.setState({\n data: expand(this.state.data, callback, false)\n })\n }\n\n /**\n * Destroy the editor\n */\n destroy () {\n\n }\n\n /**\n * Default function to determine whether or not to expand a node initially\n *\n * Rule: expand the root node only\n *\n * @param {Array.} path\n * @return {boolean}\n */\n static expand (path) {\n return path.length === 0\n }\n\n\n /**\n * Callback function to expand all nodes\n *\n * @param {Array.} path\n * @return {boolean}\n */\n static expandAll (path) {\n return true\n }\n}\n\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/TreeMode.js\n **/","import { compileJSONPointer, toDataPath, dataToJson, findNextProp } from './jsonData'\nimport { findUniqueName } from './utils/stringUtils'\nimport { getIn } from './utils/immutabilityHelpers'\nimport { isObject, stringConvert } from './utils/typeUtils'\nimport { compareAsc, compareDesc, strictShallowEqual } from './utils/arrayUtils'\n\n\n/**\n * Create a JSONPatch to change the value of a property or item\n * @param {JSONData} data\n * @param {Path} path\n * @param {*} value\n * @return {Array}\n */\nexport function changeValue (data, path, value) {\n // console.log('changeValue', data, value)\n\n const dataPath = toDataPath(data, path)\n const oldDataValue = getIn(data, dataPath)\n\n return [{\n op: 'replace',\n path: compileJSONPointer(path),\n value: value,\n jsoneditor: {\n type: oldDataValue.type\n }\n }]\n}\n\n/**\n * Create a JSONPatch to change a property name\n * @param {JSONData} data\n * @param {Path} parentPath\n * @param {string} oldProp\n * @param {string} newProp\n * @return {Array}\n */\nexport function changeProperty (data, parentPath, oldProp, newProp) {\n // console.log('changeProperty', parentPath, oldProp, newProp)\n\n const dataPath = toDataPath(data, parentPath)\n const parent = getIn(data, dataPath)\n\n // prevent duplicate property names\n const uniqueNewProp = findUniqueName(newProp, parent.props.map(p => p.name))\n\n return [{\n op: 'move',\n from: compileJSONPointer(parentPath.concat(oldProp)),\n path: compileJSONPointer(parentPath.concat(uniqueNewProp)),\n jsoneditor: {\n before: findNextProp(parent, oldProp)\n }\n }]\n}\n\n/**\n * Create a JSONPatch to change the type of a property or item\n * @param {JSONData} data\n * @param {Path} path\n * @param {JSONDataType} type\n * @return {Array}\n */\nexport function changeType (data, path, type) {\n const dataPath = toDataPath(data, path)\n const oldValue = dataToJson(getIn(data, dataPath))\n const newValue = convertType(oldValue, type)\n\n // console.log('changeType', path, type, oldValue, newValue)\n\n return [{\n op: 'replace',\n path: compileJSONPointer(path),\n value: newValue,\n jsoneditor: {\n type\n }\n }]\n}\n\n/**\n * Create a JSONPatch for a duplicate action.\n *\n * This function needs the current data in order to be able to determine\n * a unique property name for the duplicated node in case of duplicating\n * and object property\n *\n * @param {JSONData} data\n * @param {Path} path\n * @return {Array}\n */\nexport function duplicate (data, path) {\n // console.log('duplicate', path)\n\n const parentPath = path.slice(0, path.length - 1)\n\n const dataPath = toDataPath(data, parentPath)\n const parent = getIn(data, dataPath)\n\n if (parent.type === 'Array') {\n const index = parseInt(path[path.length - 1]) + 1\n return [{\n op: 'copy',\n from: compileJSONPointer(path),\n path: compileJSONPointer(parentPath.concat(index))\n }]\n }\n else { // object.type === 'Object'\n const prop = path[path.length - 1]\n const newProp = findUniqueName(prop, parent.props.map(p => p.name))\n\n return [{\n op: 'copy',\n from: compileJSONPointer(path),\n path: compileJSONPointer(parentPath.concat(newProp)),\n jsoneditor: {\n before: findNextProp(parent, prop)\n }\n }]\n }\n}\n\n/**\n * Create a JSONPatch for an insert action.\n *\n * This function needs the current data in order to be able to determine\n * a unique property name for the inserted node in case of duplicating\n * and object property\n *\n * @param {JSONData} data\n * @param {Path} path\n * @param {JSONDataType} type\n * @return {Array}\n */\nexport function insert (data, path, type) {\n // console.log('insert', path, type)\n\n const parentPath = path.slice(0, path.length - 1)\n const dataPath = toDataPath(data, parentPath)\n const parent = getIn(data, dataPath)\n const value = createEntry(type)\n\n if (parent.type === 'Array') {\n const index = parseInt(path[path.length - 1]) + 1\n return [{\n op: 'add',\n path: compileJSONPointer(parentPath.concat(index + '')),\n value,\n jsoneditor: {\n type\n }\n }]\n }\n else { // object.type === 'Object'\n const prop = path[path.length - 1]\n const newProp = findUniqueName('', parent.props.map(p => p.name))\n\n return [{\n op: 'add',\n path: compileJSONPointer(parentPath.concat(newProp)),\n value,\n jsoneditor: {\n type,\n before: findNextProp(parent, prop)\n }\n }]\n }\n}\n\n/**\n * Create a JSONPatch for an append action.\n *\n * This function needs the current data in order to be able to determine\n * a unique property name for the inserted node in case of duplicating\n * and object property\n *\n * @param {JSONData} data\n * @param {Path} parentPath\n * @param {JSONDataType} type\n * @return {Array}\n */\nexport function append (data, parentPath, type) {\n // console.log('append', parentPath, value)\n\n const dataPath = toDataPath(data, parentPath)\n const parent = getIn(data, dataPath)\n const value = createEntry(type)\n\n if (parent.type === 'Array') {\n return [{\n op: 'add',\n path: compileJSONPointer(parentPath.concat('-')),\n value,\n jsoneditor: {\n type\n }\n }]\n }\n else { // object.type === 'Object'\n const newProp = findUniqueName('', parent.props.map(p => p.name))\n\n return [{\n op: 'add',\n path: compileJSONPointer(parentPath.concat(newProp)),\n value,\n jsoneditor: {\n type\n }\n }]\n }\n}\n\n/**\n * Create a JSONPatch for a remove action\n * @param {Path} path\n */\nexport function remove (path) {\n return [{\n op: 'remove',\n path: compileJSONPointer(path)\n }]\n}\n\n/**\n * Create a JSONPatch to order the items of an array or the properties of an object in ascending\n * or descending order\n * @param {JSONData} data\n * @param {Path} path\n * @param {'asc' | 'desc' | null} [order=null] If not provided, will toggle current ordering\n * @return {Array}\n */\nexport function sort (data, path, order = null) {\n // console.log('sort', path, order)\n\n const compare = order === 'desc' ? compareDesc : compareAsc\n const dataPath = toDataPath(data, path)\n const object = getIn(data, dataPath)\n\n if (object.type === 'Array') {\n const orderedItems = object.items.slice(0)\n\n // order the items by value\n orderedItems.sort((a, b) => compare(a.value, b.value))\n\n // when no order is provided, test whether ordering ascending\n // changed anything. If not, sort descending\n if (!order && strictShallowEqual(object.items, orderedItems)) {\n orderedItems.reverse()\n }\n\n return [{\n op: 'replace',\n path: compileJSONPointer(path),\n value: dataToJson({\n type: 'Array',\n items: orderedItems\n })\n }]\n }\n else { // object.type === 'Object'\n const orderedProps = object.props.slice(0)\n\n // order the properties by key\n orderedProps.sort((a, b) => compare(a.name, b.name))\n\n // when no order is provided, test whether ordering ascending\n // changed anything. If not, sort descending\n if (!order && strictShallowEqual(object.props, orderedProps)) {\n orderedProps.reverse()\n }\n\n return [{\n op: 'replace',\n path: compileJSONPointer(path),\n value: dataToJson({\n type: 'Object',\n props: orderedProps\n }),\n jsoneditor: {\n order: orderedProps.map(prop => prop.name)\n }\n }]\n }\n}\n\n/**\n * Create a JSON entry\n * @param {JSONDataType} type\n * @return {Array | Object | string}\n */\nexport function createEntry (type) {\n if (type === 'Array') {\n return []\n }\n else if (type === 'Object') {\n return {}\n }\n else {\n return ''\n }\n}\n\n/**\n * Convert a JSON object into a different type. When possible, data is retained\n * @param {*} value\n * @param {JSONDataType} type\n * @return {*}\n */\nexport function convertType (value, type) {\n // convert contents from old value to new value where possible\n if (type === 'value') {\n if (typeof value === 'string') {\n return stringConvert(value)\n }\n else {\n return ''\n }\n }\n\n if (type === 'string') {\n if (!isObject(value) && !Array.isArray(value)) {\n return value + ''\n }\n else {\n return ''\n }\n }\n\n if (type === 'Object') {\n let object = {}\n\n if (Array.isArray(value)) {\n value.forEach((item, index) => object[index] = item)\n }\n\n return object\n }\n\n if (type === 'Array') {\n let array = []\n\n if (isObject(value)) {\n Object.keys(value).forEach(key => {\n array.push(value[key])\n })\n }\n\n return array\n }\n\n throw new Error(`Unknown type '${type}'`)\n}\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/actions.js\n **/","/**\n * Returns the last item of an array\n * @param {Array} array\n * @return {*}\n */\nexport function last (array) {\n return array[array.length - 1]\n}\n\n/**\n * Comparator to sort an array in ascending order\n *\n * Usage:\n * [4,2,5].sort(compareAsc) // [2,4,5]\n *\n * @param a\n * @param b\n * @return {number}\n */\nexport function compareAsc (a, b) {\n return a > b ? 1 : a < b ? -1 : 0\n}\n\n/**\n * Comparator to sort an array in ascending order\n *\n * Usage:\n * [4,2,5].sort(compareDesc) // [5,4,2]\n *\n * @param a\n * @param b\n * @return {number}\n */\nexport function compareDesc (a, b) {\n return a > b ? -1 : a < b ? 1 : 0\n}\n\n/**\n * Test whether all items of an array are strictly equal\n * @param {Array} a\n * @param {Array} b\n */\nexport function strictShallowEqual (a, b) {\n if (a.length !== b.length) {\n return false\n }\n\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) {\n return false\n }\n }\n\n return true\n}\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/utils/arrayUtils.js\n **/","import { h, Component } from 'preact'\n\nimport ActionButton from './menu/ActionButton'\nimport AppendActionButton from './menu/AppendActionButton'\nimport { escapeHTML, unescapeHTML } from './utils/stringUtils'\nimport { getInnerText } from './utils/domUtils'\nimport { stringConvert, valueType, isUrl } from './utils/typeUtils'\n\n/**\n * @type {JSONNode | null} activeContextMenu singleton holding the JSONNode having\n * the active (visible) context menu\n */\nlet activeContextMenu = null\n\nexport default class JSONNode extends Component {\n static URL_TITLE = 'Ctrl+Click or Ctrl+Enter to open url'\n\n constructor (props) {\n super(props)\n\n this.state = {\n menu: null, // context menu\n appendMenu: null, // append context menu (used in placeholder of empty object/array)\n }\n }\n\n render (props, state) {\n if (props.data.type === 'Array') {\n return this.renderJSONArray(props)\n }\n else if (props.data.type === 'Object') {\n return this.renderJSONObject(props)\n }\n else {\n return this.renderJSONValue(props)\n }\n }\n\n renderJSONObject ({prop, data, options, events}) {\n const childCount = data.props.length\n const contents = [\n h('div', {class: 'jsoneditor-node jsoneditor-object'}, [\n this.renderExpandButton(),\n this.renderActionMenuButton(),\n this.renderProperty(prop, data, options),\n this.renderReadonly(`{${childCount}}`, `Array containing ${childCount} items`)\n ])\n ]\n\n if (data.expanded) {\n if (data.props.length > 0) {\n const props = data.props.map(prop => {\n return h(this.constructor, {\n key: prop.name,\n parent: this,\n prop: prop.name,\n data: prop.value,\n options,\n events\n })\n })\n\n contents.push(h('ul', {key: 'props', class: 'jsoneditor-list'}, props))\n }\n else {\n contents.push(h('ul', {key: 'append', class: 'jsoneditor-list'}, [\n this.renderAppend('(empty object)')\n ]))\n }\n }\n\n return h('li', {}, contents)\n }\n\n renderJSONArray ({prop, data, options, events}) {\n const childCount = data.items.length\n const contents = [\n h('div', {class: 'jsoneditor-node jsoneditor-array'}, [\n this.renderExpandButton(),\n this.renderActionMenuButton(),\n this.renderProperty(prop, data, options),\n this.renderReadonly(`[${childCount}]`, `Array containing ${childCount} items`)\n ])\n ]\n\n if (data.expanded) {\n if (data.items.length > 0) {\n const items = data.items.map((child, index) => {\n return h(this.constructor, {\n key: index,\n parent: this,\n prop: index,\n data: child,\n options,\n events\n })\n })\n contents.push(h('ul', {key: 'items', class: 'jsoneditor-list'}, items))\n }\n else {\n contents.push(h('ul', {key: 'append', class: 'jsoneditor-list'}, [\n this.renderAppend('(empty array)')\n ]))\n }\n }\n\n return h('li', {}, contents)\n }\n\n renderJSONValue ({prop, data, options}) {\n return h('li', {}, [\n h('div', {class: 'jsoneditor-node'}, [\n this.renderPlaceholder(),\n this.renderActionMenuButton(),\n this.renderProperty(prop, data, options),\n this.renderSeparator(),\n this.renderValue(data.value)\n ])\n ])\n }\n\n /**\n * Render contents for an empty object or array\n * @param {string} text\n * @return {*}\n */\n renderAppend (text) {\n return h('li', {key: 'append'}, [\n h('div', {class: 'jsoneditor-node'}, [\n this.renderPlaceholder(),\n this.renderAppendMenuButton(),\n this.renderReadonly(text)\n ])\n ])\n }\n\n renderPlaceholder () {\n return h('div', {class: 'jsoneditor-button-placeholder'})\n }\n\n renderReadonly (text, title = null) {\n return h('div', {class: 'jsoneditor-readonly', title}, text)\n }\n\n renderProperty (prop, data, options) {\n if (prop !== null) {\n const isIndex = typeof prop === 'number' // FIXME: pass an explicit prop isIndex\n\n if (isIndex) { // array item\n return h('div', {\n class: 'jsoneditor-property jsoneditor-readonly',\n spellCheck: 'false'\n }, prop)\n }\n else { // object property\n const escapedProp = escapeHTML(prop)\n\n return h('div', {\n class: 'jsoneditor-property' + (prop.length === 0 ? ' jsoneditor-empty' : ''),\n contentEditable: 'true',\n spellCheck: 'false',\n onBlur: this.handleChangeProperty\n }, escapedProp)\n }\n }\n else {\n // root node\n const content = JSONNode.getRootName(data, options)\n\n return h('div', {\n class: 'jsoneditor-property jsoneditor-readonly',\n spellCheck: 'false',\n onBlur: this.handleChangeProperty\n }, content)\n }\n }\n\n renderSeparator() {\n return h('div', {class: 'jsoneditor-separator'}, ':')\n }\n\n renderValue (value) {\n const escapedValue = escapeHTML(value)\n const type = valueType (value)\n const itsAnUrl = isUrl(value)\n const isEmpty = escapedValue.length === 0\n\n return h('div', {\n class: JSONNode.getValueClass(type, itsAnUrl, isEmpty),\n contentEditable: 'true',\n spellCheck: 'false',\n onBlur: this.handleChangeValue,\n onInput: this.updateValueStyling,\n onClick: this.handleClickValue,\n onKeyDown: this.handleKeyDownValue,\n title: itsAnUrl ? JSONNode.URL_TITLE : null\n }, escapedValue)\n }\n\n /**\n * Note: this function manipulates the className and title of the editable div\n * outside of Preact, so the user gets immediate feedback\n * @param event\n */\n updateValueStyling = (event) => {\n const value = this.getValueFromEvent(event)\n const type = valueType (value)\n const itsAnUrl = isUrl(value)\n const isEmpty = false // not needed, our div has a border and is clearly visible\n\n // find the editable div, the root\n let target = event.target\n while (target.contentEditable !== 'true') {\n target = target.parentNode\n }\n\n target.className = JSONNode.getValueClass(type, itsAnUrl, isEmpty)\n target.title = itsAnUrl ? JSONNode.URL_TITLE : ''\n\n // remove all classNames from childs (needed for IE and Edge)\n JSONNode.removeChildClasses(target)\n }\n\n /**\n * Create the className for the property value\n * @param {string} type\n * @param {boolean} isUrl\n * @param {boolean} isEmpty\n * @return {string}\n * @public\n */\n static getValueClass (type, isUrl, isEmpty) {\n return 'jsoneditor-value ' +\n 'jsoneditor-' + type +\n (isUrl ? ' jsoneditor-url' : '') +\n (isEmpty ? ' jsoneditor-empty' : '')\n }\n\n /**\n * Recursively remove all classes from the childs of this element\n * @param elem\n * @public\n */\n static removeChildClasses (elem) {\n for (let i = 0; i < elem.childNodes.length; i++) {\n const child = elem.childNodes[i]\n if (child.class) {\n child.class = ''\n }\n JSONNode.removeChildClasses(child)\n }\n }\n\n renderExpandButton () {\n const className = `jsoneditor-button jsoneditor-${this.props.data.expanded ? 'expanded' : 'collapsed'}`\n return h('div', {class: 'jsoneditor-button-container'},\n h('button', {\n class: className,\n onClick: this.handleExpand,\n title:\n 'Click to expand/collapse this field. \\n' +\n 'Ctrl+Click to expand/collapse including all childs.'\n })\n )\n }\n\n renderActionMenuButton () {\n return h(ActionButton, {\n path: this.getPath(),\n type: this.props.data.type,\n events: this.props.events\n })\n }\n\n renderAppendMenuButton () {\n return h(AppendActionButton, {\n path: this.getPath(),\n events: this.props.events\n })\n }\n\n shouldComponentUpdate(nextProps, nextState) {\n let prop\n\n for (prop in nextProps) {\n if (nextProps.hasOwnProperty(prop) && this.props[prop] !== nextProps[prop]) {\n return true\n }\n }\n\n for (prop in nextState) {\n if (nextState.hasOwnProperty(prop) && this.state[prop] !== nextState[prop]) {\n return true\n }\n }\n\n return false\n }\n\n static getRootName (data, options) {\n return typeof options.name === 'string'\n ? options.name\n : (data.type === 'Object' || data.type === 'Array')\n ? data.type\n : valueType(data.value)\n }\n\n handleChangeProperty = (event) => {\n const parentPath = this.props.parent.getPath()\n const oldProp = this.props.prop\n const newProp = unescapeHTML(getInnerText(event.target))\n\n if (newProp !== oldProp) {\n this.props.events.onChangeProperty(parentPath, oldProp, newProp)\n }\n }\n\n handleChangeValue = (event) => {\n const value = this.getValueFromEvent(event)\n\n if (value !== this.props.data.value) {\n this.props.events.onChangeValue(this.getPath(), value)\n }\n }\n\n handleClickValue = (event) => {\n if (event.ctrlKey && event.button === 0) { // Ctrl+Left click\n this.openLinkIfUrl(event)\n }\n }\n\n handleKeyDownValue = (event) => {\n if (event.ctrlKey && event.which === 13) { // Ctrl+Enter\n this.openLinkIfUrl(event)\n }\n }\n\n handleExpand = (event) => {\n const recurse = event.ctrlKey\n const expanded = !this.props.data.expanded\n\n this.props.events.onExpand(this.getPath(), expanded, recurse)\n }\n\n handleContextMenu = (event) => {\n event.stopPropagation()\n\n if (this.state.menu) {\n // hide context menu\n JSONNode.hideActionMenu()\n }\n else {\n // hide any currently visible context menu\n JSONNode.hideActionMenu()\n\n // show context menu\n this.setState({\n menu: {\n anchor: event.target,\n root: JSONNode.findRootElement(event)\n }\n })\n activeContextMenu = this\n }\n }\n\n handleAppendContextMenu = (event) => {\n event.stopPropagation()\n\n if (this.state.appendMenu) {\n // hide append context menu\n JSONNode.hideActionMenu()\n }\n else {\n // hide any currently visible context menu\n JSONNode.hideActionMenu()\n\n // show append context menu\n this.setState({\n appendMenu: {\n anchor: event.target,\n root: JSONNode.findRootElement(event)\n }\n })\n activeContextMenu = this\n }\n }\n\n /**\n * Singleton function to hide the currently visible context menu if any.\n */\n static hideActionMenu () {\n if (activeContextMenu) {\n activeContextMenu.setState({\n menu: null,\n appendMenu: null\n })\n activeContextMenu = null\n }\n }\n\n /**\n * When this JSONNode holds an URL as value, open this URL in a new browser tab\n * @param event\n * @private\n */\n openLinkIfUrl (event) {\n const value = this.getValueFromEvent(event)\n\n if (isUrl(value)) {\n event.preventDefault()\n event.stopPropagation()\n\n window.open(value, '_blank')\n }\n }\n\n /**\n * Get the path of this JSONNode\n * @return {Path}\n */\n getPath () {\n const path = this.props.parent\n ? this.props.parent.getPath()\n : []\n\n if (this.props.prop !== null) {\n path.push(this.props.prop)\n }\n\n return path\n }\n\n /**\n * Get the value of the target of an event, and convert it to it's type\n * @param event\n * @return {string | number | boolean | null}\n * @private\n */\n getValueFromEvent (event) {\n const stringValue = unescapeHTML(getInnerText(event.target))\n return this.props.data.type === 'string'\n ? stringValue\n : stringConvert(stringValue)\n }\n\n /**\n * Find the root DOM element of the JSONEditor\n * Search is done based on the CSS class 'jsoneditor'\n * @param event\n * @return {*}\n */\n // TODO: cleanup\n static findRootElement (event) {\n function isEditorElement (elem) {\n // FIXME: this is a bit tricky. can we use a special attribute or something?\n return elem.className.split(' ').indexOf('jsoneditor') !== -1\n }\n\n let elem = event.target\n while (elem) {\n if (isEditorElement(elem)) {\n return elem\n }\n\n elem = elem.parentNode\n }\n\n return null\n }\n\n}\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/JSONNode.js\n **/","import { h, Component } from 'preact'\nimport ActionMenu from './ActionMenu'\nimport { findParentNode } from '../utils/domUtils'\n\nexport default class ActionButton extends Component {\n constructor (props) {\n super (props)\n\n this.state = {\n open: false, // whether the menu is open or not\n anchor: null,\n root: null\n }\n }\n\n /**\n * @param {{path, type, events}} props\n * @param state\n * @return {*}\n */\n render (props, state) {\n const className = 'jsoneditor-button jsoneditor-actionmenu' +\n (this.state.open ? ' jsoneditor-visible' : '')\n\n return h('div', {class: 'jsoneditor-button-container'}, [\n h(ActionMenu, {\n ...props, // path, type, events\n ...state, // open, anchor, root\n onRequestClose: this.handleRequestClose\n }),\n h('button', {class: className, onClick: this.handleOpen})\n ])\n }\n\n handleOpen = (event) => {\n this.setState({\n open: true,\n anchor: event.target,\n root: findParentNode(event.target, 'data-jsoneditor', 'true')\n })\n }\n\n handleRequestClose = () => {\n this.setState({open: false})\n }\n}\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/menu/ActionButton.js\n **/","import { h, Component } from 'preact'\nimport Menu from './Menu'\nimport {\n createChangeType, createSort,\n createSeparator,\n createInsert, createDuplicate, createRemove\n} from './entries'\n\nexport default class ActionMenu extends Component {\n /**\n * @param {{open, anchor, root, path, type, events, onRequestClose}} props\n * @param state\n * @return {JSX.Element}\n */\n render (props, state) {\n let items = [] // array with menu items\n\n items.push(createChangeType(props.path, props.type, props.events.onChangeType))\n\n if (props.type === 'Array' || props.type === 'Object') {\n // FIXME: get current sort order (to display correct icon)\n const order = 'asc'\n items.push(createSort(props.path, order, props.events.onSort))\n }\n\n const hasParent = props.path.length > 0\n if (hasParent) {\n items.push(createSeparator())\n items.push(createInsert(props.path, props.events.onInsert))\n items.push(createDuplicate(props.path, props.events.onDuplicate))\n items.push(createRemove(props.path, props.events.onRemove))\n }\n\n // TODO: implement a hook to adjust the action menu\n\n return h(Menu, {\n ...props,\n items\n })\n }\n}\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/menu/ActionMenu.js\n **/","import { h, Component } from 'preact'\nimport { findParentNode } from '../utils/domUtils'\n\nexport let CONTEXT_MENU_HEIGHT = 240\n\nexport default class Menu extends Component {\n constructor(props) {\n super(props)\n\n this.state = {\n expanded: null, // menu index of expanded menu item\n expanding: null, // menu index of expanding menu item\n collapsing: null // menu index of collapsing menu item\n }\n }\n\n /**\n * @param {{open: boolean, items: Array, anchor, root, onRequestClose: function}} props\n * @param state\n * @return {*}\n */\n render (props, state) {\n if (!props.open) {\n return null\n }\n\n // determine orientation\n const anchorRect = this.props.anchor.getBoundingClientRect()\n const rootRect = this.props.root.getBoundingClientRect()\n const orientation = (rootRect.bottom - anchorRect.bottom < CONTEXT_MENU_HEIGHT &&\n anchorRect.top - rootRect.top > CONTEXT_MENU_HEIGHT)\n ? 'top'\n : 'bottom'\n\n // TODO: create a non-visible button to set the focus to the menu\n // TODO: implement (customizable) quick keys\n\n const className = 'jsoneditor-actionmenu ' +\n ((orientation === 'top') ? 'jsoneditor-actionmenu-top' : 'jsoneditor-actionmenu-bottom')\n\n return h('div', {\n class: className,\n 'data-menu': 'true'\n },\n props.items.map(this.renderMenuItem)\n )\n }\n\n renderMenuItem = (item, index) => {\n if (item.type === 'separator') {\n return h('div', {class: 'jsoneditor-menu-separator'})\n }\n\n if (item.click && item.submenu) {\n // FIXME: don't create functions in the render function\n const onClick = (event) => {\n item.click()\n this.props.onRequestClose()\n }\n\n // two buttons: direct click and a small button to expand the submenu\n return h('div', {class: 'jsoneditor-menu-item'}, [\n h('button', {class: 'jsoneditor-menu-button jsoneditor-menu-default ' + item.className, title: item.title, onClick }, [\n h('span', {class: 'jsoneditor-icon'}),\n h('span', {class: 'jsoneditor-text'}, item.text)\n ]),\n h('button', {class: 'jsoneditor-menu-button jsoneditor-menu-expand', onClick: this.createExpandHandler(index) }, [\n h('span', {class: 'jsoneditor-icon jsoneditor-icon-expand'})\n ]),\n this.renderSubMenu(item.submenu, index)\n ])\n }\n else if (item.submenu) {\n // button expands the submenu\n return h('div', {class: 'jsoneditor-menu-item'}, [\n h('button', {class: 'jsoneditor-menu-button ' + item.className, title: item.title, onClick: this.createExpandHandler(index) }, [\n h('span', {class: 'jsoneditor-icon'}),\n h('span', {class: 'jsoneditor-text'}, item.text),\n h('span', {class: 'jsoneditor-icon jsoneditor-icon-expand'}),\n ]),\n this.renderSubMenu(item.submenu, index)\n ])\n }\n else {\n // FIXME: don't create functions in the render function\n const onClick = (event) => {\n item.click()\n this.props.onRequestClose()\n }\n\n // just a button (no submenu)\n return h('div', {class: 'jsoneditor-menu-item'}, [\n h('button', {class: 'jsoneditor-menu-button ' + item.className, title: item.title, onClick }, [\n h('span', {class: 'jsoneditor-icon'}),\n h('span', {class: 'jsoneditor-text'}, item.text)\n ]),\n ])\n }\n }\n\n /**\n * @param {Array} submenu\n * @param {number} index\n */\n renderSubMenu (submenu, index) {\n const expanded = this.state.expanded === index\n const collapsing = this.state.collapsing === index\n\n const contents = submenu.map(item => {\n // FIXME: don't create functions in the render function\n const onClick = () => {\n item.click()\n this.props.onRequestClose()\n }\n\n return h('div', {class: 'jsoneditor-menu-item'}, [\n h('button', {class: 'jsoneditor-menu-button ' + item.className, title: item.title, onClick }, [\n h('span', {class: 'jsoneditor-icon'}),\n h('span', {class: 'jsoneditor-text'}, item.text)\n ]),\n ])\n })\n\n const className = 'jsoneditor-submenu ' +\n (expanded ? ' jsoneditor-expanded' : '') +\n (collapsing ? ' jsoneditor-collapsing' : '')\n\n return h('div', {class: className}, contents)\n }\n\n createExpandHandler (index) {\n return (event) => {\n event.stopPropagation()\n\n const prev = this.state.expanded\n\n this.setState({\n expanded: (prev === index) ? null : index,\n collapsing: prev\n })\n\n // timeout after unit is collapsed\n setTimeout(() => {\n if (prev === this.state.collapsing) {\n this.setState({\n collapsing: null\n })\n }\n }, 300)\n }\n }\n\n componentDidMount () {\n this.updateRequestCloseListener()\n }\n\n componentDidUpdate () {\n this.updateRequestCloseListener()\n }\n\n componentWillUnmount () {\n this.removeRequestCloseListener()\n }\n\n updateRequestCloseListener () {\n if (this.props.open) {\n this.addRequestCloseListener()\n }\n else {\n this.removeRequestCloseListener()\n }\n }\n\n addRequestCloseListener () {\n if (!this.handleRequestClose) {\n // Attach event listener on next tick, else the current click to open\n // the menu will immediately result in requestClose event as well\n setTimeout(() => {\n this.handleRequestClose = (event) => {\n if (!findParentNode(event.target, 'data-menu', 'true')) {\n this.props.onRequestClose()\n }\n }\n window.addEventListener('click', this.handleRequestClose)\n }, 0)\n }\n }\n\n removeRequestCloseListener () {\n if (this.handleRequestClose) {\n window.removeEventListener('click', this.handleRequestClose)\n this.handleRequestClose = null\n }\n }\n\n handleRequestClose = null\n}\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/menu/Menu.js\n **/","// This file contains functions to create menu entries\n\n// TYPE_TITLES with explanation for the different types\nconst TYPE_TITLES = {\n 'value': 'Item type \"value\". ' +\n 'The item type is automatically determined from the value ' +\n 'and can be a string, number, boolean, or null.',\n 'Object': 'Item type \"object\". ' +\n 'An object contains an unordered set of key/value pairs.',\n 'Array': 'Item type \"array\". ' +\n 'An array contains an ordered collection of values.',\n 'string': 'Item type \"string\". ' +\n 'Item type is not determined from the value, ' +\n 'but always returned as string.'\n}\n\nexport function createChangeType (path, type, onChangeType) {\n return {\n text: 'Type',\n title: 'Change the type of this field',\n className: 'jsoneditor-type-' + type,\n submenu: [\n {\n text: 'Value',\n className: 'jsoneditor-type-value' + (type == 'value' ? ' jsoneditor-selected' : ''),\n title: TYPE_TITLES.value,\n click: () => onChangeType(path, 'value')\n },\n {\n text: 'Array',\n className: 'jsoneditor-type-Array' + (type == 'Array' ? ' jsoneditor-selected' : ''),\n title: TYPE_TITLES.array,\n click: () => onChangeType(path, 'Array')\n },\n {\n text: 'Object',\n className: 'jsoneditor-type-Object' + (type == 'Object' ? ' jsoneditor-selected' : ''),\n title: TYPE_TITLES.object,\n click: () => onChangeType(path, 'Object')\n },\n {\n text: 'String',\n className: 'jsoneditor-type-string' + (type == 'string' ? ' jsoneditor-selected' : ''),\n title: TYPE_TITLES.string,\n click: () => onChangeType(path, 'string')\n }\n ]\n }\n}\n\nexport function createSort (path, order, onSort) {\n var direction = ((order == 'asc') ? 'desc': 'asc')\n return {\n text: 'Sort',\n title: 'Sort the childs of this ' + TYPE_TITLES.type,\n className: 'jsoneditor-sort-' + direction,\n click: () => onSort(path),\n submenu: [\n {\n text: 'Ascending',\n className: 'jsoneditor-sort-asc',\n title: 'Sort the childs of this ' + TYPE_TITLES.type + ' in ascending order',\n click: () => onSort(path, 'asc')\n },\n {\n text: 'Descending',\n className: 'jsoneditor-sort-desc',\n title: 'Sort the childs of this ' + TYPE_TITLES.type +' in descending order',\n click: () => onSort(path, 'desc')\n }\n ]\n }\n}\n\nexport function createInsert (path, onInsert) {\n return {\n text: 'Insert',\n title: 'Insert a new item with type \\'value\\' after this item (Ctrl+Ins)',\n submenuTitle: 'Select the type of the item to be inserted',\n className: 'jsoneditor-insert',\n click: () => onInsert(path, 'value'),\n submenu: [\n {\n text: 'Value',\n className: 'jsoneditor-type-value',\n title: TYPE_TITLES.value,\n click: () => onInsert(path, 'value')\n },\n {\n text: 'Array',\n className: 'jsoneditor-type-Array',\n title: TYPE_TITLES.array,\n click: () => onInsert(path, 'Array')\n },\n {\n text: 'Object',\n className: 'jsoneditor-type-Object',\n title: TYPE_TITLES.object,\n click: () => onInsert(path, 'Object')\n },\n {\n text: 'String',\n className: 'jsoneditor-type-string',\n title: TYPE_TITLES.string,\n click: () => onInsert(path, 'string')\n }\n ]\n }\n}\n\nexport function createAppend (path, onAppend) {\n return {\n text: 'Insert',\n title: 'Insert a new item with type \\'value\\' after this item (Ctrl+Ins)',\n submenuTitle: 'Select the type of the item to be inserted',\n className: 'jsoneditor-insert',\n click: () => onAppend(path, 'value'),\n submenu: [\n {\n text: 'Value',\n className: 'jsoneditor-type-value',\n title: TYPE_TITLES.value,\n click: () => onAppend(path, 'value')\n },\n {\n text: 'Array',\n className: 'jsoneditor-type-Array',\n title: TYPE_TITLES.array,\n click: () => onAppend(path, 'Array')\n },\n {\n text: 'Object',\n className: 'jsoneditor-type-Object',\n title: TYPE_TITLES.object,\n click: () => onAppend(path, 'Object')\n },\n {\n text: 'String',\n className: 'jsoneditor-type-string',\n title: TYPE_TITLES.string,\n click: () => onAppend(path, 'string')\n }\n ]\n }\n}\n\nexport function createDuplicate (path, onDuplicate) {\n return {\n text: 'Duplicate',\n title: 'Duplicate this item (Ctrl+D)',\n className: 'jsoneditor-duplicate',\n click: () => onDuplicate(path)\n }\n}\n\nexport function createRemove (path, onRemove) {\n return {\n text: 'Remove',\n title: 'Remove this item (Ctrl+Del)',\n className: 'jsoneditor-remove',\n click: () => onRemove(path)\n }\n}\n\nexport function createSeparator () {\n return {\n 'type': 'separator'\n }\n}\n\n\n/** WEBPACK FOOTER **\n ** ./src/menu/entries.js\n **/","import { h, Component } from 'preact'\nimport AppendActionMenu from './AppendActionMenu'\nimport { findParentNode } from '../utils/domUtils'\n\nexport default class AppendActionButton extends Component {\n constructor (props) {\n super (props)\n\n this.state = {\n open: false, // whether the menu is open or not\n anchor: null,\n root: null\n }\n }\n\n /**\n * @param {{path, events}} props\n * @param state\n * @return {*}\n */\n render (props, state) {\n const className = 'jsoneditor-button jsoneditor-actionmenu' +\n (this.state.open ? ' jsoneditor-visible' : '')\n\n return h('div', {class: 'jsoneditor-button-container'}, [\n h(AppendActionMenu, {\n ...props, // path, events\n ...state, // open, anchor, root\n onRequestClose: this.handleRequestClose\n }),\n h('button', {class: className, onClick: this.handleOpen})\n ])\n }\n\n handleOpen = (event) => {\n this.setState({\n open: true,\n anchor: event.target,\n root: findParentNode(event.target, 'data-jsoneditor', 'true')\n })\n }\n\n handleRequestClose = () => {\n this.setState({open: false})\n }\n}\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/menu/AppendActionButton.js\n **/","import { h, Component } from 'preact'\nimport Menu from './Menu'\nimport { createAppend } from './entries'\n\nexport default class AppendActionMenu extends Component {\n /**\n * @param {{anchor, root, path, events}} props\n * @param state\n * @return {JSX.Element}\n */\n render (props, state) {\n const items = [\n createAppend(props.path, props.events.onAppend)\n ]\n\n // TODO: implement a hook to adjust the action menu\n\n return h(Menu, {\n ...props,\n items\n })\n }\n}\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/menu/AppendActionMenu.js\n **/","import { h } from 'preact'\n\nimport { escapeHTML } from './utils/stringUtils'\nimport JSONNode from './JSONNode'\nimport JSONNodeForm from './JSONNodeForm'\nimport { valueType, isUrl } from './utils/typeUtils'\n\n/**\n * JSONNodeView\n *\n * Creates JSONNodes without action menus and with readonly properties and values\n */\nexport default class JSONNodeView extends JSONNodeForm {\n\n // render a readonly value\n renderValue (value) {\n const escapedValue = escapeHTML(value)\n const type = valueType (value)\n const isEmpty = escapedValue.length === 0\n const itsAnUrl = isUrl(value)\n const className = JSONNode.getValueClass(type, itsAnUrl, isEmpty)\n\n if (itsAnUrl) {\n return h('a', {\n class: className,\n href: escapedValue\n }, escapedValue)\n }\n else {\n return h('div', {\n class: className,\n onClick: this.handleClickValue\n }, escapedValue)\n }\n }\n\n handleClickValue = (event) => {\n if (event.button === 0) { // Left click\n this.openLinkIfUrl(event)\n }\n }\n}\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/JSONNodeView.js\n **/","import { h } from 'preact'\n\nimport { escapeHTML } from './utils/stringUtils'\nimport JSONNode from './JSONNode'\n\n/**\n * JSONNodeForm\n *\n * Creates JSONNodes without action menus and with readonly properties\n */\nexport default class JSONNodeForm extends JSONNode {\n\n // render no action menu...\n renderActionMenuButton () {\n return null\n }\n\n // render no append menu...\n renderAppendMenuButton () {\n return null\n }\n\n // render a readonly property\n renderProperty (prop, data, options) {\n if (prop !== null) {\n const isIndex = typeof prop === 'number' // FIXME: pass an explicit prop isIndex\n\n if (isIndex) { // array item\n return h('div', {\n class: 'jsoneditor-property jsoneditor-readonly'\n }, prop)\n }\n else { // object property\n const escapedProp = escapeHTML(prop)\n\n return h('div', {\n class: 'jsoneditor-property' + (prop.length === 0 ? ' jsoneditor-empty' : '')\n }, escapedProp)\n }\n }\n else {\n // root node\n const content = JSONNode.getRootName(data, options)\n\n return h('div', {\n class: 'jsoneditor-property jsoneditor-readonly'\n }, content)\n }\n }\n}\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/JSONNodeForm.js\n **/","// style-loader: Adds some css to the DOM by adding a + + +

+ + +

+
+ + + + diff --git a/ui/app/bower_components/jsoneditor/examples/02_viewer.html b/ui/app/bower_components/jsoneditor/examples/02_viewer.html new file mode 100644 index 0000000..f6d9532 --- /dev/null +++ b/ui/app/bower_components/jsoneditor/examples/02_viewer.html @@ -0,0 +1,44 @@ + + + + JSONEditor | Viewer + + + + + + + + +

+ This editor is read-only (mode='viewer'). +

+
+ + + + diff --git a/ui/app/bower_components/jsoneditor/examples/03_switch_mode.html b/ui/app/bower_components/jsoneditor/examples/03_switch_mode.html new file mode 100644 index 0000000..f080ae2 --- /dev/null +++ b/ui/app/bower_components/jsoneditor/examples/03_switch_mode.html @@ -0,0 +1,66 @@ + + + + JSONEditor | Switch mode + + + + + + + + + + + +

+ Switch editor mode using the mode box. + Note that the mode can be changed programmatically as well using the method + editor.setMode(mode), try it in the console of your browser. +

+ +
+ + + + diff --git a/ui/app/bower_components/jsoneditor/examples/04_load_and_save.html b/ui/app/bower_components/jsoneditor/examples/04_load_and_save.html new file mode 100644 index 0000000..d8be3c9 --- /dev/null +++ b/ui/app/bower_components/jsoneditor/examples/04_load_and_save.html @@ -0,0 +1,75 @@ + + + + JSONEditor | Load and save + + + + + + + + + + +

Load and save JSON documents

+

+ This examples uses HTML5 to load/save local files. + Powered by FileReader.js and + FileSaver.js.
+ Only supported on modern browsers (Chrome, FireFox, IE10+, Safari 6.1+, Opera 15+). +

+

+ Load a JSON document: +

+

+ Save a JSON document: +

+ +
+ + + + + + diff --git a/ui/app/bower_components/jsoneditor/examples/05_custom_fields_editable.html b/ui/app/bower_components/jsoneditor/examples/05_custom_fields_editable.html new file mode 100644 index 0000000..d8a5dae --- /dev/null +++ b/ui/app/bower_components/jsoneditor/examples/05_custom_fields_editable.html @@ -0,0 +1,63 @@ + + + + JSONEditor | Custom editable fields + + + + + + + +

+ In this example: +

+
    +
  • the field _id and its value are read-only
  • +
  • the field name is read-only but has an editable value
  • +
  • the field age and its value are editable
  • +
+ +
+ + + + diff --git a/ui/app/bower_components/jsoneditor/examples/06_custom_styling.html b/ui/app/bower_components/jsoneditor/examples/06_custom_styling.html new file mode 100644 index 0000000..bc17075 --- /dev/null +++ b/ui/app/bower_components/jsoneditor/examples/06_custom_styling.html @@ -0,0 +1,51 @@ + + + + JSONEditor | Custom styling + + + + + + + + + + +

+ This example demonstrates how to customize the look of JSONEditor, + the editor below has a dark theme. Note that the example isn't worked + out for the mode code. To do that, you can load and configure + a custom theme for the Ace editor. +

+ +
+ + + + diff --git a/ui/app/bower_components/jsoneditor/examples/07_json_schema_validation.html b/ui/app/bower_components/jsoneditor/examples/07_json_schema_validation.html new file mode 100644 index 0000000..8338b67 --- /dev/null +++ b/ui/app/bower_components/jsoneditor/examples/07_json_schema_validation.html @@ -0,0 +1,71 @@ + + + + JSONEditor | JSON schema validation + + + + + + + +

JSON schema validation

+

+ This example demonstrates JSON schema validation. The JSON object in this example must contain properties firstName and lastName, can can optionally have a property age which must be a positive integer. +

+

+ See http://json-schema.org/ for more information. +

+ +
+ + + + diff --git a/ui/app/bower_components/jsoneditor/examples/css/darktheme.css b/ui/app/bower_components/jsoneditor/examples/css/darktheme.css new file mode 100644 index 0000000..3c1c881 --- /dev/null +++ b/ui/app/bower_components/jsoneditor/examples/css/darktheme.css @@ -0,0 +1,76 @@ +/* dark styling of the editor */ +div.jsoneditor, +div.jsoneditor-menu { + border-color: #4b4b4b; +} +div.jsoneditor-menu { + background-color: #4b4b4b; +} +div.jsoneditor-tree, +div.jsoneditor textarea.jsoneditor-text { + background-color: #666666; + color: #ffffff; +} +div.jsoneditor-field, +div.jsoneditor-value { + color: #ffffff; +} +table.jsoneditor-search div.jsoneditor-frame { + background: #808080; +} + +tr.jsoneditor-highlight, +tr.jsoneditor-selected { + background-color: #808080; +} + +div.jsoneditor-field[contenteditable=true]:focus, +div.jsoneditor-field[contenteditable=true]:hover, +div.jsoneditor-value[contenteditable=true]:focus, +div.jsoneditor-value[contenteditable=true]:hover, +div.jsoneditor-field.jsoneditor-highlight, +div.jsoneditor-value.jsoneditor-highlight { + background-color: #808080; + border-color: #808080; +} + +div.jsoneditor-field.highlight-active, +div.jsoneditor-field.highlight-active:focus, +div.jsoneditor-field.highlight-active:hover, +div.jsoneditor-value.highlight-active, +div.jsoneditor-value.highlight-active:focus, +div.jsoneditor-value.highlight-active:hover { + background-color: #b1b1b1; + border-color: #b1b1b1; +} + +div.jsoneditor-tree button:focus { + background-color: #868686; +} + +/* coloring of JSON in tree mode */ +div.jsoneditor-readonly { + color: #acacac; +} +div.jsoneditor td.jsoneditor-separator { + color: #acacac; +} +div.jsoneditor-value.jsoneditor-string { + color: #00ff88; +} +div.jsoneditor-value.jsoneditor-object, +div.jsoneditor-value.jsoneditor-array { + color: #bababa; +} +div.jsoneditor-value.jsoneditor-number { + color: #ff4040; +} +div.jsoneditor-value.jsoneditor-boolean { + color: #ff8048; +} +div.jsoneditor-value.jsoneditor-null { + color: #49a7fc; +} +div.jsoneditor-value.jsoneditor-invalid { + color: white; +} diff --git a/ui/app/bower_components/jsoneditor/examples/requirejs_demo/requirejs_demo.html b/ui/app/bower_components/jsoneditor/examples/requirejs_demo/requirejs_demo.html new file mode 100644 index 0000000..ba8f49e --- /dev/null +++ b/ui/app/bower_components/jsoneditor/examples/requirejs_demo/requirejs_demo.html @@ -0,0 +1,21 @@ + + + + JSONEditor | Require.js demo + + + + + +

+ + +

+
+ + diff --git a/ui/app/bower_components/jsoneditor/examples/requirejs_demo/scripts/main.js b/ui/app/bower_components/jsoneditor/examples/requirejs_demo/scripts/main.js new file mode 100644 index 0000000..4303b1a --- /dev/null +++ b/ui/app/bower_components/jsoneditor/examples/requirejs_demo/scripts/main.js @@ -0,0 +1,25 @@ +var module = '../../../dist/jsoneditor'; +require([module], function (JSONEditor) { + // create the editor + var container = document.getElementById('jsoneditor'); + var editor = new JSONEditor(container); + + // set json + document.getElementById('setJSON').onclick = function () { + var json = { + 'array': [1, 2, 3], + 'boolean': true, + 'null': null, + 'number': 123, + 'object': {'a': 'b', 'c': 'd'}, + 'string': 'Hello World' + }; + editor.set(json); + }; + + // get json + document.getElementById('getJSON').onclick = function () { + var json = editor.get(); + alert(JSON.stringify(json, null, 2)); + }; +}); diff --git a/ui/app/bower_components/jsoneditor/examples/requirejs_demo/scripts/require.js b/ui/app/bower_components/jsoneditor/examples/requirejs_demo/scripts/require.js new file mode 100644 index 0000000..d65036f --- /dev/null +++ b/ui/app/bower_components/jsoneditor/examples/requirejs_demo/scripts/require.js @@ -0,0 +1,36 @@ +/* + RequireJS 2.1.13 Copyright (c) 2010-2014, The Dojo Foundation All Rights Reserved. + Available via the MIT or new BSD license. + see: http://github.com/jrburke/requirejs for details +*/ +var requirejs,require,define; +(function(ba){function G(b){return"[object Function]"===K.call(b)}function H(b){return"[object Array]"===K.call(b)}function v(b,c){if(b){var d;for(d=0;dthis.depCount&&!this.defined){if(G(l)){if(this.events.error&&this.map.isDefine||g.onError!==ca)try{f=i.execCb(c,l,b,f)}catch(d){a=d}else f=i.execCb(c,l,b,f);this.map.isDefine&&void 0===f&&((b=this.module)?f=b.exports:this.usingExports&& +(f=this.exports));if(a)return a.requireMap=this.map,a.requireModules=this.map.isDefine?[this.map.id]:null,a.requireType=this.map.isDefine?"define":"require",w(this.error=a)}else f=l;this.exports=f;if(this.map.isDefine&&!this.ignore&&(r[c]=f,g.onResourceLoad))g.onResourceLoad(i,this.map,this.depMaps);y(c);this.defined=!0}this.defining=!1;this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete=!0)}}else this.fetch()}},callPlugin:function(){var a= +this.map,b=a.id,d=p(a.prefix);this.depMaps.push(d);q(d,"defined",u(this,function(f){var l,d;d=m(aa,this.map.id);var e=this.map.name,P=this.map.parentMap?this.map.parentMap.name:null,n=i.makeRequire(a.parentMap,{enableBuildCallback:!0});if(this.map.unnormalized){if(f.normalize&&(e=f.normalize(e,function(a){return c(a,P,!0)})||""),f=p(a.prefix+"!"+e,this.map.parentMap),q(f,"defined",u(this,function(a){this.init([],function(){return a},null,{enabled:!0,ignore:!0})})),d=m(h,f.id)){this.depMaps.push(f); +if(this.events.error)d.on("error",u(this,function(a){this.emit("error",a)}));d.enable()}}else d?(this.map.url=i.nameToUrl(d),this.load()):(l=u(this,function(a){this.init([],function(){return a},null,{enabled:!0})}),l.error=u(this,function(a){this.inited=!0;this.error=a;a.requireModules=[b];B(h,function(a){0===a.map.id.indexOf(b+"_unnormalized")&&y(a.map.id)});w(a)}),l.fromText=u(this,function(f,c){var d=a.name,e=p(d),P=M;c&&(f=c);P&&(M=!1);s(e);t(j.config,b)&&(j.config[d]=j.config[b]);try{g.exec(f)}catch(h){return w(C("fromtexteval", +"fromText eval for "+b+" failed: "+h,h,[b]))}P&&(M=!0);this.depMaps.push(e);i.completeLoad(d);n([d],l)}),f.load(a.name,n,l,j))}));i.enable(d,this);this.pluginMaps[d.id]=d},enable:function(){V[this.map.id]=this;this.enabling=this.enabled=!0;v(this.depMaps,u(this,function(a,b){var c,f;if("string"===typeof a){a=p(a,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap);this.depMaps[b]=a;if(c=m(L,a.id)){this.depExports[b]=c(this);return}this.depCount+=1;q(a,"defined",u(this,function(a){this.defineDep(b, +a);this.check()}));this.errback&&q(a,"error",u(this,this.errback))}c=a.id;f=h[c];!t(L,c)&&(f&&!f.enabled)&&i.enable(a,this)}));B(this.pluginMaps,u(this,function(a){var b=m(h,a.id);b&&!b.enabled&&i.enable(a,this)}));this.enabling=!1;this.check()},on:function(a,b){var c=this.events[a];c||(c=this.events[a]=[]);c.push(b)},emit:function(a,b){v(this.events[a],function(a){a(b)});"error"===a&&delete this.events[a]}};i={config:j,contextName:b,registry:h,defined:r,urlFetched:S,defQueue:A,Module:Z,makeModuleMap:p, +nextTick:g.nextTick,onError:w,configure:function(a){a.baseUrl&&"/"!==a.baseUrl.charAt(a.baseUrl.length-1)&&(a.baseUrl+="/");var b=j.shim,c={paths:!0,bundles:!0,config:!0,map:!0};B(a,function(a,b){c[b]?(j[b]||(j[b]={}),U(j[b],a,!0,!0)):j[b]=a});a.bundles&&B(a.bundles,function(a,b){v(a,function(a){a!==b&&(aa[a]=b)})});a.shim&&(B(a.shim,function(a,c){H(a)&&(a={deps:a});if((a.exports||a.init)&&!a.exportsFn)a.exportsFn=i.makeShimExports(a);b[c]=a}),j.shim=b);a.packages&&v(a.packages,function(a){var b, +a="string"===typeof a?{name:a}:a;b=a.name;a.location&&(j.paths[b]=a.location);j.pkgs[b]=a.name+"/"+(a.main||"main").replace(ia,"").replace(Q,"")});B(h,function(a,b){!a.inited&&!a.map.unnormalized&&(a.map=p(b))});if(a.deps||a.callback)i.require(a.deps||[],a.callback)},makeShimExports:function(a){return function(){var b;a.init&&(b=a.init.apply(ba,arguments));return b||a.exports&&da(a.exports)}},makeRequire:function(a,e){function j(c,d,m){var n,q;e.enableBuildCallback&&(d&&G(d))&&(d.__requireJsBuild= +!0);if("string"===typeof c){if(G(d))return w(C("requireargs","Invalid require call"),m);if(a&&t(L,c))return L[c](h[a.id]);if(g.get)return g.get(i,c,a,j);n=p(c,a,!1,!0);n=n.id;return!t(r,n)?w(C("notloaded",'Module name "'+n+'" has not been loaded yet for context: '+b+(a?"":". Use require([])"))):r[n]}J();i.nextTick(function(){J();q=s(p(null,a));q.skipMap=e.skipMap;q.init(c,d,m,{enabled:!0});D()});return j}e=e||{};U(j,{isBrowser:z,toUrl:function(b){var d,e=b.lastIndexOf("."),k=b.split("/")[0];if(-1!== +e&&(!("."===k||".."===k)||1e.attachEvent.toString().indexOf("[native code"))&&!Y?(M=!0,e.attachEvent("onreadystatechange",b.onScriptLoad)): +(e.addEventListener("load",b.onScriptLoad,!1),e.addEventListener("error",b.onScriptError,!1)),e.src=d,J=e,D?y.insertBefore(e,D):y.appendChild(e),J=null,e;if(ea)try{importScripts(d),b.completeLoad(c)}catch(m){b.onError(C("importscripts","importScripts failed for "+c+" at "+d,m,[c]))}};z&&!q.skipDataMain&&T(document.getElementsByTagName("script"),function(b){y||(y=b.parentNode);if(I=b.getAttribute("data-main"))return s=I,q.baseUrl||(E=s.split("/"),s=E.pop(),O=E.length?E.join("/")+"/":"./",q.baseUrl= +O),s=s.replace(Q,""),g.jsExtRegExp.test(s)&&(s=I),q.deps=q.deps?q.deps.concat(s):[s],!0});define=function(b,c,d){var e,g;"string"!==typeof b&&(d=c,c=b,b=null);H(c)||(d=c,c=null);!c&&G(d)&&(c=[],d.length&&(d.toString().replace(ka,"").replace(la,function(b,d){c.push(d)}),c=(1===d.length?["require"]:["require","exports","module"]).concat(c)));if(M){if(!(e=J))N&&"interactive"===N.readyState||T(document.getElementsByTagName("script"),function(b){if("interactive"===b.readyState)return N=b}),e=N;e&&(b|| +(b=e.getAttribute("data-requiremodule")),g=F[e.getAttribute("data-requirecontext")])}(g?g.defQueue:R).push([b,c,d])};define.amd={jQuery:!0};g.exec=function(b){return eval(b)};g(q)}})(this); diff --git a/ui/app/bower_components/jsoneditor/index.js b/ui/app/bower_components/jsoneditor/index.js new file mode 100644 index 0000000..8442caf --- /dev/null +++ b/ui/app/bower_components/jsoneditor/index.js @@ -0,0 +1 @@ +module.exports = require('./src/js/JSONEditor'); diff --git a/ui/app/bower_components/jsoneditor/package.json b/ui/app/bower_components/jsoneditor/package.json new file mode 100644 index 0000000..6673dd7 --- /dev/null +++ b/ui/app/bower_components/jsoneditor/package.json @@ -0,0 +1,42 @@ +{ + "name": "jsoneditor", + "version": "5.5.10", + "main": "./index", + "description": "A web-based tool to view, edit, format, and validate JSON", + "tags": [ + "json", + "editor", + "viewer", + "formatter" + ], + "author": "Jos de Jong ", + "license": "Apache-2.0", + "homepage": "https://github.com/josdejong/jsoneditor", + "repository": { + "type": "git", + "url": "https://github.com/josdejong/jsoneditor.git" + }, + "bugs": "https://github.com/josdejong/jsoneditor/issues", + "scripts": { + "build": "gulp", + "watch": "gulp watch", + "test": "mocha test" + }, + "dependencies": { + "ajv": "3.8.8", + "brace": "0.8.0", + "javascript-natural-sort": "0.7.1" + }, + "devDependencies": { + "gulp": "3.9.1", + "gulp-clean-css": "2.0.5", + "gulp-concat-css": "2.2.0", + "gulp-shell": "0.5.2", + "gulp-util": "3.0.7", + "json-loader": "0.5.4", + "mkdirp": "0.5.1", + "mocha": "2.4.5", + "uglify-js": "2.6.2", + "webpack": "1.12.14" + } +} diff --git a/ui/app/bower_components/jsoneditor/src/css/contextmenu.css b/ui/app/bower_components/jsoneditor/src/css/contextmenu.css new file mode 100644 index 0000000..568c20d --- /dev/null +++ b/ui/app/bower_components/jsoneditor/src/css/contextmenu.css @@ -0,0 +1,244 @@ + +/* ContextMenu - main menu */ + +div.jsoneditor-contextmenu-root { + position: relative; + width: 0; + height: 0; +} + +div.jsoneditor-contextmenu { + position: absolute; + box-sizing: content-box; + z-index: 99999; +} + +div.jsoneditor-contextmenu ul, +div.jsoneditor-contextmenu li { + box-sizing: content-box; +} + +div.jsoneditor-contextmenu ul { + position: relative; + left: 0; + top: 0; + width: 124px; + + background: white; + border: 1px solid #d3d3d3; + box-shadow: 2px 2px 12px rgba(128, 128, 128, 0.3); + + list-style: none; + margin: 0; + padding: 0; +} + +div.jsoneditor-contextmenu ul li button { + padding: 0; + margin: 0; + width: 124px; + height: 24px; + border: none; + cursor: pointer; + color: #4d4d4d; + background: transparent; + + font-size: 10pt; + font-family: arial, sans-serif; + + box-sizing: border-box; + + line-height: 26px; + text-align: left; +} + +/* Fix button padding in firefox */ +div.jsoneditor-contextmenu ul li button::-moz-focus-inner { + padding: 0; + border: 0; +} + +div.jsoneditor-contextmenu ul li button:hover, +div.jsoneditor-contextmenu ul li button:focus { + color: #1a1a1a; + background-color: #f5f5f5; + outline: none; +} + +div.jsoneditor-contextmenu ul li button.jsoneditor-default { + width: 92px; +} + +div.jsoneditor-contextmenu ul li button.jsoneditor-expand { + float: right; + width: 32px; + height: 24px; + border-left: 1px solid #e5e5e5; +} + +div.jsoneditor-contextmenu div.jsoneditor-icon { + float: left; + width: 24px; + height: 24px; + border: none; + padding: 0; + margin: 0; + background-image: url('img/jsoneditor-icons.svg'); +} + +div.jsoneditor-contextmenu ul li button div.jsoneditor-expand { + float: right; + width: 24px; + height: 24px; + padding: 0; + margin: 0 4px 0 0; + background: url('img/jsoneditor-icons.svg') 0 -72px; + opacity: 0.4; +} + +div.jsoneditor-contextmenu ul li button:hover div.jsoneditor-expand, +div.jsoneditor-contextmenu ul li button:focus div.jsoneditor-expand, +div.jsoneditor-contextmenu ul li.jsoneditor-selected div.jsoneditor-expand, +div.jsoneditor-contextmenu ul li button.jsoneditor-expand:hover div.jsoneditor-expand, +div.jsoneditor-contextmenu ul li button.jsoneditor-expand:focus div.jsoneditor-expand { + opacity: 1; +} + +div.jsoneditor-contextmenu div.jsoneditor-separator { + height: 0; + border-top: 1px solid #e5e5e5; + padding-top: 5px; + margin-top: 5px; +} + +div.jsoneditor-contextmenu button.jsoneditor-remove > div.jsoneditor-icon { + background-position: -24px -24px; +} +div.jsoneditor-contextmenu button.jsoneditor-remove:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-remove:focus > div.jsoneditor-icon { + background-position: -24px 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-append > div.jsoneditor-icon { + background-position: 0 -24px; +} +div.jsoneditor-contextmenu button.jsoneditor-append:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-append:focus > div.jsoneditor-icon { + background-position: 0 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-insert > div.jsoneditor-icon { + background-position: 0 -24px; +} +div.jsoneditor-contextmenu button.jsoneditor-insert:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-insert:focus > div.jsoneditor-icon { + background-position: 0 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-duplicate > div.jsoneditor-icon { + background-position: -48px -24px; +} +div.jsoneditor-contextmenu button.jsoneditor-duplicate:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-duplicate:focus > div.jsoneditor-icon { + background-position: -48px 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-sort-asc > div.jsoneditor-icon { + background-position: -168px -24px; +} +div.jsoneditor-contextmenu button.jsoneditor-sort-asc:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-sort-asc:focus > div.jsoneditor-icon { + background-position: -168px 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-sort-desc > div.jsoneditor-icon { + background-position: -192px -24px; +} +div.jsoneditor-contextmenu button.jsoneditor-sort-desc:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-sort-desc:focus > div.jsoneditor-icon { + background-position: -192px 0; +} + +/* ContextMenu - sub menu */ + +div.jsoneditor-contextmenu ul li button.jsoneditor-selected, +div.jsoneditor-contextmenu ul li button.jsoneditor-selected:hover, +div.jsoneditor-contextmenu ul li button.jsoneditor-selected:focus { + color: white; + background-color: #ee422e; +} + +div.jsoneditor-contextmenu ul li { + overflow: hidden; +} + +div.jsoneditor-contextmenu ul li ul { + display: none; + position: relative; + left: -10px; + top: 0; + + border: none; + box-shadow: inset 0 0 10px rgba(128, 128, 128, 0.5); + padding: 0 10px; + + /* TODO: transition is not supported on IE8-9 */ + -webkit-transition: all 0.3s ease-out; + -moz-transition: all 0.3s ease-out; + -o-transition: all 0.3s ease-out; + transition: all 0.3s ease-out; +} + +div.jsoneditor-contextmenu ul li.jsoneditor-selected ul { +} + +div.jsoneditor-contextmenu ul li ul li button { + padding-left: 24px; + animation: all ease-in-out 1s; +} + +div.jsoneditor-contextmenu ul li ul li button:hover, +div.jsoneditor-contextmenu ul li ul li button:focus { + background-color: #f5f5f5; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-string > div.jsoneditor-icon { + background-position: -144px -24px; +} +div.jsoneditor-contextmenu button.jsoneditor-type-string:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-string:focus > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-string.jsoneditor-selected > div.jsoneditor-icon{ + background-position: -144px 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-auto > div.jsoneditor-icon { + background-position: -120px -24px; +} +div.jsoneditor-contextmenu button.jsoneditor-type-auto:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-auto:focus > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-auto.jsoneditor-selected > div.jsoneditor-icon { + background-position: -120px 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-object > div.jsoneditor-icon { + background-position: -72px -24px; +} +div.jsoneditor-contextmenu button.jsoneditor-type-object:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-object:focus > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-object.jsoneditor-selected > div.jsoneditor-icon{ + background-position: -72px 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-array > div.jsoneditor-icon { + background-position: -96px -24px; +} +div.jsoneditor-contextmenu button.jsoneditor-type-array:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-array:focus > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-array.jsoneditor-selected > div.jsoneditor-icon{ + background-position: -96px 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-modes > div.jsoneditor-icon { + background-image: none; + width: 6px; +} diff --git a/ui/app/bower_components/jsoneditor/src/css/img/description.txt b/ui/app/bower_components/jsoneditor/src/css/img/description.txt new file mode 100644 index 0000000..fe410a9 --- /dev/null +++ b/ui/app/bower_components/jsoneditor/src/css/img/description.txt @@ -0,0 +1,14 @@ +JSON Editor Icons + +size: outer: 24x24 px + inner: 16x16 px + +blue background: RGBA 97b0f8ff +gray background: RGBA 4d4d4dff +grey background: RGBA d3d3d3ff + +red foreground: RGBA ff3300ff +green foreground: RGBA 13ae00ff + +characters are based on the Arial font + diff --git a/ui/app/bower_components/jsoneditor/src/css/img/jsoneditor-icons.svg b/ui/app/bower_components/jsoneditor/src/css/img/jsoneditor-icons.svg new file mode 100644 index 0000000..1b40068 --- /dev/null +++ b/ui/app/bower_components/jsoneditor/src/css/img/jsoneditor-icons.svg @@ -0,0 +1,893 @@ + + + JSON Editor Icons + + + + image/svg+xml + + JSON Editor Icons + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ui/app/bower_components/jsoneditor/src/css/jsoneditor.css b/ui/app/bower_components/jsoneditor/src/css/jsoneditor.css new file mode 100644 index 0000000..f5017df --- /dev/null +++ b/ui/app/bower_components/jsoneditor/src/css/jsoneditor.css @@ -0,0 +1,449 @@ + +div.jsoneditor { + +} + +div.jsoneditor-field, +div.jsoneditor-value, +div.jsoneditor-readonly { + border: 1px solid transparent; + min-height: 16px; + min-width: 32px; + padding: 2px; + margin: 1px; + word-wrap: break-word; + float: left; +} + +/* adjust margin of p elements inside editable divs, needed for Opera, IE */ +div.jsoneditor-field p, +div.jsoneditor-value p { + margin: 0; +} + +div.jsoneditor-value { + word-break: break-word; +} + +div.jsoneditor-readonly { + min-width: 16px; + color: gray; +} + +div.jsoneditor-empty { + border-color: lightgray; + border-style: dashed; + border-radius: 2px; +} + +div.jsoneditor-field.jsoneditor-empty::after, +div.jsoneditor-value.jsoneditor-empty::after { + pointer-events: none; + color: lightgray; + font-size: 8pt; +} + +div.jsoneditor-field.jsoneditor-empty::after { + content: "field"; +} + +div.jsoneditor-value.jsoneditor-empty::after { + content: "value"; +} + +div.jsoneditor-value.jsoneditor-url, +a.jsoneditor-value.jsoneditor-url { + color: green; + text-decoration: underline; +} + +a.jsoneditor-value.jsoneditor-url { + display: inline-block; + padding: 2px; + margin: 2px; +} + +a.jsoneditor-value.jsoneditor-url:hover, +a.jsoneditor-value.jsoneditor-url:focus { + color: #ee422e; +} + +div.jsoneditor td.jsoneditor-separator { + padding: 3px 0; + vertical-align: top; + color: gray; +} + +div.jsoneditor-field[contenteditable=true]:focus, +div.jsoneditor-field[contenteditable=true]:hover, +div.jsoneditor-value[contenteditable=true]:focus, +div.jsoneditor-value[contenteditable=true]:hover, +div.jsoneditor-field.jsoneditor-highlight, +div.jsoneditor-value.jsoneditor-highlight { + background-color: #FFFFAB; + border: 1px solid yellow; + border-radius: 2px; +} + +div.jsoneditor-field.jsoneditor-highlight-active, +div.jsoneditor-field.jsoneditor-highlight-active:focus, +div.jsoneditor-field.jsoneditor-highlight-active:hover, +div.jsoneditor-value.jsoneditor-highlight-active, +div.jsoneditor-value.jsoneditor-highlight-active:focus, +div.jsoneditor-value.jsoneditor-highlight-active:hover { + background-color: #ffee00; + border: 1px solid #ffc700; + border-radius: 2px; +} + +div.jsoneditor-value.jsoneditor-string { + color: #008000; +} + +div.jsoneditor-value.jsoneditor-object, +div.jsoneditor-value.jsoneditor-array { + min-width: 16px; + color: #808080; +} + +div.jsoneditor-value.jsoneditor-number { + color: #ee422e; +} + +div.jsoneditor-value.jsoneditor-boolean { + color: #ff8c00; +} + +div.jsoneditor-value.jsoneditor-null { + color: #004ED0; +} + +div.jsoneditor-value.jsoneditor-invalid { + color: #000000; +} + + + +div.jsoneditor-tree button { + width: 24px; + height: 24px; + padding: 0; + margin: 0; + border: none; + cursor: pointer; + background: transparent url('img/jsoneditor-icons.svg'); +} + +div.jsoneditor-mode-view tr.jsoneditor-expandable td.jsoneditor-tree, +div.jsoneditor-mode-form tr.jsoneditor-expandable td.jsoneditor-tree { + cursor: pointer; +} + +div.jsoneditor-tree button.jsoneditor-collapsed { + background-position: 0 -48px; +} + +div.jsoneditor-tree button.jsoneditor-expanded { + background-position: 0 -72px; +} + +div.jsoneditor-tree button.jsoneditor-contextmenu { + background-position: -48px -72px; +} + +div.jsoneditor-tree button.jsoneditor-contextmenu:hover, +div.jsoneditor-tree button.jsoneditor-contextmenu:focus, +div.jsoneditor-tree button.jsoneditor-contextmenu.jsoneditor-selected, +tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-contextmenu { + background-position: -48px -48px; +} + +div.jsoneditor-tree *:focus { + outline: none; +} + +div.jsoneditor-tree button:focus { + /* TODO: nice outline for buttons with focus + outline: #97B0F8 solid 2px; + box-shadow: 0 0 8px #97B0F8; + */ + background-color: #f5f5f5; + outline: #e5e5e5 solid 1px; +} + +div.jsoneditor-tree button.jsoneditor-invisible { + visibility: hidden; + background: none; +} + +div.jsoneditor { + color: #1A1A1A; + border: 1px solid #3883fa; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + + width: 100%; + height: 100%; + overflow: hidden; + position: relative; + padding: 0; + line-height: 100%; +} + + +div.jsoneditor-tree table.jsoneditor-tree { + border-collapse: collapse; + border-spacing: 0; + width: 100%; + margin: 0; +} + +div.jsoneditor-outer { + width: 100%; + height: 100%; + margin: -35px 0 0 0; + padding: 35px 0 0 0; + + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +textarea.jsoneditor-text, +.ace-jsoneditor { + min-height: 150px; +} + +div.jsoneditor-tree { + width: 100%; + height: 100%; + position: relative; + overflow: auto; +} + +textarea.jsoneditor-text { + width: 100%; + height: 100%; + margin: 0; + + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + + outline-width: 0; + border: none; + background-color: white; + resize: none; +} + +tr.jsoneditor-highlight, +tr.jsoneditor-selected { + background-color: #e6e6e6; +} + +tr.jsoneditor-selected button.jsoneditor-dragarea, +tr.jsoneditor-selected button.jsoneditor-contextmenu { + visibility: hidden; +} + +tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-dragarea, +tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-contextmenu { + visibility: visible; +} + +div.jsoneditor-tree button.jsoneditor-dragarea { + background: url('img/jsoneditor-icons.svg') -72px -72px; + cursor: move; +} + +div.jsoneditor-tree button.jsoneditor-dragarea:hover, +div.jsoneditor-tree button.jsoneditor-dragarea:focus, +tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-dragarea { + background-position: -72px -48px; +} + +div.jsoneditor tr, +div.jsoneditor th, +div.jsoneditor td { + padding: 0; + margin: 0; +} + +div.jsoneditor td { + vertical-align: top; +} + +div.jsoneditor td.jsoneditor-tree { + vertical-align: top; +} + +div.jsoneditor-field, +div.jsoneditor-value, +div.jsoneditor td, +div.jsoneditor th, +div.jsoneditor textarea, +.jsoneditor-schema-error { + font-family: droid sans mono, consolas, monospace, courier new, courier, sans-serif; + font-size: 10pt; + color: #1A1A1A; +} + + + + + +/* popover */ +.jsoneditor-schema-error { + cursor: default; + display: inline-block; + /*font-family: arial, sans-serif;*/ + height: 24px; + line-height: 24px; + position: relative; + text-align: center; + width: 24px; +} + +div.jsoneditor-tree .jsoneditor-schema-error { + width: 24px; + height: 24px; + padding: 0; + margin: 0 4px 0 0; + background: url('img/jsoneditor-icons.svg') -168px -48px; +} + +.jsoneditor-schema-error .jsoneditor-popover { + background-color: #4c4c4c; + border-radius: 3px; + box-shadow: 0 0 5px rgba(0,0,0,0.4); + color: #fff; + display: none; + padding: 7px 10px; + position: absolute; + width: 200px; + z-index: 4; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-above { + bottom: 32px; + left: -98px; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-below { + top: 32px; + left: -98px; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-left { + top: -7px; + right: 32px; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-right { + top: -7px; + left: 32px; +} + +.jsoneditor-schema-error .jsoneditor-popover:before { + border-right: 7px solid transparent; + border-left: 7px solid transparent; + content: ''; + display: block; + left: 50%; + margin-left: -7px; + position: absolute; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-above:before { + border-top: 7px solid #4c4c4c; + bottom: -7px; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-below:before { + border-bottom: 7px solid #4c4c4c; + top: -7px; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-left:before { + border-left: 7px solid #4c4c4c; + border-top: 7px solid transparent; + border-bottom: 7px solid transparent; + content: ''; + top: 19px; + right: -14px; + left: inherit; + margin-left: inherit; + margin-top: -7px; + position: absolute; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-right:before { + border-right: 7px solid #4c4c4c; + border-top: 7px solid transparent; + border-bottom: 7px solid transparent; + content: ''; + top: 19px; + left: -14px; + margin-left: inherit; + margin-top: -7px; + position: absolute; +} + +.jsoneditor-schema-error:hover .jsoneditor-popover, +.jsoneditor-schema-error:focus .jsoneditor-popover { + display: block; + -webkit-animation: fade-in .3s linear 1, move-up .3s linear 1; + -moz-animation: fade-in .3s linear 1, move-up .3s linear 1; + -ms-animation: fade-in .3s linear 1, move-up .3s linear 1; +} + +@-webkit-keyframes fade-in { + from { opacity: 0; } + to { opacity: 1; } +} +@-moz-keyframes fade-in { + from { opacity: 0; } + to { opacity: 1; } +} +@-ms-keyframes fade-in { + from { opacity: 0; } + to { opacity: 1; } +} +/*@-webkit-keyframes move-up {*/ + /*from { bottom: 24px; }*/ + /*to { bottom: 32px; }*/ +/*}*/ +/*@-moz-keyframes move-up {*/ + /*from { bottom: 24px; }*/ + /*to { bottom: 32px; }*/ +/*}*/ +/*@-ms-keyframes move-up {*/ + /*from { bottom: 24px; }*/ + /*to { bottom: 32px; }*/ +/*}*/ + + +/* JSON schema errors displayed at the bottom of the editor in mode text and code */ + +.jsoneditor .jsoneditor-text-errors { + width: 100%; + border-collapse: collapse; + background-color: #ffef8b; + border-top: 1px solid #ffd700; +} + +.jsoneditor .jsoneditor-text-errors td { + padding: 3px 6px; + vertical-align: middle; +} + +.jsoneditor-text-errors .jsoneditor-schema-error { + border: none; + width: 24px; + height: 24px; + padding: 0; + margin: 0 4px 0 0; + background: url('img/jsoneditor-icons.svg') -168px -48px; +} + diff --git a/ui/app/bower_components/jsoneditor/src/css/menu.css b/ui/app/bower_components/jsoneditor/src/css/menu.css new file mode 100644 index 0000000..6a4f44c --- /dev/null +++ b/ui/app/bower_components/jsoneditor/src/css/menu.css @@ -0,0 +1,110 @@ + +div.jsoneditor-menu { + width: 100%; + height: 35px; + padding: 2px; + margin: 0; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + + color: white; + background-color: #3883fa; + border-bottom: 1px solid #3883fa; +} + +div.jsoneditor-menu > button, +div.jsoneditor-menu > div.jsoneditor-modes > button { + width: 26px; + height: 26px; + margin: 2px; + padding: 0; + border-radius: 2px; + border: 1px solid transparent; + background: transparent url('img/jsoneditor-icons.svg'); + color: white; + opacity: 0.8; + + font-family: arial, sans-serif; + font-size: 10pt; + + float: left; +} + +div.jsoneditor-menu > button:hover, +div.jsoneditor-menu > div.jsoneditor-modes > button:hover { + background-color: rgba(255,255,255,0.2); + border: 1px solid rgba(255,255,255,0.4); +} +div.jsoneditor-menu > button:focus, +div.jsoneditor-menu > button:active, +div.jsoneditor-menu > div.jsoneditor-modes > button:focus, +div.jsoneditor-menu > div.jsoneditor-modes > button:active { + background-color: rgba(255,255,255,0.3); +} +div.jsoneditor-menu > button:disabled, +div.jsoneditor-menu > div.jsoneditor-modes > button:disabled { + opacity: 0.5; +} + +div.jsoneditor-menu > button.jsoneditor-collapse-all { + background-position: 0 -96px; +} +div.jsoneditor-menu > button.jsoneditor-expand-all { + background-position: 0 -120px; +} +div.jsoneditor-menu > button.jsoneditor-undo { + background-position: -24px -96px; +} +div.jsoneditor-menu > button.jsoneditor-undo:disabled { + background-position: -24px -120px; +} +div.jsoneditor-menu > button.jsoneditor-redo { + background-position: -48px -96px; +} +div.jsoneditor-menu > button.jsoneditor-redo:disabled { + background-position: -48px -120px; +} +div.jsoneditor-menu > button.jsoneditor-compact { + background-position: -72px -96px; +} +div.jsoneditor-menu > button.jsoneditor-format { + background-position: -72px -120px; +} + +div.jsoneditor-menu > div.jsoneditor-modes { + display: inline-block; + float: left; +} + +div.jsoneditor-menu > div.jsoneditor-modes > button { + background-image: none; + width: auto; + padding-left: 6px; + padding-right: 6px; +} + +div.jsoneditor-menu > button.jsoneditor-separator, +div.jsoneditor-menu > div.jsoneditor-modes > button.jsoneditor-separator { + margin-left: 10px; +} + +div.jsoneditor-menu a { + font-family: arial, sans-serif; + font-size: 10pt; + color: white; + opacity: 0.8; + vertical-align: middle; +} + +div.jsoneditor-menu a:hover { + opacity: 1; +} + +div.jsoneditor-menu a.jsoneditor-poweredBy { + font-size: 8pt; + position: absolute; + right: 0; + top: 0; + padding: 10px; +} diff --git a/ui/app/bower_components/jsoneditor/src/css/reset.css b/ui/app/bower_components/jsoneditor/src/css/reset.css new file mode 100644 index 0000000..13f7334 --- /dev/null +++ b/ui/app/bower_components/jsoneditor/src/css/reset.css @@ -0,0 +1,25 @@ +/* reset styling (prevent conflicts with bootstrap, materialize.css, etc.) */ + +div.jsoneditor input { + height: auto; + border: inherit; +} + +div.jsoneditor input:focus { + border: none !important; + box-shadow: none !important; +} + +div.jsoneditor table { + border-collapse: collapse; + width: auto; +} + +div.jsoneditor td, +div.jsoneditor th { + padding: 0; + display: table-cell; + text-align: left; + vertical-align: inherit; + border-radius: inherit; +} diff --git a/ui/app/bower_components/jsoneditor/src/css/searchbox.css b/ui/app/bower_components/jsoneditor/src/css/searchbox.css new file mode 100644 index 0000000..2a92eb6 --- /dev/null +++ b/ui/app/bower_components/jsoneditor/src/css/searchbox.css @@ -0,0 +1,77 @@ + +table.jsoneditor-search input, +table.jsoneditor-search div.jsoneditor-results { + font-family: arial, sans-serif; + font-size: 10pt; + color: #1A1A1A; + background: transparent; /* For Firefox */ +} + +table.jsoneditor-search div.jsoneditor-results { + color: white; + padding-right: 5px; + line-height: 24px; +} + +table.jsoneditor-search { + position: absolute; + right: 4px; + top: 4px; + border-collapse: collapse; + border-spacing: 0; +} + +table.jsoneditor-search div.jsoneditor-frame { + border: 1px solid transparent; + background-color: white; + padding: 0 2px; + margin: 0; +} + +table.jsoneditor-search div.jsoneditor-frame table { + border-collapse: collapse; +} + +table.jsoneditor-search input { + width: 120px; + border: none; + outline: none; + margin: 1px; + line-height: 20px; +} + +table.jsoneditor-search button { + width: 16px; + height: 24px; + padding: 0; + margin: 0; + border: none; + background: url('img/jsoneditor-icons.svg'); + vertical-align: top; +} + +table.jsoneditor-search button:hover { + background-color: transparent; +} + +table.jsoneditor-search button.jsoneditor-refresh { + width: 18px; + background-position: -99px -73px; +} + +table.jsoneditor-search button.jsoneditor-next { + cursor: pointer; + background-position: -124px -73px; +} +table.jsoneditor-search button.jsoneditor-next:hover { + background-position: -124px -49px; +} + +table.jsoneditor-search button.jsoneditor-previous { + cursor: pointer; + background-position: -148px -73px; + margin-right: 2px; +} +table.jsoneditor-search button.jsoneditor-previous:hover { + background-position: -148px -49px; +} diff --git a/ui/app/bower_components/jsoneditor/src/docs/which files do I need.md b/ui/app/bower_components/jsoneditor/src/docs/which files do I need.md new file mode 100644 index 0000000..726a8ae --- /dev/null +++ b/ui/app/bower_components/jsoneditor/src/docs/which files do I need.md @@ -0,0 +1,41 @@ +# Which files do I need? + +Ehhh, that's quite some files in this dist folder. Which files do I need? + + +## Full version + +If you're not sure which version to use, use the full version. + +Which files are needed when using the full version? + +- jsoneditor.min.js +- jsoneditor.map (optional, for debugging purposes only) +- jsoneditor.min.css +- img/jsoneditor-icons.svg + + +## Minimalist version + +The minimalist version has excluded the following libraries: + +- `ace` (via `brace`), used for the code editor. +- `ajv`, used for JSON schema validation. + +This reduces the the size of the minified and gzipped JavaScript file from +about 160 kB to about 40 kB. + +When to use the minimalist version? + +- If you don't need the mode "code" and don't need JSON schema validation. +- Or if you want to provide `ace` and/or `ajv` yourself via the configuration + options, for example when you already use Ace in other parts of your + web application too and don't want to bundle the library twice. + +Which files are needed when using the minimalist version? + +- jsoneditor-minimalist.min.js +- jsoneditor-minimalist.map (optional, for debugging purposes only) +- jsoneditor.min.css +- img/jsoneditor-icons.svg + diff --git a/ui/app/bower_components/jsoneditor/src/js/ContextMenu.js b/ui/app/bower_components/jsoneditor/src/js/ContextMenu.js new file mode 100644 index 0000000..216a1bc --- /dev/null +++ b/ui/app/bower_components/jsoneditor/src/js/ContextMenu.js @@ -0,0 +1,460 @@ +'use strict'; + +var util = require('./util'); + +/** + * A context menu + * @param {Object[]} items Array containing the menu structure + * TODO: describe structure + * @param {Object} [options] Object with options. Available options: + * {function} close Callback called when the + * context menu is being closed. + * @constructor + */ +function ContextMenu (items, options) { + this.dom = {}; + + var me = this; + var dom = this.dom; + this.anchor = undefined; + this.items = items; + this.eventListeners = {}; + this.selection = undefined; // holds the selection before the menu was opened + this.onClose = options ? options.close : undefined; + + // create root element + var root = document.createElement('div'); + root.className = 'jsoneditor-contextmenu-root'; + dom.root = root; + + // create a container element + var menu = document.createElement('div'); + menu.className = 'jsoneditor-contextmenu'; + dom.menu = menu; + root.appendChild(menu); + + // create a list to hold the menu items + var list = document.createElement('ul'); + list.className = 'jsoneditor-menu'; + menu.appendChild(list); + dom.list = list; + dom.items = []; // list with all buttons + + // create a (non-visible) button to set the focus to the menu + var focusButton = document.createElement('button'); + focusButton.type = 'button'; + dom.focusButton = focusButton; + var li = document.createElement('li'); + li.style.overflow = 'hidden'; + li.style.height = '0'; + li.appendChild(focusButton); + list.appendChild(li); + + function createMenuItems (list, domItems, items) { + items.forEach(function (item) { + if (item.type == 'separator') { + // create a separator + var separator = document.createElement('div'); + separator.className = 'jsoneditor-separator'; + li = document.createElement('li'); + li.appendChild(separator); + list.appendChild(li); + } + else { + var domItem = {}; + + // create a menu item + var li = document.createElement('li'); + list.appendChild(li); + + // create a button in the menu item + var button = document.createElement('button'); + button.type = 'button'; + button.className = item.className; + domItem.button = button; + if (item.title) { + button.title = item.title; + } + if (item.click) { + button.onclick = function (event) { + event.preventDefault(); + me.hide(); + item.click(); + }; + } + li.appendChild(button); + + // create the contents of the button + if (item.submenu) { + // add the icon to the button + var divIcon = document.createElement('div'); + divIcon.className = 'jsoneditor-icon'; + button.appendChild(divIcon); + button.appendChild(document.createTextNode(item.text)); + + var buttonSubmenu; + if (item.click) { + // submenu and a button with a click handler + button.className += ' jsoneditor-default'; + + var buttonExpand = document.createElement('button'); + buttonExpand.type = 'button'; + domItem.buttonExpand = buttonExpand; + buttonExpand.className = 'jsoneditor-expand'; + buttonExpand.innerHTML = '
'; + li.appendChild(buttonExpand); + if (item.submenuTitle) { + buttonExpand.title = item.submenuTitle; + } + + buttonSubmenu = buttonExpand; + } + else { + // submenu and a button without a click handler + var divExpand = document.createElement('div'); + divExpand.className = 'jsoneditor-expand'; + button.appendChild(divExpand); + + buttonSubmenu = button; + } + + // attach a handler to expand/collapse the submenu + buttonSubmenu.onclick = function (event) { + event.preventDefault(); + me._onExpandItem(domItem); + buttonSubmenu.focus(); + }; + + // create the submenu + var domSubItems = []; + domItem.subItems = domSubItems; + var ul = document.createElement('ul'); + domItem.ul = ul; + ul.className = 'jsoneditor-menu'; + ul.style.height = '0'; + li.appendChild(ul); + createMenuItems(ul, domSubItems, item.submenu); + } + else { + // no submenu, just a button with clickhandler + button.innerHTML = '
' + item.text; + } + + domItems.push(domItem); + } + }); + } + createMenuItems(list, this.dom.items, items); + + // TODO: when the editor is small, show the submenu on the right instead of inline? + + // calculate the max height of the menu with one submenu expanded + this.maxHeight = 0; // height in pixels + items.forEach(function (item) { + var height = (items.length + (item.submenu ? item.submenu.length : 0)) * 24; + me.maxHeight = Math.max(me.maxHeight, height); + }); +} + +/** + * Get the currently visible buttons + * @return {Array.} buttons + * @private + */ +ContextMenu.prototype._getVisibleButtons = function () { + var buttons = []; + var me = this; + this.dom.items.forEach(function (item) { + buttons.push(item.button); + if (item.buttonExpand) { + buttons.push(item.buttonExpand); + } + if (item.subItems && item == me.expandedItem) { + item.subItems.forEach(function (subItem) { + buttons.push(subItem.button); + if (subItem.buttonExpand) { + buttons.push(subItem.buttonExpand); + } + // TODO: change to fully recursive method + }); + } + }); + + return buttons; +}; + +// currently displayed context menu, a singleton. We may only have one visible context menu +ContextMenu.visibleMenu = undefined; + +/** + * Attach the menu to an anchor + * @param {HTMLElement} anchor Anchor where the menu will be attached + * as sibling. + * @param {HTMLElement} [contentWindow] The DIV with with the (scrollable) contents + */ +ContextMenu.prototype.show = function (anchor, contentWindow) { + this.hide(); + + // determine whether to display the menu below or above the anchor + var showBelow = true; + if (contentWindow) { + var anchorRect = anchor.getBoundingClientRect(); + var contentRect = contentWindow.getBoundingClientRect(); + + if (anchorRect.bottom + this.maxHeight < contentRect.bottom) { + // fits below -> show below + } + else if (anchorRect.top - this.maxHeight > contentRect.top) { + // fits above -> show above + showBelow = false; + } + else { + // doesn't fit above nor below -> show below + } + } + + // position the menu + if (showBelow) { + // display the menu below the anchor + var anchorHeight = anchor.offsetHeight; + this.dom.menu.style.left = '0px'; + this.dom.menu.style.top = anchorHeight + 'px'; + this.dom.menu.style.bottom = ''; + } + else { + // display the menu above the anchor + this.dom.menu.style.left = '0px'; + this.dom.menu.style.top = ''; + this.dom.menu.style.bottom = '0px'; + } + + // attach the menu to the parent of the anchor + var parent = anchor.parentNode; + parent.insertBefore(this.dom.root, parent.firstChild); + + // create and attach event listeners + var me = this; + var list = this.dom.list; + this.eventListeners.mousedown = util.addEventListener(window, 'mousedown', function (event) { + // hide menu on click outside of the menu + var target = event.target; + if ((target != list) && !me._isChildOf(target, list)) { + me.hide(); + event.stopPropagation(); + event.preventDefault(); + } + }); + this.eventListeners.keydown = util.addEventListener(window, 'keydown', function (event) { + me._onKeyDown(event); + }); + + // move focus to the first button in the context menu + this.selection = util.getSelection(); + this.anchor = anchor; + setTimeout(function () { + me.dom.focusButton.focus(); + }, 0); + + if (ContextMenu.visibleMenu) { + ContextMenu.visibleMenu.hide(); + } + ContextMenu.visibleMenu = this; +}; + +/** + * Hide the context menu if visible + */ +ContextMenu.prototype.hide = function () { + // remove the menu from the DOM + if (this.dom.root.parentNode) { + this.dom.root.parentNode.removeChild(this.dom.root); + if (this.onClose) { + this.onClose(); + } + } + + // remove all event listeners + // all event listeners are supposed to be attached to document. + for (var name in this.eventListeners) { + if (this.eventListeners.hasOwnProperty(name)) { + var fn = this.eventListeners[name]; + if (fn) { + util.removeEventListener(window, name, fn); + } + delete this.eventListeners[name]; + } + } + + if (ContextMenu.visibleMenu == this) { + ContextMenu.visibleMenu = undefined; + } +}; + +/** + * Expand a submenu + * Any currently expanded submenu will be hided. + * @param {Object} domItem + * @private + */ +ContextMenu.prototype._onExpandItem = function (domItem) { + var me = this; + var alreadyVisible = (domItem == this.expandedItem); + + // hide the currently visible submenu + var expandedItem = this.expandedItem; + if (expandedItem) { + //var ul = expandedItem.ul; + expandedItem.ul.style.height = '0'; + expandedItem.ul.style.padding = ''; + setTimeout(function () { + if (me.expandedItem != expandedItem) { + expandedItem.ul.style.display = ''; + util.removeClassName(expandedItem.ul.parentNode, 'jsoneditor-selected'); + } + }, 300); // timeout duration must match the css transition duration + this.expandedItem = undefined; + } + + if (!alreadyVisible) { + var ul = domItem.ul; + ul.style.display = 'block'; + var height = ul.clientHeight; // force a reflow in Firefox + setTimeout(function () { + if (me.expandedItem == domItem) { + ul.style.height = (ul.childNodes.length * 24) + 'px'; + ul.style.padding = '5px 10px'; + } + }, 0); + util.addClassName(ul.parentNode, 'jsoneditor-selected'); + this.expandedItem = domItem; + } +}; + +/** + * Handle onkeydown event + * @param {Event} event + * @private + */ +ContextMenu.prototype._onKeyDown = function (event) { + var target = event.target; + var keynum = event.which; + var handled = false; + var buttons, targetIndex, prevButton, nextButton; + + if (keynum == 27) { // ESC + // hide the menu on ESC key + + // restore previous selection and focus + if (this.selection) { + util.setSelection(this.selection); + } + if (this.anchor) { + this.anchor.focus(); + } + + this.hide(); + + handled = true; + } + else if (keynum == 9) { // Tab + if (!event.shiftKey) { // Tab + buttons = this._getVisibleButtons(); + targetIndex = buttons.indexOf(target); + if (targetIndex == buttons.length - 1) { + // move to first button + buttons[0].focus(); + handled = true; + } + } + else { // Shift+Tab + buttons = this._getVisibleButtons(); + targetIndex = buttons.indexOf(target); + if (targetIndex == 0) { + // move to last button + buttons[buttons.length - 1].focus(); + handled = true; + } + } + } + else if (keynum == 37) { // Arrow Left + if (target.className == 'jsoneditor-expand') { + buttons = this._getVisibleButtons(); + targetIndex = buttons.indexOf(target); + prevButton = buttons[targetIndex - 1]; + if (prevButton) { + prevButton.focus(); + } + } + handled = true; + } + else if (keynum == 38) { // Arrow Up + buttons = this._getVisibleButtons(); + targetIndex = buttons.indexOf(target); + prevButton = buttons[targetIndex - 1]; + if (prevButton && prevButton.className == 'jsoneditor-expand') { + // skip expand button + prevButton = buttons[targetIndex - 2]; + } + if (!prevButton) { + // move to last button + prevButton = buttons[buttons.length - 1]; + } + if (prevButton) { + prevButton.focus(); + } + handled = true; + } + else if (keynum == 39) { // Arrow Right + buttons = this._getVisibleButtons(); + targetIndex = buttons.indexOf(target); + nextButton = buttons[targetIndex + 1]; + if (nextButton && nextButton.className == 'jsoneditor-expand') { + nextButton.focus(); + } + handled = true; + } + else if (keynum == 40) { // Arrow Down + buttons = this._getVisibleButtons(); + targetIndex = buttons.indexOf(target); + nextButton = buttons[targetIndex + 1]; + if (nextButton && nextButton.className == 'jsoneditor-expand') { + // skip expand button + nextButton = buttons[targetIndex + 2]; + } + if (!nextButton) { + // move to first button + nextButton = buttons[0]; + } + if (nextButton) { + nextButton.focus(); + handled = true; + } + handled = true; + } + // TODO: arrow left and right + + if (handled) { + event.stopPropagation(); + event.preventDefault(); + } +}; + +/** + * Test if an element is a child of a parent element. + * @param {Element} child + * @param {Element} parent + * @return {boolean} isChild + */ +ContextMenu.prototype._isChildOf = function (child, parent) { + var e = child.parentNode; + while (e) { + if (e == parent) { + return true; + } + e = e.parentNode; + } + + return false; +}; + +module.exports = ContextMenu; diff --git a/ui/app/bower_components/jsoneditor/src/js/Highlighter.js b/ui/app/bower_components/jsoneditor/src/js/Highlighter.js new file mode 100644 index 0000000..09b03f6 --- /dev/null +++ b/ui/app/bower_components/jsoneditor/src/js/Highlighter.js @@ -0,0 +1,86 @@ +'use strict'; + +/** + * The highlighter can highlight/unhighlight a node, and + * animate the visibility of a context menu. + * @constructor Highlighter + */ +function Highlighter () { + this.locked = false; +} + +/** + * Hightlight given node and its childs + * @param {Node} node + */ +Highlighter.prototype.highlight = function (node) { + if (this.locked) { + return; + } + + if (this.node != node) { + // unhighlight current node + if (this.node) { + this.node.setHighlight(false); + } + + // highlight new node + this.node = node; + this.node.setHighlight(true); + } + + // cancel any current timeout + this._cancelUnhighlight(); +}; + +/** + * Unhighlight currently highlighted node. + * Will be done after a delay + */ +Highlighter.prototype.unhighlight = function () { + if (this.locked) { + return; + } + + var me = this; + if (this.node) { + this._cancelUnhighlight(); + + // do the unhighlighting after a small delay, to prevent re-highlighting + // the same node when moving from the drag-icon to the contextmenu-icon + // or vice versa. + this.unhighlightTimer = setTimeout(function () { + me.node.setHighlight(false); + me.node = undefined; + me.unhighlightTimer = undefined; + }, 0); + } +}; + +/** + * Cancel an unhighlight action (if before the timeout of the unhighlight action) + * @private + */ +Highlighter.prototype._cancelUnhighlight = function () { + if (this.unhighlightTimer) { + clearTimeout(this.unhighlightTimer); + this.unhighlightTimer = undefined; + } +}; + +/** + * Lock highlighting or unhighlighting nodes. + * methods highlight and unhighlight do not work while locked. + */ +Highlighter.prototype.lock = function () { + this.locked = true; +}; + +/** + * Unlock highlighting or unhighlighting nodes + */ +Highlighter.prototype.unlock = function () { + this.locked = false; +}; + +module.exports = Highlighter; diff --git a/ui/app/bower_components/jsoneditor/src/js/History.js b/ui/app/bower_components/jsoneditor/src/js/History.js new file mode 100644 index 0000000..1a8b0bf --- /dev/null +++ b/ui/app/bower_components/jsoneditor/src/js/History.js @@ -0,0 +1,267 @@ +'use strict'; + +var util = require('./util'); + +/** + * @constructor History + * Store action history, enables undo and redo + * @param {JSONEditor} editor + */ +function History (editor) { + this.editor = editor; + this.history = []; + this.index = -1; + + this.clear(); + + // map with all supported actions + this.actions = { + 'editField': { + 'undo': function (params) { + params.node.updateField(params.oldValue); + }, + 'redo': function (params) { + params.node.updateField(params.newValue); + } + }, + 'editValue': { + 'undo': function (params) { + params.node.updateValue(params.oldValue); + }, + 'redo': function (params) { + params.node.updateValue(params.newValue); + } + }, + 'changeType': { + 'undo': function (params) { + params.node.changeType(params.oldType); + }, + 'redo': function (params) { + params.node.changeType(params.newType); + } + }, + + 'appendNodes': { + 'undo': function (params) { + params.nodes.forEach(function (node) { + params.parent.removeChild(node); + }); + }, + 'redo': function (params) { + params.nodes.forEach(function (node) { + params.parent.appendChild(node); + }); + } + }, + 'insertBeforeNodes': { + 'undo': function (params) { + params.nodes.forEach(function (node) { + params.parent.removeChild(node); + }); + }, + 'redo': function (params) { + params.nodes.forEach(function (node) { + params.parent.insertBefore(node, params.beforeNode); + }); + } + }, + 'insertAfterNodes': { + 'undo': function (params) { + params.nodes.forEach(function (node) { + params.parent.removeChild(node); + }); + }, + 'redo': function (params) { + var afterNode = params.afterNode; + params.nodes.forEach(function (node) { + params.parent.insertAfter(params.node, afterNode); + afterNode = node; + }); + } + }, + 'removeNodes': { + 'undo': function (params) { + var parent = params.parent; + var beforeNode = parent.childs[params.index] || parent.append; + params.nodes.forEach(function (node) { + parent.insertBefore(node, beforeNode); + }); + }, + 'redo': function (params) { + params.nodes.forEach(function (node) { + params.parent.removeChild(node); + }); + } + }, + 'duplicateNodes': { + 'undo': function (params) { + params.nodes.forEach(function (node) { + params.parent.removeChild(node); + }); + }, + 'redo': function (params) { + var afterNode = params.afterNode; + params.nodes.forEach(function (node) { + params.parent.insertAfter(node, afterNode); + afterNode = node; + }); + } + }, + 'moveNodes': { + 'undo': function (params) { + params.nodes.forEach(function (node) { + params.oldBeforeNode.parent.moveBefore(node, params.oldBeforeNode); + }); + }, + 'redo': function (params) { + params.nodes.forEach(function (node) { + params.newBeforeNode.parent.moveBefore(node, params.newBeforeNode); + }); + } + }, + + 'sort': { + 'undo': function (params) { + var node = params.node; + node.hideChilds(); + node.sort = params.oldSort; + node.childs = params.oldChilds; + node.showChilds(); + }, + 'redo': function (params) { + var node = params.node; + node.hideChilds(); + node.sort = params.newSort; + node.childs = params.newChilds; + node.showChilds(); + } + } + + // TODO: restore the original caret position and selection with each undo + // TODO: implement history for actions "expand", "collapse", "scroll", "setDocument" + }; +} + +/** + * The method onChange is executed when the History is changed, and can + * be overloaded. + */ +History.prototype.onChange = function () {}; + +/** + * Add a new action to the history + * @param {String} action The executed action. Available actions: "editField", + * "editValue", "changeType", "appendNode", + * "removeNode", "duplicateNode", "moveNode" + * @param {Object} params Object containing parameters describing the change. + * The parameters in params depend on the action (for + * example for "editValue" the Node, old value, and new + * value are provided). params contains all information + * needed to undo or redo the action. + */ +History.prototype.add = function (action, params) { + this.index++; + this.history[this.index] = { + 'action': action, + 'params': params, + 'timestamp': new Date() + }; + + // remove redo actions which are invalid now + if (this.index < this.history.length - 1) { + this.history.splice(this.index + 1, this.history.length - this.index - 1); + } + + // fire onchange event + this.onChange(); +}; + +/** + * Clear history + */ +History.prototype.clear = function () { + this.history = []; + this.index = -1; + + // fire onchange event + this.onChange(); +}; + +/** + * Check if there is an action available for undo + * @return {Boolean} canUndo + */ +History.prototype.canUndo = function () { + return (this.index >= 0); +}; + +/** + * Check if there is an action available for redo + * @return {Boolean} canRedo + */ +History.prototype.canRedo = function () { + return (this.index < this.history.length - 1); +}; + +/** + * Undo the last action + */ +History.prototype.undo = function () { + if (this.canUndo()) { + var obj = this.history[this.index]; + if (obj) { + var action = this.actions[obj.action]; + if (action && action.undo) { + action.undo(obj.params); + if (obj.params.oldSelection) { + this.editor.setSelection(obj.params.oldSelection); + } + } + else { + console.error(new Error('unknown action "' + obj.action + '"')); + } + } + this.index--; + + // fire onchange event + this.onChange(); + } +}; + +/** + * Redo the last action + */ +History.prototype.redo = function () { + if (this.canRedo()) { + this.index++; + + var obj = this.history[this.index]; + if (obj) { + var action = this.actions[obj.action]; + if (action && action.redo) { + action.redo(obj.params); + if (obj.params.newSelection) { + this.editor.setSelection(obj.params.newSelection); + } + } + else { + console.error(new Error('unknown action "' + obj.action + '"')); + } + } + + // fire onchange event + this.onChange(); + } +}; + +/** + * Destroy history + */ +History.prototype.destroy = function () { + this.editor = null; + + this.history = []; + this.index = -1; +}; + +module.exports = History; diff --git a/ui/app/bower_components/jsoneditor/src/js/JSONEditor.js b/ui/app/bower_components/jsoneditor/src/js/JSONEditor.js new file mode 100644 index 0000000..7420d49 --- /dev/null +++ b/ui/app/bower_components/jsoneditor/src/js/JSONEditor.js @@ -0,0 +1,385 @@ +'use strict'; + +var Ajv; +try { + Ajv = require('ajv'); +} +catch (err) { + // no problem... when we need Ajv we will throw a neat exception +} + +var treemode = require('./treemode'); +var textmode = require('./textmode'); +var util = require('./util'); + +/** + * @constructor JSONEditor + * @param {Element} container Container element + * @param {Object} [options] Object with options. available options: + * {String} mode Editor mode. Available values: + * 'tree' (default), 'view', + * 'form', 'text', and 'code'. + * {function} onChange Callback method, triggered + * on change of contents + * {function} onError Callback method, triggered + * when an error occurs + * {Boolean} search Enable search box. + * True by default + * Only applicable for modes + * 'tree', 'view', and 'form' + * {Boolean} history Enable history (undo/redo). + * True by default + * Only applicable for modes + * 'tree', 'view', and 'form' + * {String} name Field name for the root node. + * Only applicable for modes + * 'tree', 'view', and 'form' + * {Number} indentation Number of indentation + * spaces. 4 by default. + * Only applicable for + * modes 'text' and 'code' + * {boolean} escapeUnicode If true, unicode + * characters are escaped. + * false by default. + * {boolean} sortObjectKeys If true, object keys are + * sorted before display. + * false by default. + * @param {Object | undefined} json JSON object + */ +function JSONEditor (container, options, json) { + if (!(this instanceof JSONEditor)) { + throw new Error('JSONEditor constructor called without "new".'); + } + + // check for unsupported browser (IE8 and older) + var ieVersion = util.getInternetExplorerVersion(); + if (ieVersion != -1 && ieVersion < 9) { + throw new Error('Unsupported browser, IE9 or newer required. ' + + 'Please install the newest version of your browser.'); + } + + if (options) { + // check for deprecated options + if (options.error) { + console.warn('Option "error" has been renamed to "onError"'); + options.onError = options.error; + delete options.error; + } + if (options.change) { + console.warn('Option "change" has been renamed to "onChange"'); + options.onChange = options.change; + delete options.change; + } + if (options.editable) { + console.warn('Option "editable" has been renamed to "onEditable"'); + options.onEditable = options.editable; + delete options.editable; + } + + // validate options + if (options) { + var VALID_OPTIONS = [ + 'ace', 'theme', + 'ajv', 'schema', + 'onChange', 'onEditable', 'onError', 'onModeChange', + 'escapeUnicode', 'history', 'search', 'mode', 'modes', 'name', 'indentation', 'sortObjectKeys' + ]; + + Object.keys(options).forEach(function (option) { + if (VALID_OPTIONS.indexOf(option) === -1) { + console.warn('Unknown option "' + option + '". This option will be ignored'); + } + }); + } + } + + if (arguments.length) { + this._create(container, options, json); + } +} + +/** + * Configuration for all registered modes. Example: + * { + * tree: { + * mixin: TreeEditor, + * data: 'json' + * }, + * text: { + * mixin: TextEditor, + * data: 'text' + * } + * } + * + * @type { Object. } + */ +JSONEditor.modes = {}; + +// debounce interval for JSON schema vaidation in milliseconds +JSONEditor.prototype.DEBOUNCE_INTERVAL = 150; + +/** + * Create the JSONEditor + * @param {Element} container Container element + * @param {Object} [options] See description in constructor + * @param {Object | undefined} json JSON object + * @private + */ +JSONEditor.prototype._create = function (container, options, json) { + this.container = container; + this.options = options || {}; + this.json = json || {}; + + var mode = this.options.mode || 'tree'; + this.setMode(mode); +}; + +/** + * Destroy the editor. Clean up DOM, event listeners, and web workers. + */ +JSONEditor.prototype.destroy = function () {}; + +/** + * Set JSON object in editor + * @param {Object | undefined} json JSON data + */ +JSONEditor.prototype.set = function (json) { + this.json = json; +}; + +/** + * Get JSON from the editor + * @returns {Object} json + */ +JSONEditor.prototype.get = function () { + return this.json; +}; + +/** + * Set string containing JSON for the editor + * @param {String | undefined} jsonText + */ +JSONEditor.prototype.setText = function (jsonText) { + this.json = util.parse(jsonText); +}; + +/** + * Get stringified JSON contents from the editor + * @returns {String} jsonText + */ +JSONEditor.prototype.getText = function () { + return JSON.stringify(this.json); +}; + +/** + * Set a field name for the root node. + * @param {String | undefined} name + */ +JSONEditor.prototype.setName = function (name) { + if (!this.options) { + this.options = {}; + } + this.options.name = name; +}; + +/** + * Get the field name for the root node. + * @return {String | undefined} name + */ +JSONEditor.prototype.getName = function () { + return this.options && this.options.name; +}; + +/** + * Change the mode of the editor. + * JSONEditor will be extended with all methods needed for the chosen mode. + * @param {String} mode Available modes: 'tree' (default), 'view', 'form', + * 'text', and 'code'. + */ +JSONEditor.prototype.setMode = function (mode) { + var container = this.container; + var options = util.extend({}, this.options); + var oldMode = options.mode; + var data; + var name; + + options.mode = mode; + var config = JSONEditor.modes[mode]; + if (config) { + try { + var asText = (config.data == 'text'); + name = this.getName(); + data = this[asText ? 'getText' : 'get'](); // get text or json + + this.destroy(); + util.clear(this); + util.extend(this, config.mixin); + this.create(container, options); + + this.setName(name); + this[asText ? 'setText' : 'set'](data); // set text or json + + if (typeof config.load === 'function') { + try { + config.load.call(this); + } + catch (err) { + console.error(err); + } + } + + if (typeof options.onModeChange === 'function' && mode !== oldMode) { + try { + options.onModeChange(mode, oldMode); + } + catch (err) { + console.error(err); + } + } + } + catch (err) { + this._onError(err); + } + } + else { + throw new Error('Unknown mode "' + options.mode + '"'); + } +}; + +/** + * Get the current mode + * @return {string} + */ +JSONEditor.prototype.getMode = function () { + return this.options.mode; +}; + +/** + * Throw an error. If an error callback is configured in options.error, this + * callback will be invoked. Else, a regular error is thrown. + * @param {Error} err + * @private + */ +JSONEditor.prototype._onError = function(err) { + if (this.options && typeof this.options.onError === 'function') { + this.options.onError(err); + } + else { + throw err; + } +}; + +/** + * Set a JSON schema for validation of the JSON object. + * To remove the schema, call JSONEditor.setSchema(null) + * @param {Object | null} schema + */ +JSONEditor.prototype.setSchema = function (schema) { + // compile a JSON schema validator if a JSON schema is provided + if (schema) { + var ajv; + try { + // grab ajv from options if provided, else create a new instance + ajv = this.options.ajv || Ajv({ allErrors: true, verbose: true }); + + } + catch (err) { + console.warn('Failed to create an instance of Ajv, JSON Schema validation is not available. Please use a JSONEditor bundle including Ajv, or pass an instance of Ajv as via the configuration option `ajv`.'); + } + + if (ajv) { + this.validateSchema = ajv.compile(schema); + + // add schema to the options, so that when switching to an other mode, + // the set schema is not lost + this.options.schema = schema; + + // validate now + this.validate(); + } + + this.refresh(); // update DOM + } + else { + // remove current schema + this.validateSchema = null; + this.options.schema = null; + this.validate(); // to clear current error messages + this.refresh(); // update DOM + } +}; + +/** + * Validate current JSON object against the configured JSON schema + * Throws an exception when no JSON schema is configured + */ +JSONEditor.prototype.validate = function () { + // must be implemented by treemode and textmode +}; + +/** + * Refresh the rendered contents + */ +JSONEditor.prototype.refresh = function () { + // can be implemented by treemode and textmode +}; + +/** + * Register a plugin with one ore multiple modes for the JSON Editor. + * + * A mode is described as an object with properties: + * + * - `mode: String` The name of the mode. + * - `mixin: Object` An object containing the mixin functions which + * will be added to the JSONEditor. Must contain functions + * create, get, getText, set, and setText. May have + * additional functions. + * When the JSONEditor switches to a mixin, all mixin + * functions are added to the JSONEditor, and then + * the function `create(container, options)` is executed. + * - `data: 'text' | 'json'` The type of data that will be used to load the mixin. + * - `[load: function]` An optional function called after the mixin + * has been loaded. + * + * @param {Object | Array} mode A mode object or an array with multiple mode objects. + */ +JSONEditor.registerMode = function (mode) { + var i, prop; + + if (util.isArray(mode)) { + // multiple modes + for (i = 0; i < mode.length; i++) { + JSONEditor.registerMode(mode[i]); + } + } + else { + // validate the new mode + if (!('mode' in mode)) throw new Error('Property "mode" missing'); + if (!('mixin' in mode)) throw new Error('Property "mixin" missing'); + if (!('data' in mode)) throw new Error('Property "data" missing'); + var name = mode.mode; + if (name in JSONEditor.modes) { + throw new Error('Mode "' + name + '" already registered'); + } + + // validate the mixin + if (typeof mode.mixin.create !== 'function') { + throw new Error('Required function "create" missing on mixin'); + } + var reserved = ['setMode', 'registerMode', 'modes']; + for (i = 0; i < reserved.length; i++) { + prop = reserved[i]; + if (prop in mode.mixin) { + throw new Error('Reserved property "' + prop + '" not allowed in mixin'); + } + } + + JSONEditor.modes[name] = mode; + } +}; + +// register tree and text modes +JSONEditor.registerMode(treemode); +JSONEditor.registerMode(textmode); + +module.exports = JSONEditor; diff --git a/ui/app/bower_components/jsoneditor/src/js/ModeSwitcher.js b/ui/app/bower_components/jsoneditor/src/js/ModeSwitcher.js new file mode 100644 index 0000000..77c6c49 --- /dev/null +++ b/ui/app/bower_components/jsoneditor/src/js/ModeSwitcher.js @@ -0,0 +1,115 @@ +'use strict'; + +var ContextMenu = require('./ContextMenu'); + +/** + * Create a select box to be used in the editor menu's, which allows to switch mode + * @param {HTMLElement} container + * @param {String[]} modes Available modes: 'code', 'form', 'text', 'tree', 'view' + * @param {String} current Available modes: 'code', 'form', 'text', 'tree', 'view' + * @param {function(mode: string)} onSwitch Callback invoked on switch + * @constructor + */ +function ModeSwitcher(container, modes, current, onSwitch) { + // available modes + var availableModes = { + code: { + 'text': 'Code', + 'title': 'Switch to code highlighter', + 'click': function () { + onSwitch('code') + } + }, + form: { + 'text': 'Form', + 'title': 'Switch to form editor', + 'click': function () { + onSwitch('form'); + } + }, + text: { + 'text': 'Text', + 'title': 'Switch to plain text editor', + 'click': function () { + onSwitch('text'); + } + }, + tree: { + 'text': 'Tree', + 'title': 'Switch to tree editor', + 'click': function () { + onSwitch('tree'); + } + }, + view: { + 'text': 'View', + 'title': 'Switch to tree view', + 'click': function () { + onSwitch('view'); + } + } + }; + + // list the selected modes + var items = []; + for (var i = 0; i < modes.length; i++) { + var mode = modes[i]; + var item = availableModes[mode]; + if (!item) { + throw new Error('Unknown mode "' + mode + '"'); + } + + item.className = 'jsoneditor-type-modes' + ((current == mode) ? ' jsoneditor-selected' : ''); + items.push(item); + } + + // retrieve the title of current mode + var currentMode = availableModes[current]; + if (!currentMode) { + throw new Error('Unknown mode "' + current + '"'); + } + var currentTitle = currentMode.text; + + // create the html element + var box = document.createElement('button'); + box.type = 'button'; + box.className = 'jsoneditor-modes jsoneditor-separator'; + box.innerHTML = currentTitle + ' ▾'; + box.title = 'Switch editor mode'; + box.onclick = function () { + var menu = new ContextMenu(items); + menu.show(box); + }; + + var frame = document.createElement('div'); + frame.className = 'jsoneditor-modes'; + frame.style.position = 'relative'; + frame.appendChild(box); + + container.appendChild(frame); + + this.dom = { + container: container, + box: box, + frame: frame + }; +} + +/** + * Set focus to switcher + */ +ModeSwitcher.prototype.focus = function () { + this.dom.box.focus(); +}; + +/** + * Destroy the ModeSwitcher, remove from DOM + */ +ModeSwitcher.prototype.destroy = function () { + if (this.dom && this.dom.frame && this.dom.frame.parentNode) { + this.dom.frame.parentNode.removeChild(this.dom.frame); + } + this.dom = null; +}; + +module.exports = ModeSwitcher; diff --git a/ui/app/bower_components/jsoneditor/src/js/Node.js b/ui/app/bower_components/jsoneditor/src/js/Node.js new file mode 100644 index 0000000..8a6d0fa --- /dev/null +++ b/ui/app/bower_components/jsoneditor/src/js/Node.js @@ -0,0 +1,3530 @@ +'use strict'; + +var naturalSort = require('javascript-natural-sort'); +var ContextMenu = require('./ContextMenu'); +var appendNodeFactory = require('./appendNodeFactory'); +var util = require('./util'); + +/** + * @constructor Node + * Create a new Node + * @param {./treemode} editor + * @param {Object} [params] Can contain parameters: + * {string} field + * {boolean} fieldEditable + * {*} value + * {String} type Can have values 'auto', 'array', + * 'object', or 'string'. + */ +function Node (editor, params) { + /** @type {./treemode} */ + this.editor = editor; + this.dom = {}; + this.expanded = false; + + if(params && (params instanceof Object)) { + this.setField(params.field, params.fieldEditable); + this.setValue(params.value, params.type); + } + else { + this.setField(''); + this.setValue(null); + } + + this._debouncedOnChangeValue = util.debounce(this._onChangeValue.bind(this), Node.prototype.DEBOUNCE_INTERVAL); + this._debouncedOnChangeField = util.debounce(this._onChangeField.bind(this), Node.prototype.DEBOUNCE_INTERVAL); +} + +// debounce interval for keyboard input in milliseconds +Node.prototype.DEBOUNCE_INTERVAL = 150; + +/** + * Determine whether the field and/or value of this node are editable + * @private + */ +Node.prototype._updateEditability = function () { + this.editable = { + field: true, + value: true + }; + + if (this.editor) { + this.editable.field = this.editor.options.mode === 'tree'; + this.editable.value = this.editor.options.mode !== 'view'; + + if ((this.editor.options.mode === 'tree' || this.editor.options.mode === 'form') && + (typeof this.editor.options.onEditable === 'function')) { + var editable = this.editor.options.onEditable({ + field: this.field, + value: this.value, + path: this.getPath() + }); + + if (typeof editable === 'boolean') { + this.editable.field = editable; + this.editable.value = editable; + } + else { + if (typeof editable.field === 'boolean') this.editable.field = editable.field; + if (typeof editable.value === 'boolean') this.editable.value = editable.value; + } + } + } +}; + +/** + * Get the path of this node + * @return {String[]} Array containing the path to this node + */ +Node.prototype.getPath = function () { + var node = this; + var path = []; + while (node) { + var field = !node.parent + ? undefined // do not add an (optional) field name of the root node + : (node.parent.type != 'array') + ? node.field + : node.index; + + if (field !== undefined) { + path.unshift(field); + } + node = node.parent; + } + return path; +}; + +/** + * Find a Node from a JSON path like '.items[3].name' + * @param {string} jsonPath + * @return {Node | null} Returns the Node when found, returns null if not found + */ +Node.prototype.findNode = function (jsonPath) { + var path = util.parsePath(jsonPath); + var node = this; + while (node && path.length > 0) { + var prop = path.shift(); + if (typeof prop === 'number') { + if (node.type !== 'array') { + throw new Error('Cannot get child node at index ' + prop + ': node is no array'); + } + node = node.childs[prop]; + } + else { // string + if (node.type !== 'object') { + throw new Error('Cannot get child node ' + prop + ': node is no object'); + } + node = node.childs.filter(function (child) { + return child.field === prop; + })[0]; + } + } + + return node; +}; + +/** + * Find all parents of this node. The parents are ordered from root node towards + * the original node. + * @return {Array.} + */ +Node.prototype.findParents = function () { + var parents = []; + var parent = this.parent; + while (parent) { + parents.unshift(parent); + parent = parent.parent; + } + return parents; +}; + +/** + * + * @param {{dataPath: string, keyword: string, message: string, params: Object, schemaPath: string} | null} error + * @param {Node} [child] When this is the error of a parent node, pointing + * to an invalid child node, the child node itself + * can be provided. If provided, clicking the error + * icon will set focus to the invalid child node. + */ +Node.prototype.setError = function (error, child) { + // ensure the dom exists + this.getDom(); + + this.error = error; + var tdError = this.dom.tdError; + if (error) { + if (!tdError) { + tdError = document.createElement('td'); + this.dom.tdError = tdError; + this.dom.tdValue.parentNode.appendChild(tdError); + } + + var popover = document.createElement('div'); + popover.className = 'jsoneditor-popover jsoneditor-right'; + popover.appendChild(document.createTextNode(error.message)); + + var button = document.createElement('button'); + button.type = 'button'; + button.className = 'jsoneditor-schema-error'; + button.appendChild(popover); + + // update the direction of the popover + button.onmouseover = button.onfocus = function updateDirection() { + var directions = ['right', 'above', 'below', 'left']; + for (var i = 0; i < directions.length; i++) { + var direction = directions[i]; + popover.className = 'jsoneditor-popover jsoneditor-' + direction; + + var contentRect = this.editor.content.getBoundingClientRect(); + var popoverRect = popover.getBoundingClientRect(); + var margin = 20; // account for a scroll bar + var fit = util.insideRect(contentRect, popoverRect, margin); + + if (fit) { + break; + } + } + }.bind(this); + + // when clicking the error icon, expand all nodes towards the invalid + // child node, and set focus to the child node + if (child) { + button.onclick = function showInvalidNode() { + child.findParents().forEach(function (parent) { + parent.expand(false); + }); + + child.scrollTo(function () { + child.focus(); + }); + }; + } + + // apply the error message to the node + while (tdError.firstChild) { + tdError.removeChild(tdError.firstChild); + } + tdError.appendChild(button); + } + else { + if (tdError) { + this.dom.tdError.parentNode.removeChild(this.dom.tdError); + delete this.dom.tdError; + } + } +}; + +/** + * Get the index of this node: the index in the list of childs where this + * node is part of + * @return {number} Returns the index, or -1 if this is the root node + */ +Node.prototype.getIndex = function () { + return this.parent ? this.parent.childs.indexOf(this) : -1; +}; + +/** + * Set parent node + * @param {Node} parent + */ +Node.prototype.setParent = function(parent) { + this.parent = parent; +}; + +/** + * Set field + * @param {String} field + * @param {boolean} [fieldEditable] + */ +Node.prototype.setField = function(field, fieldEditable) { + this.field = field; + this.previousField = field; + this.fieldEditable = (fieldEditable === true); +}; + +/** + * Get field + * @return {String} + */ +Node.prototype.getField = function() { + if (this.field === undefined) { + this._getDomField(); + } + + return this.field; +}; + +/** + * Set value. Value is a JSON structure or an element String, Boolean, etc. + * @param {*} value + * @param {String} [type] Specify the type of the value. Can be 'auto', + * 'array', 'object', or 'string' + */ +Node.prototype.setValue = function(value, type) { + var childValue, child; + + // first clear all current childs (if any) + var childs = this.childs; + if (childs) { + while (childs.length) { + this.removeChild(childs[0]); + } + } + + // TODO: remove the DOM of this Node + + this.type = this._getType(value); + + // check if type corresponds with the provided type + if (type && type != this.type) { + if (type == 'string' && this.type == 'auto') { + this.type = type; + } + else { + throw new Error('Type mismatch: ' + + 'cannot cast value of type "' + this.type + + ' to the specified type "' + type + '"'); + } + } + + if (this.type == 'array') { + // array + this.childs = []; + for (var i = 0, iMax = value.length; i < iMax; i++) { + childValue = value[i]; + if (childValue !== undefined && !(childValue instanceof Function)) { + // ignore undefined and functions + child = new Node(this.editor, { + value: childValue + }); + this.appendChild(child); + } + } + this.value = ''; + } + else if (this.type == 'object') { + // object + this.childs = []; + for (var childField in value) { + if (value.hasOwnProperty(childField)) { + childValue = value[childField]; + if (childValue !== undefined && !(childValue instanceof Function)) { + // ignore undefined and functions + child = new Node(this.editor, { + field: childField, + value: childValue + }); + this.appendChild(child); + } + } + } + this.value = ''; + + // sort object keys + if (this.editor.options.sortObjectKeys === true) { + this.sort('asc'); + } + } + else { + // value + this.childs = undefined; + this.value = value; + } + + this.previousValue = this.value; +}; + +/** + * Get value. Value is a JSON structure + * @return {*} value + */ +Node.prototype.getValue = function() { + //var childs, i, iMax; + + if (this.type == 'array') { + var arr = []; + this.childs.forEach (function (child) { + arr.push(child.getValue()); + }); + return arr; + } + else if (this.type == 'object') { + var obj = {}; + this.childs.forEach (function (child) { + obj[child.getField()] = child.getValue(); + }); + return obj; + } + else { + if (this.value === undefined) { + this._getDomValue(); + } + + return this.value; + } +}; + +/** + * Get the nesting level of this node + * @return {Number} level + */ +Node.prototype.getLevel = function() { + return (this.parent ? this.parent.getLevel() + 1 : 0); +}; + +/** + * Get path of the root node till the current node + * @return {Node[]} Returns an array with nodes + */ +Node.prototype.getNodePath = function() { + var path = this.parent ? this.parent.getNodePath() : []; + path.push(this); + return path; +}; + +/** + * Create a clone of a node + * The complete state of a clone is copied, including whether it is expanded or + * not. The DOM elements are not cloned. + * @return {Node} clone + */ +Node.prototype.clone = function() { + var clone = new Node(this.editor); + clone.type = this.type; + clone.field = this.field; + clone.fieldInnerText = this.fieldInnerText; + clone.fieldEditable = this.fieldEditable; + clone.value = this.value; + clone.valueInnerText = this.valueInnerText; + clone.expanded = this.expanded; + + if (this.childs) { + // an object or array + var cloneChilds = []; + this.childs.forEach(function (child) { + var childClone = child.clone(); + childClone.setParent(clone); + cloneChilds.push(childClone); + }); + clone.childs = cloneChilds; + } + else { + // a value + clone.childs = undefined; + } + + return clone; +}; + +/** + * Expand this node and optionally its childs. + * @param {boolean} [recurse] Optional recursion, true by default. When + * true, all childs will be expanded recursively + */ +Node.prototype.expand = function(recurse) { + if (!this.childs) { + return; + } + + // set this node expanded + this.expanded = true; + if (this.dom.expand) { + this.dom.expand.className = 'jsoneditor-expanded'; + } + + this.showChilds(); + + if (recurse !== false) { + this.childs.forEach(function (child) { + child.expand(recurse); + }); + } +}; + +/** + * Collapse this node and optionally its childs. + * @param {boolean} [recurse] Optional recursion, true by default. When + * true, all childs will be collapsed recursively + */ +Node.prototype.collapse = function(recurse) { + if (!this.childs) { + return; + } + + this.hideChilds(); + + // collapse childs in case of recurse + if (recurse !== false) { + this.childs.forEach(function (child) { + child.collapse(recurse); + }); + + } + + // make this node collapsed + if (this.dom.expand) { + this.dom.expand.className = 'jsoneditor-collapsed'; + } + this.expanded = false; +}; + +/** + * Recursively show all childs when they are expanded + */ +Node.prototype.showChilds = function() { + var childs = this.childs; + if (!childs) { + return; + } + if (!this.expanded) { + return; + } + + var tr = this.dom.tr; + var table = tr ? tr.parentNode : undefined; + if (table) { + // show row with append button + var append = this.getAppend(); + var nextTr = tr.nextSibling; + if (nextTr) { + table.insertBefore(append, nextTr); + } + else { + table.appendChild(append); + } + + // show childs + this.childs.forEach(function (child) { + table.insertBefore(child.getDom(), append); + child.showChilds(); + }); + } +}; + +/** + * Hide the node with all its childs + */ +Node.prototype.hide = function() { + var tr = this.dom.tr; + var table = tr ? tr.parentNode : undefined; + if (table) { + table.removeChild(tr); + } + this.hideChilds(); +}; + + +/** + * Recursively hide all childs + */ +Node.prototype.hideChilds = function() { + var childs = this.childs; + if (!childs) { + return; + } + if (!this.expanded) { + return; + } + + // hide append row + var append = this.getAppend(); + if (append.parentNode) { + append.parentNode.removeChild(append); + } + + // hide childs + this.childs.forEach(function (child) { + child.hide(); + }); +}; + + +/** + * Add a new child to the node. + * Only applicable when Node value is of type array or object + * @param {Node} node + */ +Node.prototype.appendChild = function(node) { + if (this._hasChilds()) { + // adjust the link to the parent + node.setParent(this); + node.fieldEditable = (this.type == 'object'); + if (this.type == 'array') { + node.index = this.childs.length; + } + this.childs.push(node); + + if (this.expanded) { + // insert into the DOM, before the appendRow + var newTr = node.getDom(); + var appendTr = this.getAppend(); + var table = appendTr ? appendTr.parentNode : undefined; + if (appendTr && table) { + table.insertBefore(newTr, appendTr); + } + + node.showChilds(); + } + + this.updateDom({'updateIndexes': true}); + node.updateDom({'recurse': true}); + } +}; + + +/** + * Move a node from its current parent to this node + * Only applicable when Node value is of type array or object + * @param {Node} node + * @param {Node} beforeNode + */ +Node.prototype.moveBefore = function(node, beforeNode) { + if (this._hasChilds()) { + // create a temporary row, to prevent the scroll position from jumping + // when removing the node + var tbody = (this.dom.tr) ? this.dom.tr.parentNode : undefined; + if (tbody) { + var trTemp = document.createElement('tr'); + trTemp.style.height = tbody.clientHeight + 'px'; + tbody.appendChild(trTemp); + } + + if (node.parent) { + node.parent.removeChild(node); + } + + if (beforeNode instanceof AppendNode) { + this.appendChild(node); + } + else { + this.insertBefore(node, beforeNode); + } + + if (tbody) { + tbody.removeChild(trTemp); + } + } +}; + +/** + * Move a node from its current parent to this node + * Only applicable when Node value is of type array or object. + * If index is out of range, the node will be appended to the end + * @param {Node} node + * @param {Number} index + */ +Node.prototype.moveTo = function (node, index) { + if (node.parent == this) { + // same parent + var currentIndex = this.childs.indexOf(node); + if (currentIndex < index) { + // compensate the index for removal of the node itself + index++; + } + } + + var beforeNode = this.childs[index] || this.append; + this.moveBefore(node, beforeNode); +}; + +/** + * Insert a new child before a given node + * Only applicable when Node value is of type array or object + * @param {Node} node + * @param {Node} beforeNode + */ +Node.prototype.insertBefore = function(node, beforeNode) { + if (this._hasChilds()) { + if (beforeNode == this.append) { + // append to the child nodes + + // adjust the link to the parent + node.setParent(this); + node.fieldEditable = (this.type == 'object'); + this.childs.push(node); + } + else { + // insert before a child node + var index = this.childs.indexOf(beforeNode); + if (index == -1) { + throw new Error('Node not found'); + } + + // adjust the link to the parent + node.setParent(this); + node.fieldEditable = (this.type == 'object'); + this.childs.splice(index, 0, node); + } + + if (this.expanded) { + // insert into the DOM + var newTr = node.getDom(); + var nextTr = beforeNode.getDom(); + var table = nextTr ? nextTr.parentNode : undefined; + if (nextTr && table) { + table.insertBefore(newTr, nextTr); + } + + node.showChilds(); + } + + this.updateDom({'updateIndexes': true}); + node.updateDom({'recurse': true}); + } +}; + +/** + * Insert a new child before a given node + * Only applicable when Node value is of type array or object + * @param {Node} node + * @param {Node} afterNode + */ +Node.prototype.insertAfter = function(node, afterNode) { + if (this._hasChilds()) { + var index = this.childs.indexOf(afterNode); + var beforeNode = this.childs[index + 1]; + if (beforeNode) { + this.insertBefore(node, beforeNode); + } + else { + this.appendChild(node); + } + } +}; + +/** + * Search in this node + * The node will be expanded when the text is found one of its childs, else + * it will be collapsed. Searches are case insensitive. + * @param {String} text + * @return {Node[]} results Array with nodes containing the search text + */ +Node.prototype.search = function(text) { + var results = []; + var index; + var search = text ? text.toLowerCase() : undefined; + + // delete old search data + delete this.searchField; + delete this.searchValue; + + // search in field + if (this.field != undefined) { + var field = String(this.field).toLowerCase(); + index = field.indexOf(search); + if (index != -1) { + this.searchField = true; + results.push({ + 'node': this, + 'elem': 'field' + }); + } + + // update dom + this._updateDomField(); + } + + // search in value + if (this._hasChilds()) { + // array, object + + // search the nodes childs + if (this.childs) { + var childResults = []; + this.childs.forEach(function (child) { + childResults = childResults.concat(child.search(text)); + }); + results = results.concat(childResults); + } + + // update dom + if (search != undefined) { + var recurse = false; + if (childResults.length == 0) { + this.collapse(recurse); + } + else { + this.expand(recurse); + } + } + } + else { + // string, auto + if (this.value != undefined ) { + var value = String(this.value).toLowerCase(); + index = value.indexOf(search); + if (index != -1) { + this.searchValue = true; + results.push({ + 'node': this, + 'elem': 'value' + }); + } + } + + // update dom + this._updateDomValue(); + } + + return results; +}; + +/** + * Move the scroll position such that this node is in the visible area. + * The node will not get the focus + * @param {function(boolean)} [callback] + */ +Node.prototype.scrollTo = function(callback) { + if (!this.dom.tr || !this.dom.tr.parentNode) { + // if the node is not visible, expand its parents + var parent = this.parent; + var recurse = false; + while (parent) { + parent.expand(recurse); + parent = parent.parent; + } + } + + if (this.dom.tr && this.dom.tr.parentNode) { + this.editor.scrollTo(this.dom.tr.offsetTop, callback); + } +}; + + +// stores the element name currently having the focus +Node.focusElement = undefined; + +/** + * Set focus to this node + * @param {String} [elementName] The field name of the element to get the + * focus available values: 'drag', 'menu', + * 'expand', 'field', 'value' (default) + */ +Node.prototype.focus = function(elementName) { + Node.focusElement = elementName; + + if (this.dom.tr && this.dom.tr.parentNode) { + var dom = this.dom; + + switch (elementName) { + case 'drag': + if (dom.drag) { + dom.drag.focus(); + } + else { + dom.menu.focus(); + } + break; + + case 'menu': + dom.menu.focus(); + break; + + case 'expand': + if (this._hasChilds()) { + dom.expand.focus(); + } + else if (dom.field && this.fieldEditable) { + dom.field.focus(); + util.selectContentEditable(dom.field); + } + else if (dom.value && !this._hasChilds()) { + dom.value.focus(); + util.selectContentEditable(dom.value); + } + else { + dom.menu.focus(); + } + break; + + case 'field': + if (dom.field && this.fieldEditable) { + dom.field.focus(); + util.selectContentEditable(dom.field); + } + else if (dom.value && !this._hasChilds()) { + dom.value.focus(); + util.selectContentEditable(dom.value); + } + else if (this._hasChilds()) { + dom.expand.focus(); + } + else { + dom.menu.focus(); + } + break; + + case 'value': + default: + if (dom.value && !this._hasChilds()) { + dom.value.focus(); + util.selectContentEditable(dom.value); + } + else if (dom.field && this.fieldEditable) { + dom.field.focus(); + util.selectContentEditable(dom.field); + } + else if (this._hasChilds()) { + dom.expand.focus(); + } + else { + dom.menu.focus(); + } + break; + } + } +}; + +/** + * Select all text in an editable div after a delay of 0 ms + * @param {Element} editableDiv + */ +Node.select = function(editableDiv) { + setTimeout(function () { + util.selectContentEditable(editableDiv); + }, 0); +}; + +/** + * Update the values from the DOM field and value of this node + */ +Node.prototype.blur = function() { + // retrieve the actual field and value from the DOM. + this._getDomValue(false); + this._getDomField(false); +}; + +/** + * Check if given node is a child. The method will check recursively to find + * this node. + * @param {Node} node + * @return {boolean} containsNode + */ +Node.prototype.containsNode = function(node) { + if (this == node) { + return true; + } + + var childs = this.childs; + if (childs) { + // TODO: use the js5 Array.some() here? + for (var i = 0, iMax = childs.length; i < iMax; i++) { + if (childs[i].containsNode(node)) { + return true; + } + } + } + + return false; +}; + +/** + * Move given node into this node + * @param {Node} node the childNode to be moved + * @param {Node} beforeNode node will be inserted before given + * node. If no beforeNode is given, + * the node is appended at the end + * @private + */ +Node.prototype._move = function(node, beforeNode) { + if (node == beforeNode) { + // nothing to do... + return; + } + + // check if this node is not a child of the node to be moved here + if (node.containsNode(this)) { + throw new Error('Cannot move a field into a child of itself'); + } + + // remove the original node + if (node.parent) { + node.parent.removeChild(node); + } + + // create a clone of the node + var clone = node.clone(); + node.clearDom(); + + // insert or append the node + if (beforeNode) { + this.insertBefore(clone, beforeNode); + } + else { + this.appendChild(clone); + } + + /* TODO: adjust the field name (to prevent equal field names) + if (this.type == 'object') { + } + */ +}; + +/** + * Remove a child from the node. + * Only applicable when Node value is of type array or object + * @param {Node} node The child node to be removed; + * @return {Node | undefined} node The removed node on success, + * else undefined + */ +Node.prototype.removeChild = function(node) { + if (this.childs) { + var index = this.childs.indexOf(node); + + if (index != -1) { + node.hide(); + + // delete old search results + delete node.searchField; + delete node.searchValue; + + var removedNode = this.childs.splice(index, 1)[0]; + removedNode.parent = null; + + this.updateDom({'updateIndexes': true}); + + return removedNode; + } + } + + return undefined; +}; + +/** + * Remove a child node node from this node + * This method is equal to Node.removeChild, except that _remove fire an + * onChange event. + * @param {Node} node + * @private + */ +Node.prototype._remove = function (node) { + this.removeChild(node); +}; + +/** + * Change the type of the value of this Node + * @param {String} newType + */ +Node.prototype.changeType = function (newType) { + var oldType = this.type; + + if (oldType == newType) { + // type is not changed + return; + } + + if ((newType == 'string' || newType == 'auto') && + (oldType == 'string' || oldType == 'auto')) { + // this is an easy change + this.type = newType; + } + else { + // change from array to object, or from string/auto to object/array + var table = this.dom.tr ? this.dom.tr.parentNode : undefined; + var lastTr; + if (this.expanded) { + lastTr = this.getAppend(); + } + else { + lastTr = this.getDom(); + } + var nextTr = (lastTr && lastTr.parentNode) ? lastTr.nextSibling : undefined; + + // hide current field and all its childs + this.hide(); + this.clearDom(); + + // adjust the field and the value + this.type = newType; + + // adjust childs + if (newType == 'object') { + if (!this.childs) { + this.childs = []; + } + + this.childs.forEach(function (child, index) { + child.clearDom(); + delete child.index; + child.fieldEditable = true; + if (child.field == undefined) { + child.field = ''; + } + }); + + if (oldType == 'string' || oldType == 'auto') { + this.expanded = true; + } + } + else if (newType == 'array') { + if (!this.childs) { + this.childs = []; + } + + this.childs.forEach(function (child, index) { + child.clearDom(); + child.fieldEditable = false; + child.index = index; + }); + + if (oldType == 'string' || oldType == 'auto') { + this.expanded = true; + } + } + else { + this.expanded = false; + } + + // create new DOM + if (table) { + if (nextTr) { + table.insertBefore(this.getDom(), nextTr); + } + else { + table.appendChild(this.getDom()); + } + } + this.showChilds(); + } + + if (newType == 'auto' || newType == 'string') { + // cast value to the correct type + if (newType == 'string') { + this.value = String(this.value); + } + else { + this.value = this._stringCast(String(this.value)); + } + + this.focus(); + } + + this.updateDom({'updateIndexes': true}); +}; + +/** + * Retrieve value from DOM + * @param {boolean} [silent] If true (default), no errors will be thrown in + * case of invalid data + * @private + */ +Node.prototype._getDomValue = function(silent) { + if (this.dom.value && this.type != 'array' && this.type != 'object') { + this.valueInnerText = util.getInnerText(this.dom.value); + } + + if (this.valueInnerText != undefined) { + try { + // retrieve the value + var value; + if (this.type == 'string') { + value = this._unescapeHTML(this.valueInnerText); + } + else { + var str = this._unescapeHTML(this.valueInnerText); + value = this._stringCast(str); + } + if (value !== this.value) { + this.value = value; + this._debouncedOnChangeValue(); + } + } + catch (err) { + this.value = undefined; + // TODO: sent an action with the new, invalid value? + if (silent !== true) { + throw err; + } + } + } +}; + +/** + * Handle a changed value + * @private + */ +Node.prototype._onChangeValue = function () { + // get current selection, then override the range such that we can select + // the added/removed text on undo/redo + var oldSelection = this.editor.getSelection(); + if (oldSelection.range) { + var undoDiff = util.textDiff(String(this.value), String(this.previousValue)); + oldSelection.range.startOffset = undoDiff.start; + oldSelection.range.endOffset = undoDiff.end; + } + var newSelection = this.editor.getSelection(); + if (newSelection.range) { + var redoDiff = util.textDiff(String(this.previousValue), String(this.value)); + newSelection.range.startOffset = redoDiff.start; + newSelection.range.endOffset = redoDiff.end; + } + + this.editor._onAction('editValue', { + node: this, + oldValue: this.previousValue, + newValue: this.value, + oldSelection: oldSelection, + newSelection: newSelection + }); + + this.previousValue = this.value; +}; + +/** + * Handle a changed field + * @private + */ +Node.prototype._onChangeField = function () { + // get current selection, then override the range such that we can select + // the added/removed text on undo/redo + var oldSelection = this.editor.getSelection(); + if (oldSelection.range) { + var undoDiff = util.textDiff(this.field, this.previousField); + oldSelection.range.startOffset = undoDiff.start; + oldSelection.range.endOffset = undoDiff.end; + } + var newSelection = this.editor.getSelection(); + if (newSelection.range) { + var redoDiff = util.textDiff(this.previousField, this.field); + newSelection.range.startOffset = redoDiff.start; + newSelection.range.endOffset = redoDiff.end; + } + + this.editor._onAction('editField', { + node: this, + oldValue: this.previousField, + newValue: this.field, + oldSelection: oldSelection, + newSelection: newSelection + }); + + this.previousField = this.field; +}; + +/** + * Update dom value: + * - the text color of the value, depending on the type of the value + * - the height of the field, depending on the width + * - background color in case it is empty + * @private + */ +Node.prototype._updateDomValue = function () { + var domValue = this.dom.value; + if (domValue) { + var classNames = ['jsoneditor-value']; + + + // set text color depending on value type + var value = this.value; + var type = (this.type == 'auto') ? util.type(value) : this.type; + var isUrl = type == 'string' && util.isUrl(value); + classNames.push('jsoneditor-' + type); + if (isUrl) { + classNames.push('jsoneditor-url'); + } + + // visual styling when empty + var isEmpty = (String(this.value) == '' && this.type != 'array' && this.type != 'object'); + if (isEmpty) { + classNames.push('jsoneditor-empty'); + } + + // highlight when there is a search result + if (this.searchValueActive) { + classNames.push('jsoneditor-highlight-active'); + } + if (this.searchValue) { + classNames.push('jsoneditor-highlight'); + } + + domValue.className = classNames.join(' '); + + // update title + if (type == 'array' || type == 'object') { + var count = this.childs ? this.childs.length : 0; + domValue.title = this.type + ' containing ' + count + ' items'; + } + else if (isUrl && this.editable.value) { + domValue.title = 'Ctrl+Click or Ctrl+Enter to open url in new window'; + } + else { + domValue.title = ''; + } + + // show checkbox when the value is a boolean + if (type === 'boolean' && this.editable.value) { + if (!this.dom.checkbox) { + this.dom.checkbox = document.createElement('input'); + this.dom.checkbox.type = 'checkbox'; + this.dom.tdCheckbox = document.createElement('td'); + this.dom.tdCheckbox.className = 'jsoneditor-tree'; + this.dom.tdCheckbox.appendChild(this.dom.checkbox); + + this.dom.tdValue.parentNode.insertBefore(this.dom.tdCheckbox, this.dom.tdValue); + } + + this.dom.checkbox.checked = this.value; + } + else { + // cleanup checkbox when displayed + if (this.dom.tdCheckbox) { + this.dom.tdCheckbox.parentNode.removeChild(this.dom.tdCheckbox); + delete this.dom.tdCheckbox; + delete this.dom.checkbox; + } + } + + if (this.enum && this.editable.value) { + // create select box when this node has an enum object + if (!this.dom.select) { + this.dom.select = document.createElement('select'); + this.id = this.field + "_" + new Date().getUTCMilliseconds(); + this.dom.select.id = this.id; + this.dom.select.name = this.dom.select.id; + + //Create the default empty option + this.dom.select.option = document.createElement('option'); + this.dom.select.option.value = ''; + this.dom.select.option.innerHTML = '--'; + this.dom.select.appendChild(this.dom.select.option); + + //Iterate all enum values and add them as options + for(var i = 0; i < this.enum.length; i++) { + this.dom.select.option = document.createElement('option'); + this.dom.select.option.value = this.enum[i]; + this.dom.select.option.innerHTML = this.enum[i]; + if(this.dom.select.option.value == this.value){ + this.dom.select.option.selected = true; + } + this.dom.select.appendChild(this.dom.select.option); + } + + this.dom.tdSelect = document.createElement('td'); + this.dom.tdSelect.className = 'jsoneditor-tree'; + this.dom.tdSelect.appendChild(this.dom.select); + this.dom.tdValue.parentNode.insertBefore(this.dom.tdSelect, this.dom.tdValue); + } + + // If the enum is inside a composite type display + // both the simple input and the dropdown field + if(this.schema && ( + !this.schema.hasOwnProperty("oneOf") && + !this.schema.hasOwnProperty("anyOf") && + !this.schema.hasOwnProperty("allOf")) + ) { + this.valueFieldHTML = this.dom.tdValue.innerHTML; + this.dom.tdValue.style.visibility = 'hidden'; + this.dom.tdValue.innerHTML = ''; + } else { + delete this.valueFieldHTML; + } + } + else { + // cleanup select box when displayed + if (this.dom.tdSelect) { + this.dom.tdSelect.parentNode.removeChild(this.dom.tdSelect); + delete this.dom.tdSelect; + delete this.dom.select; + this.dom.tdValue.innerHTML = this.valueFieldHTML; + this.dom.tdValue.style.visibility = ''; + delete this.valueFieldHTML; + } + } + + // strip formatting from the contents of the editable div + util.stripFormatting(domValue); + } +}; + +/** + * Update dom field: + * - the text color of the field, depending on the text + * - the height of the field, depending on the width + * - background color in case it is empty + * @private + */ +Node.prototype._updateDomField = function () { + var domField = this.dom.field; + if (domField) { + // make backgound color lightgray when empty + var isEmpty = (String(this.field) == '' && this.parent.type != 'array'); + if (isEmpty) { + util.addClassName(domField, 'jsoneditor-empty'); + } + else { + util.removeClassName(domField, 'jsoneditor-empty'); + } + + // highlight when there is a search result + if (this.searchFieldActive) { + util.addClassName(domField, 'jsoneditor-highlight-active'); + } + else { + util.removeClassName(domField, 'jsoneditor-highlight-active'); + } + if (this.searchField) { + util.addClassName(domField, 'jsoneditor-highlight'); + } + else { + util.removeClassName(domField, 'jsoneditor-highlight'); + } + + // strip formatting from the contents of the editable div + util.stripFormatting(domField); + } +}; + +/** + * Retrieve field from DOM + * @param {boolean} [silent] If true (default), no errors will be thrown in + * case of invalid data + * @private + */ +Node.prototype._getDomField = function(silent) { + if (this.dom.field && this.fieldEditable) { + this.fieldInnerText = util.getInnerText(this.dom.field); + } + + if (this.fieldInnerText != undefined) { + try { + var field = this._unescapeHTML(this.fieldInnerText); + + if (field !== this.field) { + this.field = field; + this._debouncedOnChangeField(); + } + } + catch (err) { + this.field = undefined; + // TODO: sent an action here, with the new, invalid value? + if (silent !== true) { + throw err; + } + } + } +}; + +/** + * Validate this node and all it's childs + * @return {Array.<{node: Node, error: {message: string}}>} Returns a list with duplicates + */ +Node.prototype.validate = function () { + var errors = []; + + // find duplicate keys + if (this.type === 'object') { + var keys = {}; + var duplicateKeys = []; + for (var i = 0; i < this.childs.length; i++) { + var child = this.childs[i]; + if (keys.hasOwnProperty(child.field)) { + duplicateKeys.push(child.field); + } + keys[child.field] = true; + } + + if (duplicateKeys.length > 0) { + errors = this.childs + .filter(function (node) { + return duplicateKeys.indexOf(node.field) !== -1; + }) + .map(function (node) { + return { + node: node, + error: { + message: 'duplicate key "' + node.field + '"' + } + } + }); + } + } + + // recurse over the childs + if (this.childs) { + for (var i = 0; i < this.childs.length; i++) { + var e = this.childs[i].validate(); + if (e.length > 0) { + errors = errors.concat(e); + } + } + } + + return errors; +}; + +/** + * Clear the dom of the node + */ +Node.prototype.clearDom = function() { + // TODO: hide the node first? + //this.hide(); + // TODO: recursively clear dom? + + this.dom = {}; +}; + +/** + * Get the HTML DOM TR element of the node. + * The dom will be generated when not yet created + * @return {Element} tr HTML DOM TR Element + */ +Node.prototype.getDom = function() { + var dom = this.dom; + if (dom.tr) { + return dom.tr; + } + + this._updateEditability(); + + // create row + dom.tr = document.createElement('tr'); + dom.tr.node = this; + + if (this.editor.options.mode === 'tree') { // note: we take here the global setting + var tdDrag = document.createElement('td'); + if (this.editable.field) { + // create draggable area + if (this.parent) { + var domDrag = document.createElement('button'); + domDrag.type = 'button'; + dom.drag = domDrag; + domDrag.className = 'jsoneditor-dragarea'; + domDrag.title = 'Drag to move this field (Alt+Shift+Arrows)'; + tdDrag.appendChild(domDrag); + } + } + dom.tr.appendChild(tdDrag); + + // create context menu + var tdMenu = document.createElement('td'); + var menu = document.createElement('button'); + menu.type = 'button'; + dom.menu = menu; + menu.className = 'jsoneditor-contextmenu'; + menu.title = 'Click to open the actions menu (Ctrl+M)'; + tdMenu.appendChild(dom.menu); + dom.tr.appendChild(tdMenu); + } + + // create tree and field + var tdField = document.createElement('td'); + dom.tr.appendChild(tdField); + dom.tree = this._createDomTree(); + tdField.appendChild(dom.tree); + + this.updateDom({'updateIndexes': true}); + + return dom.tr; +}; + +/** + * DragStart event, fired on mousedown on the dragarea at the left side of a Node + * @param {Node[] | Node} nodes + * @param {Event} event + */ +Node.onDragStart = function (nodes, event) { + if (!Array.isArray(nodes)) { + return Node.onDragStart([nodes], event); + } + if (nodes.length === 0) { + return; + } + + var firstNode = nodes[0]; + var lastNode = nodes[nodes.length - 1]; + var draggedNode = Node.getNodeFromTarget(event.target); + var beforeNode = lastNode._nextSibling(); + var editor = firstNode.editor; + + // in case of multiple selected nodes, offsetY prevents the selection from + // jumping when you start dragging one of the lower down nodes in the selection + var offsetY = util.getAbsoluteTop(draggedNode.dom.tr) - util.getAbsoluteTop(firstNode.dom.tr); + + if (!editor.mousemove) { + editor.mousemove = util.addEventListener(window, 'mousemove', function (event) { + Node.onDrag(nodes, event); + }); + } + + if (!editor.mouseup) { + editor.mouseup = util.addEventListener(window, 'mouseup',function (event ) { + Node.onDragEnd(nodes, event); + }); + } + + editor.highlighter.lock(); + editor.drag = { + oldCursor: document.body.style.cursor, + oldSelection: editor.getSelection(), + oldBeforeNode: beforeNode, + mouseX: event.pageX, + offsetY: offsetY, + level: firstNode.getLevel() + }; + document.body.style.cursor = 'move'; + + event.preventDefault(); +}; + +/** + * Drag event, fired when moving the mouse while dragging a Node + * @param {Node[] | Node} nodes + * @param {Event} event + */ +Node.onDrag = function (nodes, event) { + if (!Array.isArray(nodes)) { + return Node.onDrag([nodes], event); + } + if (nodes.length === 0) { + return; + } + + // TODO: this method has grown too large. Split it in a number of methods + var editor = nodes[0].editor; + var mouseY = event.pageY - editor.drag.offsetY; + var mouseX = event.pageX; + var trThis, trPrev, trNext, trFirst, trLast, trRoot; + var nodePrev, nodeNext; + var topThis, topPrev, topFirst, heightThis, bottomNext, heightNext; + var moved = false; + + // TODO: add an ESC option, which resets to the original position + + // move up/down + var firstNode = nodes[0]; + trThis = firstNode.dom.tr; + topThis = util.getAbsoluteTop(trThis); + heightThis = trThis.offsetHeight; + if (mouseY < topThis) { + // move up + trPrev = trThis; + do { + trPrev = trPrev.previousSibling; + nodePrev = Node.getNodeFromTarget(trPrev); + topPrev = trPrev ? util.getAbsoluteTop(trPrev) : 0; + } + while (trPrev && mouseY < topPrev); + + if (nodePrev && !nodePrev.parent) { + nodePrev = undefined; + } + + if (!nodePrev) { + // move to the first node + trRoot = trThis.parentNode.firstChild; + trPrev = trRoot ? trRoot.nextSibling : undefined; + nodePrev = Node.getNodeFromTarget(trPrev); + if (nodePrev == firstNode) { + nodePrev = undefined; + } + } + + if (nodePrev) { + // check if mouseY is really inside the found node + trPrev = nodePrev.dom.tr; + topPrev = trPrev ? util.getAbsoluteTop(trPrev) : 0; + if (mouseY > topPrev + heightThis) { + nodePrev = undefined; + } + } + + if (nodePrev) { + nodes.forEach(function (node) { + nodePrev.parent.moveBefore(node, nodePrev); + }); + moved = true; + } + } + else { + // move down + var lastNode = nodes[nodes.length - 1]; + trLast = (lastNode.expanded && lastNode.append) ? lastNode.append.getDom() : lastNode.dom.tr; + trFirst = trLast ? trLast.nextSibling : undefined; + if (trFirst) { + topFirst = util.getAbsoluteTop(trFirst); + trNext = trFirst; + do { + nodeNext = Node.getNodeFromTarget(trNext); + if (trNext) { + bottomNext = trNext.nextSibling ? + util.getAbsoluteTop(trNext.nextSibling) : 0; + heightNext = trNext ? (bottomNext - topFirst) : 0; + + if (nodeNext.parent.childs.length == nodes.length && + nodeNext.parent.childs[nodes.length - 1] == lastNode) { + // We are about to remove the last child of this parent, + // which will make the parents appendNode visible. + topThis += 27; + // TODO: dangerous to suppose the height of the appendNode a constant of 27 px. + } + } + + trNext = trNext.nextSibling; + } + while (trNext && mouseY > topThis + heightNext); + + if (nodeNext && nodeNext.parent) { + // calculate the desired level + var diffX = (mouseX - editor.drag.mouseX); + var diffLevel = Math.round(diffX / 24 / 2); + var level = editor.drag.level + diffLevel; // desired level + var levelNext = nodeNext.getLevel(); // level to be + + // find the best fitting level (move upwards over the append nodes) + trPrev = nodeNext.dom.tr.previousSibling; + while (levelNext < level && trPrev) { + nodePrev = Node.getNodeFromTarget(trPrev); + + var isDraggedNode = nodes.some(function (node) { + return node === nodePrev || nodePrev._isChildOf(node); + }); + + if (isDraggedNode) { + // neglect the dragged nodes themselves and their childs + } + else if (nodePrev instanceof AppendNode) { + var childs = nodePrev.parent.childs; + if (childs.length != nodes.length || childs[nodes.length - 1] != lastNode) { + // non-visible append node of a list of childs + // consisting of not only this node (else the + // append node will change into a visible "empty" + // text when removing this node). + nodeNext = Node.getNodeFromTarget(trPrev); + levelNext = nodeNext.getLevel(); + } + else { + break; + } + } + else { + break; + } + + trPrev = trPrev.previousSibling; + } + + // move the node when its position is changed + if (trLast.nextSibling != nodeNext.dom.tr) { + nodes.forEach(function (node) { + nodeNext.parent.moveBefore(node, nodeNext); + }); + moved = true; + } + } + } + } + + if (moved) { + // update the dragging parameters when moved + editor.drag.mouseX = mouseX; + editor.drag.level = firstNode.getLevel(); + } + + // auto scroll when hovering around the top of the editor + editor.startAutoScroll(mouseY); + + event.preventDefault(); +}; + +/** + * Drag event, fired on mouseup after having dragged a node + * @param {Node[] | Node} nodes + * @param {Event} event + */ +Node.onDragEnd = function (nodes, event) { + if (!Array.isArray(nodes)) { + return Node.onDrag([nodes], event); + } + if (nodes.length === 0) { + return; + } + + var firstNode = nodes[0]; + var editor = firstNode.editor; + var parent = firstNode.parent; + var firstIndex = parent.childs.indexOf(firstNode); + var beforeNode = parent.childs[firstIndex + nodes.length] || parent.append; + + // set focus to the context menu button of the first node + if (nodes[0]) { + nodes[0].dom.menu.focus(); + } + + var params = { + nodes: nodes, + oldSelection: editor.drag.oldSelection, + newSelection: editor.getSelection(), + oldBeforeNode: editor.drag.oldBeforeNode, + newBeforeNode: beforeNode + }; + + if (params.oldBeforeNode != params.newBeforeNode) { + // only register this action if the node is actually moved to another place + editor._onAction('moveNodes', params); + } + + document.body.style.cursor = editor.drag.oldCursor; + editor.highlighter.unlock(); + nodes.forEach(function (node) { + if (event.target !== node.dom.drag && event.target !== node.dom.menu) { + editor.highlighter.unhighlight(); + } + }); + delete editor.drag; + + if (editor.mousemove) { + util.removeEventListener(window, 'mousemove', editor.mousemove); + delete editor.mousemove; + } + if (editor.mouseup) { + util.removeEventListener(window, 'mouseup', editor.mouseup); + delete editor.mouseup; + } + + // Stop any running auto scroll + editor.stopAutoScroll(); + + event.preventDefault(); +}; + +/** + * Test if this node is a child of an other node + * @param {Node} node + * @return {boolean} isChild + * @private + */ +Node.prototype._isChildOf = function (node) { + var n = this.parent; + while (n) { + if (n == node) { + return true; + } + n = n.parent; + } + + return false; +}; + +/** + * Create an editable field + * @return {Element} domField + * @private + */ +Node.prototype._createDomField = function () { + return document.createElement('div'); +}; + +/** + * Set highlighting for this node and all its childs. + * Only applied to the currently visible (expanded childs) + * @param {boolean} highlight + */ +Node.prototype.setHighlight = function (highlight) { + if (this.dom.tr) { + if (highlight) { + util.addClassName(this.dom.tr, 'jsoneditor-highlight'); + } + else { + util.removeClassName(this.dom.tr, 'jsoneditor-highlight'); + } + + if (this.append) { + this.append.setHighlight(highlight); + } + + if (this.childs) { + this.childs.forEach(function (child) { + child.setHighlight(highlight); + }); + } + } +}; + +/** + * Select or deselect a node + * @param {boolean} selected + * @param {boolean} [isFirst] + */ +Node.prototype.setSelected = function (selected, isFirst) { + this.selected = selected; + + if (this.dom.tr) { + if (selected) { + util.addClassName(this.dom.tr, 'jsoneditor-selected'); + } + else { + util.removeClassName(this.dom.tr, 'jsoneditor-selected'); + } + + if (isFirst) { + util.addClassName(this.dom.tr, 'jsoneditor-first'); + } + else { + util.removeClassName(this.dom.tr, 'jsoneditor-first'); + } + + if (this.append) { + this.append.setSelected(selected); + } + + if (this.childs) { + this.childs.forEach(function (child) { + child.setSelected(selected); + }); + } + } +}; + +/** + * Update the value of the node. Only primitive types are allowed, no Object + * or Array is allowed. + * @param {String | Number | Boolean | null} value + */ +Node.prototype.updateValue = function (value) { + this.value = value; + this.updateDom(); +}; + +/** + * Update the field of the node. + * @param {String} field + */ +Node.prototype.updateField = function (field) { + this.field = field; + this.updateDom(); +}; + +/** + * Update the HTML DOM, optionally recursing through the childs + * @param {Object} [options] Available parameters: + * {boolean} [recurse] If true, the + * DOM of the childs will be updated recursively. + * False by default. + * {boolean} [updateIndexes] If true, the childs + * indexes of the node will be updated too. False by + * default. + */ +Node.prototype.updateDom = function (options) { + // update level indentation + var domTree = this.dom.tree; + if (domTree) { + domTree.style.marginLeft = this.getLevel() * 24 + 'px'; + } + + // apply field to DOM + var domField = this.dom.field; + if (domField) { + if (this.fieldEditable) { + // parent is an object + domField.contentEditable = this.editable.field; + domField.spellcheck = false; + domField.className = 'jsoneditor-field'; + } + else { + // parent is an array this is the root node + domField.className = 'jsoneditor-readonly'; + } + + var fieldText; + if (this.index != undefined) { + fieldText = this.index; + } + else if (this.field != undefined) { + fieldText = this.field; + } + else if (this._hasChilds()) { + fieldText = this.type; + } + else { + fieldText = ''; + } + domField.innerHTML = this._escapeHTML(fieldText); + + this._updateSchema(); + } + + // apply value to DOM + var domValue = this.dom.value; + if (domValue) { + var count = this.childs ? this.childs.length : 0; + if (this.type == 'array') { + domValue.innerHTML = '[' + count + ']'; + util.addClassName(this.dom.tr, 'jsoneditor-expandable'); + } + else if (this.type == 'object') { + domValue.innerHTML = '{' + count + '}'; + util.addClassName(this.dom.tr, 'jsoneditor-expandable'); + } + else { + domValue.innerHTML = this._escapeHTML(this.value); + util.removeClassName(this.dom.tr, 'jsoneditor-expandable'); + } + } + + // update field and value + this._updateDomField(); + this._updateDomValue(); + + // update childs indexes + if (options && options.updateIndexes === true) { + // updateIndexes is true or undefined + this._updateDomIndexes(); + } + + if (options && options.recurse === true) { + // recurse is true or undefined. update childs recursively + if (this.childs) { + this.childs.forEach(function (child) { + child.updateDom(options); + }); + } + } + + // update row with append button + if (this.append) { + this.append.updateDom(); + } +}; + +/** + * Locate the JSON schema of the node and check for any enum type + * @private + */ +Node.prototype._updateSchema = function () { + //Locating the schema of the node and checking for any enum type + if(this.editor && this.editor.options) { + // find the part of the json schema matching this nodes path + this.schema = Node._findSchema(this.editor.options.schema, this.getPath()); + if (this.schema) { + this.enum = Node._findEnum(this.schema); + } + else { + delete this.enum; + } + } +}; + +/** + * find an enum definition in a JSON schema, as property `enum` or inside + * one of the schemas composites (`oneOf`, `anyOf`, `allOf`) + * @param {Object} schema + * @return {Array | null} Returns the enum when found, null otherwise. + * @private + */ +Node._findEnum = function (schema) { + if (schema.enum) { + return schema.enum; + } + + var composite = schema.oneOf || schema.anyOf || schema.allOf; + if (composite) { + var match = composite.filter(function (entry) {return entry.enum}); + if (match.length > 0) { + return match[0].enum; + } + } + + return null +}; + +/** + * Return the part of a JSON schema matching given path. + * @param {Object} schema + * @param {Array.} path + * @return {Object | null} + * @private + */ +Node._findSchema = function (schema, path) { + var childSchema = schema; + + for (var i = 0; i < path.length && childSchema; i++) { + var key = path[i]; + if (typeof key === 'string' && childSchema.properties) { + childSchema = childSchema.properties[key] || null + } + else if (typeof key === 'number' && childSchema.items) { + childSchema = childSchema.items + } + } + + return childSchema +}; + +/** + * Update the DOM of the childs of a node: update indexes and undefined field + * names. + * Only applicable when structure is an array or object + * @private + */ +Node.prototype._updateDomIndexes = function () { + var domValue = this.dom.value; + var childs = this.childs; + if (domValue && childs) { + if (this.type == 'array') { + childs.forEach(function (child, index) { + child.index = index; + var childField = child.dom.field; + if (childField) { + childField.innerHTML = index; + } + }); + } + else if (this.type == 'object') { + childs.forEach(function (child) { + if (child.index != undefined) { + delete child.index; + + if (child.field == undefined) { + child.field = ''; + } + } + }); + } + } +}; + +/** + * Create an editable value + * @private + */ +Node.prototype._createDomValue = function () { + var domValue; + + if (this.type == 'array') { + domValue = document.createElement('div'); + domValue.innerHTML = '[...]'; + } + else if (this.type == 'object') { + domValue = document.createElement('div'); + domValue.innerHTML = '{...}'; + } + else { + if (!this.editable.value && util.isUrl(this.value)) { + // create a link in case of read-only editor and value containing an url + domValue = document.createElement('a'); + domValue.href = this.value; + domValue.target = '_blank'; + domValue.innerHTML = this._escapeHTML(this.value); + } + else { + // create an editable or read-only div + domValue = document.createElement('div'); + domValue.contentEditable = this.editable.value; + domValue.spellcheck = false; + domValue.innerHTML = this._escapeHTML(this.value); + } + } + + return domValue; +}; + +/** + * Create an expand/collapse button + * @return {Element} expand + * @private + */ +Node.prototype._createDomExpandButton = function () { + // create expand button + var expand = document.createElement('button'); + expand.type = 'button'; + if (this._hasChilds()) { + expand.className = this.expanded ? 'jsoneditor-expanded' : 'jsoneditor-collapsed'; + expand.title = + 'Click to expand/collapse this field (Ctrl+E). \n' + + 'Ctrl+Click to expand/collapse including all childs.'; + } + else { + expand.className = 'jsoneditor-invisible'; + expand.title = ''; + } + + return expand; +}; + + +/** + * Create a DOM tree element, containing the expand/collapse button + * @return {Element} domTree + * @private + */ +Node.prototype._createDomTree = function () { + var dom = this.dom; + var domTree = document.createElement('table'); + var tbody = document.createElement('tbody'); + domTree.style.borderCollapse = 'collapse'; // TODO: put in css + domTree.className = 'jsoneditor-values'; + domTree.appendChild(tbody); + var tr = document.createElement('tr'); + tbody.appendChild(tr); + + // create expand button + var tdExpand = document.createElement('td'); + tdExpand.className = 'jsoneditor-tree'; + tr.appendChild(tdExpand); + dom.expand = this._createDomExpandButton(); + tdExpand.appendChild(dom.expand); + dom.tdExpand = tdExpand; + + // create the field + var tdField = document.createElement('td'); + tdField.className = 'jsoneditor-tree'; + tr.appendChild(tdField); + dom.field = this._createDomField(); + tdField.appendChild(dom.field); + dom.tdField = tdField; + + // create a separator + var tdSeparator = document.createElement('td'); + tdSeparator.className = 'jsoneditor-tree'; + tr.appendChild(tdSeparator); + if (this.type != 'object' && this.type != 'array') { + tdSeparator.appendChild(document.createTextNode(':')); + tdSeparator.className = 'jsoneditor-separator'; + } + dom.tdSeparator = tdSeparator; + + // create the value + var tdValue = document.createElement('td'); + tdValue.className = 'jsoneditor-tree'; + tr.appendChild(tdValue); + dom.value = this._createDomValue(); + tdValue.appendChild(dom.value); + dom.tdValue = tdValue; + + return domTree; +}; + +/** + * Handle an event. The event is caught centrally by the editor + * @param {Event} event + */ +Node.prototype.onEvent = function (event) { + var type = event.type, + target = event.target || event.srcElement, + dom = this.dom, + node = this, + expandable = this._hasChilds(); + + // check if mouse is on menu or on dragarea. + // If so, highlight current row and its childs + if (target == dom.drag || target == dom.menu) { + if (type == 'mouseover') { + this.editor.highlighter.highlight(this); + } + else if (type == 'mouseout') { + this.editor.highlighter.unhighlight(); + } + } + + // context menu events + if (type == 'click' && target == dom.menu) { + var highlighter = node.editor.highlighter; + highlighter.highlight(node); + highlighter.lock(); + util.addClassName(dom.menu, 'jsoneditor-selected'); + this.showContextMenu(dom.menu, function () { + util.removeClassName(dom.menu, 'jsoneditor-selected'); + highlighter.unlock(); + highlighter.unhighlight(); + }); + } + + // expand events + if (type == 'click') { + if (target == dom.expand || + ((node.editor.options.mode === 'view' || node.editor.options.mode === 'form') && target.nodeName === 'DIV')) { + if (expandable) { + var recurse = event.ctrlKey; // with ctrl-key, expand/collapse all + this._onExpand(recurse); + } + } + } + + // swap the value of a boolean when the checkbox displayed left is clicked + if (type == 'change' && target == dom.checkbox) { + this.dom.value.innerHTML = !this.value; + this._getDomValue(); + } + + // update the value of the node based on the selected option + if (type == 'change' && target == dom.select) { + this.dom.value.innerHTML = dom.select.value; + this._getDomValue(); + this._updateDomValue(); + } + + // value events + var domValue = dom.value; + if (target == domValue) { + //noinspection FallthroughInSwitchStatementJS + switch (type) { + case 'blur': + case 'change': + this._getDomValue(true); + this._updateDomValue(); + if (this.value) { + domValue.innerHTML = this._escapeHTML(this.value); + } + break; + + case 'input': + //this._debouncedGetDomValue(true); // TODO + this._getDomValue(true); + this._updateDomValue(); + break; + + case 'keydown': + case 'mousedown': + // TODO: cleanup + this.editor.selection = this.editor.getSelection(); + break; + + case 'click': + if (event.ctrlKey || !this.editable.value) { + if (util.isUrl(this.value)) { + window.open(this.value, '_blank'); + } + } + break; + + case 'keyup': + //this._debouncedGetDomValue(true); // TODO + this._getDomValue(true); + this._updateDomValue(); + break; + + case 'cut': + case 'paste': + setTimeout(function () { + node._getDomValue(true); + node._updateDomValue(); + }, 1); + break; + } + } + + // field events + var domField = dom.field; + if (target == domField) { + switch (type) { + case 'blur': + case 'change': + this._getDomField(true); + this._updateDomField(); + if (this.field) { + domField.innerHTML = this._escapeHTML(this.field); + } + break; + + case 'input': + this._getDomField(true); + this._updateSchema(); + this._updateDomField(); + this._updateDomValue(); + break; + + case 'keydown': + case 'mousedown': + this.editor.selection = this.editor.getSelection(); + break; + + case 'keyup': + this._getDomField(true); + this._updateDomField(); + break; + + case 'cut': + case 'paste': + setTimeout(function () { + node._getDomField(true); + node._updateDomField(); + }, 1); + break; + } + } + + // focus + // when clicked in whitespace left or right from the field or value, set focus + var domTree = dom.tree; + if (target == domTree.parentNode && type == 'click' && !event.hasMoved) { + var left = (event.offsetX != undefined) ? + (event.offsetX < (this.getLevel() + 1) * 24) : + (event.pageX < util.getAbsoluteLeft(dom.tdSeparator));// for FF + if (left || expandable) { + // node is expandable when it is an object or array + if (domField) { + util.setEndOfContentEditable(domField); + domField.focus(); + } + } + else { + if (domValue && !this.enum) { + util.setEndOfContentEditable(domValue); + domValue.focus(); + } + } + } + if (((target == dom.tdExpand && !expandable) || target == dom.tdField || target == dom.tdSeparator) && + (type == 'click' && !event.hasMoved)) { + if (domField) { + util.setEndOfContentEditable(domField); + domField.focus(); + } + } + + if (type == 'keydown') { + this.onKeyDown(event); + } +}; + +/** + * Key down event handler + * @param {Event} event + */ +Node.prototype.onKeyDown = function (event) { + var keynum = event.which || event.keyCode; + var target = event.target || event.srcElement; + var ctrlKey = event.ctrlKey; + var shiftKey = event.shiftKey; + var altKey = event.altKey; + var handled = false; + var prevNode, nextNode, nextDom, nextDom2; + var editable = this.editor.options.mode === 'tree'; + var oldSelection; + var oldBeforeNode; + var nodes; + var multiselection; + var selectedNodes = this.editor.multiselection.nodes.length > 0 + ? this.editor.multiselection.nodes + : [this]; + var firstNode = selectedNodes[0]; + var lastNode = selectedNodes[selectedNodes.length - 1]; + + // console.log(ctrlKey, keynum, event.charCode); // TODO: cleanup + if (keynum == 13) { // Enter + if (target == this.dom.value) { + if (!this.editable.value || event.ctrlKey) { + if (util.isUrl(this.value)) { + window.open(this.value, '_blank'); + handled = true; + } + } + } + else if (target == this.dom.expand) { + var expandable = this._hasChilds(); + if (expandable) { + var recurse = event.ctrlKey; // with ctrl-key, expand/collapse all + this._onExpand(recurse); + target.focus(); + handled = true; + } + } + } + else if (keynum == 68) { // D + if (ctrlKey && editable) { // Ctrl+D + Node.onDuplicate(selectedNodes); + handled = true; + } + } + else if (keynum == 69) { // E + if (ctrlKey) { // Ctrl+E and Ctrl+Shift+E + this._onExpand(shiftKey); // recurse = shiftKey + target.focus(); // TODO: should restore focus in case of recursing expand (which takes DOM offline) + handled = true; + } + } + else if (keynum == 77 && editable) { // M + if (ctrlKey) { // Ctrl+M + this.showContextMenu(target); + handled = true; + } + } + else if (keynum == 46 && editable) { // Del + if (ctrlKey) { // Ctrl+Del + Node.onRemove(selectedNodes); + handled = true; + } + } + else if (keynum == 45 && editable) { // Ins + if (ctrlKey && !shiftKey) { // Ctrl+Ins + this._onInsertBefore(); + handled = true; + } + else if (ctrlKey && shiftKey) { // Ctrl+Shift+Ins + this._onInsertAfter(); + handled = true; + } + } + else if (keynum == 35) { // End + if (altKey) { // Alt+End + // find the last node + var endNode = this._lastNode(); + if (endNode) { + endNode.focus(Node.focusElement || this._getElementName(target)); + } + handled = true; + } + } + else if (keynum == 36) { // Home + if (altKey) { // Alt+Home + // find the first node + var homeNode = this._firstNode(); + if (homeNode) { + homeNode.focus(Node.focusElement || this._getElementName(target)); + } + handled = true; + } + } + else if (keynum == 37) { // Arrow Left + if (altKey && !shiftKey) { // Alt + Arrow Left + // move to left element + var prevElement = this._previousElement(target); + if (prevElement) { + this.focus(this._getElementName(prevElement)); + } + handled = true; + } + else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow left + if (lastNode.expanded) { + var appendDom = lastNode.getAppend(); + nextDom = appendDom ? appendDom.nextSibling : undefined; + } + else { + var dom = lastNode.getDom(); + nextDom = dom.nextSibling; + } + if (nextDom) { + nextNode = Node.getNodeFromTarget(nextDom); + nextDom2 = nextDom.nextSibling; + nextNode2 = Node.getNodeFromTarget(nextDom2); + if (nextNode && nextNode instanceof AppendNode && + !(lastNode.parent.childs.length == 1) && + nextNode2 && nextNode2.parent) { + oldSelection = this.editor.getSelection(); + oldBeforeNode = lastNode._nextSibling(); + + selectedNodes.forEach(function (node) { + nextNode2.parent.moveBefore(node, nextNode2); + }); + this.focus(Node.focusElement || this._getElementName(target)); + + this.editor._onAction('moveNodes', { + nodes: selectedNodes, + oldBeforeNode: oldBeforeNode, + newBeforeNode: nextNode2, + oldSelection: oldSelection, + newSelection: this.editor.getSelection() + }); + } + } + } + } + else if (keynum == 38) { // Arrow Up + if (altKey && !shiftKey) { // Alt + Arrow Up + // find the previous node + prevNode = this._previousNode(); + if (prevNode) { + this.editor.deselect(true); + prevNode.focus(Node.focusElement || this._getElementName(target)); + } + handled = true; + } + else if (!altKey && ctrlKey && shiftKey && editable) { // Ctrl + Shift + Arrow Up + // select multiple nodes + prevNode = this._previousNode(); + if (prevNode) { + multiselection = this.editor.multiselection; + multiselection.start = multiselection.start || this; + multiselection.end = prevNode; + nodes = this.editor._findTopLevelNodes(multiselection.start, multiselection.end); + + this.editor.select(nodes); + prevNode.focus('field'); // select field as we know this always exists + } + handled = true; + } + else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow Up + // find the previous node + prevNode = firstNode._previousNode(); + if (prevNode && prevNode.parent) { + oldSelection = this.editor.getSelection(); + oldBeforeNode = lastNode._nextSibling(); + + selectedNodes.forEach(function (node) { + prevNode.parent.moveBefore(node, prevNode); + }); + this.focus(Node.focusElement || this._getElementName(target)); + + this.editor._onAction('moveNodes', { + nodes: selectedNodes, + oldBeforeNode: oldBeforeNode, + newBeforeNode: prevNode, + oldSelection: oldSelection, + newSelection: this.editor.getSelection() + }); + } + handled = true; + } + } + else if (keynum == 39) { // Arrow Right + if (altKey && !shiftKey) { // Alt + Arrow Right + // move to right element + var nextElement = this._nextElement(target); + if (nextElement) { + this.focus(this._getElementName(nextElement)); + } + handled = true; + } + else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow Right + dom = firstNode.getDom(); + var prevDom = dom.previousSibling; + if (prevDom) { + prevNode = Node.getNodeFromTarget(prevDom); + if (prevNode && prevNode.parent && + (prevNode instanceof AppendNode) + && !prevNode.isVisible()) { + oldSelection = this.editor.getSelection(); + oldBeforeNode = lastNode._nextSibling(); + + selectedNodes.forEach(function (node) { + prevNode.parent.moveBefore(node, prevNode); + }); + this.focus(Node.focusElement || this._getElementName(target)); + + this.editor._onAction('moveNodes', { + nodes: selectedNodes, + oldBeforeNode: oldBeforeNode, + newBeforeNode: prevNode, + oldSelection: oldSelection, + newSelection: this.editor.getSelection() + }); + } + } + } + } + else if (keynum == 40) { // Arrow Down + if (altKey && !shiftKey) { // Alt + Arrow Down + // find the next node + nextNode = this._nextNode(); + if (nextNode) { + this.editor.deselect(true); + nextNode.focus(Node.focusElement || this._getElementName(target)); + } + handled = true; + } + else if (!altKey && ctrlKey && shiftKey && editable) { // Ctrl + Shift + Arrow Down + // select multiple nodes + nextNode = this._nextNode(); + if (nextNode) { + multiselection = this.editor.multiselection; + multiselection.start = multiselection.start || this; + multiselection.end = nextNode; + nodes = this.editor._findTopLevelNodes(multiselection.start, multiselection.end); + + this.editor.select(nodes); + nextNode.focus('field'); // select field as we know this always exists + } + handled = true; + } + else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow Down + // find the 2nd next node and move before that one + if (lastNode.expanded) { + nextNode = lastNode.append ? lastNode.append._nextNode() : undefined; + } + else { + nextNode = lastNode._nextNode(); + } + var nextNode2 = nextNode && (nextNode._nextNode() || nextNode.parent.append); + if (nextNode2 && nextNode2.parent) { + oldSelection = this.editor.getSelection(); + oldBeforeNode = lastNode._nextSibling(); + + selectedNodes.forEach(function (node) { + nextNode2.parent.moveBefore(node, nextNode2); + }); + this.focus(Node.focusElement || this._getElementName(target)); + + this.editor._onAction('moveNodes', { + nodes: selectedNodes, + oldBeforeNode: oldBeforeNode, + newBeforeNode: nextNode2, + oldSelection: oldSelection, + newSelection: this.editor.getSelection() + }); + } + handled = true; + } + } + + if (handled) { + event.preventDefault(); + event.stopPropagation(); + } +}; + +/** + * Handle the expand event, when clicked on the expand button + * @param {boolean} recurse If true, child nodes will be expanded too + * @private + */ +Node.prototype._onExpand = function (recurse) { + if (recurse) { + // Take the table offline + var table = this.dom.tr.parentNode; // TODO: not nice to access the main table like this + var frame = table.parentNode; + var scrollTop = frame.scrollTop; + frame.removeChild(table); + } + + if (this.expanded) { + this.collapse(recurse); + } + else { + this.expand(recurse); + } + + if (recurse) { + // Put the table online again + frame.appendChild(table); + frame.scrollTop = scrollTop; + } +}; + +/** + * Remove nodes + * @param {Node[] | Node} nodes + */ +Node.onRemove = function(nodes) { + if (!Array.isArray(nodes)) { + return Node.onRemove([nodes]); + } + + if (nodes && nodes.length > 0) { + var firstNode = nodes[0]; + var parent = firstNode.parent; + var editor = firstNode.editor; + var firstIndex = firstNode.getIndex(); + editor.highlighter.unhighlight(); + + // adjust the focus + var oldSelection = editor.getSelection(); + Node.blurNodes(nodes); + var newSelection = editor.getSelection(); + + // remove the nodes + nodes.forEach(function (node) { + node.parent._remove(node); + }); + + // store history action + editor._onAction('removeNodes', { + nodes: nodes.slice(0), // store a copy of the array! + parent: parent, + index: firstIndex, + oldSelection: oldSelection, + newSelection: newSelection + }); + } +}; + + +/** + * Duplicate nodes + * duplicated nodes will be added right after the original nodes + * @param {Node[] | Node} nodes + */ +Node.onDuplicate = function(nodes) { + if (!Array.isArray(nodes)) { + return Node.onDuplicate([nodes]); + } + + if (nodes && nodes.length > 0) { + var lastNode = nodes[nodes.length - 1]; + var parent = lastNode.parent; + var editor = lastNode.editor; + + editor.deselect(editor.multiselection.nodes); + + // duplicate the nodes + var oldSelection = editor.getSelection(); + var afterNode = lastNode; + var clones = nodes.map(function (node) { + var clone = node.clone(); + parent.insertAfter(clone, afterNode); + afterNode = clone; + return clone; + }); + + // set selection to the duplicated nodes + if (nodes.length === 1) { + clones[0].focus(); + } + else { + editor.select(clones); + } + var newSelection = editor.getSelection(); + + editor._onAction('duplicateNodes', { + afterNode: lastNode, + nodes: clones, + parent: parent, + oldSelection: oldSelection, + newSelection: newSelection + }); + } +}; + +/** + * Handle insert before event + * @param {String} [field] + * @param {*} [value] + * @param {String} [type] Can be 'auto', 'array', 'object', or 'string' + * @private + */ +Node.prototype._onInsertBefore = function (field, value, type) { + var oldSelection = this.editor.getSelection(); + + var newNode = new Node(this.editor, { + field: (field != undefined) ? field : '', + value: (value != undefined) ? value : '', + type: type + }); + newNode.expand(true); + this.parent.insertBefore(newNode, this); + this.editor.highlighter.unhighlight(); + newNode.focus('field'); + var newSelection = this.editor.getSelection(); + + this.editor._onAction('insertBeforeNodes', { + nodes: [newNode], + beforeNode: this, + parent: this.parent, + oldSelection: oldSelection, + newSelection: newSelection + }); +}; + +/** + * Handle insert after event + * @param {String} [field] + * @param {*} [value] + * @param {String} [type] Can be 'auto', 'array', 'object', or 'string' + * @private + */ +Node.prototype._onInsertAfter = function (field, value, type) { + var oldSelection = this.editor.getSelection(); + + var newNode = new Node(this.editor, { + field: (field != undefined) ? field : '', + value: (value != undefined) ? value : '', + type: type + }); + newNode.expand(true); + this.parent.insertAfter(newNode, this); + this.editor.highlighter.unhighlight(); + newNode.focus('field'); + var newSelection = this.editor.getSelection(); + + this.editor._onAction('insertAfterNodes', { + nodes: [newNode], + afterNode: this, + parent: this.parent, + oldSelection: oldSelection, + newSelection: newSelection + }); +}; + +/** + * Handle append event + * @param {String} [field] + * @param {*} [value] + * @param {String} [type] Can be 'auto', 'array', 'object', or 'string' + * @private + */ +Node.prototype._onAppend = function (field, value, type) { + var oldSelection = this.editor.getSelection(); + + var newNode = new Node(this.editor, { + field: (field != undefined) ? field : '', + value: (value != undefined) ? value : '', + type: type + }); + newNode.expand(true); + this.parent.appendChild(newNode); + this.editor.highlighter.unhighlight(); + newNode.focus('field'); + var newSelection = this.editor.getSelection(); + + this.editor._onAction('appendNodes', { + nodes: [newNode], + parent: this.parent, + oldSelection: oldSelection, + newSelection: newSelection + }); +}; + +/** + * Change the type of the node's value + * @param {String} newType + * @private + */ +Node.prototype._onChangeType = function (newType) { + var oldType = this.type; + if (newType != oldType) { + var oldSelection = this.editor.getSelection(); + this.changeType(newType); + var newSelection = this.editor.getSelection(); + + this.editor._onAction('changeType', { + node: this, + oldType: oldType, + newType: newType, + oldSelection: oldSelection, + newSelection: newSelection + }); + } +}; + +/** + * Sort the child's of the node. Only applicable when the node has type 'object' + * or 'array'. + * @param {String} direction Sorting direction. Available values: "asc", "desc" + * @private + */ +Node.prototype.sort = function (direction) { + if (!this._hasChilds()) { + return; + } + + var order = (direction == 'desc') ? -1 : 1; + var prop = (this.type == 'array') ? 'value': 'field'; + this.hideChilds(); + + var oldChilds = this.childs; + var oldSortOrder = this.sortOrder; + + // copy the array (the old one will be kept for an undo action + this.childs = this.childs.concat(); + + // sort the arrays + this.childs.sort(function (a, b) { + return order * naturalSort(a[prop], b[prop]); + }); + this.sortOrder = (order == 1) ? 'asc' : 'desc'; + + this.editor._onAction('sort', { + node: this, + oldChilds: oldChilds, + oldSort: oldSortOrder, + newChilds: this.childs, + newSort: this.sortOrder + }); + + this.showChilds(); +}; + +/** + * Create a table row with an append button. + * @return {HTMLElement | undefined} buttonAppend or undefined when inapplicable + */ +Node.prototype.getAppend = function () { + if (!this.append) { + this.append = new AppendNode(this.editor); + this.append.setParent(this); + } + return this.append.getDom(); +}; + +/** + * Find the node from an event target + * @param {Node} target + * @return {Node | undefined} node or undefined when not found + * @static + */ +Node.getNodeFromTarget = function (target) { + while (target) { + if (target.node) { + return target.node; + } + target = target.parentNode; + } + + return undefined; +}; + +/** + * Remove the focus of given nodes, and move the focus to the (a) node before, + * (b) the node after, or (c) the parent node. + * @param {Array. | Node} nodes + */ +Node.blurNodes = function (nodes) { + if (!Array.isArray(nodes)) { + Node.blurNodes([nodes]); + return; + } + + var firstNode = nodes[0]; + var parent = firstNode.parent; + var firstIndex = firstNode.getIndex(); + + if (parent.childs[firstIndex + nodes.length]) { + parent.childs[firstIndex + nodes.length].focus(); + } + else if (parent.childs[firstIndex - 1]) { + parent.childs[firstIndex - 1].focus(); + } + else { + parent.focus(); + } +}; + +/** + * Get the next sibling of current node + * @return {Node} nextSibling + * @private + */ +Node.prototype._nextSibling = function () { + var index = this.parent.childs.indexOf(this); + return this.parent.childs[index + 1] || this.parent.append; +}; + +/** + * Get the previously rendered node + * @return {Node | null} previousNode + * @private + */ +Node.prototype._previousNode = function () { + var prevNode = null; + var dom = this.getDom(); + if (dom && dom.parentNode) { + // find the previous field + var prevDom = dom; + do { + prevDom = prevDom.previousSibling; + prevNode = Node.getNodeFromTarget(prevDom); + } + while (prevDom && (prevNode instanceof AppendNode && !prevNode.isVisible())); + } + return prevNode; +}; + +/** + * Get the next rendered node + * @return {Node | null} nextNode + * @private + */ +Node.prototype._nextNode = function () { + var nextNode = null; + var dom = this.getDom(); + if (dom && dom.parentNode) { + // find the previous field + var nextDom = dom; + do { + nextDom = nextDom.nextSibling; + nextNode = Node.getNodeFromTarget(nextDom); + } + while (nextDom && (nextNode instanceof AppendNode && !nextNode.isVisible())); + } + + return nextNode; +}; + +/** + * Get the first rendered node + * @return {Node | null} firstNode + * @private + */ +Node.prototype._firstNode = function () { + var firstNode = null; + var dom = this.getDom(); + if (dom && dom.parentNode) { + var firstDom = dom.parentNode.firstChild; + firstNode = Node.getNodeFromTarget(firstDom); + } + + return firstNode; +}; + +/** + * Get the last rendered node + * @return {Node | null} lastNode + * @private + */ +Node.prototype._lastNode = function () { + var lastNode = null; + var dom = this.getDom(); + if (dom && dom.parentNode) { + var lastDom = dom.parentNode.lastChild; + lastNode = Node.getNodeFromTarget(lastDom); + while (lastDom && (lastNode instanceof AppendNode && !lastNode.isVisible())) { + lastDom = lastDom.previousSibling; + lastNode = Node.getNodeFromTarget(lastDom); + } + } + return lastNode; +}; + +/** + * Get the next element which can have focus. + * @param {Element} elem + * @return {Element | null} nextElem + * @private + */ +Node.prototype._previousElement = function (elem) { + var dom = this.dom; + // noinspection FallthroughInSwitchStatementJS + switch (elem) { + case dom.value: + if (this.fieldEditable) { + return dom.field; + } + // intentional fall through + case dom.field: + if (this._hasChilds()) { + return dom.expand; + } + // intentional fall through + case dom.expand: + return dom.menu; + case dom.menu: + if (dom.drag) { + return dom.drag; + } + // intentional fall through + default: + return null; + } +}; + +/** + * Get the next element which can have focus. + * @param {Element} elem + * @return {Element | null} nextElem + * @private + */ +Node.prototype._nextElement = function (elem) { + var dom = this.dom; + // noinspection FallthroughInSwitchStatementJS + switch (elem) { + case dom.drag: + return dom.menu; + case dom.menu: + if (this._hasChilds()) { + return dom.expand; + } + // intentional fall through + case dom.expand: + if (this.fieldEditable) { + return dom.field; + } + // intentional fall through + case dom.field: + if (!this._hasChilds()) { + return dom.value; + } + default: + return null; + } +}; + +/** + * Get the dom name of given element. returns null if not found. + * For example when element == dom.field, "field" is returned. + * @param {Element} element + * @return {String | null} elementName Available elements with name: 'drag', + * 'menu', 'expand', 'field', 'value' + * @private + */ +Node.prototype._getElementName = function (element) { + var dom = this.dom; + for (var name in dom) { + if (dom.hasOwnProperty(name)) { + if (dom[name] == element) { + return name; + } + } + } + return null; +}; + +/** + * Test if this node has childs. This is the case when the node is an object + * or array. + * @return {boolean} hasChilds + * @private + */ +Node.prototype._hasChilds = function () { + return this.type == 'array' || this.type == 'object'; +}; + +// titles with explanation for the different types +Node.TYPE_TITLES = { + 'auto': 'Field type "auto". ' + + 'The field type is automatically determined from the value ' + + 'and can be a string, number, boolean, or null.', + 'object': 'Field type "object". ' + + 'An object contains an unordered set of key/value pairs.', + 'array': 'Field type "array". ' + + 'An array contains an ordered collection of values.', + 'string': 'Field type "string". ' + + 'Field type is not determined from the value, ' + + 'but always returned as string.' +}; + +/** + * Show a contextmenu for this node + * @param {HTMLElement} anchor Anchor element to attach the context menu to + * as sibling. + * @param {function} [onClose] Callback method called when the context menu + * is being closed. + */ +Node.prototype.showContextMenu = function (anchor, onClose) { + var node = this; + var titles = Node.TYPE_TITLES; + var items = []; + + if (this.editable.value) { + items.push({ + text: 'Type', + title: 'Change the type of this field', + className: 'jsoneditor-type-' + this.type, + submenu: [ + { + text: 'Auto', + className: 'jsoneditor-type-auto' + + (this.type == 'auto' ? ' jsoneditor-selected' : ''), + title: titles.auto, + click: function () { + node._onChangeType('auto'); + } + }, + { + text: 'Array', + className: 'jsoneditor-type-array' + + (this.type == 'array' ? ' jsoneditor-selected' : ''), + title: titles.array, + click: function () { + node._onChangeType('array'); + } + }, + { + text: 'Object', + className: 'jsoneditor-type-object' + + (this.type == 'object' ? ' jsoneditor-selected' : ''), + title: titles.object, + click: function () { + node._onChangeType('object'); + } + }, + { + text: 'String', + className: 'jsoneditor-type-string' + + (this.type == 'string' ? ' jsoneditor-selected' : ''), + title: titles.string, + click: function () { + node._onChangeType('string'); + } + } + ] + }); + } + + if (this._hasChilds()) { + var direction = ((this.sortOrder == 'asc') ? 'desc': 'asc'); + items.push({ + text: 'Sort', + title: 'Sort the childs of this ' + this.type, + className: 'jsoneditor-sort-' + direction, + click: function () { + node.sort(direction); + }, + submenu: [ + { + text: 'Ascending', + className: 'jsoneditor-sort-asc', + title: 'Sort the childs of this ' + this.type + ' in ascending order', + click: function () { + node.sort('asc'); + } + }, + { + text: 'Descending', + className: 'jsoneditor-sort-desc', + title: 'Sort the childs of this ' + this.type +' in descending order', + click: function () { + node.sort('desc'); + } + } + ] + }); + } + + if (this.parent && this.parent._hasChilds()) { + if (items.length) { + // create a separator + items.push({ + 'type': 'separator' + }); + } + + // create append button (for last child node only) + var childs = node.parent.childs; + if (node == childs[childs.length - 1]) { + items.push({ + text: 'Append', + title: 'Append a new field with type \'auto\' after this field (Ctrl+Shift+Ins)', + submenuTitle: 'Select the type of the field to be appended', + className: 'jsoneditor-append', + click: function () { + node._onAppend('', '', 'auto'); + }, + submenu: [ + { + text: 'Auto', + className: 'jsoneditor-type-auto', + title: titles.auto, + click: function () { + node._onAppend('', '', 'auto'); + } + }, + { + text: 'Array', + className: 'jsoneditor-type-array', + title: titles.array, + click: function () { + node._onAppend('', []); + } + }, + { + text: 'Object', + className: 'jsoneditor-type-object', + title: titles.object, + click: function () { + node._onAppend('', {}); + } + }, + { + text: 'String', + className: 'jsoneditor-type-string', + title: titles.string, + click: function () { + node._onAppend('', '', 'string'); + } + } + ] + }); + } + + // create insert button + items.push({ + text: 'Insert', + title: 'Insert a new field with type \'auto\' before this field (Ctrl+Ins)', + submenuTitle: 'Select the type of the field to be inserted', + className: 'jsoneditor-insert', + click: function () { + node._onInsertBefore('', '', 'auto'); + }, + submenu: [ + { + text: 'Auto', + className: 'jsoneditor-type-auto', + title: titles.auto, + click: function () { + node._onInsertBefore('', '', 'auto'); + } + }, + { + text: 'Array', + className: 'jsoneditor-type-array', + title: titles.array, + click: function () { + node._onInsertBefore('', []); + } + }, + { + text: 'Object', + className: 'jsoneditor-type-object', + title: titles.object, + click: function () { + node._onInsertBefore('', {}); + } + }, + { + text: 'String', + className: 'jsoneditor-type-string', + title: titles.string, + click: function () { + node._onInsertBefore('', '', 'string'); + } + } + ] + }); + + if (this.editable.field) { + // create duplicate button + items.push({ + text: 'Duplicate', + title: 'Duplicate this field (Ctrl+D)', + className: 'jsoneditor-duplicate', + click: function () { + Node.onDuplicate(node); + } + }); + + // create remove button + items.push({ + text: 'Remove', + title: 'Remove this field (Ctrl+Del)', + className: 'jsoneditor-remove', + click: function () { + Node.onRemove(node); + } + }); + } + } + + var menu = new ContextMenu(items, {close: onClose}); + menu.show(anchor, this.editor.content); +}; + +/** + * get the type of a value + * @param {*} value + * @return {String} type Can be 'object', 'array', 'string', 'auto' + * @private + */ +Node.prototype._getType = function(value) { + if (value instanceof Array) { + return 'array'; + } + if (value instanceof Object) { + return 'object'; + } + if (typeof(value) == 'string' && typeof(this._stringCast(value)) != 'string') { + return 'string'; + } + + return 'auto'; +}; + +/** + * cast contents of a string to the correct type. This can be a string, + * a number, a boolean, etc + * @param {String} str + * @return {*} castedStr + * @private + */ +Node.prototype._stringCast = function(str) { + var lower = str.toLowerCase(), + num = Number(str), // will nicely fail with '123ab' + numFloat = parseFloat(str); // will nicely fail with ' ' + + if (str == '') { + return ''; + } + else if (lower == 'null') { + return null; + } + else if (lower == 'true') { + return true; + } + else if (lower == 'false') { + return false; + } + else if (!isNaN(num) && !isNaN(numFloat)) { + return num; + } + else { + return str; + } +}; + +/** + * escape a text, such that it can be displayed safely in an HTML element + * @param {String} text + * @return {String} escapedText + * @private + */ +Node.prototype._escapeHTML = function (text) { + if (typeof text !== 'string') { + return String(text); + } + else { + var htmlEscaped = String(text) + .replace(/&/g, '&') // must be replaced first! + .replace(//g, '>') + .replace(/ /g, '  ') // replace double space with an nbsp and space + .replace(/^ /, ' ') // space at start + .replace(/ $/, ' '); // space at end + + var json = JSON.stringify(htmlEscaped); + var html = json.substring(1, json.length - 1); + if (this.editor.options.escapeUnicode === true) { + html = util.escapeUnicodeChars(html); + } + return html; + } +}; + +/** + * unescape a string. + * @param {String} escapedText + * @return {String} text + * @private + */ +Node.prototype._unescapeHTML = function (escapedText) { + var json = '"' + this._escapeJSON(escapedText) + '"'; + var htmlEscaped = util.parse(json); + + return htmlEscaped + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/ |\u00A0/g, ' ') + .replace(/&/g, '&'); // must be replaced last +}; + +/** + * escape a text to make it a valid JSON string. The method will: + * - replace unescaped double quotes with '\"' + * - replace unescaped backslash with '\\' + * - replace returns with '\n' + * @param {String} text + * @return {String} escapedText + * @private + */ +Node.prototype._escapeJSON = function (text) { + // TODO: replace with some smart regex (only when a new solution is faster!) + var escaped = ''; + var i = 0; + while (i < text.length) { + var c = text.charAt(i); + if (c == '\n') { + escaped += '\\n'; + } + else if (c == '\\') { + escaped += c; + i++; + + c = text.charAt(i); + if (c === '' || '"\\/bfnrtu'.indexOf(c) == -1) { + escaped += '\\'; // no valid escape character + } + escaped += c; + } + else if (c == '"') { + escaped += '\\"'; + } + else { + escaped += c; + } + i++; + } + + return escaped; +}; + +// TODO: find a nicer solution to resolve this circular dependency between Node and AppendNode +var AppendNode = appendNodeFactory(Node); + +module.exports = Node; diff --git a/ui/app/bower_components/jsoneditor/src/js/SearchBox.js b/ui/app/bower_components/jsoneditor/src/js/SearchBox.js new file mode 100644 index 0000000..61ba943 --- /dev/null +++ b/ui/app/bower_components/jsoneditor/src/js/SearchBox.js @@ -0,0 +1,316 @@ +'use strict'; + +/** + * @constructor SearchBox + * Create a search box in given HTML container + * @param {JSONEditor} editor The JSON Editor to attach to + * @param {Element} container HTML container element of where to + * create the search box + */ +function SearchBox (editor, container) { + var searchBox = this; + + this.editor = editor; + this.timeout = undefined; + this.delay = 200; // ms + this.lastText = undefined; + + this.dom = {}; + this.dom.container = container; + + var table = document.createElement('table'); + this.dom.table = table; + table.className = 'jsoneditor-search'; + container.appendChild(table); + var tbody = document.createElement('tbody'); + this.dom.tbody = tbody; + table.appendChild(tbody); + var tr = document.createElement('tr'); + tbody.appendChild(tr); + + var td = document.createElement('td'); + tr.appendChild(td); + var results = document.createElement('div'); + this.dom.results = results; + results.className = 'jsoneditor-results'; + td.appendChild(results); + + td = document.createElement('td'); + tr.appendChild(td); + var divInput = document.createElement('div'); + this.dom.input = divInput; + divInput.className = 'jsoneditor-frame'; + divInput.title = 'Search fields and values'; + td.appendChild(divInput); + + // table to contain the text input and search button + var tableInput = document.createElement('table'); + divInput.appendChild(tableInput); + var tbodySearch = document.createElement('tbody'); + tableInput.appendChild(tbodySearch); + tr = document.createElement('tr'); + tbodySearch.appendChild(tr); + + var refreshSearch = document.createElement('button'); + refreshSearch.type = 'button'; + refreshSearch.className = 'jsoneditor-refresh'; + td = document.createElement('td'); + td.appendChild(refreshSearch); + tr.appendChild(td); + + var search = document.createElement('input'); + // search.type = 'button'; + this.dom.search = search; + search.oninput = function (event) { + searchBox._onDelayedSearch(event); + }; + search.onchange = function (event) { // For IE 9 + searchBox._onSearch(); + }; + search.onkeydown = function (event) { + searchBox._onKeyDown(event); + }; + search.onkeyup = function (event) { + searchBox._onKeyUp(event); + }; + refreshSearch.onclick = function (event) { + search.select(); + }; + + // TODO: ESC in FF restores the last input, is a FF bug, https://bugzilla.mozilla.org/show_bug.cgi?id=598819 + td = document.createElement('td'); + td.appendChild(search); + tr.appendChild(td); + + var searchNext = document.createElement('button'); + searchNext.type = 'button'; + searchNext.title = 'Next result (Enter)'; + searchNext.className = 'jsoneditor-next'; + searchNext.onclick = function () { + searchBox.next(); + }; + td = document.createElement('td'); + td.appendChild(searchNext); + tr.appendChild(td); + + var searchPrevious = document.createElement('button'); + searchPrevious.type = 'button'; + searchPrevious.title = 'Previous result (Shift+Enter)'; + searchPrevious.className = 'jsoneditor-previous'; + searchPrevious.onclick = function () { + searchBox.previous(); + }; + td = document.createElement('td'); + td.appendChild(searchPrevious); + tr.appendChild(td); +} + +/** + * Go to the next search result + * @param {boolean} [focus] If true, focus will be set to the next result + * focus is false by default. + */ +SearchBox.prototype.next = function(focus) { + if (this.results != undefined) { + var index = (this.resultIndex != undefined) ? this.resultIndex + 1 : 0; + if (index > this.results.length - 1) { + index = 0; + } + this._setActiveResult(index, focus); + } +}; + +/** + * Go to the prevous search result + * @param {boolean} [focus] If true, focus will be set to the next result + * focus is false by default. + */ +SearchBox.prototype.previous = function(focus) { + if (this.results != undefined) { + var max = this.results.length - 1; + var index = (this.resultIndex != undefined) ? this.resultIndex - 1 : max; + if (index < 0) { + index = max; + } + this._setActiveResult(index, focus); + } +}; + +/** + * Set new value for the current active result + * @param {Number} index + * @param {boolean} [focus] If true, focus will be set to the next result. + * focus is false by default. + * @private + */ +SearchBox.prototype._setActiveResult = function(index, focus) { + // de-activate current active result + if (this.activeResult) { + var prevNode = this.activeResult.node; + var prevElem = this.activeResult.elem; + if (prevElem == 'field') { + delete prevNode.searchFieldActive; + } + else { + delete prevNode.searchValueActive; + } + prevNode.updateDom(); + } + + if (!this.results || !this.results[index]) { + // out of range, set to undefined + this.resultIndex = undefined; + this.activeResult = undefined; + return; + } + + this.resultIndex = index; + + // set new node active + var node = this.results[this.resultIndex].node; + var elem = this.results[this.resultIndex].elem; + if (elem == 'field') { + node.searchFieldActive = true; + } + else { + node.searchValueActive = true; + } + this.activeResult = this.results[this.resultIndex]; + node.updateDom(); + + // TODO: not so nice that the focus is only set after the animation is finished + node.scrollTo(function () { + if (focus) { + node.focus(elem); + } + }); +}; + +/** + * Cancel any running onDelayedSearch. + * @private + */ +SearchBox.prototype._clearDelay = function() { + if (this.timeout != undefined) { + clearTimeout(this.timeout); + delete this.timeout; + } +}; + +/** + * Start a timer to execute a search after a short delay. + * Used for reducing the number of searches while typing. + * @param {Event} event + * @private + */ +SearchBox.prototype._onDelayedSearch = function (event) { + // execute the search after a short delay (reduces the number of + // search actions while typing in the search text box) + this._clearDelay(); + var searchBox = this; + this.timeout = setTimeout(function (event) { + searchBox._onSearch(); + }, + this.delay); +}; + +/** + * Handle onSearch event + * @param {boolean} [forceSearch] If true, search will be executed again even + * when the search text is not changed. + * Default is false. + * @private + */ +SearchBox.prototype._onSearch = function (forceSearch) { + this._clearDelay(); + + var value = this.dom.search.value; + var text = (value.length > 0) ? value : undefined; + if (text != this.lastText || forceSearch) { + // only search again when changed + this.lastText = text; + this.results = this.editor.search(text); + this._setActiveResult(undefined); + + // display search results + if (text != undefined) { + var resultCount = this.results.length; + switch (resultCount) { + case 0: this.dom.results.innerHTML = 'no results'; break; + case 1: this.dom.results.innerHTML = '1 result'; break; + default: this.dom.results.innerHTML = resultCount + ' results'; break; + } + } + else { + this.dom.results.innerHTML = ''; + } + } +}; + +/** + * Handle onKeyDown event in the input box + * @param {Event} event + * @private + */ +SearchBox.prototype._onKeyDown = function (event) { + var keynum = event.which; + if (keynum == 27) { // ESC + this.dom.search.value = ''; // clear search + this._onSearch(); + event.preventDefault(); + event.stopPropagation(); + } + else if (keynum == 13) { // Enter + if (event.ctrlKey) { + // force to search again + this._onSearch(true); + } + else if (event.shiftKey) { + // move to the previous search result + this.previous(); + } + else { + // move to the next search result + this.next(); + } + event.preventDefault(); + event.stopPropagation(); + } +}; + +/** + * Handle onKeyUp event in the input box + * @param {Event} event + * @private + */ +SearchBox.prototype._onKeyUp = function (event) { + var keynum = event.keyCode; + if (keynum != 27 && keynum != 13) { // !show and !Enter + this._onDelayedSearch(event); // For IE 9 + } +}; + +/** + * Clear the search results + */ +SearchBox.prototype.clear = function () { + this.dom.search.value = ''; + this._onSearch(); +}; + +/** + * Destroy the search box + */ +SearchBox.prototype.destroy = function () { + this.editor = null; + this.dom.container.removeChild(this.dom.table); + this.dom = null; + + this.results = null; + this.activeResult = null; + + this._clearDelay(); + +}; + +module.exports = SearchBox; diff --git a/ui/app/bower_components/jsoneditor/src/js/ace/index.js b/ui/app/bower_components/jsoneditor/src/js/ace/index.js new file mode 100644 index 0000000..846ae0a --- /dev/null +++ b/ui/app/bower_components/jsoneditor/src/js/ace/index.js @@ -0,0 +1,9 @@ +// load brace +var ace = require('brace'); + +// load required ace modules +require('brace/mode/json'); +require('brace/ext/searchbox'); +require('./theme-jsoneditor'); + +module.exports = ace; diff --git a/ui/app/bower_components/jsoneditor/src/js/ace/theme-jsoneditor.js b/ui/app/bower_components/jsoneditor/src/js/ace/theme-jsoneditor.js new file mode 100644 index 0000000..6cec3a6 --- /dev/null +++ b/ui/app/bower_components/jsoneditor/src/js/ace/theme-jsoneditor.js @@ -0,0 +1,144 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +ace.define('ace/theme/jsoneditor', ['require', 'exports', 'module', 'ace/lib/dom'], function(acequire, exports, module) { + +exports.isDark = false; +exports.cssClass = "ace-jsoneditor"; +exports.cssText = ".ace-jsoneditor .ace_gutter {\ +background: #ebebeb;\ +color: #333\ +}\ +\ +.ace-jsoneditor.ace_editor {\ +font-family: droid sans mono, consolas, monospace, courier new, courier, sans-serif;\ +line-height: 1.3;\ +}\ +.ace-jsoneditor .ace_print-margin {\ +width: 1px;\ +background: #e8e8e8\ +}\ +.ace-jsoneditor .ace_scroller {\ +background-color: #FFFFFF\ +}\ +.ace-jsoneditor .ace_text-layer {\ +color: gray\ +}\ +.ace-jsoneditor .ace_variable {\ +color: #1a1a1a\ +}\ +.ace-jsoneditor .ace_cursor {\ +border-left: 2px solid #000000\ +}\ +.ace-jsoneditor .ace_overwrite-cursors .ace_cursor {\ +border-left: 0px;\ +border-bottom: 1px solid #000000\ +}\ +.ace-jsoneditor .ace_marker-layer .ace_selection {\ +background: lightgray\ +}\ +.ace-jsoneditor.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px #FFFFFF;\ +border-radius: 2px\ +}\ +.ace-jsoneditor .ace_marker-layer .ace_step {\ +background: rgb(255, 255, 0)\ +}\ +.ace-jsoneditor .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid #BFBFBF\ +}\ +.ace-jsoneditor .ace_marker-layer .ace_active-line {\ +background: #FFFBD1\ +}\ +.ace-jsoneditor .ace_gutter-active-line {\ +background-color : #dcdcdc\ +}\ +.ace-jsoneditor .ace_marker-layer .ace_selected-word {\ +border: 1px solid lightgray\ +}\ +.ace-jsoneditor .ace_invisible {\ +color: #BFBFBF\ +}\ +.ace-jsoneditor .ace_keyword,\ +.ace-jsoneditor .ace_meta,\ +.ace-jsoneditor .ace_support.ace_constant.ace_property-value {\ +color: #AF956F\ +}\ +.ace-jsoneditor .ace_keyword.ace_operator {\ +color: #484848\ +}\ +.ace-jsoneditor .ace_keyword.ace_other.ace_unit {\ +color: #96DC5F\ +}\ +.ace-jsoneditor .ace_constant.ace_language {\ +color: darkorange\ +}\ +.ace-jsoneditor .ace_constant.ace_numeric {\ +color: red\ +}\ +.ace-jsoneditor .ace_constant.ace_character.ace_entity {\ +color: #BF78CC\ +}\ +.ace-jsoneditor .ace_invalid {\ +color: #FFFFFF;\ +background-color: #FF002A;\ +}\ +.ace-jsoneditor .ace_fold {\ +background-color: #AF956F;\ +border-color: #000000\ +}\ +.ace-jsoneditor .ace_storage,\ +.ace-jsoneditor .ace_support.ace_class,\ +.ace-jsoneditor .ace_support.ace_function,\ +.ace-jsoneditor .ace_support.ace_other,\ +.ace-jsoneditor .ace_support.ace_type {\ +color: #C52727\ +}\ +.ace-jsoneditor .ace_string {\ +color: green\ +}\ +.ace-jsoneditor .ace_comment {\ +color: #BCC8BA\ +}\ +.ace-jsoneditor .ace_entity.ace_name.ace_tag,\ +.ace-jsoneditor .ace_entity.ace_other.ace_attribute-name {\ +color: #606060\ +}\ +.ace-jsoneditor .ace_markup.ace_underline {\ +text-decoration: underline\ +}\ +.ace-jsoneditor .ace_indent-guide {\ +background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y\ +}"; + +var dom = acequire("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/ui/app/bower_components/jsoneditor/src/js/appendNodeFactory.js b/ui/app/bower_components/jsoneditor/src/js/appendNodeFactory.js new file mode 100644 index 0000000..494dcb6 --- /dev/null +++ b/ui/app/bower_components/jsoneditor/src/js/appendNodeFactory.js @@ -0,0 +1,229 @@ +'use strict'; + +var util = require('./util'); +var ContextMenu = require('./ContextMenu'); + +/** + * A factory function to create an AppendNode, which depends on a Node + * @param {Node} Node + */ +function appendNodeFactory(Node) { + /** + * @constructor AppendNode + * @extends Node + * @param {TreeEditor} editor + * Create a new AppendNode. This is a special node which is created at the + * end of the list with childs for an object or array + */ + function AppendNode (editor) { + /** @type {TreeEditor} */ + this.editor = editor; + this.dom = {}; + } + + AppendNode.prototype = new Node(); + + /** + * Return a table row with an append button. + * @return {Element} dom TR element + */ + AppendNode.prototype.getDom = function () { + // TODO: implement a new solution for the append node + var dom = this.dom; + + if (dom.tr) { + return dom.tr; + } + + this._updateEditability(); + + // a row for the append button + var trAppend = document.createElement('tr'); + trAppend.node = this; + dom.tr = trAppend; + + // TODO: consistent naming + + if (this.editor.options.mode === 'tree') { + // a cell for the dragarea column + dom.tdDrag = document.createElement('td'); + + // create context menu + var tdMenu = document.createElement('td'); + dom.tdMenu = tdMenu; + var menu = document.createElement('button'); + menu.type = 'button'; + menu.className = 'jsoneditor-contextmenu'; + menu.title = 'Click to open the actions menu (Ctrl+M)'; + dom.menu = menu; + tdMenu.appendChild(dom.menu); + } + + // a cell for the contents (showing text 'empty') + var tdAppend = document.createElement('td'); + var domText = document.createElement('div'); + domText.innerHTML = '(empty)'; + domText.className = 'jsoneditor-readonly'; + tdAppend.appendChild(domText); + dom.td = tdAppend; + dom.text = domText; + + this.updateDom(); + + return trAppend; + }; + + /** + * Update the HTML dom of the Node + */ + AppendNode.prototype.updateDom = function () { + var dom = this.dom; + var tdAppend = dom.td; + if (tdAppend) { + tdAppend.style.paddingLeft = (this.getLevel() * 24 + 26) + 'px'; + // TODO: not so nice hard coded offset + } + + var domText = dom.text; + if (domText) { + domText.innerHTML = '(empty ' + this.parent.type + ')'; + } + + // attach or detach the contents of the append node: + // hide when the parent has childs, show when the parent has no childs + var trAppend = dom.tr; + if (!this.isVisible()) { + if (dom.tr.firstChild) { + if (dom.tdDrag) { + trAppend.removeChild(dom.tdDrag); + } + if (dom.tdMenu) { + trAppend.removeChild(dom.tdMenu); + } + trAppend.removeChild(tdAppend); + } + } + else { + if (!dom.tr.firstChild) { + if (dom.tdDrag) { + trAppend.appendChild(dom.tdDrag); + } + if (dom.tdMenu) { + trAppend.appendChild(dom.tdMenu); + } + trAppend.appendChild(tdAppend); + } + } + }; + + /** + * Check whether the AppendNode is currently visible. + * the AppendNode is visible when its parent has no childs (i.e. is empty). + * @return {boolean} isVisible + */ + AppendNode.prototype.isVisible = function () { + return (this.parent.childs.length == 0); + }; + + /** + * Show a contextmenu for this node + * @param {HTMLElement} anchor The element to attach the menu to. + * @param {function} [onClose] Callback method called when the context menu + * is being closed. + */ + AppendNode.prototype.showContextMenu = function (anchor, onClose) { + var node = this; + var titles = Node.TYPE_TITLES; + var items = [ + // create append button + { + 'text': 'Append', + 'title': 'Append a new field with type \'auto\' (Ctrl+Shift+Ins)', + 'submenuTitle': 'Select the type of the field to be appended', + 'className': 'jsoneditor-insert', + 'click': function () { + node._onAppend('', '', 'auto'); + }, + 'submenu': [ + { + 'text': 'Auto', + 'className': 'jsoneditor-type-auto', + 'title': titles.auto, + 'click': function () { + node._onAppend('', '', 'auto'); + } + }, + { + 'text': 'Array', + 'className': 'jsoneditor-type-array', + 'title': titles.array, + 'click': function () { + node._onAppend('', []); + } + }, + { + 'text': 'Object', + 'className': 'jsoneditor-type-object', + 'title': titles.object, + 'click': function () { + node._onAppend('', {}); + } + }, + { + 'text': 'String', + 'className': 'jsoneditor-type-string', + 'title': titles.string, + 'click': function () { + node._onAppend('', '', 'string'); + } + } + ] + } + ]; + + var menu = new ContextMenu(items, {close: onClose}); + menu.show(anchor, this.editor.content); + }; + + /** + * Handle an event. The event is catched centrally by the editor + * @param {Event} event + */ + AppendNode.prototype.onEvent = function (event) { + var type = event.type; + var target = event.target || event.srcElement; + var dom = this.dom; + + // highlight the append nodes parent + var menu = dom.menu; + if (target == menu) { + if (type == 'mouseover') { + this.editor.highlighter.highlight(this.parent); + } + else if (type == 'mouseout') { + this.editor.highlighter.unhighlight(); + } + } + + // context menu events + if (type == 'click' && target == dom.menu) { + var highlighter = this.editor.highlighter; + highlighter.highlight(this.parent); + highlighter.lock(); + util.addClassName(dom.menu, 'jsoneditor-selected'); + this.showContextMenu(dom.menu, function () { + util.removeClassName(dom.menu, 'jsoneditor-selected'); + highlighter.unlock(); + highlighter.unhighlight(); + }); + } + + if (type == 'keydown') { + this.onKeyDown(event); + } + }; + + return AppendNode; +} + +module.exports = appendNodeFactory; diff --git a/ui/app/bower_components/jsoneditor/src/js/assets/jsonlint/README.md b/ui/app/bower_components/jsoneditor/src/js/assets/jsonlint/README.md new file mode 100644 index 0000000..ae26ff6 --- /dev/null +++ b/ui/app/bower_components/jsoneditor/src/js/assets/jsonlint/README.md @@ -0,0 +1,15 @@ +The file jsonlint.js is copied from the following project: + +https://github.com/josdejong/jsonlint at 85a19d7 + +which is a fork of the (currently not maintained) project: + +https://github.com/zaach/jsonlint + +The forked project contains some fixes to allow the file to be bundled with +browserify. The file is copied in this project to prevent issues with linking +to a github project from package.json, which is for example not supported +by jspm. + +As soon as zaach/jsonlint is being maintained again we can push the fix +to the original library and use it as dependency again. diff --git a/ui/app/bower_components/jsoneditor/src/js/assets/jsonlint/jsonlint.js b/ui/app/bower_components/jsoneditor/src/js/assets/jsonlint/jsonlint.js new file mode 100644 index 0000000..ae9b2f4 --- /dev/null +++ b/ui/app/bower_components/jsoneditor/src/js/assets/jsonlint/jsonlint.js @@ -0,0 +1,418 @@ +/* Jison generated parser */ +var jsonlint = (function(){ +var parser = {trace: function trace() { }, +yy: {}, +symbols_: {"error":2,"JSONString":3,"STRING":4,"JSONNumber":5,"NUMBER":6,"JSONNullLiteral":7,"NULL":8,"JSONBooleanLiteral":9,"TRUE":10,"FALSE":11,"JSONText":12,"JSONValue":13,"EOF":14,"JSONObject":15,"JSONArray":16,"{":17,"}":18,"JSONMemberList":19,"JSONMember":20,":":21,",":22,"[":23,"]":24,"JSONElementList":25,"$accept":0,"$end":1}, +terminals_: {2:"error",4:"STRING",6:"NUMBER",8:"NULL",10:"TRUE",11:"FALSE",14:"EOF",17:"{",18:"}",21:":",22:",",23:"[",24:"]"}, +productions_: [0,[3,1],[5,1],[7,1],[9,1],[9,1],[12,2],[13,1],[13,1],[13,1],[13,1],[13,1],[13,1],[15,2],[15,3],[20,3],[19,1],[19,3],[16,2],[16,3],[25,1],[25,3]], +performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) { + +var $0 = $$.length - 1; +switch (yystate) { +case 1: // replace escaped characters with actual character + this.$ = yytext.replace(/\\(\\|")/g, "$"+"1") + .replace(/\\n/g,'\n') + .replace(/\\r/g,'\r') + .replace(/\\t/g,'\t') + .replace(/\\v/g,'\v') + .replace(/\\f/g,'\f') + .replace(/\\b/g,'\b'); + +break; +case 2:this.$ = Number(yytext); +break; +case 3:this.$ = null; +break; +case 4:this.$ = true; +break; +case 5:this.$ = false; +break; +case 6:return this.$ = $$[$0-1]; +break; +case 13:this.$ = {}; +break; +case 14:this.$ = $$[$0-1]; +break; +case 15:this.$ = [$$[$0-2], $$[$0]]; +break; +case 16:this.$ = {}; this.$[$$[$0][0]] = $$[$0][1]; +break; +case 17:this.$ = $$[$0-2]; $$[$0-2][$$[$0][0]] = $$[$0][1]; +break; +case 18:this.$ = []; +break; +case 19:this.$ = $$[$0-1]; +break; +case 20:this.$ = [$$[$0]]; +break; +case 21:this.$ = $$[$0-2]; $$[$0-2].push($$[$0]); +break; +} +}, +table: [{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],12:1,13:2,15:7,16:8,17:[1,14],23:[1,15]},{1:[3]},{14:[1,16]},{14:[2,7],18:[2,7],22:[2,7],24:[2,7]},{14:[2,8],18:[2,8],22:[2,8],24:[2,8]},{14:[2,9],18:[2,9],22:[2,9],24:[2,9]},{14:[2,10],18:[2,10],22:[2,10],24:[2,10]},{14:[2,11],18:[2,11],22:[2,11],24:[2,11]},{14:[2,12],18:[2,12],22:[2,12],24:[2,12]},{14:[2,3],18:[2,3],22:[2,3],24:[2,3]},{14:[2,4],18:[2,4],22:[2,4],24:[2,4]},{14:[2,5],18:[2,5],22:[2,5],24:[2,5]},{14:[2,1],18:[2,1],21:[2,1],22:[2,1],24:[2,1]},{14:[2,2],18:[2,2],22:[2,2],24:[2,2]},{3:20,4:[1,12],18:[1,17],19:18,20:19},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:23,15:7,16:8,17:[1,14],23:[1,15],24:[1,21],25:22},{1:[2,6]},{14:[2,13],18:[2,13],22:[2,13],24:[2,13]},{18:[1,24],22:[1,25]},{18:[2,16],22:[2,16]},{21:[1,26]},{14:[2,18],18:[2,18],22:[2,18],24:[2,18]},{22:[1,28],24:[1,27]},{22:[2,20],24:[2,20]},{14:[2,14],18:[2,14],22:[2,14],24:[2,14]},{3:20,4:[1,12],20:29},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:30,15:7,16:8,17:[1,14],23:[1,15]},{14:[2,19],18:[2,19],22:[2,19],24:[2,19]},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:31,15:7,16:8,17:[1,14],23:[1,15]},{18:[2,17],22:[2,17]},{18:[2,15],22:[2,15]},{22:[2,21],24:[2,21]}], +defaultActions: {16:[2,6]}, +parseError: function parseError(str, hash) { + throw new Error(str); +}, +parse: function parse(input) { + var self = this, + stack = [0], + vstack = [null], // semantic value stack + lstack = [], // location stack + table = this.table, + yytext = '', + yylineno = 0, + yyleng = 0, + recovering = 0, + TERROR = 2, + EOF = 1; + + //this.reductionCount = this.shiftCount = 0; + + this.lexer.setInput(input); + this.lexer.yy = this.yy; + this.yy.lexer = this.lexer; + if (typeof this.lexer.yylloc == 'undefined') + this.lexer.yylloc = {}; + var yyloc = this.lexer.yylloc; + lstack.push(yyloc); + + if (typeof this.yy.parseError === 'function') + this.parseError = this.yy.parseError; + + function popStack (n) { + stack.length = stack.length - 2*n; + vstack.length = vstack.length - n; + lstack.length = lstack.length - n; + } + + function lex() { + var token; + token = self.lexer.lex() || 1; // $end = 1 + // if token isn't its numeric value, convert + if (typeof token !== 'number') { + token = self.symbols_[token] || token; + } + return token; + } + + var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected; + while (true) { + // retreive state number from top of stack + state = stack[stack.length-1]; + + // use default actions if available + if (this.defaultActions[state]) { + action = this.defaultActions[state]; + } else { + if (symbol == null) + symbol = lex(); + // read action for current state and first input + action = table[state] && table[state][symbol]; + } + + // handle parse error + _handle_error: + if (typeof action === 'undefined' || !action.length || !action[0]) { + + if (!recovering) { + // Report error + expected = []; + for (p in table[state]) if (this.terminals_[p] && p > 2) { + expected.push("'"+this.terminals_[p]+"'"); + } + var errStr = ''; + if (this.lexer.showPosition) { + errStr = 'Parse error on line '+(yylineno+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+expected.join(', ') + ", got '" + this.terminals_[symbol]+ "'"; + } else { + errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " + + (symbol == 1 /*EOF*/ ? "end of input" : + ("'"+(this.terminals_[symbol] || symbol)+"'")); + } + this.parseError(errStr, + {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected}); + } + + // just recovered from another error + if (recovering == 3) { + if (symbol == EOF) { + throw new Error(errStr || 'Parsing halted.'); + } + + // discard current lookahead and grab another + yyleng = this.lexer.yyleng; + yytext = this.lexer.yytext; + yylineno = this.lexer.yylineno; + yyloc = this.lexer.yylloc; + symbol = lex(); + } + + // try to recover from error + while (1) { + // check for error recovery rule in this state + if ((TERROR.toString()) in table[state]) { + break; + } + if (state == 0) { + throw new Error(errStr || 'Parsing halted.'); + } + popStack(1); + state = stack[stack.length-1]; + } + + preErrorSymbol = symbol; // save the lookahead token + symbol = TERROR; // insert generic error symbol as new lookahead + state = stack[stack.length-1]; + action = table[state] && table[state][TERROR]; + recovering = 3; // allow 3 real symbols to be shifted before reporting a new error + } + + // this shouldn't happen, unless resolve defaults are off + if (action[0] instanceof Array && action.length > 1) { + throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol); + } + + switch (action[0]) { + + case 1: // shift + //this.shiftCount++; + + stack.push(symbol); + vstack.push(this.lexer.yytext); + lstack.push(this.lexer.yylloc); + stack.push(action[1]); // push state + symbol = null; + if (!preErrorSymbol) { // normal execution/no error + yyleng = this.lexer.yyleng; + yytext = this.lexer.yytext; + yylineno = this.lexer.yylineno; + yyloc = this.lexer.yylloc; + if (recovering > 0) + recovering--; + } else { // error just occurred, resume old lookahead f/ before error + symbol = preErrorSymbol; + preErrorSymbol = null; + } + break; + + case 2: // reduce + //this.reductionCount++; + + len = this.productions_[action[1]][1]; + + // perform semantic action + yyval.$ = vstack[vstack.length-len]; // default to $$ = $1 + // default location, uses first token for firsts, last for lasts + yyval._$ = { + first_line: lstack[lstack.length-(len||1)].first_line, + last_line: lstack[lstack.length-1].last_line, + first_column: lstack[lstack.length-(len||1)].first_column, + last_column: lstack[lstack.length-1].last_column + }; + r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); + + if (typeof r !== 'undefined') { + return r; + } + + // pop off stack + if (len) { + stack = stack.slice(0,-1*len*2); + vstack = vstack.slice(0, -1*len); + lstack = lstack.slice(0, -1*len); + } + + stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce) + vstack.push(yyval.$); + lstack.push(yyval._$); + // goto new state = table[STATE][NONTERMINAL] + newState = table[stack[stack.length-2]][stack[stack.length-1]]; + stack.push(newState); + break; + + case 3: // accept + return true; + } + + } + + return true; +}}; +/* Jison generated lexer */ +var lexer = (function(){ +var lexer = ({EOF:1, +parseError:function parseError(str, hash) { + if (this.yy.parseError) { + this.yy.parseError(str, hash); + } else { + throw new Error(str); + } + }, +setInput:function (input) { + this._input = input; + this._more = this._less = this.done = false; + this.yylineno = this.yyleng = 0; + this.yytext = this.matched = this.match = ''; + this.conditionStack = ['INITIAL']; + this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0}; + return this; + }, +input:function () { + var ch = this._input[0]; + this.yytext+=ch; + this.yyleng++; + this.match+=ch; + this.matched+=ch; + var lines = ch.match(/\n/); + if (lines) this.yylineno++; + this._input = this._input.slice(1); + return ch; + }, +unput:function (ch) { + this._input = ch + this._input; + return this; + }, +more:function () { + this._more = true; + return this; + }, +less:function (n) { + this._input = this.match.slice(n) + this._input; + }, +pastInput:function () { + var past = this.matched.substr(0, this.matched.length - this.match.length); + return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, ""); + }, +upcomingInput:function () { + var next = this.match; + if (next.length < 20) { + next += this._input.substr(0, 20-next.length); + } + return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, ""); + }, +showPosition:function () { + var pre = this.pastInput(); + var c = new Array(pre.length + 1).join("-"); + return pre + this.upcomingInput() + "\n" + c+"^"; + }, +next:function () { + if (this.done) { + return this.EOF; + } + if (!this._input) this.done = true; + + var token, + match, + tempMatch, + index, + col, + lines; + if (!this._more) { + this.yytext = ''; + this.match = ''; + } + var rules = this._currentRules(); + for (var i=0;i < rules.length; i++) { + tempMatch = this._input.match(this.rules[rules[i]]); + if (tempMatch && (!match || tempMatch[0].length > match[0].length)) { + match = tempMatch; + index = i; + if (!this.options.flex) break; + } + } + if (match) { + lines = match[0].match(/\n.*/g); + if (lines) this.yylineno += lines.length; + this.yylloc = {first_line: this.yylloc.last_line, + last_line: this.yylineno+1, + first_column: this.yylloc.last_column, + last_column: lines ? lines[lines.length-1].length-1 : this.yylloc.last_column + match[0].length} + this.yytext += match[0]; + this.match += match[0]; + this.yyleng = this.yytext.length; + this._more = false; + this._input = this._input.slice(match[0].length); + this.matched += match[0]; + token = this.performAction.call(this, this.yy, this, rules[index],this.conditionStack[this.conditionStack.length-1]); + if (this.done && this._input) this.done = false; + if (token) return token; + else return; + } + if (this._input === "") { + return this.EOF; + } else { + this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(), + {text: "", token: null, line: this.yylineno}); + } + }, +lex:function lex() { + var r = this.next(); + if (typeof r !== 'undefined') { + return r; + } else { + return this.lex(); + } + }, +begin:function begin(condition) { + this.conditionStack.push(condition); + }, +popState:function popState() { + return this.conditionStack.pop(); + }, +_currentRules:function _currentRules() { + return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules; + }, +topState:function () { + return this.conditionStack[this.conditionStack.length-2]; + }, +pushState:function begin(condition) { + this.begin(condition); + }}); +lexer.options = {}; +lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) { + +var YYSTATE=YY_START +switch($avoiding_name_collisions) { +case 0:/* skip whitespace */ +break; +case 1:return 6 +break; +case 2:yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2); return 4 +break; +case 3:return 17 +break; +case 4:return 18 +break; +case 5:return 23 +break; +case 6:return 24 +break; +case 7:return 22 +break; +case 8:return 21 +break; +case 9:return 10 +break; +case 10:return 11 +break; +case 11:return 8 +break; +case 12:return 14 +break; +case 13:return 'INVALID' +break; +} +}; +lexer.rules = [/^(?:\s+)/,/^(?:(-?([0-9]|[1-9][0-9]+))(\.[0-9]+)?([eE][-+]?[0-9]+)?\b)/,/^(?:"(?:\\[\\"bfnrt/]|\\u[a-fA-F0-9]{4}|[^\\\0-\x09\x0a-\x1f"])*")/,/^(?:\{)/,/^(?:\})/,/^(?:\[)/,/^(?:\])/,/^(?:,)/,/^(?::)/,/^(?:true\b)/,/^(?:false\b)/,/^(?:null\b)/,/^(?:$)/,/^(?:.)/]; +lexer.conditions = {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13],"inclusive":true}}; + + +; +return lexer;})() +parser.lexer = lexer; +return parser; +})(); +if (typeof require !== 'undefined' && typeof exports !== 'undefined') { + exports.parser = jsonlint; + exports.parse = jsonlint.parse.bind(jsonlint); +} \ No newline at end of file diff --git a/ui/app/bower_components/jsoneditor/src/js/header.js b/ui/app/bower_components/jsoneditor/src/js/header.js new file mode 100644 index 0000000..52ef8d3 --- /dev/null +++ b/ui/app/bower_components/jsoneditor/src/js/header.js @@ -0,0 +1,29 @@ +/*! + * jsoneditor.js + * + * @brief + * JSONEditor is a web-based tool to view, edit, format, and validate JSON. + * It has various modes such as a tree editor, a code editor, and a plain text + * editor. + * + * Supported browsers: Chrome, Firefox, Safari, Opera, Internet Explorer 8+ + * + * @license + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + * + * Copyright (c) 2011-2016 Jos de Jong, http://jsoneditoronline.org + * + * @author Jos de Jong, + * @version @@version + * @date @@date + */ \ No newline at end of file diff --git a/ui/app/bower_components/jsoneditor/src/js/textmode.js b/ui/app/bower_components/jsoneditor/src/js/textmode.js new file mode 100644 index 0000000..eba801f --- /dev/null +++ b/ui/app/bower_components/jsoneditor/src/js/textmode.js @@ -0,0 +1,491 @@ +'use strict'; + +var ace; +try { + ace = require('./ace'); +} +catch (err) { + // failed to load ace, no problem, we will fall back to plain text +} + +var ModeSwitcher = require('./ModeSwitcher'); +var util = require('./util'); + +// create a mixin with the functions for text mode +var textmode = {}; + +var MAX_ERRORS = 3; // maximum number of displayed errors at the bottom + +/** + * Create a text editor + * @param {Element} container + * @param {Object} [options] Object with options. available options: + * {String} mode Available values: + * "text" (default) + * or "code". + * {Number} indentation Number of indentation + * spaces. 2 by default. + * {function} onChange Callback method + * triggered on change + * {function} onModeChange Callback method + * triggered after setMode + * {Object} ace A custom instance of + * Ace editor. + * {boolean} escapeUnicode If true, unicode + * characters are escaped. + * false by default. + * @private + */ +textmode.create = function (container, options) { + // read options + options = options || {}; + this.options = options; + + // indentation + if (options.indentation) { + this.indentation = Number(options.indentation); + } + else { + this.indentation = 2; // number of spaces + } + + // grab ace from options if provided + var _ace = options.ace ? options.ace : ace; + + // determine mode + this.mode = (options.mode == 'code') ? 'code' : 'text'; + if (this.mode == 'code') { + // verify whether Ace editor is available and supported + if (typeof _ace === 'undefined') { + this.mode = 'text'; + console.warn('Failed to load Ace editor, falling back to plain text mode. Please use a JSONEditor bundle including Ace, or pass Ace as via the configuration option `ace`.'); + } + } + + // determine theme + this.theme = options.theme || 'ace/theme/jsoneditor'; + + var me = this; + this.container = container; + this.dom = {}; + this.aceEditor = undefined; // ace code editor + this.textarea = undefined; // plain text editor (fallback when Ace is not available) + this.validateSchema = null; + + // create a debounced validate function + this._debouncedValidate = util.debounce(this.validate.bind(this), this.DEBOUNCE_INTERVAL); + + this.width = container.clientWidth; + this.height = container.clientHeight; + + this.frame = document.createElement('div'); + this.frame.className = 'jsoneditor jsoneditor-mode-' + this.options.mode; + this.frame.onclick = function (event) { + // prevent default submit action when the editor is located inside a form + event.preventDefault(); + }; + this.frame.onkeydown = function (event) { + me._onKeyDown(event); + }; + + // create menu + this.menu = document.createElement('div'); + this.menu.className = 'jsoneditor-menu'; + this.frame.appendChild(this.menu); + + // create format button + var buttonFormat = document.createElement('button'); + buttonFormat.type = 'button'; + buttonFormat.className = 'jsoneditor-format'; + buttonFormat.title = 'Format JSON data, with proper indentation and line feeds (Ctrl+\\)'; + this.menu.appendChild(buttonFormat); + buttonFormat.onclick = function () { + try { + me.format(); + me._onChange(); + } + catch (err) { + me._onError(err); + } + }; + + // create compact button + var buttonCompact = document.createElement('button'); + buttonCompact.type = 'button'; + buttonCompact.className = 'jsoneditor-compact'; + buttonCompact.title = 'Compact JSON data, remove all whitespaces (Ctrl+Shift+\\)'; + this.menu.appendChild(buttonCompact); + buttonCompact.onclick = function () { + try { + me.compact(); + me._onChange(); + } + catch (err) { + me._onError(err); + } + }; + + // create mode box + if (this.options && this.options.modes && this.options.modes.length) { + this.modeSwitcher = new ModeSwitcher(this.menu, this.options.modes, this.options.mode, function onSwitch(mode) { + // switch mode and restore focus + me.setMode(mode); + me.modeSwitcher.focus(); + }); + } + + this.content = document.createElement('div'); + this.content.className = 'jsoneditor-outer'; + this.frame.appendChild(this.content); + + this.container.appendChild(this.frame); + + if (this.mode == 'code') { + this.editorDom = document.createElement('div'); + this.editorDom.style.height = '100%'; // TODO: move to css + this.editorDom.style.width = '100%'; // TODO: move to css + this.content.appendChild(this.editorDom); + + var aceEditor = _ace.edit(this.editorDom); + aceEditor.$blockScrolling = Infinity; + aceEditor.setTheme(this.theme); + aceEditor.setShowPrintMargin(false); + aceEditor.setFontSize(13); + aceEditor.getSession().setMode('ace/mode/json'); + aceEditor.getSession().setTabSize(this.indentation); + aceEditor.getSession().setUseSoftTabs(true); + aceEditor.getSession().setUseWrapMode(true); + aceEditor.commands.bindKey('Ctrl-L', null); // disable Ctrl+L (is used by the browser to select the address bar) + aceEditor.commands.bindKey('Command-L', null); // disable Ctrl+L (is used by the browser to select the address bar) + this.aceEditor = aceEditor; + + // TODO: deprecated since v5.0.0. Cleanup backward compatibility some day + if (!this.hasOwnProperty('editor')) { + Object.defineProperty(this, 'editor', { + get: function () { + console.warn('Property "editor" has been renamed to "aceEditor".'); + return me.aceEditor; + }, + set: function (aceEditor) { + console.warn('Property "editor" has been renamed to "aceEditor".'); + me.aceEditor = aceEditor; + } + }); + } + + var poweredBy = document.createElement('a'); + poweredBy.appendChild(document.createTextNode('powered by ace')); + poweredBy.href = 'http://ace.ajax.org'; + poweredBy.target = '_blank'; + poweredBy.className = 'jsoneditor-poweredBy'; + poweredBy.onclick = function () { + // TODO: this anchor falls below the margin of the content, + // therefore the normal a.href does not work. We use a click event + // for now, but this should be fixed. + window.open(poweredBy.href, poweredBy.target); + }; + this.menu.appendChild(poweredBy); + + // register onchange event + aceEditor.on('change', this._onChange.bind(this)); + } + else { + // load a plain text textarea + var textarea = document.createElement('textarea'); + textarea.className = 'jsoneditor-text'; + textarea.spellcheck = false; + this.content.appendChild(textarea); + this.textarea = textarea; + + // register onchange event + if (this.textarea.oninput === null) { + this.textarea.oninput = this._onChange.bind(this); + } + else { + // oninput is undefined. For IE8- + this.textarea.onchange = this._onChange.bind(this); + } + } + + this.setSchema(this.options.schema); +}; + +/** + * Handle a change: + * - Validate JSON schema + * - Send a callback to the onChange listener if provided + * @private + */ +textmode._onChange = function () { + // validate JSON schema (if configured) + this._debouncedValidate(); + + // trigger the onChange callback + if (this.options.onChange) { + try { + this.options.onChange(); + } + catch (err) { + console.error('Error in onChange callback: ', err); + } + } +}; + +/** + * Event handler for keydown. Handles shortcut keys + * @param {Event} event + * @private + */ +textmode._onKeyDown = function (event) { + var keynum = event.which || event.keyCode; + var handled = false; + + if (keynum == 220 && event.ctrlKey) { + if (event.shiftKey) { // Ctrl+Shift+\ + this.compact(); + this._onChange(); + } + else { // Ctrl+\ + this.format(); + this._onChange(); + } + handled = true; + } + + if (handled) { + event.preventDefault(); + event.stopPropagation(); + } +}; + +/** + * Destroy the editor. Clean up DOM, event listeners, and web workers. + */ +textmode.destroy = function () { + // remove old ace editor + if (this.aceEditor) { + this.aceEditor.destroy(); + this.aceEditor = null; + } + + if (this.frame && this.container && this.frame.parentNode == this.container) { + this.container.removeChild(this.frame); + } + + if (this.modeSwitcher) { + this.modeSwitcher.destroy(); + this.modeSwitcher = null; + } + + this.textarea = null; + + this._debouncedValidate = null; +}; + +/** + * Compact the code in the formatter + */ +textmode.compact = function () { + var json = this.get(); + var text = JSON.stringify(json); + this.setText(text); +}; + +/** + * Format the code in the formatter + */ +textmode.format = function () { + var json = this.get(); + var text = JSON.stringify(json, null, this.indentation); + this.setText(text); +}; + +/** + * Set focus to the formatter + */ +textmode.focus = function () { + if (this.textarea) { + this.textarea.focus(); + } + if (this.aceEditor) { + this.aceEditor.focus(); + } +}; + +/** + * Resize the formatter + */ +textmode.resize = function () { + if (this.aceEditor) { + var force = false; + this.aceEditor.resize(force); + } +}; + +/** + * Set json data in the formatter + * @param {Object} json + */ +textmode.set = function(json) { + this.setText(JSON.stringify(json, null, this.indentation)); +}; + +/** + * Get json data from the formatter + * @return {Object} json + */ +textmode.get = function() { + var text = this.getText(); + var json; + + try { + json = util.parse(text); // this can throw an error + } + catch (err) { + // try to sanitize json, replace JavaScript notation with JSON notation + text = util.sanitize(text); + + // try to parse again + json = util.parse(text); // this can throw an error + } + + return json; +}; + +/** + * Get the text contents of the editor + * @return {String} jsonText + */ +textmode.getText = function() { + if (this.textarea) { + return this.textarea.value; + } + if (this.aceEditor) { + return this.aceEditor.getValue(); + } + return ''; +}; + +/** + * Set the text contents of the editor + * @param {String} jsonText + */ +textmode.setText = function(jsonText) { + var text; + + if (this.options.escapeUnicode === true) { + text = util.escapeUnicodeChars(jsonText); + } + else { + text = jsonText; + } + + if (this.textarea) { + this.textarea.value = text; + } + if (this.aceEditor) { + // prevent emitting onChange events while setting new text + var originalOnChange = this.options.onChange; + this.options.onChange = null; + + this.aceEditor.setValue(text, -1); + + this.options.onChange = originalOnChange; + } + + // validate JSON schema + this.validate(); +}; + +/** + * Validate current JSON object against the configured JSON schema + * Throws an exception when no JSON schema is configured + */ +textmode.validate = function () { + // clear all current errors + if (this.dom.validationErrors) { + this.dom.validationErrors.parentNode.removeChild(this.dom.validationErrors); + this.dom.validationErrors = null; + + this.content.style.marginBottom = ''; + this.content.style.paddingBottom = ''; + } + + var doValidate = false; + var errors = []; + var json; + try { + json = this.get(); // this can fail when there is no valid json + doValidate = true; + } + catch (err) { + // no valid JSON, don't validate + } + + // only validate the JSON when parsing the JSON succeeded + if (doValidate && this.validateSchema) { + var valid = this.validateSchema(json); + if (!valid) { + errors = this.validateSchema.errors.map(function (error) { + return util.improveSchemaError(error); + }); + } + } + + if (errors.length > 0) { + // limit the number of displayed errors + var limit = errors.length > MAX_ERRORS; + if (limit) { + errors = errors.slice(0, MAX_ERRORS); + var hidden = this.validateSchema.errors.length - MAX_ERRORS; + errors.push('(' + hidden + ' more errors...)') + } + + var validationErrors = document.createElement('div'); + validationErrors.innerHTML = '' + + '' + + errors.map(function (error) { + var message; + if (typeof error === 'string') { + message = ''; + } + else { + message = '' + + ''; + } + + return '' + message + '' + }).join('') + + '' + + '
' + error + '
' + error.dataPath + '' + error.message + '
'; + + this.dom.validationErrors = validationErrors; + this.frame.appendChild(validationErrors); + + var height = validationErrors.clientHeight; + this.content.style.marginBottom = (-height) + 'px'; + this.content.style.paddingBottom = height + 'px'; + } + + // update the height of the ace editor + if (this.aceEditor) { + var force = false; + this.aceEditor.resize(force); + } +}; + +// define modes +module.exports = [ + { + mode: 'text', + mixin: textmode, + data: 'text', + load: textmode.format + }, + { + mode: 'code', + mixin: textmode, + data: 'text', + load: textmode.format + } +]; diff --git a/ui/app/bower_components/jsoneditor/src/js/treemode.js b/ui/app/bower_components/jsoneditor/src/js/treemode.js new file mode 100644 index 0000000..1fc243e --- /dev/null +++ b/ui/app/bower_components/jsoneditor/src/js/treemode.js @@ -0,0 +1,1198 @@ +'use strict'; + + +var Highlighter = require('./Highlighter'); +var History = require('./History'); +var SearchBox = require('./SearchBox'); +var ContextMenu = require('./ContextMenu'); +var Node = require('./Node'); +var ModeSwitcher = require('./ModeSwitcher'); +var util = require('./util'); + +// create a mixin with the functions for tree mode +var treemode = {}; + +/** + * Create a tree editor + * @param {Element} container Container element + * @param {Object} [options] Object with options. available options: + * {String} mode Editor mode. Available values: + * 'tree' (default), 'view', + * and 'form'. + * {Boolean} search Enable search box. + * True by default + * {Boolean} history Enable history (undo/redo). + * True by default + * {function} onChange Callback method, triggered + * on change of contents + * {String} name Field name for the root node. + * {boolean} escapeUnicode If true, unicode + * characters are escaped. + * false by default. + * {Object} schema A JSON Schema for validation + * @private + */ +treemode.create = function (container, options) { + if (!container) { + throw new Error('No container element provided.'); + } + this.container = container; + this.dom = {}; + this.highlighter = new Highlighter(); + this.selection = undefined; // will hold the last input selection + this.multiselection = { + nodes: [] + }; + this.validateSchema = null; // will be set in .setSchema(schema) + this.errorNodes = []; + + this.node = null; + this.focusTarget = null; + + this._setOptions(options); + + if (this.options.history && this.options.mode !== 'view') { + this.history = new History(this); + } + + this._createFrame(); + this._createTable(); +}; + +/** + * Destroy the editor. Clean up DOM, event listeners, and web workers. + */ +treemode.destroy = function () { + if (this.frame && this.container && this.frame.parentNode == this.container) { + this.container.removeChild(this.frame); + this.frame = null; + } + this.container = null; + + this.dom = null; + + this.clear(); + this.node = null; + this.focusTarget = null; + this.selection = null; + this.multiselection = null; + this.errorNodes = null; + this.validateSchema = null; + this._debouncedValidate = null; + + if (this.history) { + this.history.destroy(); + this.history = null; + } + + if (this.searchBox) { + this.searchBox.destroy(); + this.searchBox = null; + } + + if (this.modeSwitcher) { + this.modeSwitcher.destroy(); + this.modeSwitcher = null; + } +}; + +/** + * Initialize and set default options + * @param {Object} [options] See description in constructor + * @private + */ +treemode._setOptions = function (options) { + this.options = { + search: true, + history: true, + mode: 'tree', + name: undefined, // field name of root node + schema: null + }; + + // copy all options + if (options) { + for (var prop in options) { + if (options.hasOwnProperty(prop)) { + this.options[prop] = options[prop]; + } + } + } + + // compile a JSON schema validator if a JSON schema is provided + this.setSchema(this.options.schema); + + // create a debounced validate function + this._debouncedValidate = util.debounce(this.validate.bind(this), this.DEBOUNCE_INTERVAL); +}; + +/** + * Set JSON object in editor + * @param {Object | undefined} json JSON data + * @param {String} [name] Optional field name for the root node. + * Can also be set using setName(name). + */ +treemode.set = function (json, name) { + // adjust field name for root node + if (name) { + // TODO: deprecated since version 2.2.0. Cleanup some day. + console.warn('Second parameter "name" is deprecated. Use setName(name) instead.'); + this.options.name = name; + } + + // verify if json is valid JSON, ignore when a function + if (json instanceof Function || (json === undefined)) { + this.clear(); + } + else { + this.content.removeChild(this.table); // Take the table offline + + // replace the root node + var params = { + field: this.options.name, + value: json + }; + var node = new Node(this, params); + this._setRoot(node); + + // validate JSON schema (if configured) + this.validate(); + + // expand + var recurse = false; + this.node.expand(recurse); + + this.content.appendChild(this.table); // Put the table online again + } + + // TODO: maintain history, store last state and previous document + if (this.history) { + this.history.clear(); + } + + // clear search + if (this.searchBox) { + this.searchBox.clear(); + } +}; + +/** + * Get JSON object from editor + * @return {Object | undefined} json + */ +treemode.get = function () { + // remove focus from currently edited node + if (this.focusTarget) { + var node = Node.getNodeFromTarget(this.focusTarget); + if (node) { + node.blur(); + } + } + + if (this.node) { + return this.node.getValue(); + } + else { + return undefined; + } +}; + +/** + * Get the text contents of the editor + * @return {String} jsonText + */ +treemode.getText = function() { + return JSON.stringify(this.get()); +}; + +/** + * Set the text contents of the editor + * @param {String} jsonText + */ +treemode.setText = function(jsonText) { + this.set(util.parse(jsonText)); +}; + +/** + * Set a field name for the root node. + * @param {String | undefined} name + */ +treemode.setName = function (name) { + this.options.name = name; + if (this.node) { + this.node.updateField(this.options.name); + } +}; + +/** + * Get the field name for the root node. + * @return {String | undefined} name + */ +treemode.getName = function () { + return this.options.name; +}; + +/** + * Set focus to the editor. Focus will be set to: + * - the first editable field or value, or else + * - to the expand button of the root node, or else + * - to the context menu button of the root node, or else + * - to the first button in the top menu + */ +treemode.focus = function () { + var input = this.content.querySelector('[contenteditable=true]'); + if (input) { + input.focus(); + } + else if (this.node.dom.expand) { + this.node.dom.expand.focus(); + } + else if (this.node.dom.menu) { + this.node.dom.menu.focus(); + } + else { + // focus to the first button in the menu + input = this.frame.querySelector('button'); + if (input) { + input.focus(); + } + } +}; + +/** + * Remove the root node from the editor + */ +treemode.clear = function () { + if (this.node) { + this.node.collapse(); + this.tbody.removeChild(this.node.getDom()); + delete this.node; + } +}; + +/** + * Set the root node for the json editor + * @param {Node} node + * @private + */ +treemode._setRoot = function (node) { + this.clear(); + + this.node = node; + + // append to the dom + this.tbody.appendChild(node.getDom()); +}; + +/** + * Search text in all nodes + * The nodes will be expanded when the text is found one of its childs, + * else it will be collapsed. Searches are case insensitive. + * @param {String} text + * @return {Object[]} results Array with nodes containing the search results + * The result objects contains fields: + * - {Node} node, + * - {String} elem the dom element name where + * the result is found ('field' or + * 'value') + */ +treemode.search = function (text) { + var results; + if (this.node) { + this.content.removeChild(this.table); // Take the table offline + results = this.node.search(text); + this.content.appendChild(this.table); // Put the table online again + } + else { + results = []; + } + + return results; +}; + +/** + * Expand all nodes + */ +treemode.expandAll = function () { + if (this.node) { + this.content.removeChild(this.table); // Take the table offline + this.node.expand(); + this.content.appendChild(this.table); // Put the table online again + } +}; + +/** + * Collapse all nodes + */ +treemode.collapseAll = function () { + if (this.node) { + this.content.removeChild(this.table); // Take the table offline + this.node.collapse(); + this.content.appendChild(this.table); // Put the table online again + } +}; + +/** + * The method onChange is called whenever a field or value is changed, created, + * deleted, duplicated, etc. + * @param {String} action Change action. Available values: "editField", + * "editValue", "changeType", "appendNode", + * "removeNode", "duplicateNode", "moveNode", "expand", + * "collapse". + * @param {Object} params Object containing parameters describing the change. + * The parameters in params depend on the action (for + * example for "editValue" the Node, old value, and new + * value are provided). params contains all information + * needed to undo or redo the action. + * @private + */ +treemode._onAction = function (action, params) { + // add an action to the history + if (this.history) { + this.history.add(action, params); + } + + this._onChange(); +}; + +/** + * Handle a change: + * - Validate JSON schema + * - Send a callback to the onChange listener if provided + * @private + */ +treemode._onChange = function () { + // validate JSON schema (if configured) + this._debouncedValidate(); + + // trigger the onChange callback + if (this.options.onChange) { + try { + this.options.onChange(); + } + catch (err) { + console.error('Error in onChange callback: ', err); + } + } +}; + +/** + * Validate current JSON object against the configured JSON schema + * Throws an exception when no JSON schema is configured + */ +treemode.validate = function () { + // clear all current errors + if (this.errorNodes) { + this.errorNodes.forEach(function (node) { + node.setError(null); + }); + } + + var root = this.node; + if (!root) { // TODO: this should be redundant but is needed on mode switch + return; + } + + // check for duplicate keys + var duplicateErrors = root.validate(); + + // validate the JSON + var schemaErrors = []; + if (this.validateSchema) { + var valid = this.validateSchema(root.getValue()); + if (!valid) { + // apply all new errors + schemaErrors = this.validateSchema.errors + .map(function (error) { + return util.improveSchemaError(error); + }) + .map(function findNode (error) { + return { + node: root.findNode(error.dataPath), + error: error + } + }) + .filter(function hasNode (entry) { + return entry.node != null + }); + } + } + + // display the error in the nodes with a problem + this.errorNodes = duplicateErrors + .concat(schemaErrors) + .reduce(function expandParents (all, entry) { + // expand parents, then merge such that parents come first and + // original entries last + return entry.node + .findParents() + .map(function (parent) { + return { + node: parent, + child: entry.node, + error: { + message: parent.type === 'object' + ? 'Contains invalid properties' // object + : 'Contains invalid items' // array + } + }; + }) + .concat(all, [entry]); + }, []) + // TODO: dedupe the parent nodes + .map(function setError (entry) { + entry.node.setError(entry.error, entry.child); + return entry.node; + }); +}; + +/** + * Refresh the rendered contents + */ +treemode.refresh = function () { + if (this.node) { + this.node.updateDom({recurse: true}); + } +}; + +/** + * Start autoscrolling when given mouse position is above the top of the + * editor contents, or below the bottom. + * @param {Number} mouseY Absolute mouse position in pixels + */ +treemode.startAutoScroll = function (mouseY) { + var me = this; + var content = this.content; + var top = util.getAbsoluteTop(content); + var height = content.clientHeight; + var bottom = top + height; + var margin = 24; + var interval = 50; // ms + + if ((mouseY < top + margin) && content.scrollTop > 0) { + this.autoScrollStep = ((top + margin) - mouseY) / 3; + } + else if (mouseY > bottom - margin && + height + content.scrollTop < content.scrollHeight) { + this.autoScrollStep = ((bottom - margin) - mouseY) / 3; + } + else { + this.autoScrollStep = undefined; + } + + if (this.autoScrollStep) { + if (!this.autoScrollTimer) { + this.autoScrollTimer = setInterval(function () { + if (me.autoScrollStep) { + content.scrollTop -= me.autoScrollStep; + } + else { + me.stopAutoScroll(); + } + }, interval); + } + } + else { + this.stopAutoScroll(); + } +}; + +/** + * Stop auto scrolling. Only applicable when scrolling + */ +treemode.stopAutoScroll = function () { + if (this.autoScrollTimer) { + clearTimeout(this.autoScrollTimer); + delete this.autoScrollTimer; + } + if (this.autoScrollStep) { + delete this.autoScrollStep; + } +}; + + +/** + * Set the focus to an element in the editor, set text selection, and + * set scroll position. + * @param {Object} selection An object containing fields: + * {Element | undefined} dom The dom element + * which has focus + * {Range | TextRange} range A text selection + * {Node[]} nodes Nodes in case of multi selection + * {Number} scrollTop Scroll position + */ +treemode.setSelection = function (selection) { + if (!selection) { + return; + } + + if ('scrollTop' in selection && this.content) { + // TODO: animated scroll + this.content.scrollTop = selection.scrollTop; + } + if (selection.nodes) { + // multi-select + this.select(selection.nodes); + } + if (selection.range) { + util.setSelectionOffset(selection.range); + } + if (selection.dom) { + selection.dom.focus(); + } +}; + +/** + * Get the current focus + * @return {Object} selection An object containing fields: + * {Element | undefined} dom The dom element + * which has focus + * {Range | TextRange} range A text selection + * {Node[]} nodes Nodes in case of multi selection + * {Number} scrollTop Scroll position + */ +treemode.getSelection = function () { + var range = util.getSelectionOffset(); + if (range && range.container.nodeName !== 'DIV') { // filter on (editable) divs) + range = null; + } + + return { + dom: this.focusTarget, + range: range, + nodes: this.multiselection.nodes.slice(0), + scrollTop: this.content ? this.content.scrollTop : 0 + }; +}; + +/** + * Adjust the scroll position such that given top position is shown at 1/4 + * of the window height. + * @param {Number} top + * @param {function(boolean)} [callback] Callback, executed when animation is + * finished. The callback returns true + * when animation is finished, or false + * when not. + */ +treemode.scrollTo = function (top, callback) { + var content = this.content; + if (content) { + var editor = this; + // cancel any running animation + if (editor.animateTimeout) { + clearTimeout(editor.animateTimeout); + delete editor.animateTimeout; + } + if (editor.animateCallback) { + editor.animateCallback(false); + delete editor.animateCallback; + } + + // calculate final scroll position + var height = content.clientHeight; + var bottom = content.scrollHeight - height; + var finalScrollTop = Math.min(Math.max(top - height / 4, 0), bottom); + + // animate towards the new scroll position + var animate = function () { + var scrollTop = content.scrollTop; + var diff = (finalScrollTop - scrollTop); + if (Math.abs(diff) > 3) { + content.scrollTop += diff / 3; + editor.animateCallback = callback; + editor.animateTimeout = setTimeout(animate, 50); + } + else { + // finished + if (callback) { + callback(true); + } + content.scrollTop = finalScrollTop; + delete editor.animateTimeout; + delete editor.animateCallback; + } + }; + animate(); + } + else { + if (callback) { + callback(false); + } + } +}; + +/** + * Create main frame + * @private + */ +treemode._createFrame = function () { + // create the frame + this.frame = document.createElement('div'); + this.frame.className = 'jsoneditor jsoneditor-mode-' + this.options.mode; + this.container.appendChild(this.frame); + + // create one global event listener to handle all events from all nodes + var editor = this; + function onEvent(event) { + // when switching to mode "code" or "text" via the menu, some events + // are still fired whilst the _onEvent methods is already removed. + if (editor._onEvent) { + editor._onEvent(event); + } + } + this.frame.onclick = function (event) { + var target = event.target;// || event.srcElement; + + onEvent(event); + + // prevent default submit action of buttons when editor is located + // inside a form + if (target.nodeName == 'BUTTON') { + event.preventDefault(); + } + }; + this.frame.oninput = onEvent; + this.frame.onchange = onEvent; + this.frame.onkeydown = onEvent; + this.frame.onkeyup = onEvent; + this.frame.oncut = onEvent; + this.frame.onpaste = onEvent; + this.frame.onmousedown = onEvent; + this.frame.onmouseup = onEvent; + this.frame.onmouseover = onEvent; + this.frame.onmouseout = onEvent; + // Note: focus and blur events do not propagate, therefore they defined + // using an eventListener with useCapture=true + // see http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html + util.addEventListener(this.frame, 'focus', onEvent, true); + util.addEventListener(this.frame, 'blur', onEvent, true); + this.frame.onfocusin = onEvent; // for IE + this.frame.onfocusout = onEvent; // for IE + + // create menu + this.menu = document.createElement('div'); + this.menu.className = 'jsoneditor-menu'; + this.frame.appendChild(this.menu); + + // create expand all button + var expandAll = document.createElement('button'); + expandAll.type = 'button'; + expandAll.className = 'jsoneditor-expand-all'; + expandAll.title = 'Expand all fields'; + expandAll.onclick = function () { + editor.expandAll(); + }; + this.menu.appendChild(expandAll); + + // create expand all button + var collapseAll = document.createElement('button'); + collapseAll.type = 'button'; + collapseAll.title = 'Collapse all fields'; + collapseAll.className = 'jsoneditor-collapse-all'; + collapseAll.onclick = function () { + editor.collapseAll(); + }; + this.menu.appendChild(collapseAll); + + // create undo/redo buttons + if (this.history) { + // create undo button + var undo = document.createElement('button'); + undo.type = 'button'; + undo.className = 'jsoneditor-undo jsoneditor-separator'; + undo.title = 'Undo last action (Ctrl+Z)'; + undo.onclick = function () { + editor._onUndo(); + }; + this.menu.appendChild(undo); + this.dom.undo = undo; + + // create redo button + var redo = document.createElement('button'); + redo.type = 'button'; + redo.className = 'jsoneditor-redo'; + redo.title = 'Redo (Ctrl+Shift+Z)'; + redo.onclick = function () { + editor._onRedo(); + }; + this.menu.appendChild(redo); + this.dom.redo = redo; + + // register handler for onchange of history + this.history.onChange = function () { + undo.disabled = !editor.history.canUndo(); + redo.disabled = !editor.history.canRedo(); + }; + this.history.onChange(); + } + + // create mode box + if (this.options && this.options.modes && this.options.modes.length) { + var me = this; + this.modeSwitcher = new ModeSwitcher(this.menu, this.options.modes, this.options.mode, function onSwitch(mode) { + me.modeSwitcher.destroy(); + + // switch mode and restore focus + me.setMode(mode); + me.modeSwitcher.focus(); + }); + } + + // create search box + if (this.options.search) { + this.searchBox = new SearchBox(this, this.menu); + } +}; + +/** + * Perform an undo action + * @private + */ +treemode._onUndo = function () { + if (this.history) { + // undo last action + this.history.undo(); + + // fire change event + this._onChange(); + } +}; + +/** + * Perform a redo action + * @private + */ +treemode._onRedo = function () { + if (this.history) { + // redo last action + this.history.redo(); + + // fire change event + this._onChange(); + } +}; + +/** + * Event handler + * @param event + * @private + */ +treemode._onEvent = function (event) { + if (event.type == 'keydown') { + this._onKeyDown(event); + } + + if (event.type == 'focus') { + this.focusTarget = event.target; + } + + if (event.type == 'mousedown') { + this._startDragDistance(event); + } + if (event.type == 'mousemove' || event.type == 'mouseup' || event.type == 'click') { + this._updateDragDistance(event); + } + + var node = Node.getNodeFromTarget(event.target); + + if (node && node.selected) { + if (event.type == 'click') { + if (event.target == node.dom.menu) { + this.showContextMenu(event.target); + + // stop propagation (else we will open the context menu of a single node) + return; + } + + // deselect a multi selection + if (!event.hasMoved) { + this.deselect(); + } + } + + if (event.type == 'mousedown') { + // drag multiple nodes + Node.onDragStart(this.multiselection.nodes, event); + } + } + else { + if (event.type == 'mousedown') { + this.deselect(); + + if (node && event.target == node.dom.drag) { + // drag a singe node + Node.onDragStart(node, event); + } + else if (!node || (event.target != node.dom.field && event.target != node.dom.value && event.target != node.dom.select)) { + // select multiple nodes + this._onMultiSelectStart(event); + } + } + } + + if (node) { + node.onEvent(event); + } +}; + +treemode._startDragDistance = function (event) { + this.dragDistanceEvent = { + initialTarget: event.target, + initialPageX: event.pageX, + initialPageY: event.pageY, + dragDistance: 0, + hasMoved: false + }; +}; + +treemode._updateDragDistance = function (event) { + if (!this.dragDistanceEvent) { + this._startDragDistance(event); + } + + var diffX = event.pageX - this.dragDistanceEvent.initialPageX; + var diffY = event.pageY - this.dragDistanceEvent.initialPageY; + + this.dragDistanceEvent.dragDistance = Math.sqrt(diffX * diffX + diffY * diffY); + this.dragDistanceEvent.hasMoved = + this.dragDistanceEvent.hasMoved || this.dragDistanceEvent.dragDistance > 10; + + event.dragDistance = this.dragDistanceEvent.dragDistance; + event.hasMoved = this.dragDistanceEvent.hasMoved; + + return event.dragDistance; +}; + +/** + * Start multi selection of nodes by dragging the mouse + * @param event + * @private + */ +treemode._onMultiSelectStart = function (event) { + var node = Node.getNodeFromTarget(event.target); + + if (this.options.mode !== 'tree' || this.options.onEditable !== undefined) { + // dragging not allowed in modes 'view' and 'form' + // TODO: allow multiselection of items when option onEditable is specified + return; + } + + this.multiselection = { + start: node || null, + end: null, + nodes: [] + }; + + this._startDragDistance(event); + + var editor = this; + if (!this.mousemove) { + this.mousemove = util.addEventListener(window, 'mousemove', function (event) { + editor._onMultiSelect(event); + }); + } + if (!this.mouseup) { + this.mouseup = util.addEventListener(window, 'mouseup', function (event ) { + editor._onMultiSelectEnd(event); + }); + } + +}; + +/** + * Multiselect nodes by dragging + * @param event + * @private + */ +treemode._onMultiSelect = function (event) { + event.preventDefault(); + + this._updateDragDistance(event); + if (!event.hasMoved) { + return; + } + + var node = Node.getNodeFromTarget(event.target); + + if (node) { + if (this.multiselection.start == null) { + this.multiselection.start = node; + } + this.multiselection.end = node; + } + + // deselect previous selection + this.deselect(); + + // find the selected nodes in the range from first to last + var start = this.multiselection.start; + var end = this.multiselection.end || this.multiselection.start; + if (start && end) { + // find the top level childs, all having the same parent + this.multiselection.nodes = this._findTopLevelNodes(start, end); + this.select(this.multiselection.nodes); + } +}; + +/** + * End of multiselect nodes by dragging + * @param event + * @private + */ +treemode._onMultiSelectEnd = function (event) { + // set focus to the context menu button of the first node + if (this.multiselection.nodes[0]) { + this.multiselection.nodes[0].dom.menu.focus(); + } + + this.multiselection.start = null; + this.multiselection.end = null; + + // cleanup global event listeners + if (this.mousemove) { + util.removeEventListener(window, 'mousemove', this.mousemove); + delete this.mousemove; + } + if (this.mouseup) { + util.removeEventListener(window, 'mouseup', this.mouseup); + delete this.mouseup; + } +}; + +/** + * deselect currently selected nodes + * @param {boolean} [clearStartAndEnd=false] If true, the `start` and `end` + * state is cleared too. + */ +treemode.deselect = function (clearStartAndEnd) { + this.multiselection.nodes.forEach(function (node) { + node.setSelected(false); + }); + this.multiselection.nodes = []; + + if (clearStartAndEnd) { + this.multiselection.start = null; + this.multiselection.end = null; + } +}; + +/** + * select nodes + * @param {Node[] | Node} nodes + */ +treemode.select = function (nodes) { + if (!Array.isArray(nodes)) { + return this.select([nodes]); + } + + if (nodes) { + this.deselect(); + + this.multiselection.nodes = nodes.slice(0); + + var first = nodes[0]; + nodes.forEach(function (node) { + node.setSelected(true, node === first); + }); + } +}; + +/** + * From two arbitrary selected nodes, find their shared parent node. + * From that parent node, select the two child nodes in the brances going to + * nodes `start` and `end`, and select all childs in between. + * @param {Node} start + * @param {Node} end + * @return {Array.} Returns an ordered list with child nodes + * @private + */ +treemode._findTopLevelNodes = function (start, end) { + var startPath = start.getNodePath(); + var endPath = end.getNodePath(); + var i = 0; + while (i < startPath.length && startPath[i] === endPath[i]) { + i++; + } + var root = startPath[i - 1]; + var startChild = startPath[i]; + var endChild = endPath[i]; + + if (!startChild || !endChild) { + if (root.parent) { + // startChild is a parent of endChild or vice versa + startChild = root; + endChild = root; + root = root.parent + } + else { + // we have selected the root node (which doesn't have a parent) + startChild = root.childs[0]; + endChild = root.childs[root.childs.length - 1]; + } + } + + if (root && startChild && endChild) { + var startIndex = root.childs.indexOf(startChild); + var endIndex = root.childs.indexOf(endChild); + var firstIndex = Math.min(startIndex, endIndex); + var lastIndex = Math.max(startIndex, endIndex); + + return root.childs.slice(firstIndex, lastIndex + 1); + } + else { + return []; + } +}; + +/** + * Event handler for keydown. Handles shortcut keys + * @param {Event} event + * @private + */ +treemode._onKeyDown = function (event) { + var keynum = event.which || event.keyCode; + var ctrlKey = event.ctrlKey; + var shiftKey = event.shiftKey; + var handled = false; + + if (keynum == 9) { // Tab or Shift+Tab + var me = this; + setTimeout(function () { + // select all text when moving focus to an editable div + util.selectContentEditable(me.focusTarget); + }, 0); + } + + if (this.searchBox) { + if (ctrlKey && keynum == 70) { // Ctrl+F + this.searchBox.dom.search.focus(); + this.searchBox.dom.search.select(); + handled = true; + } + else if (keynum == 114 || (ctrlKey && keynum == 71)) { // F3 or Ctrl+G + var focus = true; + if (!shiftKey) { + // select next search result (F3 or Ctrl+G) + this.searchBox.next(focus); + } + else { + // select previous search result (Shift+F3 or Ctrl+Shift+G) + this.searchBox.previous(focus); + } + + handled = true; + } + } + + if (this.history) { + if (ctrlKey && !shiftKey && keynum == 90) { // Ctrl+Z + // undo + this._onUndo(); + handled = true; + } + else if (ctrlKey && shiftKey && keynum == 90) { // Ctrl+Shift+Z + // redo + this._onRedo(); + handled = true; + } + } + + if (handled) { + event.preventDefault(); + event.stopPropagation(); + } +}; + +/** + * Create main table + * @private + */ +treemode._createTable = function () { + var contentOuter = document.createElement('div'); + contentOuter.className = 'jsoneditor-outer'; + this.contentOuter = contentOuter; + + this.content = document.createElement('div'); + this.content.className = 'jsoneditor-tree'; + contentOuter.appendChild(this.content); + + this.table = document.createElement('table'); + this.table.className = 'jsoneditor-tree'; + this.content.appendChild(this.table); + + // create colgroup where the first two columns don't have a fixed + // width, and the edit columns do have a fixed width + var col; + this.colgroupContent = document.createElement('colgroup'); + if (this.options.mode === 'tree') { + col = document.createElement('col'); + col.width = "24px"; + this.colgroupContent.appendChild(col); + } + col = document.createElement('col'); + col.width = "24px"; + this.colgroupContent.appendChild(col); + col = document.createElement('col'); + this.colgroupContent.appendChild(col); + this.table.appendChild(this.colgroupContent); + + this.tbody = document.createElement('tbody'); + this.table.appendChild(this.tbody); + + this.frame.appendChild(contentOuter); +}; + +/** + * Show a contextmenu for this node. + * Used for multiselection + * @param {HTMLElement} anchor Anchor element to attache the context menu to. + * @param {function} [onClose] Callback method called when the context menu + * is being closed. + */ +treemode.showContextMenu = function (anchor, onClose) { + var items = []; + var editor = this; + + // create duplicate button + items.push({ + text: 'Duplicate', + title: 'Duplicate selected fields (Ctrl+D)', + className: 'jsoneditor-duplicate', + click: function () { + Node.onDuplicate(editor.multiselection.nodes); + } + }); + + // create remove button + items.push({ + text: 'Remove', + title: 'Remove selected fields (Ctrl+Del)', + className: 'jsoneditor-remove', + click: function () { + Node.onRemove(editor.multiselection.nodes); + } + }); + + var menu = new ContextMenu(items, {close: onClose}); + menu.show(anchor, this.content); +}; + + +// define modes +module.exports = [ + { + mode: 'tree', + mixin: treemode, + data: 'json' + }, + { + mode: 'view', + mixin: treemode, + data: 'json' + }, + { + mode: 'form', + mixin: treemode, + data: 'json' + } +]; diff --git a/ui/app/bower_components/jsoneditor/src/js/util.js b/ui/app/bower_components/jsoneditor/src/js/util.js new file mode 100644 index 0000000..e02e043 --- /dev/null +++ b/ui/app/bower_components/jsoneditor/src/js/util.js @@ -0,0 +1,778 @@ +'use strict'; + +var jsonlint = require('./assets/jsonlint/jsonlint'); + +/** + * Parse JSON using the parser built-in in the browser. + * On exception, the jsonString is validated and a detailed error is thrown. + * @param {String} jsonString + * @return {JSON} json + */ +exports.parse = function parse(jsonString) { + try { + return JSON.parse(jsonString); + } + catch (err) { + // try to throw a more detailed error message using validate + exports.validate(jsonString); + + // rethrow the original error + throw err; + } +}; + +/** + * Sanitize a JSON-like string containing. For example changes JavaScript + * notation into JSON notation. + * This function for example changes a string like "{a: 2, 'b': {c: 'd'}" + * into '{"a": 2, "b": {"c": "d"}' + * @param {string} jsString + * @returns {string} json + */ +exports.sanitize = function (jsString) { + // escape all single and double quotes inside strings + var chars = []; + var i = 0; + + //If JSON starts with a function (characters/digits/"_-"), remove this function. + //This is useful for "stripping" JSONP objects to become JSON + //For example: /* some comment */ function_12321321 ( [{"a":"b"}] ); => [{"a":"b"}] + var match = jsString.match(/^\s*(\/\*(.|[\r\n])*?\*\/)?\s*[\da-zA-Z_$]+\s*\(([\s\S]*)\)\s*;?\s*$/); + if (match) { + jsString = match[3]; + } + + // helper functions to get the current/prev/next character + function curr () { return jsString.charAt(i); } + function next() { return jsString.charAt(i + 1); } + function prev() { return jsString.charAt(i - 1); } + + // get the last parsed non-whitespace character + function lastNonWhitespace () { + var p = chars.length - 1; + + while (p >= 0) { + var pp = chars[p]; + if (pp !== ' ' && pp !== '\n' && pp !== '\r' && pp !== '\t') { // non whitespace + return pp; + } + p--; + } + + return ''; + } + + // skip a block comment '/* ... */' + function skipBlockComment () { + i += 2; + while (i < jsString.length && (curr() !== '*' || next() !== '/')) { + i++; + } + i += 2; + } + + // skip a comment '// ...' + function skipComment () { + i += 2; + while (i < jsString.length && (curr() !== '\n')) { + i++; + } + } + + // parse single or double quoted string + function parseString(quote) { + chars.push('"'); + i++; + var c = curr(); + while (i < jsString.length && c !== quote) { + if (c === '"' && prev() !== '\\') { + // unescaped double quote, escape it + chars.push('\\'); + } + + // handle escape character + if (c === '\\') { + i++; + c = curr(); + + // remove the escape character when followed by a single quote ', not needed + if (c !== '\'') { + chars.push('\\'); + } + } + chars.push(c); + + i++; + c = curr(); + } + if (c === quote) { + chars.push('"'); + i++; + } + } + + // parse an unquoted key + function parseKey() { + var specialValues = ['null', 'true', 'false']; + var key = ''; + var c = curr(); + + var regexp = /[a-zA-Z_$\d]/; // letter, number, underscore, dollar character + while (regexp.test(c)) { + key += c; + i++; + c = curr(); + } + + if (specialValues.indexOf(key) === -1) { + chars.push('"' + key + '"'); + } + else { + chars.push(key); + } + } + + while(i < jsString.length) { + var c = curr(); + + if (c === '/' && next() === '*') { + skipBlockComment(); + } + else if (c === '/' && next() === '/') { + skipComment(); + } + else if (c === '\'' || c === '"') { + parseString(c); + } + else if (/[a-zA-Z_$]/.test(c) && ['{', ','].indexOf(lastNonWhitespace()) !== -1) { + // an unquoted object key (like a in '{a:2}') + parseKey(); + } + else { + chars.push(c); + i++; + } + } + + return chars.join(''); +}; + +/** + * Escape unicode characters. + * For example input '\u2661' (length 1) will output '\\u2661' (length 5). + * @param {string} text + * @return {string} + */ +exports.escapeUnicodeChars = function (text) { + // see https://www.wikiwand.com/en/UTF-16 + // note: we leave surrogate pairs as two individual chars, + // as JSON doesn't interpret them as a single unicode char. + return text.replace(/[\u007F-\uFFFF]/g, function(c) { + return '\\u'+('0000' + c.charCodeAt(0).toString(16)).slice(-4); + }) +}; + +/** + * Validate a string containing a JSON object + * This method uses JSONLint to validate the String. If JSONLint is not + * available, the built-in JSON parser of the browser is used. + * @param {String} jsonString String with an (invalid) JSON object + * @throws Error + */ +exports.validate = function validate(jsonString) { + if (typeof(jsonlint) != 'undefined') { + jsonlint.parse(jsonString); + } + else { + JSON.parse(jsonString); + } +}; + +/** + * Extend object a with the properties of object b + * @param {Object} a + * @param {Object} b + * @return {Object} a + */ +exports.extend = function extend(a, b) { + for (var prop in b) { + if (b.hasOwnProperty(prop)) { + a[prop] = b[prop]; + } + } + return a; +}; + +/** + * Remove all properties from object a + * @param {Object} a + * @return {Object} a + */ +exports.clear = function clear (a) { + for (var prop in a) { + if (a.hasOwnProperty(prop)) { + delete a[prop]; + } + } + return a; +}; + +/** + * Get the type of an object + * @param {*} object + * @return {String} type + */ +exports.type = function type (object) { + if (object === null) { + return 'null'; + } + if (object === undefined) { + return 'undefined'; + } + if ((object instanceof Number) || (typeof object === 'number')) { + return 'number'; + } + if ((object instanceof String) || (typeof object === 'string')) { + return 'string'; + } + if ((object instanceof Boolean) || (typeof object === 'boolean')) { + return 'boolean'; + } + if ((object instanceof RegExp) || (typeof object === 'regexp')) { + return 'regexp'; + } + if (exports.isArray(object)) { + return 'array'; + } + + return 'object'; +}; + +/** + * Test whether a text contains a url (matches when a string starts + * with 'http://*' or 'https://*' and has no whitespace characters) + * @param {String} text + */ +var isUrlRegex = /^https?:\/\/\S+$/; +exports.isUrl = function isUrl (text) { + return (typeof text == 'string' || text instanceof String) && + isUrlRegex.test(text); +}; + +/** + * Tes whether given object is an Array + * @param {*} obj + * @returns {boolean} returns true when obj is an array + */ +exports.isArray = function (obj) { + return Object.prototype.toString.call(obj) === '[object Array]'; +}; + +/** + * Retrieve the absolute left value of a DOM element + * @param {Element} elem A dom element, for example a div + * @return {Number} left The absolute left position of this element + * in the browser page. + */ +exports.getAbsoluteLeft = function getAbsoluteLeft(elem) { + var rect = elem.getBoundingClientRect(); + return rect.left + window.pageXOffset || document.scrollLeft || 0; +}; + +/** + * Retrieve the absolute top value of a DOM element + * @param {Element} elem A dom element, for example a div + * @return {Number} top The absolute top position of this element + * in the browser page. + */ +exports.getAbsoluteTop = function getAbsoluteTop(elem) { + var rect = elem.getBoundingClientRect(); + return rect.top + window.pageYOffset || document.scrollTop || 0; +}; + +/** + * add a className to the given elements style + * @param {Element} elem + * @param {String} className + */ +exports.addClassName = function addClassName(elem, className) { + var classes = elem.className.split(' '); + if (classes.indexOf(className) == -1) { + classes.push(className); // add the class to the array + elem.className = classes.join(' '); + } +}; + +/** + * add a className to the given elements style + * @param {Element} elem + * @param {String} className + */ +exports.removeClassName = function removeClassName(elem, className) { + var classes = elem.className.split(' '); + var index = classes.indexOf(className); + if (index != -1) { + classes.splice(index, 1); // remove the class from the array + elem.className = classes.join(' '); + } +}; + +/** + * Strip the formatting from the contents of a div + * the formatting from the div itself is not stripped, only from its childs. + * @param {Element} divElement + */ +exports.stripFormatting = function stripFormatting(divElement) { + var childs = divElement.childNodes; + for (var i = 0, iMax = childs.length; i < iMax; i++) { + var child = childs[i]; + + // remove the style + if (child.style) { + // TODO: test if child.attributes does contain style + child.removeAttribute('style'); + } + + // remove all attributes + var attributes = child.attributes; + if (attributes) { + for (var j = attributes.length - 1; j >= 0; j--) { + var attribute = attributes[j]; + if (attribute.specified === true) { + child.removeAttribute(attribute.name); + } + } + } + + // recursively strip childs + exports.stripFormatting(child); + } +}; + +/** + * Set focus to the end of an editable div + * code from Nico Burns + * http://stackoverflow.com/users/140293/nico-burns + * http://stackoverflow.com/questions/1125292/how-to-move-cursor-to-end-of-contenteditable-entity + * @param {Element} contentEditableElement A content editable div + */ +exports.setEndOfContentEditable = function setEndOfContentEditable(contentEditableElement) { + var range, selection; + if(document.createRange) { + range = document.createRange();//Create a range (a range is a like the selection but invisible) + range.selectNodeContents(contentEditableElement);//Select the entire contents of the element with the range + range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start + selection = window.getSelection();//get the selection object (allows you to change selection) + selection.removeAllRanges();//remove any selections already made + selection.addRange(range);//make the range you have just created the visible selection + } +}; + +/** + * Select all text of a content editable div. + * http://stackoverflow.com/a/3806004/1262753 + * @param {Element} contentEditableElement A content editable div + */ +exports.selectContentEditable = function selectContentEditable(contentEditableElement) { + if (!contentEditableElement || contentEditableElement.nodeName != 'DIV') { + return; + } + + var sel, range; + if (window.getSelection && document.createRange) { + range = document.createRange(); + range.selectNodeContents(contentEditableElement); + sel = window.getSelection(); + sel.removeAllRanges(); + sel.addRange(range); + } +}; + +/** + * Get text selection + * http://stackoverflow.com/questions/4687808/contenteditable-selected-text-save-and-restore + * @return {Range | TextRange | null} range + */ +exports.getSelection = function getSelection() { + if (window.getSelection) { + var sel = window.getSelection(); + if (sel.getRangeAt && sel.rangeCount) { + return sel.getRangeAt(0); + } + } + return null; +}; + +/** + * Set text selection + * http://stackoverflow.com/questions/4687808/contenteditable-selected-text-save-and-restore + * @param {Range | TextRange | null} range + */ +exports.setSelection = function setSelection(range) { + if (range) { + if (window.getSelection) { + var sel = window.getSelection(); + sel.removeAllRanges(); + sel.addRange(range); + } + } +}; + +/** + * Get selected text range + * @return {Object} params object containing parameters: + * {Number} startOffset + * {Number} endOffset + * {Element} container HTML element holding the + * selected text element + * Returns null if no text selection is found + */ +exports.getSelectionOffset = function getSelectionOffset() { + var range = exports.getSelection(); + + if (range && 'startOffset' in range && 'endOffset' in range && + range.startContainer && (range.startContainer == range.endContainer)) { + return { + startOffset: range.startOffset, + endOffset: range.endOffset, + container: range.startContainer.parentNode + }; + } + + return null; +}; + +/** + * Set selected text range in given element + * @param {Object} params An object containing: + * {Element} container + * {Number} startOffset + * {Number} endOffset + */ +exports.setSelectionOffset = function setSelectionOffset(params) { + if (document.createRange && window.getSelection) { + var selection = window.getSelection(); + if(selection) { + var range = document.createRange(); + + if (!params.container.firstChild) { + params.container.appendChild(document.createTextNode('')); + } + + // TODO: do not suppose that the first child of the container is a textnode, + // but recursively find the textnodes + range.setStart(params.container.firstChild, params.startOffset); + range.setEnd(params.container.firstChild, params.endOffset); + + exports.setSelection(range); + } + } +}; + +/** + * Get the inner text of an HTML element (for example a div element) + * @param {Element} element + * @param {Object} [buffer] + * @return {String} innerText + */ +exports.getInnerText = function getInnerText(element, buffer) { + var first = (buffer == undefined); + if (first) { + buffer = { + 'text': '', + 'flush': function () { + var text = this.text; + this.text = ''; + return text; + }, + 'set': function (text) { + this.text = text; + } + }; + } + + // text node + if (element.nodeValue) { + return buffer.flush() + element.nodeValue; + } + + // divs or other HTML elements + if (element.hasChildNodes()) { + var childNodes = element.childNodes; + var innerText = ''; + + for (var i = 0, iMax = childNodes.length; i < iMax; i++) { + var child = childNodes[i]; + + if (child.nodeName == 'DIV' || child.nodeName == 'P') { + var prevChild = childNodes[i - 1]; + var prevName = prevChild ? prevChild.nodeName : undefined; + if (prevName && prevName != 'DIV' && prevName != 'P' && prevName != 'BR') { + innerText += '\n'; + buffer.flush(); + } + innerText += exports.getInnerText(child, buffer); + buffer.set('\n'); + } + else if (child.nodeName == 'BR') { + innerText += buffer.flush(); + buffer.set('\n'); + } + else { + innerText += exports.getInnerText(child, buffer); + } + } + + return innerText; + } + else { + if (element.nodeName == 'P' && exports.getInternetExplorerVersion() != -1) { + // On Internet Explorer, a

with hasChildNodes()==false is + // rendered with a new line. Note that a

with + // hasChildNodes()==true is rendered without a new line + // Other browsers always ensure there is a
inside the

, + // and if not, the

does not render a new line + return buffer.flush(); + } + } + + // br or unknown + return ''; +}; + +/** + * Returns the version of Internet Explorer or a -1 + * (indicating the use of another browser). + * Source: http://msdn.microsoft.com/en-us/library/ms537509(v=vs.85).aspx + * @return {Number} Internet Explorer version, or -1 in case of an other browser + */ +exports.getInternetExplorerVersion = function getInternetExplorerVersion() { + if (_ieVersion == -1) { + var rv = -1; // Return value assumes failure. + if (navigator.appName == 'Microsoft Internet Explorer') + { + var ua = navigator.userAgent; + var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})"); + if (re.exec(ua) != null) { + rv = parseFloat( RegExp.$1 ); + } + } + + _ieVersion = rv; + } + + return _ieVersion; +}; + +/** + * Test whether the current browser is Firefox + * @returns {boolean} isFirefox + */ +exports.isFirefox = function isFirefox () { + return (navigator.userAgent.indexOf("Firefox") != -1); +}; + +/** + * cached internet explorer version + * @type {Number} + * @private + */ +var _ieVersion = -1; + +/** + * Add and event listener. Works for all browsers + * @param {Element} element An html element + * @param {string} action The action, for example "click", + * without the prefix "on" + * @param {function} listener The callback function to be executed + * @param {boolean} [useCapture] false by default + * @return {function} the created event listener + */ +exports.addEventListener = function addEventListener(element, action, listener, useCapture) { + if (element.addEventListener) { + if (useCapture === undefined) + useCapture = false; + + if (action === "mousewheel" && exports.isFirefox()) { + action = "DOMMouseScroll"; // For Firefox + } + + element.addEventListener(action, listener, useCapture); + return listener; + } else if (element.attachEvent) { + // Old IE browsers + var f = function () { + return listener.call(element, window.event); + }; + element.attachEvent("on" + action, f); + return f; + } +}; + +/** + * Remove an event listener from an element + * @param {Element} element An html dom element + * @param {string} action The name of the event, for example "mousedown" + * @param {function} listener The listener function + * @param {boolean} [useCapture] false by default + */ +exports.removeEventListener = function removeEventListener(element, action, listener, useCapture) { + if (element.removeEventListener) { + if (useCapture === undefined) + useCapture = false; + + if (action === "mousewheel" && exports.isFirefox()) { + action = "DOMMouseScroll"; // For Firefox + } + + element.removeEventListener(action, listener, useCapture); + } else if (element.detachEvent) { + // Old IE browsers + element.detachEvent("on" + action, listener); + } +}; + +/** + * Parse a JSON path like '.items[3].name' into an array + * @param {string} jsonPath + * @return {Array} + */ +exports.parsePath = function parsePath(jsonPath) { + var prop, remainder; + + if (jsonPath.length === 0) { + return []; + } + + // find a match like '.prop' + var match = jsonPath.match(/^\.(\w+)/); + if (match) { + prop = match[1]; + remainder = jsonPath.substr(prop.length + 1); + } + else if (jsonPath[0] === '[') { + // find a match like + var end = jsonPath.indexOf(']'); + if (end === -1) { + throw new SyntaxError('Character ] expected in path'); + } + if (end === 1) { + throw new SyntaxError('Index expected after ['); + } + + var value = jsonPath.substring(1, end); + if (value[0] === '\'') { + // ajv produces string prop names with single quotes, so we need + // to reformat them into valid double-quoted JSON strings + value = '\"' + value.substring(1, value.length - 1) + '\"'; + } + + prop = value === '*' ? value : JSON.parse(value); // parse string and number + remainder = jsonPath.substr(end + 1); + } + else { + throw new SyntaxError('Failed to parse path'); + } + + return [prop].concat(parsePath(remainder)) +}; + +/** + * Improve the error message of a JSON schema error + * @param {Object} error + * @return {Object} The error + */ +exports.improveSchemaError = function (error) { + if (error.keyword === 'enum' && Array.isArray(error.schema)) { + var enums = error.schema; + if (enums) { + enums = enums.map(function (value) { + return JSON.stringify(value); + }); + + if (enums.length > 5) { + var more = ['(' + (enums.length - 5) + ' more...)']; + enums = enums.slice(0, 5); + enums.push(more); + } + error.message = 'should be equal to one of: ' + enums.join(', '); + } + } + + if (error.keyword === 'additionalProperties') { + error.message = 'should NOT have additional property: ' + error.params.additionalProperty; + } + + return error; +}; + +/** + * Test whether the child rect fits completely inside the parent rect. + * @param {ClientRect} parent + * @param {ClientRect} child + * @param {number} margin + */ +exports.insideRect = function (parent, child, margin) { + var _margin = margin !== undefined ? margin : 0; + return child.left - _margin >= parent.left + && child.right + _margin <= parent.right + && child.top - _margin >= parent.top + && child.bottom + _margin <= parent.bottom; +}; + +/** + * Returns a function, that, as long as it continues to be invoked, will not + * be triggered. The function will be called after it stops being called for + * N milliseconds. + * + * Source: https://davidwalsh.name/javascript-debounce-function + * + * @param {function} func + * @param {number} wait Number in milliseconds + * @param {boolean} [immediate=false] If `immediate` is passed, trigger the + * function on the leading edge, instead + * of the trailing. + * @return {function} Return the debounced function + */ +exports.debounce = function debounce(func, wait, immediate) { + var timeout; + return function() { + var context = this, args = arguments; + var later = function() { + timeout = null; + if (!immediate) func.apply(context, args); + }; + var callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) func.apply(context, args); + }; +}; + +/** + * Determines the difference between two texts. + * Can only detect one removed or inserted block of characters. + * @param {string} oldText + * @param {string} newText + * @return {{start: number, end: number}} Returns the start and end + * of the changed part in newText. + */ +exports.textDiff = function textDiff(oldText, newText) { + var len = newText.length; + var start = 0; + var oldEnd = oldText.length; + var newEnd = newText.length; + + while (newText.charAt(start) === oldText.charAt(start) + && start < len) { + start++; + } + + while (newText.charAt(newEnd - 1) === oldText.charAt(oldEnd - 1) + && newEnd > start && oldEnd > 0) { + newEnd--; + oldEnd--; + } + + return {start: start, end: newEnd}; +}; diff --git a/ui/app/bower_components/ng-jsoneditor/.bower.json b/ui/app/bower_components/ng-jsoneditor/.bower.json new file mode 100644 index 0000000..cc785b7 --- /dev/null +++ b/ui/app/bower_components/ng-jsoneditor/.bower.json @@ -0,0 +1,36 @@ +{ + "name": "ng-jsoneditor", + "main": "ng-jsoneditor.min.js", + "homepage": "https://github.com/angular-tools/ng-jsoneditor", + "authors": [ + "angular-tools " + ], + "description": "Angular version of the insanely cool jsoneditor", + "keywords": [ + "jsoneditor" + ], + "bugs": "https://github.com/angular-tools/ng-jsoneditor/issues", + "license": "The Artistic License 2.0", + "dependencies": { + "angular": "~1.x", + "jsoneditor": "~4" + }, + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "test", + "tests" + ], + "version": "1.0.0", + "_release": "1.0.0", + "_resolution": { + "type": "version", + "tag": "v1.0.0", + "commit": "37d95e77b174c4a1d7771152ea6a8d158fb085e6" + }, + "_source": "git://github.com/angular-tools/ng-jsoneditor.git", + "_target": "^1.0.0", + "_originalSource": "angular-tools/ng-jsoneditor", + "_direct": true +} \ No newline at end of file diff --git a/ui/app/bower_components/ng-jsoneditor/LICENSE b/ui/app/bower_components/ng-jsoneditor/LICENSE new file mode 100644 index 0000000..14fb370 --- /dev/null +++ b/ui/app/bower_components/ng-jsoneditor/LICENSE @@ -0,0 +1,202 @@ + The Artistic License 2.0 + + Copyright (c) 2015 Angular tools + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +Preamble + +This license establishes the terms under which a given free software +Package may be copied, modified, distributed, and/or redistributed. +The intent is that the Copyright Holder maintains some artistic +control over the development of that Package while still keeping the +Package available as open source and free software. + +You are always permitted to make arrangements wholly outside of this +license directly with the Copyright Holder of a given Package. If the +terms of this license do not permit the full use that you propose to +make of the Package, you should contact the Copyright Holder and seek +a different licensing arrangement. + +Definitions + + "Copyright Holder" means the individual(s) or organization(s) + named in the copyright notice for the entire Package. + + "Contributor" means any party that has contributed code or other + material to the Package, in accordance with the Copyright Holder's + procedures. + + "You" and "your" means any person who would like to copy, + distribute, or modify the Package. + + "Package" means the collection of files distributed by the + Copyright Holder, and derivatives of that collection and/or of + those files. A given Package may consist of either the Standard + Version, or a Modified Version. + + "Distribute" means providing a copy of the Package or making it + accessible to anyone else, or in the case of a company or + organization, to others outside of your company or organization. + + "Distributor Fee" means any fee that you charge for Distributing + this Package or providing support for this Package to another + party. It does not mean licensing fees. + + "Standard Version" refers to the Package if it has not been + modified, or has been modified only in ways explicitly requested + by the Copyright Holder. + + "Modified Version" means the Package, if it has been changed, and + such changes were not explicitly requested by the Copyright + Holder. + + "Original License" means this Artistic License as Distributed with + the Standard Version of the Package, in its current version or as + it may be modified by The Perl Foundation in the future. + + "Source" form means the source code, documentation source, and + configuration files for the Package. + + "Compiled" form means the compiled bytecode, object code, binary, + or any other form resulting from mechanical transformation or + translation of the Source form. + + +Permission for Use and Modification Without Distribution + +(1) You are permitted to use the Standard Version and create and use +Modified Versions for any purpose without restriction, provided that +you do not Distribute the Modified Version. + + +Permissions for Redistribution of the Standard Version + +(2) You may Distribute verbatim copies of the Source form of the +Standard Version of this Package in any medium without restriction, +either gratis or for a Distributor Fee, provided that you duplicate +all of the original copyright notices and associated disclaimers. At +your discretion, such verbatim copies may or may not include a +Compiled form of the Package. + +(3) You may apply any bug fixes, portability changes, and other +modifications made available from the Copyright Holder. The resulting +Package will still be considered the Standard Version, and as such +will be subject to the Original License. + + +Distribution of Modified Versions of the Package as Source + +(4) You may Distribute your Modified Version as Source (either gratis +or for a Distributor Fee, and with or without a Compiled form of the +Modified Version) provided that you clearly document how it differs +from the Standard Version, including, but not limited to, documenting +any non-standard features, executables, or modules, and provided that +you do at least ONE of the following: + + (a) make the Modified Version available to the Copyright Holder + of the Standard Version, under the Original License, so that the + Copyright Holder may include your modifications in the Standard + Version. + + (b) ensure that installation of your Modified Version does not + prevent the user installing or running the Standard Version. In + addition, the Modified Version must bear a name that is different + from the name of the Standard Version. + + (c) allow anyone who receives a copy of the Modified Version to + make the Source form of the Modified Version available to others + under + + (i) the Original License or + + (ii) a license that permits the licensee to freely copy, + modify and redistribute the Modified Version using the same + licensing terms that apply to the copy that the licensee + received, and requires that the Source form of the Modified + Version, and of any works derived from it, be made freely + available in that license fees are prohibited but Distributor + Fees are allowed. + + +Distribution of Compiled Forms of the Standard Version +or Modified Versions without the Source + +(5) You may Distribute Compiled forms of the Standard Version without +the Source, provided that you include complete instructions on how to +get the Source of the Standard Version. Such instructions must be +valid at the time of your distribution. If these instructions, at any +time while you are carrying out such distribution, become invalid, you +must provide new instructions on demand or cease further distribution. +If you provide valid instructions or cease distribution within thirty +days after you become aware that the instructions are invalid, then +you do not forfeit any of your rights under this license. + +(6) You may Distribute a Modified Version in Compiled form without +the Source, provided that you comply with Section 4 with respect to +the Source of the Modified Version. + + +Aggregating or Linking the Package + +(7) You may aggregate the Package (either the Standard Version or +Modified Version) with other packages and Distribute the resulting +aggregation provided that you do not charge a licensing fee for the +Package. Distributor Fees are permitted, and licensing fees for other +components in the aggregation are permitted. The terms of this license +apply to the use and Distribution of the Standard or Modified Versions +as included in the aggregation. + +(8) You are permitted to link Modified and Standard Versions with +other works, to embed the Package in a larger work of your own, or to +build stand-alone binary or bytecode versions of applications that +include the Package, and Distribute the result without restriction, +provided the result does not expose a direct interface to the Package. + + +Items That are Not Considered Part of a Modified Version + +(9) Works (including, but not limited to, modules and scripts) that +merely extend or make use of the Package, do not, by themselves, cause +the Package to be a Modified Version. In addition, such works are not +considered parts of the Package itself, and are not subject to the +terms of this license. + + +General Provisions + +(10) Any use, modification, and distribution of the Standard or +Modified Versions is governed by this Artistic License. By using, +modifying or distributing the Package, you accept this license. Do not +use, modify, or distribute the Package, if you do not accept this +license. + +(11) If your Modified Version has been derived from a Modified +Version made by someone other than you, you are nevertheless required +to ensure that your Modified Version complies with the requirements of +this license. + +(12) This license does not grant you the right to use any trademark, +service mark, tradename, or logo of the Copyright Holder. + +(13) This license includes the non-exclusive, worldwide, +free-of-charge patent license to make, have made, use, offer to sell, +sell, import and otherwise transfer the Package with respect to any +patent claims licensable by the Copyright Holder that are necessarily +infringed by the Package. If you institute patent litigation +(including a cross-claim or counterclaim) against any party alleging +that the Package constitutes direct or contributory patent +infringement, then this Artistic License to you shall terminate on the +date that such litigation is filed. + +(14) Disclaimer of Warranty: +THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS +IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL +LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/ui/app/bower_components/ng-jsoneditor/README.md b/ui/app/bower_components/ng-jsoneditor/README.md new file mode 100644 index 0000000..a86a81e --- /dev/null +++ b/ui/app/bower_components/ng-jsoneditor/README.md @@ -0,0 +1,98 @@ +# ng-jsoneditor + +Angular version of the insanely cool [jsoneditor](https://github.com/josdejong/jsoneditor) + +## Requirements + +- AngularJS +- [Jsoneditor](https://github.com/josdejong/jsoneditor) + +## Usage + +You can get it from [Bower](http://bower.io/) + +```sh +bower install angular-tools/ng-jsoneditor +``` + +This will copy the ng-jsoneditor.js files into a `bower_components` folder, along with its dependencies. Load the script files in your application: + +```html + + + +``` + +Add the 'ng.jsoneditor' module as a dependency to your application module: + +```javascript +var myAppModule = angular.module('MyApp', ['ng.jsoneditor']); +``` + +Finally, add the directive to your html: + +```html +

+``` + +## Demo + +[Try this fiddle](http://jsfiddle.net/angulartools/sd3at5ek/) + +http://jsfiddle.net/angulartools/sd3at5ek/ + +### Sample code + +```javascript +myAppModule.controller('MyController', [ '$scope', function($scope) { + $scope.obj = {data: json, options: { mode: 'tree' }}; + + $scope.btnClick = function() { + $scope.obj.options.mode = 'code'; //should switch you to code view + } +}); +``` +### Working with ng-model + +Any changes to Jsoneditor or ng-model are reflected instantly. + +Instead of `editor.get()` now you can simply access your `ng-model`, or `$scope.obj.data` in this case, to get or set values. + +If you would to get and set your JSON data as text (instead of JSON Objects), then you can set `prefix-text="true"` like this: + +```html +
+``` + +### Additional options + +There are some additional options specific to ng-jsoneditor only. + +`expanded`: can be set to either `true` or `false` to have Jsoneditor fully expanded or collapsed by default. + +`timeout`: the timeout interval after which the `ng-model` is updated to reflect changes in Jsoneditor (as described [here](https://github.com/josdejong/jsoneditor/issues/192)). Default is 100ms. + +### Jsoneditor direct access + +For more interaction with the Jsoneditor instance in the directive, we provide a direct access to it. +Using + +```html +
+``` + +the `$scope.editorLoaded` function will be called with the [Jsoneditor instance](https://github.com/josdejong/jsoneditor/blob/master/docs/api.md) as first argument + +```javascript +myAppModule.controller('MyController', [ '$scope', function($scope) { + + $scope.editorLoaded = function(jsonEditor){ + jsonEditor.expandAll() + }; + +}]); +``` + +### Licence + +The Artistic License 2.0: see LICENSE.md diff --git a/ui/app/bower_components/ng-jsoneditor/bower.json b/ui/app/bower_components/ng-jsoneditor/bower.json new file mode 100644 index 0000000..f4fb053 --- /dev/null +++ b/ui/app/bower_components/ng-jsoneditor/bower.json @@ -0,0 +1,25 @@ +{ + "name": "ng-jsoneditor", + "main": "ng-jsoneditor.min.js", + "homepage": "https://github.com/angular-tools/ng-jsoneditor", + "authors": [ + "angular-tools " + ], + "description": "Angular version of the insanely cool jsoneditor", + "keywords": [ + "jsoneditor" + ], + "bugs": "https://github.com/angular-tools/ng-jsoneditor/issues", + "license": "The Artistic License 2.0", + "dependencies": { + "angular": "~1.x", + "jsoneditor": "~4" + }, + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "test", + "tests" + ] +} diff --git a/ui/app/bower_components/ng-jsoneditor/ng-jsoneditor.js b/ui/app/bower_components/ng-jsoneditor/ng-jsoneditor.js new file mode 100644 index 0000000..b28635d --- /dev/null +++ b/ui/app/bower_components/ng-jsoneditor/ng-jsoneditor.js @@ -0,0 +1,105 @@ +(function () { + var module = angular.module('ng.jsoneditor', []); + module.constant('ngJsoneditorConfig', {}); + + module.directive('ngJsoneditor', ['ngJsoneditorConfig', '$timeout', function (ngJsoneditorConfig, $timeout) { + var defaults = ngJsoneditorConfig || {}; + + return { + restrict: 'A', + require: 'ngModel', + scope: {'options': '=', 'ngJsoneditor': '=', 'preferText': '='}, + link: function ($scope, element, attrs, ngModel) { + var debounceTo, debounceFrom; + var editor; + var internalTrigger = false; + + if (!angular.isDefined(window.JSONEditor)) { + throw new Error("Please add the jsoneditor.js script first!"); + } + + function _createEditor(options) { + var settings = angular.extend({}, defaults, options); + var theOptions = angular.extend({}, settings, { + change: function () { + if (typeof debounceTo !== 'undefined') { + $timeout.cancel(debounceTo); + } + + debounceTo = $timeout(function () { + if (editor) { + internalTrigger = true; + ngModel.$setViewValue($scope.preferText === true ? editor.getText() : editor.get()); + internalTrigger = false; + + if (settings && settings.hasOwnProperty('change')) { + settings.change(); + } + } + }, settings.timeout || 100); + } + }); + + element.html(''); + + var instance = new JSONEditor(element[0], theOptions); + + if ($scope.ngJsoneditor instanceof Function) { + $timeout(function () { $scope.ngJsoneditor(instance);}); + } + + return instance; + } + + $scope.$watch('options', function (newValue, oldValue) { + for (var k in newValue) { + if (newValue.hasOwnProperty(k)) { + var v = newValue[k]; + + if (newValue[k] !== oldValue[k]) { + if (k === 'mode') { + editor.setMode(v); + } else if (k === 'name') { + editor.setName(v); + } else { //other settings cannot be changed without re-creating the JsonEditor + editor = _createEditor(newValue); + $scope.updateJsonEditor(); + return; + } + } + } + } + }, true); + + $scope.$on('$destroy', function () { + //remove jsoneditor? + }); + + $scope.updateJsonEditor = function (newValue) { + if (internalTrigger) return; //ignore if called by $setViewValue + + if (typeof debounceFrom !== 'undefined') { + $timeout.cancel(debounceFrom); + } + + debounceFrom = $timeout(function () { + if (($scope.preferText === true) && !angular.isObject(ngModel.$viewValue)) { + editor.setText(ngModel.$viewValue || '{}'); + } else { + editor.set(ngModel.$viewValue || {}); + } + }, $scope.options.timeout || 100); + }; + + editor = _createEditor($scope.options); + + if ($scope.options.hasOwnProperty('expanded')) { + $timeout($scope.options.expanded ? function () {editor.expandAll()} : function () {editor.collapseAll()}, ($scope.options.timeout || 100) + 100); + } + + ngModel.$render = $scope.updateJsonEditor; + $scope.$watch(function () { return ngModel.$modelValue; }, $scope.updateJsonEditor, true); //if someone changes ng-model from outside + } + }; + }]); +})(); diff --git a/ui/app/bower_components/ng-jsoneditor/ng-jsoneditor.min.js b/ui/app/bower_components/ng-jsoneditor/ng-jsoneditor.min.js new file mode 100644 index 0000000..e419679 --- /dev/null +++ b/ui/app/bower_components/ng-jsoneditor/ng-jsoneditor.min.js @@ -0,0 +1 @@ +(function(){var module=angular.module("ng.jsoneditor",[]);module.constant("ngJsoneditorConfig",{});module.directive("ngJsoneditor",["ngJsoneditorConfig","$timeout",function(ngJsoneditorConfig,$timeout){var defaults=ngJsoneditorConfig||{};return{restrict:"A",require:"ngModel",scope:{options:"=",ngJsoneditor:"=",preferText:"="},link:function($scope,element,attrs,ngModel){var debounceTo,debounceFrom;var editor;var internalTrigger=false;if(!angular.isDefined(window.JSONEditor)){throw new Error("Please add the jsoneditor.js script first!")}function _createEditor(options){var settings=angular.extend({},defaults,options);var theOptions=angular.extend({},settings,{change:function(){if(typeof debounceTo!=="undefined"){$timeout.cancel(debounceTo)}debounceTo=$timeout(function(){if(editor){internalTrigger=true;ngModel.$setViewValue($scope.preferText===true?editor.getText():editor.get());internalTrigger=false;if(settings&&settings.hasOwnProperty("change")){settings.change()}}},settings.timeout||100)}});element.html("");var instance=new JSONEditor(element[0],theOptions);if($scope.ngJsoneditor instanceof Function){$timeout(function(){$scope.ngJsoneditor(instance)})}return instance}$scope.$watch("options",function(newValue,oldValue){for(var k in newValue){if(newValue.hasOwnProperty(k)){var v=newValue[k];if(newValue[k]!==oldValue[k]){if(k==="mode"){editor.setMode(v)}else if(k==="name"){editor.setName(v)}else{editor=_createEditor(newValue);$scope.updateJsonEditor();return}}}}},true);$scope.$on("$destroy",function(){});$scope.updateJsonEditor=function(newValue){if(internalTrigger)return;if(typeof debounceFrom!=="undefined"){$timeout.cancel(debounceFrom)}debounceFrom=$timeout(function(){if($scope.preferText===true&&!angular.isObject(ngModel.$viewValue)){editor.setText(ngModel.$viewValue||"{}")}else{editor.set(ngModel.$viewValue||{})}},$scope.options.timeout||100)};editor=_createEditor($scope.options);if($scope.options.hasOwnProperty("expanded")){$timeout($scope.options.expanded?function(){editor.expandAll()}:function(){editor.collapseAll()},($scope.options.timeout||100)+100)}ngModel.$render=$scope.updateJsonEditor;$scope.$watch(function(){return ngModel.$modelValue},$scope.updateJsonEditor,true)}}}])})(); \ No newline at end of file diff --git a/ui/app/bower_components/ng-jsoneditor/ng-jsoneditor.min.min.js b/ui/app/bower_components/ng-jsoneditor/ng-jsoneditor.min.min.js new file mode 100644 index 0000000..e419679 --- /dev/null +++ b/ui/app/bower_components/ng-jsoneditor/ng-jsoneditor.min.min.js @@ -0,0 +1 @@ +(function(){var module=angular.module("ng.jsoneditor",[]);module.constant("ngJsoneditorConfig",{});module.directive("ngJsoneditor",["ngJsoneditorConfig","$timeout",function(ngJsoneditorConfig,$timeout){var defaults=ngJsoneditorConfig||{};return{restrict:"A",require:"ngModel",scope:{options:"=",ngJsoneditor:"=",preferText:"="},link:function($scope,element,attrs,ngModel){var debounceTo,debounceFrom;var editor;var internalTrigger=false;if(!angular.isDefined(window.JSONEditor)){throw new Error("Please add the jsoneditor.js script first!")}function _createEditor(options){var settings=angular.extend({},defaults,options);var theOptions=angular.extend({},settings,{change:function(){if(typeof debounceTo!=="undefined"){$timeout.cancel(debounceTo)}debounceTo=$timeout(function(){if(editor){internalTrigger=true;ngModel.$setViewValue($scope.preferText===true?editor.getText():editor.get());internalTrigger=false;if(settings&&settings.hasOwnProperty("change")){settings.change()}}},settings.timeout||100)}});element.html("");var instance=new JSONEditor(element[0],theOptions);if($scope.ngJsoneditor instanceof Function){$timeout(function(){$scope.ngJsoneditor(instance)})}return instance}$scope.$watch("options",function(newValue,oldValue){for(var k in newValue){if(newValue.hasOwnProperty(k)){var v=newValue[k];if(newValue[k]!==oldValue[k]){if(k==="mode"){editor.setMode(v)}else if(k==="name"){editor.setName(v)}else{editor=_createEditor(newValue);$scope.updateJsonEditor();return}}}}},true);$scope.$on("$destroy",function(){});$scope.updateJsonEditor=function(newValue){if(internalTrigger)return;if(typeof debounceFrom!=="undefined"){$timeout.cancel(debounceFrom)}debounceFrom=$timeout(function(){if($scope.preferText===true&&!angular.isObject(ngModel.$viewValue)){editor.setText(ngModel.$viewValue||"{}")}else{editor.set(ngModel.$viewValue||{})}},$scope.options.timeout||100)};editor=_createEditor($scope.options);if($scope.options.hasOwnProperty("expanded")){$timeout($scope.options.expanded?function(){editor.expandAll()}:function(){editor.collapseAll()},($scope.options.timeout||100)+100)}ngModel.$render=$scope.updateJsonEditor;$scope.$watch(function(){return ngModel.$modelValue},$scope.updateJsonEditor,true)}}}])})(); \ No newline at end of file diff --git a/ui/app/index.html b/ui/app/index.html index b746cf1..7656a78 100644 --- a/ui/app/index.html +++ b/ui/app/index.html @@ -14,6 +14,7 @@ + @@ -70,6 +71,8 @@ + + diff --git a/ui/app/scripts/app.js b/ui/app/scripts/app.js index 659faa1..8bff13d 100644 --- a/ui/app/scripts/app.js +++ b/ui/app/scripts/app.js @@ -9,7 +9,7 @@ * Main module of the application. */ -angular.module('tNovaApp', ['ui.router', 'ngSanitize', 'tNovaApp.config', 'tNovaApp.controllers', 'tNovaApp.directives', 'tNovaApp.services', 'smart-table', 'mgcrea.ngStrap', 'LocalStorageModule', 'cb.x2js', 'darthwade.dwLoading', 'checklist-model', 'angularResizable', 'FBAngular']) +angular.module('tNovaApp', ['ui.router', 'ngSanitize', 'tNovaApp.config', 'tNovaApp.controllers', 'tNovaApp.directives', 'tNovaApp.services', 'smart-table', 'mgcrea.ngStrap', 'LocalStorageModule', 'cb.x2js', 'darthwade.dwLoading', 'checklist-model', 'angularResizable', 'FBAngular', 'ng.jsoneditor']) .config(function (localStorageServiceProvider) { localStorageServiceProvider .setPrefix('tNovaApp') diff --git a/ui/app/scripts/controllers/nsController.js b/ui/app/scripts/controllers/nsController.js index bbb7b02..b4f58b5 100644 --- a/ui/app/scripts/controllers/nsController.js +++ b/ui/app/scripts/controllers/nsController.js @@ -3,12 +3,15 @@ angular.module('tNovaApp') .controller('nsController', function ($scope, $stateParams, $filter, tenorService, $interval, $modal, $location, AuthService, $window, $alert) { + $scope.descriptor = {}; + $scope.descriptor_options = { mode: 'code' }; + $scope.obj = {data: {}, options: { mode: 'code' }}; + $scope.registeredDcList = []; tenorService.get("modules/services/type/mapping").then(function (data) { if (data === undefined) return; $scope.serviceMapping = data; }); - $scope.descriptor = {}; var page_num = 20; var page = 1; $scope.dataCollection = []; @@ -25,9 +28,14 @@ angular.module('tNovaApp') }); }; + $scope.restartServiceList = function (page) { + $scope.dataCollection = []; + $scope.getServiceList(page); + }; + $scope.getServiceList(page); var promise = $interval(function () { - $scope.getServiceList(page); + $scope.restartServiceList(page); }, defaultTimer); $scope.deleteDialog = function (id) { @@ -41,7 +49,7 @@ angular.module('tNovaApp') }; $scope.deleteItem = function (id) { tenorService.delete('network-services/' + id).then(function (data) { - $scope.getServiceList(); + $scope.restartServiceList(1); }); this.$hide(); }; @@ -67,6 +75,7 @@ angular.module('tNovaApp') $scope.getPoPs(); $scope.nsd = nsd; $scope.object = {}; + $scope.object.vnfds = nsd.vnfds; $scope.object.ns_id = nsd.id; $scope.object.callbackUrl = "https://httpbin.org/post"; $scope.object.pop_id = null; @@ -155,12 +164,13 @@ angular.module('tNovaApp') $scope.uploadFile = function(files){ var fd = new FormData(); //Take the first selected file - fd.append('file', files[0]); - var obj = JSON.parse(files); + //fd.append('file', files[0]); + //var obj = JSON.parse(files); + var obj = files; console.log(obj); tenorService.post('network-services', obj).then(function (data) { console.log(data); - $scope.getServiceList(page); + $scope.restartServiceList(1); }); this.$hide(); } @@ -170,7 +180,8 @@ angular.module('tNovaApp') var reader = new FileReader(); reader.onload = function () { //event waits the file content $scope.$apply(function () { - $scope.descriptor = JSON.stringify(JSON.parse(reader.result), undefined, 4); //JSON.parse(reader.result); + //$scope.descriptor = JSON.stringify(JSON.parse(reader.result), undefined, 4); //JSON.parse(reader.result); + $scope.obj.data = JSON.parse(reader.result); //JSON.parse(reader.result); }); }; reader.readAsText(file); diff --git a/ui/app/scripts/controllers/vnfController.js b/ui/app/scripts/controllers/vnfController.js index b339f59..854430c 100644 --- a/ui/app/scripts/controllers/vnfController.js +++ b/ui/app/scripts/controllers/vnfController.js @@ -4,6 +4,8 @@ angular.module('tNovaApp') .controller('vnfController', function ($scope, $stateParams, $filter, tenorService, $interval, $modal) { $scope.descriptor = {}; + $scope.descriptor_options = { mode: 'code' }; + $scope.obj = {data: {}, options: { mode: 'code' }}; var page_num = 20; var page = 1; $scope.dataCollection = []; @@ -20,6 +22,11 @@ angular.module('tNovaApp') }); }; + $scope.restartServiceList = function (page) { + $scope.dataCollection = []; + $scope.getVnfList(page); + }; + $scope.getVnfList(page); var promise = $interval(function () { $scope.dataCollection = []; @@ -37,7 +44,7 @@ angular.module('tNovaApp') }; $scope.deleteItem = function (id) { tenorService.delete('vnfs/' + id).then(function (data) { - $scope.getVnfList(page); + $scope.restartServiceList(1); }); this.$hide(); }; @@ -71,12 +78,13 @@ angular.module('tNovaApp') $scope.uploadFile = function(files){ var fd = new FormData(); //Take the first selected file - fd.append('file', files[0]); - var obj = JSON.parse(files); + //fd.append('file', files[0]); + //var obj = JSON.parse(files); + var obj = files; console.log(obj); tenorService.post('vnfs', obj).then(function (data) { console.log(data); - $scope.getVnfList(page); + $scope.restartServiceList(1); }); this.$hide(); } @@ -86,7 +94,8 @@ angular.module('tNovaApp') var reader = new FileReader(); reader.onload = function () { //event waits the file content $scope.$apply(function () { - $scope.descriptor = JSON.stringify(JSON.parse(reader.result), undefined, 4); //JSON.parse(reader.result); + //$scope.descriptor = JSON.stringify(JSON.parse(reader.result), undefined, 4); //JSON.parse(reader.result); + $scope.obj.data = JSON.parse(reader.result); //JSON.parse(reader.result); }); }; reader.readAsText(file); diff --git a/ui/app/scripts/directives/modalScroll.js b/ui/app/scripts/directives/modalScroll.js index 7d3e524..308539c 100644 --- a/ui/app/scripts/directives/modalScroll.js +++ b/ui/app/scripts/directives/modalScroll.js @@ -10,11 +10,11 @@ angular.module('tNovaApp') }, function (newValue, oldValue) { var windowElement = angular.element($window); var scrollHeight = element[0].scrollHeight; - if (scrollHeight + 180 > windowElement.height()) { - console.log("Set bigger") - element.css('height', windowElement.height() - 200); + if (scrollHeight + 180 < windowElement.height()) { + console.log("Set bigger"); + element.css('height', windowElement.height() - 220); } else { - console.log("Set small") + console.log("Set small"); if(scrollHeight == 22) element.css('height', windowElement.height() - 200); else element.css('height', scrollHeight); } diff --git a/ui/app/views/t-nova/modals/upload.html b/ui/app/views/t-nova/modals/upload.html index ff9f2f1..182b4ea 100644 --- a/ui/app/views/t-nova/modals/upload.html +++ b/ui/app/views/t-nova/modals/upload.html @@ -17,13 +17,14 @@
diff --git a/ui/bower.json b/ui/bower.json index a040a01..1a96b86 100644 --- a/ui/bower.json +++ b/ui/bower.json @@ -31,7 +31,9 @@ "angular-resizable": "^1.2.0", "tv4": "^1.2.7", "angular-fullscreen": "^1.0.1", - "bootstrap-additions": "^0.3.1" + "bootstrap-additions": "^0.3.1", + "jsoneditor": "^5.5.10", + "ng-jsoneditor": "angular-tools/ng-jsoneditor#^1.0.0" }, "devDependencies": { "angular-mocks": "^1.3.0" From ce4db5d99ad4b91cc5f37236ce4cbbb5a6008307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Mon, 7 Nov 2016 10:38:38 +0100 Subject: [PATCH 23/35] Updated Angular version from 1.4.1 to 1.5.8 --- ui/app/bower_components/angular/.bower.json | 11 +- ui/app/bower_components/angular/LICENSE.md | 21 + ui/app/bower_components/angular/angular.js | 8398 ++++++++++++----- .../bower_components/angular/angular.min.js | 600 +- .../angular/angular.min.js.gzip | Bin 51566 -> 56905 bytes .../angular/angular.min.js.map | 6 +- ui/app/bower_components/angular/bower.json | 3 +- ui/app/bower_components/angular/package.json | 2 +- 8 files changed, 6283 insertions(+), 2758 deletions(-) create mode 100644 ui/app/bower_components/angular/LICENSE.md diff --git a/ui/app/bower_components/angular/.bower.json b/ui/app/bower_components/angular/.bower.json index ff3b166..ab17812 100644 --- a/ui/app/bower_components/angular/.bower.json +++ b/ui/app/bower_components/angular/.bower.json @@ -1,17 +1,18 @@ { "name": "angular", - "version": "1.4.1", + "version": "1.5.8", + "license": "MIT", "main": "./angular.js", "ignore": [], "dependencies": {}, "homepage": "https://github.com/angular/bower-angular", - "_release": "1.4.1", + "_release": "1.5.8", "_resolution": { "type": "version", - "tag": "v1.4.1", - "commit": "00565b0834478e6a5b4d8ca0373b109c9d963f4b" + "tag": "v1.5.8", + "commit": "7e0e546eb6caedbb298c91a9f6bf7de7eeaa4ad2" }, "_source": "https://github.com/angular/bower-angular.git", - "_target": "^1.0.8", + "_target": ">=1.0.8", "_originalSource": "angular" } \ No newline at end of file diff --git a/ui/app/bower_components/angular/LICENSE.md b/ui/app/bower_components/angular/LICENSE.md new file mode 100644 index 0000000..2c395ee --- /dev/null +++ b/ui/app/bower_components/angular/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Angular + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/ui/app/bower_components/angular/angular.js b/ui/app/bower_components/angular/angular.js index c147ec5..54f6558 100644 --- a/ui/app/bower_components/angular/angular.js +++ b/ui/app/bower_components/angular/angular.js @@ -1,9 +1,9 @@ /** - * @license AngularJS v1.4.1 - * (c) 2010-2015 Google, Inc. http://angularjs.org + * @license AngularJS v1.5.8 + * (c) 2010-2016 Google, Inc. http://angularjs.org * License: MIT */ -(function(window, document, undefined) {'use strict'; +(function(window) {'use strict'; /** * @description @@ -57,7 +57,7 @@ function minErr(module, ErrorConstructor) { return match; }); - message += '\nhttp://errors.angularjs.org/1.4.1/' + + message += '\nhttp://errors.angularjs.org/1.5.8/' + (module ? module + '/' : '') + code; for (i = SKIP_INDEXES, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') { @@ -126,7 +126,6 @@ function minErr(module, ErrorConstructor) { includes: true, arrayRemove: true, copy: true, - shallowCopy: true, equals: true, csp: true, jq: true, @@ -171,6 +170,7 @@ function minErr(module, ErrorConstructor) { * @ngdoc module * @name ng * @module ng + * @installation * @description * * # ng (core module) @@ -188,29 +188,9 @@ var REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/; // This is used so that it's possible for internal tests to create mock ValidityStates. var VALIDITY_STATE_PROPERTY = 'validity'; -/** - * @ngdoc function - * @name angular.lowercase - * @module ng - * @kind function - * - * @description Converts the specified string to lowercase. - * @param {string} string String to be converted to lowercase. - * @returns {string} Lowercased string. - */ -var lowercase = function(string) {return isString(string) ? string.toLowerCase() : string;}; var hasOwnProperty = Object.prototype.hasOwnProperty; -/** - * @ngdoc function - * @name angular.uppercase - * @module ng - * @kind function - * - * @description Converts the specified string to uppercase. - * @param {string} string String to be converted to uppercase. - * @returns {string} Uppercased string. - */ +var lowercase = function(string) {return isString(string) ? string.toLowerCase() : string;}; var uppercase = function(string) {return isString(string) ? string.toUpperCase() : string;}; @@ -230,7 +210,7 @@ var manualUppercase = function(s) { // String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish // locale, for this reason we need to detect this case and redefine lowercase/uppercase methods -// with correct but slower alternatives. +// with correct but slower alternatives. See https://github.com/angular/angular.js/issues/11387 if ('i' !== 'I'.toLowerCase()) { lowercase = manualLowercase; uppercase = manualUppercase; @@ -257,7 +237,7 @@ var * documentMode is an IE-only property * http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx */ -msie = document.documentMode; +msie = window.document.documentMode; /** @@ -267,20 +247,25 @@ msie = document.documentMode; * String ...) */ function isArrayLike(obj) { - if (obj == null || isWindow(obj)) { - return false; - } + + // `null`, `undefined` and `window` are not array-like + if (obj == null || isWindow(obj)) return false; + + // arrays, strings and jQuery/jqLite objects are array like + // * jqLite is either the jQuery or jqLite constructor function + // * we have to check the existence of jqLite first as this method is called + // via the forEach method when constructing the jqLite object in the first place + if (isArray(obj) || isString(obj) || (jqLite && obj instanceof jqLite)) return true; // Support: iOS 8.2 (not reproducible in simulator) // "length" in obj used to prevent JIT error (gh-11508) var length = "length" in Object(obj) && obj.length; - if (obj.nodeType === NODE_TYPE_ELEMENT && length) { - return true; - } + // NodeList objects (with `item` method) and + // other objects with suitable length characteristics are array-like + return isNumber(length) && + (length >= 0 && ((length - 1) in obj || obj instanceof Array) || typeof obj.item == 'function'); - return isString(obj) || isArray(obj) || length === 0 || - typeof length === 'number' && length > 0 && (length - 1) in obj; } /** @@ -300,7 +285,7 @@ function isArrayLike(obj) { * * Unlike ES262's * [Array.prototype.forEach](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18), - * Providing 'undefined' or 'null' values for `obj` will not throw a TypeError, but rather just + * providing 'undefined' or 'null' values for `obj` will not throw a TypeError, but rather just * return the value provided. * ```js @@ -377,7 +362,7 @@ function forEachSorted(obj, iterator, context) { * @returns {function(*, string)} */ function reverseParams(iteratorFn) { - return function(value, key) { iteratorFn(key, value); }; + return function(value, key) {iteratorFn(key, value);}; } /** @@ -421,8 +406,18 @@ function baseExtend(dst, objs, deep) { var src = obj[key]; if (deep && isObject(src)) { - if (!isObject(dst[key])) dst[key] = isArray(src) ? [] : {}; - baseExtend(dst[key], [src], true); + if (isDate(src)) { + dst[key] = new Date(src.valueOf()); + } else if (isRegExp(src)) { + dst[key] = new RegExp(src); + } else if (src.nodeName) { + dst[key] = src.cloneNode(true); + } else if (isElement(src)) { + dst[key] = src.clone(); + } else { + if (!isObject(dst[key])) dst[key] = isArray(src) ? [] : {}; + baseExtend(dst[key], [src], true); + } } else { dst[key] = src; } @@ -520,18 +515,33 @@ noop.$inject = []; * functional style. * ```js - function transformer(transformationFn, value) { - return (transformationFn || angular.identity)(value); - }; + function transformer(transformationFn, value) { + return (transformationFn || angular.identity)(value); + }; + + // E.g. + function getResult(fn, input) { + return (fn || angular.identity)(input); + }; + + getResult(function(n) { return n * 2; }, 21); // returns 42 + getResult(null, 21); // returns 21 + getResult(undefined, 21); // returns 21 ``` - * @param {*} value to be returned. - * @returns {*} the value passed in. + * + * @param {*} value to be returned. + * @returns {*} the value passed in. */ function identity($) {return $;} identity.$inject = []; -function valueFn(value) {return function() {return value;};} +function valueFn(value) {return function valueRef() {return value;};} + +function hasCustomToString(obj) { + return isFunction(obj.toString) && obj.toString !== toString; +} + /** * @ngdoc function @@ -728,9 +738,13 @@ function isPromiseLike(obj) { } -var TYPED_ARRAY_REGEXP = /^\[object (Uint8(Clamped)?)|(Uint16)|(Uint32)|(Int8)|(Int16)|(Int32)|(Float(32)|(64))Array\]$/; +var TYPED_ARRAY_REGEXP = /^\[object (?:Uint8|Uint8Clamped|Uint16|Uint32|Int8|Int16|Int32|Float32|Float64)Array\]$/; function isTypedArray(value) { - return TYPED_ARRAY_REGEXP.test(toString.call(value)); + return value && isNumber(value.length) && TYPED_ARRAY_REGEXP.test(toString.call(value)); +} + +function isArrayBuffer(obj) { + return toString.call(obj) === '[object ArrayBuffer]'; } @@ -761,8 +775,8 @@ var escapeForRegexp = function(s) { */ function isElement(node) { return !!(node && - (node.nodeName // we are a direct element - || (node.prop && node.attr && node.find))); // we have an on and find method part of jQuery API + (node.nodeName // We are a direct element. + || (node.prop && node.attr && node.find))); // We have an on and find method part of jQuery API. } /** @@ -770,7 +784,7 @@ function isElement(node) { * @returns {object} in the form of {key1:true, key2:true, ...} */ function makeMap(str) { - var obj = {}, items = str.split(","), i; + var obj = {}, items = str.split(','), i; for (i = 0; i < items.length; i++) { obj[items[i]] = true; } @@ -807,7 +821,13 @@ function arrayRemove(array, value) { * * If a destination is provided, all of its elements (for arrays) or properties (for objects) * are deleted and then all elements/properties from the source are copied to it. * * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned. - * * If `source` is identical to 'destination' an exception will be thrown. + * * If `source` is identical to `destination` an exception will be thrown. + * + *
+ *
+ * Only enumerable properties are taken into account. Non-enumerable properties (both on `source` + * and on `destination`) will be ignored. + *
* * @param {*} source The source that will be used to make a copy. * Can be any type, including primitives, `null`, and `undefined`. @@ -816,159 +836,178 @@ function arrayRemove(array, value) { * @returns {*} The copy or updated `destination`, if `destination` was specified. * * @example - - -
- - Name:
- E-mail:
- Gender: male - female
- - - -
form = {{user | json}}
-
master = {{master | json}}
-
- - -
-
+ $scope.reset(); + }]); + + */ -function copy(source, destination, stackSource, stackDest) { - if (isWindow(source) || isScope(source)) { - throw ngMinErr('cpws', - "Can't copy! Making copies of Window or Scope instances is not supported."); - } - if (isTypedArray(destination)) { - throw ngMinErr('cpta', - "Can't copy! TypedArray destination cannot be mutated."); - } - - if (!destination) { - destination = source; - if (isObject(source)) { - var index; - if (stackSource && (index = stackSource.indexOf(source)) !== -1) { - return stackDest[index]; - } - - // TypedArray, Date and RegExp have specific copy functionality and must be - // pushed onto the stack before returning. - // Array and other objects create the base object and recurse to copy child - // objects. The array/object will be pushed onto the stack when recursed. - if (isArray(source)) { - return copy(source, [], stackSource, stackDest); - } else if (isTypedArray(source)) { - destination = new source.constructor(source); - } else if (isDate(source)) { - destination = new Date(source.getTime()); - } else if (isRegExp(source)) { - destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]); - destination.lastIndex = source.lastIndex; - } else { - var emptyObject = Object.create(getPrototypeOf(source)); - return copy(source, emptyObject, stackSource, stackDest); - } +function copy(source, destination) { + var stackSource = []; + var stackDest = []; - if (stackDest) { - stackSource.push(source); - stackDest.push(destination); - } + if (destination) { + if (isTypedArray(destination) || isArrayBuffer(destination)) { + throw ngMinErr('cpta', "Can't copy! TypedArray destination cannot be mutated."); } - } else { - if (source === destination) throw ngMinErr('cpi', - "Can't copy! Source and destination are identical."); - - stackSource = stackSource || []; - stackDest = stackDest || []; - - if (isObject(source)) { - stackSource.push(source); - stackDest.push(destination); + if (source === destination) { + throw ngMinErr('cpi', "Can't copy! Source and destination are identical."); } - var result, key; - if (isArray(source)) { + // Empty the destination object + if (isArray(destination)) { destination.length = 0; - for (var i = 0; i < source.length; i++) { - destination.push(copy(source[i], null, stackSource, stackDest)); - } } else { - var h = destination.$$hashKey; - if (isArray(destination)) { - destination.length = 0; - } else { - forEach(destination, function(value, key) { + forEach(destination, function(value, key) { + if (key !== '$$hashKey') { delete destination[key]; - }); - } - if (isBlankObject(source)) { - // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty - for (key in source) { - destination[key] = copy(source[key], null, stackSource, stackDest); } - } else if (source && typeof source.hasOwnProperty === 'function') { - // Slow path, which must rely on hasOwnProperty - for (key in source) { - if (source.hasOwnProperty(key)) { - destination[key] = copy(source[key], null, stackSource, stackDest); - } + }); + } + + stackSource.push(source); + stackDest.push(destination); + return copyRecurse(source, destination); + } + + return copyElement(source); + + function copyRecurse(source, destination) { + var h = destination.$$hashKey; + var key; + if (isArray(source)) { + for (var i = 0, ii = source.length; i < ii; i++) { + destination.push(copyElement(source[i])); + } + } else if (isBlankObject(source)) { + // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty + for (key in source) { + destination[key] = copyElement(source[key]); + } + } else if (source && typeof source.hasOwnProperty === 'function') { + // Slow path, which must rely on hasOwnProperty + for (key in source) { + if (source.hasOwnProperty(key)) { + destination[key] = copyElement(source[key]); } - } else { - // Slowest path --- hasOwnProperty can't be called as a method - for (key in source) { - if (hasOwnProperty.call(source, key)) { - destination[key] = copy(source[key], null, stackSource, stackDest); - } + } + } else { + // Slowest path --- hasOwnProperty can't be called as a method + for (key in source) { + if (hasOwnProperty.call(source, key)) { + destination[key] = copyElement(source[key]); } } - setHashKey(destination,h); } + setHashKey(destination, h); + return destination; } - return destination; -} -/** - * Creates a shallow copy of an object, an array or a primitive. - * - * Assumes that there are no proto properties for objects. - */ -function shallowCopy(src, dst) { - if (isArray(src)) { - dst = dst || []; + function copyElement(source) { + // Simple values + if (!isObject(source)) { + return source; + } - for (var i = 0, ii = src.length; i < ii; i++) { - dst[i] = src[i]; + // Already copied values + var index = stackSource.indexOf(source); + if (index !== -1) { + return stackDest[index]; } - } else if (isObject(src)) { - dst = dst || {}; - for (var key in src) { - if (!(key.charAt(0) === '$' && key.charAt(1) === '$')) { - dst[key] = src[key]; - } + if (isWindow(source) || isScope(source)) { + throw ngMinErr('cpws', + "Can't copy! Making copies of Window or Scope instances is not supported."); + } + + var needsRecurse = false; + var destination = copyType(source); + + if (destination === undefined) { + destination = isArray(source) ? [] : Object.create(getPrototypeOf(source)); + needsRecurse = true; } + + stackSource.push(source); + stackDest.push(destination); + + return needsRecurse + ? copyRecurse(source, destination) + : destination; } - return dst || src; + function copyType(source) { + switch (toString.call(source)) { + case '[object Int8Array]': + case '[object Int16Array]': + case '[object Int32Array]': + case '[object Float32Array]': + case '[object Float64Array]': + case '[object Uint8Array]': + case '[object Uint8ClampedArray]': + case '[object Uint16Array]': + case '[object Uint32Array]': + return new source.constructor(copyElement(source.buffer), source.byteOffset, source.length); + + case '[object ArrayBuffer]': + //Support: IE10 + if (!source.slice) { + var copied = new ArrayBuffer(source.byteLength); + new Uint8Array(copied).set(new Uint8Array(source)); + return copied; + } + return source.slice(0); + + case '[object Boolean]': + case '[object Number]': + case '[object String]': + case '[object Date]': + return new source.constructor(source.valueOf()); + + case '[object RegExp]': + var re = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]); + re.lastIndex = source.lastIndex; + return re; + + case '[object Blob]': + return new source.constructor([source], {type: source.type}); + } + + if (isFunction(source.cloneNode)) { + return source.cloneNode(true); + } + } } @@ -1000,66 +1039,117 @@ function shallowCopy(src, dst) { * @param {*} o1 Object or value to compare. * @param {*} o2 Object or value to compare. * @returns {boolean} True if arguments are equal. + * + * @example + + +
+
+

User 1

+ Name: + Age: + +

User 2

+ Name: + Age: + +
+
+ +
+ User 1:
{{user1 | json}}
+ User 2:
{{user2 | json}}
+ Equal:
{{result}}
+
+
+
+ + angular.module('equalsExample', []).controller('ExampleController', ['$scope', function($scope) { + $scope.user1 = {}; + $scope.user2 = {}; + $scope.result; + $scope.compare = function() { + $scope.result = angular.equals($scope.user1, $scope.user2); + }; + }]); + +
*/ function equals(o1, o2) { if (o1 === o2) return true; if (o1 === null || o2 === null) return false; if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN var t1 = typeof o1, t2 = typeof o2, length, key, keySet; - if (t1 == t2) { - if (t1 == 'object') { - if (isArray(o1)) { - if (!isArray(o2)) return false; - if ((length = o1.length) == o2.length) { - for (key = 0; key < length; key++) { - if (!equals(o1[key], o2[key])) return false; - } - return true; - } - } else if (isDate(o1)) { - if (!isDate(o2)) return false; - return equals(o1.getTime(), o2.getTime()); - } else if (isRegExp(o1)) { - return isRegExp(o2) ? o1.toString() == o2.toString() : false; - } else { - if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || - isArray(o2) || isDate(o2) || isRegExp(o2)) return false; - keySet = createMap(); - for (key in o1) { - if (key.charAt(0) === '$' || isFunction(o1[key])) continue; + if (t1 == t2 && t1 == 'object') { + if (isArray(o1)) { + if (!isArray(o2)) return false; + if ((length = o1.length) == o2.length) { + for (key = 0; key < length; key++) { if (!equals(o1[key], o2[key])) return false; - keySet[key] = true; - } - for (key in o2) { - if (!(key in keySet) && - key.charAt(0) !== '$' && - o2[key] !== undefined && - !isFunction(o2[key])) return false; } return true; } + } else if (isDate(o1)) { + if (!isDate(o2)) return false; + return equals(o1.getTime(), o2.getTime()); + } else if (isRegExp(o1)) { + if (!isRegExp(o2)) return false; + return o1.toString() == o2.toString(); + } else { + if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || + isArray(o2) || isDate(o2) || isRegExp(o2)) return false; + keySet = createMap(); + for (key in o1) { + if (key.charAt(0) === '$' || isFunction(o1[key])) continue; + if (!equals(o1[key], o2[key])) return false; + keySet[key] = true; + } + for (key in o2) { + if (!(key in keySet) && + key.charAt(0) !== '$' && + isDefined(o2[key]) && + !isFunction(o2[key])) return false; + } + return true; } } return false; } var csp = function() { - if (isDefined(csp.isActive_)) return csp.isActive_; + if (!isDefined(csp.rules)) { + + + var ngCspElement = (window.document.querySelector('[ng-csp]') || + window.document.querySelector('[data-ng-csp]')); + + if (ngCspElement) { + var ngCspAttribute = ngCspElement.getAttribute('ng-csp') || + ngCspElement.getAttribute('data-ng-csp'); + csp.rules = { + noUnsafeEval: !ngCspAttribute || (ngCspAttribute.indexOf('no-unsafe-eval') !== -1), + noInlineStyle: !ngCspAttribute || (ngCspAttribute.indexOf('no-inline-style') !== -1) + }; + } else { + csp.rules = { + noUnsafeEval: noUnsafeEval(), + noInlineStyle: false + }; + } + } - var active = !!(document.querySelector('[ng-csp]') || - document.querySelector('[data-ng-csp]')); + return csp.rules; - if (!active) { + function noUnsafeEval() { try { /* jshint -W031, -W054 */ new Function(''); /* jshint +W031, +W054 */ + return false; } catch (e) { - active = true; + return true; } } - - return (csp.isActive_ = active); }; /** @@ -1106,7 +1196,7 @@ var jq = function() { var i, ii = ngAttrPrefixes.length, prefix, name; for (i = 0; i < ii; ++i) { prefix = ngAttrPrefixes[i]; - if (el = document.querySelector('[' + prefix.replace(':', '\\:') + 'jq]')) { + if (el = window.document.querySelector('[' + prefix.replace(':', '\\:') + 'jq]')) { name = el.getAttribute(prefix + 'jq'); break; } @@ -1158,7 +1248,7 @@ function bind(self, fn) { : fn.call(self); }; } else { - // in IE, native methods are not functions so they cannot be bound (note: they don't need to be) + // In IE, native methods are not functions so they cannot be bound (note: they don't need to be). return fn; } } @@ -1171,7 +1261,7 @@ function toJsonReplacer(key, value) { val = undefined; } else if (isWindow(value)) { val = '$WINDOW'; - } else if (value && document === value) { + } else if (value && window.document === value) { val = '$DOCUMENT'; } else if (isScope(value)) { val = '$SCOPE'; @@ -1195,9 +1285,30 @@ function toJsonReplacer(key, value) { * @param {boolean|number} [pretty=2] If set to true, the JSON output will contain newlines and whitespace. * If set to an integer, the JSON output will contain that many spaces per indentation. * @returns {string|undefined} JSON-ified string representing `obj`. + * @knownIssue + * + * The Safari browser throws a `RangeError` instead of returning `null` when it tries to stringify a `Date` + * object with an invalid date value. The only reliable way to prevent this is to monkeypatch the + * `Date.prototype.toJSON` method as follows: + * + * ``` + * var _DatetoJSON = Date.prototype.toJSON; + * Date.prototype.toJSON = function() { + * try { + * return _DatetoJSON.call(this); + * } catch(e) { + * if (e instanceof RangeError) { + * return null; + * } + * throw e; + * } + * }; + * ``` + * + * See https://github.com/angular/angular.js/pull/14221 for more information. */ function toJson(obj, pretty) { - if (typeof obj === 'undefined') return undefined; + if (isUndefined(obj)) return undefined; if (!isNumber(pretty)) { pretty = pretty ? 2 : null; } @@ -1224,7 +1335,10 @@ function fromJson(json) { } +var ALL_COLONS = /:/g; function timezoneToOffset(timezone, fallback) { + // IE/Edge do not "understand" colon (`:`) in timezone + timezone = timezone.replace(ALL_COLONS, ''); var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000; return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset; } @@ -1239,8 +1353,9 @@ function addDateMinutes(date, minutes) { function convertTimezoneToLocal(date, timezone, reverse) { reverse = reverse ? -1 : 1; - var timezoneOffset = timezoneToOffset(timezone, date.getTimezoneOffset()); - return addDateMinutes(date, reverse * (timezoneOffset - date.getTimezoneOffset())); + var dateTimezoneOffset = date.getTimezoneOffset(); + var timezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset); + return addDateMinutes(date, reverse * (timezoneOffset - dateTimezoneOffset)); } @@ -1259,7 +1374,7 @@ function startingTag(element) { return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) : elemHtml. match(/^(<[^>]+>)/)[1]. - replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); }); + replace(/^<([\w\-]+)/, function(match, nodeName) {return '<' + lowercase(nodeName);}); } catch (e) { return lowercase(elemHtml); } @@ -1281,7 +1396,7 @@ function tryDecodeURIComponent(value) { try { return decodeURIComponent(value); } catch (e) { - // Ignore any invalid uri component + // Ignore any invalid uri component. } } @@ -1291,13 +1406,19 @@ function tryDecodeURIComponent(value) { * @returns {Object.} */ function parseKeyValue(/**string*/keyValue) { - var obj = {}, key_value, key; + var obj = {}; forEach((keyValue || "").split('&'), function(keyValue) { + var splitPoint, key, val; if (keyValue) { - key_value = keyValue.replace(/\+/g,'%20').split('='); - key = tryDecodeURIComponent(key_value[0]); + key = keyValue = keyValue.replace(/\+/g,'%20'); + splitPoint = keyValue.indexOf('='); + if (splitPoint !== -1) { + key = keyValue.substring(0, splitPoint); + val = keyValue.substring(splitPoint + 1); + } + key = tryDecodeURIComponent(key); if (isDefined(key)) { - var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true; + val = isDefined(val) ? tryDecodeURIComponent(val) : true; if (!hasOwnProperty.call(obj, key)) { obj[key] = val; } else if (isArray(obj[key])) { @@ -1401,10 +1522,17 @@ function getNgAttribute(element, ngAttr) { * designates the **root element** of the application and is typically placed near the root element * of the page - e.g. on the `` or `` tags. * - * Only one AngularJS application can be auto-bootstrapped per HTML document. The first `ngApp` - * found in the document will be used to define the root element to auto-bootstrap as an - * application. To run multiple applications in an HTML document you must manually bootstrap them using - * {@link angular.bootstrap} instead. AngularJS applications cannot be nested within each other. + * There are a few things to keep in mind when using `ngApp`: + * - only one AngularJS application can be auto-bootstrapped per HTML document. The first `ngApp` + * found in the document will be used to define the root element to auto-bootstrap as an + * application. To run multiple applications in an HTML document you must manually bootstrap them using + * {@link angular.bootstrap} instead. + * - AngularJS applications cannot be nested within each other. + * - Do not use a directive that uses {@link ng.$compile#transclusion transclusion} on the same element as `ngApp`. + * This includes directives such as {@link ng.ngIf `ngIf`}, {@link ng.ngInclude `ngInclude`} and + * {@link ngRoute.ngView `ngView`}. + * Doing this misplaces the app {@link ng.$rootElement `$rootElement`} and the app's {@link auto.$injector injector}, + * causing animations to stop working and making the injector inaccessible from outside the app. * * You can specify an **AngularJS module** to be used as the root module for the application. This * module will be loaded into the {@link auto.$injector} when the application is bootstrapped. It @@ -1513,7 +1641,7 @@ function angularInit(element, bootstrap) { module, config = {}; - // The element `element` has priority over any other element + // The element `element` has priority over any other element. forEach(ngAttrPrefixes, function(prefix) { var name = prefix + 'app'; @@ -1544,16 +1672,25 @@ function angularInit(element, bootstrap) { * @description * Use this function to manually start up angular application. * - * See: {@link guide/bootstrap Bootstrap} - * - * Note that Protractor based end-to-end tests cannot use this function to bootstrap manually. - * They must use {@link ng.directive:ngApp ngApp}. + * For more information, see the {@link guide/bootstrap Bootstrap guide}. * * Angular will detect if it has been loaded into the browser more than once and only allow the * first loaded script to be bootstrapped and will report a warning to the browser console for * each of the subsequent scripts. This prevents strange results in applications, where otherwise * multiple instances of Angular try to work on the DOM. * + *
+ * **Note:** Protractor based end-to-end tests cannot use this function to bootstrap manually. + * They must use {@link ng.directive:ngApp ngApp}. + *
+ * + *
+ * **Note:** Do not bootstrap the app on an element with a directive that uses {@link ng.$compile#transclusion transclusion}, + * such as {@link ng.ngIf `ngIf`}, {@link ng.ngInclude `ngInclude`} and {@link ngRoute.ngView `ngView`}. + * Doing this misplaces the app {@link ng.$rootElement `$rootElement`} and the app's {@link auto.$injector injector}, + * causing animations to stop working and making the injector inaccessible from outside the app. + *
+ * * ```html * * @@ -1597,11 +1734,11 @@ function bootstrap(element, modules, config) { element = jqLite(element); if (element.injector()) { - var tag = (element[0] === document) ? 'document' : startingTag(element); - //Encode angle brackets to prevent input from being sanitized to empty string #8683 + var tag = (element[0] === window.document) ? 'document' : startingTag(element); + // Encode angle brackets to prevent input from being sanitized to empty string #8683. throw ngMinErr( 'btstrpd', - "App Already Bootstrapped with this Element '{0}'", + "App already bootstrapped with this element '{0}'", tag.replace(//,'>')); } @@ -1696,7 +1833,6 @@ function snake_case(name, separator) { } var bindJQueryFired = false; -var skipDestroyOnNextJQueryCleanData; function bindJQuery() { var originalCleanData; @@ -1706,10 +1842,9 @@ function bindJQuery() { // bind to jQuery if present; var jqName = jq(); - jQuery = window.jQuery; // use default jQuery. - if (isDefined(jqName)) { // `ngJq` present - jQuery = jqName === null ? undefined : window[jqName]; // if empty; use jqLite. if not empty, use jQuery specified by `ngJq`. - } + jQuery = isUndefined(jqName) ? window.jQuery : // use jQuery (if present) + !jqName ? undefined : // use jqLite + window[jqName]; // use jQuery specified by `ngJq` // Use jQuery if it exists with proper functionality, otherwise default to us. // Angular 1.2+ requires jQuery 1.7+ for on()/off() support. @@ -1731,15 +1866,11 @@ function bindJQuery() { originalCleanData = jQuery.cleanData; jQuery.cleanData = function(elems) { var events; - if (!skipDestroyOnNextJQueryCleanData) { - for (var i = 0, elem; (elem = elems[i]) != null; i++) { - events = jQuery._data(elem, "events"); - if (events && events.$destroy) { - jQuery(elem).triggerHandler('$destroy'); - } + for (var i = 0, elem; (elem = elems[i]) != null; i++) { + events = jQuery._data(elem, "events"); + if (events && events.$destroy) { + jQuery(elem).triggerHandler('$destroy'); } - } else { - skipDestroyOnNextJQueryCleanData = false; } originalCleanData(elems); }; @@ -1814,22 +1945,24 @@ function getter(obj, path, bindFnToScope) { /** * Return the DOM siblings between the first and last node in the given array. * @param {Array} array like object - * @returns {jqLite} jqLite collection containing the nodes + * @returns {Array} the inputted object or a jqLite collection containing the nodes */ function getBlockNodes(nodes) { - // TODO(perf): just check if all items in `nodes` are siblings and if they are return the original - // collection, otherwise update the original collection. + // TODO(perf): update `nodes` instead of creating a new object? var node = nodes[0]; var endNode = nodes[nodes.length - 1]; - var blockNodes = [node]; + var blockNodes; - do { - node = node.nextSibling; - if (!node) break; - blockNodes.push(node); - } while (node !== endNode); + for (var i = 1; node !== endNode && (node = node.nextSibling); i++) { + if (blockNodes || nodes[i] !== node) { + if (!blockNodes) { + blockNodes = jqLite(slice.call(nodes, 0, i)); + } + blockNodes.push(node); + } + } - return jqLite(blockNodes); + return blockNodes || nodes; } @@ -1893,8 +2026,8 @@ function setupModuleLoader(window) { * All modules (angular core or 3rd party) that should be available to an application must be * registered using this mechanism. * - * When passed two or more arguments, a new module is created. If passed only one argument, an - * existing module (the name passed as the first argument to `module`) is retrieved. + * Passing one argument retrieves an existing {@link angular.Module}, + * whereas passing more than one argument creates a new {@link angular.Module} * * * # Module @@ -1931,7 +2064,7 @@ function setupModuleLoader(window) { * unspecified then the module is being retrieved for further configuration. * @param {Function=} configFn Optional configuration function for the module. Same as * {@link angular.Module#config Module#config()}. - * @returns {module} new module with the {@link angular.Module} api. + * @returns {angular.Module} new module with the {@link angular.Module} api. */ return function module(name, requires, configFn) { var assertNotHasOwnProperty = function(name, context) { @@ -2043,7 +2176,7 @@ function setupModuleLoader(window) { * @param {string} name constant name * @param {*} object Constant value. * @description - * Because the constant are fixed, they get applied before other provide methods. + * Because the constants are fixed, they get applied before other provide methods. * See {@link auto.$provide#constant $provide.constant()}. */ constant: invokeLater('$provide', 'constant', 'unshift'), @@ -2052,9 +2185,9 @@ function setupModuleLoader(window) { * @ngdoc method * @name angular.Module#decorator * @module ng - * @param {string} The name of the service to decorate. - * @param {Function} This function will be invoked when the service needs to be - * instantiated and should return the decorated service instance. + * @param {string} name The name of the service to decorate. + * @param {Function} decorFn This function will be invoked when the service needs to be + * instantiated and should return the decorated service instance. * @description * See {@link auto.$provide#decorator $provide.decorator()}. */ @@ -2137,6 +2270,19 @@ function setupModuleLoader(window) { */ directive: invokeLaterAndSetModuleName('$compileProvider', 'directive'), + /** + * @ngdoc method + * @name angular.Module#component + * @module ng + * @param {string} name Name of the component in camel-case (i.e. myComp which will match as my-comp) + * @param {Object} options Component definition object (a simplified + * {@link ng.$compile#directive-definition-object directive definition object}) + * + * @description + * See {@link ng.$compileProvider#component $compileProvider.component()}. + */ + component: invokeLaterAndSetModuleName('$compileProvider', 'component'), + /** * @ngdoc method * @name angular.Module#config @@ -2204,7 +2350,34 @@ function setupModuleLoader(window) { } -/* global: toDebugString: true */ +/* global shallowCopy: true */ + +/** + * Creates a shallow copy of an object, an array or a primitive. + * + * Assumes that there are no proto properties for objects. + */ +function shallowCopy(src, dst) { + if (isArray(src)) { + dst = dst || []; + + for (var i = 0, ii = src.length; i < ii; i++) { + dst[i] = src[i]; + } + } else if (isObject(src)) { + dst = dst || {}; + + for (var key in src) { + if (!(key.charAt(0) === '$' && key.charAt(1) === '$')) { + dst[key] = src[key]; + } + } + } + + return dst || src; +} + +/* global toDebugString: true */ function serializeObject(obj) { var seen = []; @@ -2213,7 +2386,7 @@ function serializeObject(obj) { val = toJsonReplacer(key, val); if (isObject(val)) { - if (seen.indexOf(val) >= 0) return '<>'; + if (seen.indexOf(val) >= 0) return '...'; seen.push(val); } @@ -2224,7 +2397,7 @@ function serializeObject(obj) { function toDebugString(obj) { if (typeof obj === 'function') { return obj.toString().replace(/ \{[\s\S]*$/, ''); - } else if (typeof obj === 'undefined') { + } else if (isUndefined(obj)) { return 'undefined'; } else if (typeof obj !== 'string') { return serializeObject(obj); @@ -2235,7 +2408,6 @@ function toDebugString(obj) { /* global angularModule: true, version: true, - $LocaleProvider, $CompileProvider, htmlAnchorDirective, @@ -2252,7 +2424,6 @@ function toDebugString(obj) { ngClassDirective, ngClassEvenDirective, ngClassOddDirective, - ngCspDirective, ngCloakDirective, ngControllerDirective, ngFormDirective, @@ -2289,14 +2460,19 @@ function toDebugString(obj) { $AnchorScrollProvider, $AnimateProvider, + $CoreAnimateCssProvider, + $$CoreAnimateJsProvider, $$CoreAnimateQueueProvider, - $$CoreAnimateRunnerProvider, + $$AnimateRunnerFactoryProvider, + $$AnimateAsyncRunFactoryProvider, $BrowserProvider, $CacheFactoryProvider, $ControllerProvider, + $DateProvider, $DocumentProvider, $ExceptionHandlerProvider, $FilterProvider, + $$ForceReflowProvider, $InterpolateProvider, $IntervalProvider, $$HashMapProvider, @@ -2304,6 +2480,8 @@ function toDebugString(obj) { $HttpParamSerializerProvider, $HttpParamSerializerJQLikeProvider, $HttpBackendProvider, + $xhrFactoryProvider, + $jsonpCallbacksProvider, $LocationProvider, $LogProvider, $ParseProvider, @@ -2319,7 +2497,6 @@ function toDebugString(obj) { $$TestabilityProvider, $TimeoutProvider, $$RAFProvider, - $$AsyncCallbackProvider, $WindowProvider, $$jqLiteProvider, $$CookieReaderProvider @@ -2331,8 +2508,9 @@ function toDebugString(obj) { * @name angular.version * @module ng * @description - * An object that contains information about the current AngularJS version. This object has the - * following properties: + * An object that contains information about the current AngularJS version. + * + * This object has the following properties: * * - `full` – `{string}` – Full version string, such as "0.9.18". * - `major` – `{number}` – Major version number, such as "0". @@ -2341,11 +2519,11 @@ function toDebugString(obj) { * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat". */ var version = { - full: '1.4.1', // all of these placeholder strings will be replaced by grunt's + full: '1.5.8', // all of these placeholder strings will be replaced by grunt's major: 1, // package task - minor: 4, - dot: 1, - codeName: 'hyperionic-illumination' + minor: 5, + dot: 8, + codeName: 'arbitrary-fallbacks' }; @@ -2376,7 +2554,7 @@ function publishExternalAPI(angular) { 'isDate': isDate, 'lowercase': lowercase, 'uppercase': uppercase, - 'callbacks': {counter: 0}, + 'callbacks': {$$counter: 0}, 'getTestability': getTestability, '$$minErr': minErr, '$$csp': csp, @@ -2384,11 +2562,6 @@ function publishExternalAPI(angular) { }); angularModule = setupModuleLoader(window); - try { - angularModule('ngLocale'); - } catch (e) { - angularModule('ngLocale', []).provider('$locale', $LocaleProvider); - } angularModule('ng', ['ngLocale'], ['$provide', function ngModule($provide) { @@ -2451,20 +2624,26 @@ function publishExternalAPI(angular) { $provide.provider({ $anchorScroll: $AnchorScrollProvider, $animate: $AnimateProvider, + $animateCss: $CoreAnimateCssProvider, + $$animateJs: $$CoreAnimateJsProvider, $$animateQueue: $$CoreAnimateQueueProvider, - $$AnimateRunner: $$CoreAnimateRunnerProvider, + $$AnimateRunner: $$AnimateRunnerFactoryProvider, + $$animateAsyncRun: $$AnimateAsyncRunFactoryProvider, $browser: $BrowserProvider, $cacheFactory: $CacheFactoryProvider, $controller: $ControllerProvider, $document: $DocumentProvider, $exceptionHandler: $ExceptionHandlerProvider, $filter: $FilterProvider, + $$forceReflow: $$ForceReflowProvider, $interpolate: $InterpolateProvider, $interval: $IntervalProvider, $http: $HttpProvider, $httpParamSerializer: $HttpParamSerializerProvider, $httpParamSerializerJQLike: $HttpParamSerializerJQLikeProvider, $httpBackend: $HttpBackendProvider, + $xhrFactory: $xhrFactoryProvider, + $jsonpCallbacks: $jsonpCallbacksProvider, $location: $LocationProvider, $log: $LogProvider, $parse: $ParseProvider, @@ -2480,7 +2659,6 @@ function publishExternalAPI(angular) { $timeout: $TimeoutProvider, $window: $WindowProvider, $$rAF: $$RAFProvider, - $$asyncCallback: $$AsyncCallbackProvider, $$jqLite: $$jqLiteProvider, $$HashMap: $$HashMapProvider, $$cookieReader: $$CookieReaderProvider @@ -2522,21 +2700,27 @@ function publishExternalAPI(angular) { * * If jQuery is available, `angular.element` is an alias for the * [jQuery](http://api.jquery.com/jQuery/) function. If jQuery is not available, `angular.element` - * delegates to Angular's built-in subset of jQuery, called "jQuery lite" or "jqLite." + * delegates to Angular's built-in subset of jQuery, called "jQuery lite" or **jqLite**. + * + * jqLite is a tiny, API-compatible subset of jQuery that allows + * Angular to manipulate the DOM in a cross-browser compatible way. jqLite implements only the most + * commonly needed functionality with the goal of having a very small footprint. * - *
jqLite is a tiny, API-compatible subset of jQuery that allows - * Angular to manipulate the DOM in a cross-browser compatible way. **jqLite** implements only the most - * commonly needed functionality with the goal of having a very small footprint.
+ * To use `jQuery`, simply ensure it is loaded before the `angular.js` file. You can also use the + * {@link ngJq `ngJq`} directive to specify that jqlite should be used over jQuery, or to use a + * specific version of jQuery if multiple versions exist on the page. * - * To use `jQuery`, simply ensure it is loaded before the `angular.js` file. + *
**Note:** All element references in Angular are always wrapped with jQuery or + * jqLite (such as the element argument in a directive's compile / link function). They are never raw DOM references.
* - *
**Note:** all element references in Angular are always wrapped with jQuery or - * jqLite; they are never raw DOM references.
+ *
**Note:** Keep in mind that this function will not find elements + * by tag name / CSS selector. For lookups by tag name, try instead `angular.element(document).find(...)` + * or `$document.find()`, or use the standard DOM APIs, e.g. `document.querySelectorAll()`.
* * ## Angular's jqLite * jqLite provides only the following jQuery methods: * - * - [`addClass()`](http://api.jquery.com/addClass/) + * - [`addClass()`](http://api.jquery.com/addClass/) - Does not support a function as first argument * - [`after()`](http://api.jquery.com/after/) * - [`append()`](http://api.jquery.com/append/) * - [`attr()`](http://api.jquery.com/attr/) - Does not support functions as parameters @@ -2544,7 +2728,8 @@ function publishExternalAPI(angular) { * - [`children()`](http://api.jquery.com/children/) - Does not support selectors * - [`clone()`](http://api.jquery.com/clone/) * - [`contents()`](http://api.jquery.com/contents/) - * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`. As a setter, does not convert numbers to strings or append 'px'. + * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`. + * As a setter, does not convert numbers to strings or append 'px', and also does not have automatic property prefixing. * - [`data()`](http://api.jquery.com/data/) * - [`detach()`](http://api.jquery.com/detach/) * - [`empty()`](http://api.jquery.com/empty/) @@ -2554,7 +2739,7 @@ function publishExternalAPI(angular) { * - [`html()`](http://api.jquery.com/html/) * - [`next()`](http://api.jquery.com/next/) - Does not support selectors * - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData - * - [`off()`](http://api.jquery.com/off/) - Does not support namespaces or selectors + * - [`off()`](http://api.jquery.com/off/) - Does not support namespaces, selectors or event object as parameter * - [`one()`](http://api.jquery.com/one/) - Does not support namespaces or selectors * - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors * - [`prepend()`](http://api.jquery.com/prepend/) @@ -2562,13 +2747,13 @@ function publishExternalAPI(angular) { * - [`ready()`](http://api.jquery.com/ready/) * - [`remove()`](http://api.jquery.com/remove/) * - [`removeAttr()`](http://api.jquery.com/removeAttr/) - * - [`removeClass()`](http://api.jquery.com/removeClass/) + * - [`removeClass()`](http://api.jquery.com/removeClass/) - Does not support a function as first argument * - [`removeData()`](http://api.jquery.com/removeData/) * - [`replaceWith()`](http://api.jquery.com/replaceWith/) * - [`text()`](http://api.jquery.com/text/) - * - [`toggleClass()`](http://api.jquery.com/toggleClass/) - * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers. - * - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces + * - [`toggleClass()`](http://api.jquery.com/toggleClass/) - Does not support a function as first argument + * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers + * - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces or event object as parameter * - [`val()`](http://api.jquery.com/val/) * - [`wrap()`](http://api.jquery.com/wrap/) * @@ -2596,6 +2781,9 @@ function publishExternalAPI(angular) { * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top * parent element is reached. * + * @knownIssue You cannot spy on `angular.element` if you are using Jasmine version 1.x. See + * https://github.com/angular/angular.js/issues/14251 for more information. + * * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery. * @returns {Object} jQuery object. */ @@ -2640,10 +2828,10 @@ function camelCase(name) { replace(MOZ_HACK_REGEXP, 'Moz$1'); } -var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/; +var SINGLE_TAG_REGEXP = /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/; var HTML_REGEXP = /<|&#?\w+;/; -var TAG_NAME_REGEXP = /<([\w:]+)/; -var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi; +var TAG_NAME_REGEXP = /<([\w:-]+)/; +var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi; var wrapMap = { 'option': [1, ''], @@ -2678,6 +2866,12 @@ function jqLiteHasData(node) { return false; } +function jqLiteCleanData(nodes) { + for (var i = 0, ii = nodes.length; i < ii; i++) { + jqLiteRemoveData(nodes[i]); + } +} + function jqLiteBuildFragment(html, context) { var tmp, tag, wrap, fragment = context.createDocumentFragment(), @@ -2688,7 +2882,7 @@ function jqLiteBuildFragment(html, context) { nodes.push(context.createTextNode(html)); } else { // Convert html into DOM nodes - tmp = tmp || fragment.appendChild(context.createElement("div")); + tmp = fragment.appendChild(context.createElement("div")); tag = (TAG_NAME_REGEXP.exec(html) || ["", ""])[1].toLowerCase(); wrap = wrapMap[tag] || wrapMap._default; tmp.innerHTML = wrap[1] + html.replace(XHTML_TAG_REGEXP, "<$1>") + wrap[2]; @@ -2716,7 +2910,7 @@ function jqLiteBuildFragment(html, context) { } function jqLiteParseHTML(html, context) { - context = context || document; + context = context || window.document; var parsed; if ((parsed = SINGLE_TAG_REGEXP.exec(html))) { @@ -2730,6 +2924,24 @@ function jqLiteParseHTML(html, context) { return []; } +function jqLiteWrapNode(node, wrapper) { + var parent = node.parentNode; + + if (parent) { + parent.replaceChild(wrapper, node); + } + + wrapper.appendChild(node); +} + + +// IE9-11 has no method "contains" in SVG element and in Node.prototype. Bug #10259. +var jqLiteContains = window.Node.prototype.contains || function(arg) { + // jshint bitwise: false + return !!(this.compareDocumentPosition(arg) & 16); + // jshint bitwise: true +}; + ///////////////////////////////////////////// function JQLite(element) { if (element instanceof JQLite) { @@ -2788,17 +3000,23 @@ function jqLiteOff(element, type, fn, unsupported) { delete events[type]; } } else { - forEach(type.split(' '), function(type) { + + var removeHandler = function(type) { + var listenerFns = events[type]; if (isDefined(fn)) { - var listenerFns = events[type]; arrayRemove(listenerFns || [], fn); - if (listenerFns && listenerFns.length > 0) { - return; - } } + if (!(isDefined(fn) && listenerFns && listenerFns.length > 0)) { + removeEventListenerFn(element, type, handle); + delete events[type]; + } + }; - removeEventListenerFn(element, type, handle); - delete events[type]; + forEach(type.split(' '), function(type) { + removeHandler(type); + if (MOUSE_EVENT_MAP[type]) { + removeHandler(MOUSE_EVENT_MAP[type]); + } }); } } @@ -2939,7 +3157,7 @@ function jqLiteInheritedData(element, name, value) { while (element) { for (var i = 0, ii = names.length; i < ii; i++) { - if ((value = jqLite.data(element, names[i])) !== undefined) return value; + if (isDefined(value = jqLite.data(element, names[i]))) return value; } // If dealing with a document fragment node with a host element, and no parent, use the host @@ -2966,7 +3184,7 @@ function jqLiteRemove(element, keepData) { function jqLiteDocumentLoaded(action, win) { win = win || window; if (win.document.readyState === 'complete') { - // Force the action to be run async for consistent behaviour + // Force the action to be run async for consistent behavior // from the action's point of view // i.e. it will definitely not be in a $apply win.setTimeout(action); @@ -2990,8 +3208,8 @@ var JQLitePrototype = JQLite.prototype = { } // check if document is already loaded - if (document.readyState === 'complete') { - setTimeout(trigger); + if (window.document.readyState === 'complete') { + window.setTimeout(trigger); } else { this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9 // we can not use jqLite since we are not done loading and jQuery could be loaded later. @@ -3045,15 +3263,15 @@ function getBooleanAttrName(element, name) { return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr; } -function getAliasedAttrName(element, name) { - var nodeName = element.nodeName; - return (nodeName === 'INPUT' || nodeName === 'TEXTAREA') && ALIASED_ATTR[name]; +function getAliasedAttrName(name) { + return ALIASED_ATTR[name]; } forEach({ data: jqLiteData, removeData: jqLiteRemoveData, - hasData: jqLiteHasData + hasData: jqLiteHasData, + cleanData: jqLiteCleanData }, function(fn, name) { JQLite[name] = fn; }); @@ -3184,7 +3402,7 @@ forEach({ // in a way that survives minification. // jqLiteEmpty takes no arguments but is a setter. if (fn !== jqLiteEmpty && - (((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2) === undefined)) { + (isUndefined((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2))) { if (isObject(arg1)) { // we are a write, but the object properties are the key/values @@ -3205,7 +3423,7 @@ forEach({ // TODO: do we still need this? var value = fn.$dv; // Only if we have $dv do we iterate over all, otherwise it is just the first element. - var jj = (value === undefined) ? Math.min(nodeCount, 1) : nodeCount; + var jj = (isUndefined(value)) ? Math.min(nodeCount, 1) : nodeCount; for (var j = 0; j < jj; j++) { var nodeValue = fn(this[j], arg1, arg2); value = value ? value + nodeValue : nodeValue; @@ -3254,6 +3472,9 @@ function createEventHandler(element, events) { return event.immediatePropagationStopped === true; }; + // Some events have special handlers that wrap the real handler + var handlerWrapper = eventFns.specialHandlerWrapper || defaultHandlerWrapper; + // Copy event handlers in case event handlers array is modified during execution. if ((eventFnsLength > 1)) { eventFns = shallowCopy(eventFns); @@ -3261,7 +3482,7 @@ function createEventHandler(element, events) { for (var i = 0; i < eventFnsLength; i++) { if (!event.isImmediatePropagationStopped()) { - eventFns[i].call(element, event); + handlerWrapper(element, event, eventFns[i]); } } }; @@ -3272,6 +3493,22 @@ function createEventHandler(element, events) { return eventHandler; } +function defaultHandlerWrapper(element, event, handler) { + handler.call(element, event); +} + +function specialMouseHandlerWrapper(target, event, handler) { + // Refer to jQuery's implementation of mouseenter & mouseleave + // Read about mouseenter and mouseleave: + // http://www.quirksmode.org/js/events_mouse.html#link8 + var related = event.relatedTarget; + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if (!related || (related !== target && !jqLiteContains.call(target, related))) { + handler.call(target, event); + } +} + ////////////////////////////////////////// // Functions iterating traversal. // These functions chain results into a single @@ -3300,35 +3537,28 @@ forEach({ var types = type.indexOf(' ') >= 0 ? type.split(' ') : [type]; var i = types.length; - while (i--) { - type = types[i]; + var addHandler = function(type, specialHandlerWrapper, noEventListener) { var eventFns = events[type]; if (!eventFns) { - events[type] = []; - - if (type === 'mouseenter' || type === 'mouseleave') { - // Refer to jQuery's implementation of mouseenter & mouseleave - // Read about mouseenter and mouseleave: - // http://www.quirksmode.org/js/events_mouse.html#link8 - - jqLiteOn(element, MOUSE_EVENT_MAP[type], function(event) { - var target = this, related = event.relatedTarget; - // For mousenter/leave call the handler if related is outside the target. - // NB: No relatedTarget if the mouse left/entered the browser window - if (!related || (related !== target && !target.contains(related))) { - handle(event, type); - } - }); - - } else { - if (type !== '$destroy') { - addEventListenerFn(element, type, handle); - } + eventFns = events[type] = []; + eventFns.specialHandlerWrapper = specialHandlerWrapper; + if (type !== '$destroy' && !noEventListener) { + addEventListenerFn(element, type, handle); } - eventFns = events[type]; } + eventFns.push(fn); + }; + + while (i--) { + type = types[i]; + if (MOUSE_EVENT_MAP[type]) { + addHandler(MOUSE_EVENT_MAP[type], specialMouseHandlerWrapper); + addHandler(type, undefined, true); + } else { + addHandler(type); + } } }, @@ -3396,12 +3626,7 @@ forEach({ }, wrap: function(element, wrapNode) { - wrapNode = jqLite(wrapNode).eq(0).clone()[0]; - var parent = element.parentNode; - if (parent) { - parent.replaceChild(wrapNode, element); - } - wrapNode.appendChild(element); + jqLiteWrapNode(element, jqLite(wrapNode).eq(0).clone()[0]); }, remove: jqLiteRemove, @@ -3674,22 +3899,37 @@ var $$HashMapProvider = [function() { /** * @ngdoc module * @name auto + * @installation * @description * * Implicit module which gets automatically added to each {@link auto.$injector $injector}. */ -var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m; +var ARROW_ARG = /^([^\(]+?)=>/; +var FN_ARGS = /^[^\(]*\(\s*([^\)]*)\)/m; var FN_ARG_SPLIT = /,/; var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/; var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; var $injectorMinErr = minErr('$injector'); +function stringifyFn(fn) { + // Support: Chrome 50-51 only + // Creating a new string by adding `' '` at the end, to hack around some bug in Chrome v50/51 + // (See https://github.com/angular/angular.js/issues/14487.) + // TODO (gkalpak): Remove workaround when Chrome v52 is released + return Function.prototype.toString.call(fn) + ' '; +} + +function extractArgs(fn) { + var fnText = stringifyFn(fn).replace(STRIP_COMMENTS, ''), + args = fnText.match(ARROW_ARG) || fnText.match(FN_ARGS); + return args; +} + function anonFn(fn) { // For anonymous functions, showing at the very least the function signature can help in // debugging. - var fnText = fn.toString().replace(STRIP_COMMENTS, ''), - args = fnText.match(FN_ARGS); + var args = extractArgs(fn); if (args) { return 'function(' + (args[1] || '').replace(/[\s\r\n]+/, ' ') + ')'; } @@ -3698,7 +3938,6 @@ function anonFn(fn) { function annotate(fn, strictDi, name) { var $inject, - fnText, argDecl, last; @@ -3713,8 +3952,7 @@ function annotate(fn, strictDi, name) { throw $injectorMinErr('strictdi', '{0} is not using explicit annotation and cannot be invoked in strict mode', name); } - fnText = fn.toString().replace(STRIP_COMMENTS, ''); - argDecl = fnText.match(FN_ARGS); + argDecl = extractArgs(fn); forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg) { arg.replace(FN_ARG, function(all, underscore, name) { $inject.push(name); @@ -3951,18 +4189,20 @@ function annotate(fn, strictDi, name) { * these cases the {@link auto.$provide $provide} service has additional helper methods to register * services without specifying a provider. * - * * {@link auto.$provide#provider provider(provider)} - registers a **service provider** with the + * * {@link auto.$provide#provider provider(name, provider)} - registers a **service provider** with the * {@link auto.$injector $injector} - * * {@link auto.$provide#constant constant(obj)} - registers a value/object that can be accessed by + * * {@link auto.$provide#constant constant(name, obj)} - registers a value/object that can be accessed by * providers and services. - * * {@link auto.$provide#value value(obj)} - registers a value/object that can only be accessed by + * * {@link auto.$provide#value value(name, obj)} - registers a value/object that can only be accessed by * services, not providers. - * * {@link auto.$provide#factory factory(fn)} - registers a service **factory function**, `fn`, + * * {@link auto.$provide#factory factory(name, fn)} - registers a service **factory function** * that will be wrapped in a **service provider** object, whose `$get` property will contain the * given factory function. - * * {@link auto.$provide#service service(class)} - registers a **constructor function**, `class` + * * {@link auto.$provide#service service(name, Fn)} - registers a **constructor function** * that will be wrapped in a **service provider** object, whose `$get` property will instantiate * a new object using the given constructor function. + * * {@link auto.$provide#decorator decorator(name, decorFn)} - registers a **decorator function** that + * will be able to modify or replace the implementation of another service. * * See the individual methods for more information and examples. */ @@ -4104,14 +4344,26 @@ function annotate(fn, strictDi, name) { * * Register a **service constructor**, which will be invoked with `new` to create the service * instance. - * This is short for registering a service where its provider's `$get` property is the service - * constructor function that will be used to instantiate the service instance. + * This is short for registering a service where its provider's `$get` property is a factory + * function that returns an instance instantiated by the injector from the service constructor + * function. * - * You should use {@link auto.$provide#service $provide.service(class)} if you define your service - * as a type/class. + * Internally it looks a bit like this: * - * @param {string} name The name of the instance. - * @param {Function|Array.} constructor An injectable class (constructor function) + * ``` + * { + * $get: function() { + * return $injector.instantiate(constructor); + * } + * } + * ``` + * + * + * You should use {@link auto.$provide#service $provide.service(class)} if you define your service + * as a type/class. + * + * @param {string} name The name of the instance. + * @param {Function|Array.} constructor An injectable class (constructor function) * that will be instantiated. * @returns {Object} registered provider instance * @@ -4145,14 +4397,13 @@ function annotate(fn, strictDi, name) { * @description * * Register a **value service** with the {@link auto.$injector $injector}, such as a string, a - * number, an array, an object or a function. This is short for registering a service where its + * number, an array, an object or a function. This is short for registering a service where its * provider's `$get` property is a factory function that takes no arguments and returns the **value - * service**. + * service**. That also means it is not possible to inject other services into a value service. * * Value services are similar to constant services, except that they cannot be injected into a * module configuration function (see {@link angular.Module#config}) but they can be overridden by - * an Angular - * {@link auto.$provide#decorator decorator}. + * an Angular {@link auto.$provide#decorator decorator}. * * @param {string} name The name of the instance. * @param {*} value The value. @@ -4177,8 +4428,11 @@ function annotate(fn, strictDi, name) { * @name $provide#constant * @description * - * Register a **constant service**, such as a string, a number, an array, an object or a function, - * with the {@link auto.$injector $injector}. Unlike {@link auto.$provide#value value} it can be + * Register a **constant service** with the {@link auto.$injector $injector}, such as a string, + * a number, an array, an object or a function. Like the {@link auto.$provide#value value}, it is not + * possible to inject other services into a constant. + * + * But unlike {@link auto.$provide#value value}, a constant can be * injected into a module configuration function (see {@link angular.Module#config}) and it cannot * be overridden by an Angular {@link auto.$provide#decorator decorator}. * @@ -4205,18 +4459,20 @@ function annotate(fn, strictDi, name) { * @name $provide#decorator * @description * - * Register a **service decorator** with the {@link auto.$injector $injector}. A service decorator - * intercepts the creation of a service, allowing it to override or modify the behaviour of the - * service. The object returned by the decorator may be the original service, or a new service - * object which replaces or wraps and delegates to the original service. + * Register a **decorator function** with the {@link auto.$injector $injector}. A decorator function + * intercepts the creation of a service, allowing it to override or modify the behavior of the + * service. The return value of the decorator function may be the original service, or a new service + * that replaces (or wraps and delegates to) the original service. + * + * You can find out more about using decorators in the {@link guide/decorators} guide. * * @param {string} name The name of the service to decorate. * @param {Function|Array.} decorator This function will be invoked when the service needs to be - * instantiated and should return the decorated service instance. The function is called using + * provided and should return the decorated service instance. The function is called using * the {@link auto.$injector#invoke injector.invoke} method and is therefore fully injectable. * Local injection arguments: * - * * `$delegate` - The original service instance, which can be monkey patched, configured, + * * `$delegate` - The original service instance, which can be replaced, monkey patched, configured, * decorated or delegated to. * * @example @@ -4255,14 +4511,19 @@ function createInjector(modulesToLoad, strictDi) { throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- ')); })), instanceCache = {}, - instanceInjector = (instanceCache.$injector = + protoInstanceInjector = createInternalInjector(instanceCache, function(serviceName, caller) { var provider = providerInjector.get(serviceName + providerSuffix, caller); - return instanceInjector.invoke(provider.$get, provider, undefined, serviceName); - })); - + return instanceInjector.invoke( + provider.$get, provider, undefined, serviceName); + }), + instanceInjector = protoInstanceInjector; - forEach(loadModules(modulesToLoad), function(fn) { if (fn) instanceInjector.invoke(fn); }); + providerCache['$injector' + providerSuffix] = { $get: valueFn(protoInstanceInjector) }; + var runBlocks = loadModules(modulesToLoad); + instanceInjector = protoInstanceInjector.get('$injector'); + instanceInjector.strictDi = strictDi; + forEach(runBlocks, function(fn) { if (fn) instanceInjector.invoke(fn); }); return instanceInjector; @@ -4335,6 +4596,7 @@ function createInjector(modulesToLoad, strictDi) { // Module Loading //////////////////////////////////// function loadModules(modulesToLoad) { + assertArg(isUndefined(modulesToLoad) || isArray(modulesToLoad), 'modulesToLoad', 'not an array'); var runBlocks = [], moduleFn; forEach(modulesToLoad, function(module) { if (loadedModules.get(module)) return; @@ -4411,48 +4673,67 @@ function createInjector(modulesToLoad, strictDi) { } } - function invoke(fn, self, locals, serviceName) { - if (typeof locals === 'string') { - serviceName = locals; - locals = null; - } + function injectionArgs(fn, locals, serviceName) { var args = [], - $inject = createInjector.$$annotate(fn, strictDi, serviceName), - length, i, - key; + $inject = createInjector.$$annotate(fn, strictDi, serviceName); - for (i = 0, length = $inject.length; i < length; i++) { - key = $inject[i]; + for (var i = 0, length = $inject.length; i < length; i++) { + var key = $inject[i]; if (typeof key !== 'string') { throw $injectorMinErr('itkn', 'Incorrect injection token! Expected service name as string, got {0}', key); } - args.push( - locals && locals.hasOwnProperty(key) - ? locals[key] - : getService(key, serviceName) - ); + args.push(locals && locals.hasOwnProperty(key) ? locals[key] : + getService(key, serviceName)); + } + return args; + } + + function isClass(func) { + // IE 9-11 do not support classes and IE9 leaks with the code below. + if (msie <= 11) { + return false; + } + // Support: Edge 12-13 only + // See: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/6156135/ + return typeof func === 'function' + && /^(?:class\b|constructor\()/.test(stringifyFn(func)); + } + + function invoke(fn, self, locals, serviceName) { + if (typeof locals === 'string') { + serviceName = locals; + locals = null; } + + var args = injectionArgs(fn, locals, serviceName); if (isArray(fn)) { - fn = fn[length]; + fn = fn[fn.length - 1]; } - // http://jsperf.com/angularjs-invoke-apply-vs-switch - // #5388 - return fn.apply(self, args); + if (!isClass(fn)) { + // http://jsperf.com/angularjs-invoke-apply-vs-switch + // #5388 + return fn.apply(self, args); + } else { + args.unshift(null); + return new (Function.prototype.bind.apply(fn, args))(); + } } + function instantiate(Type, locals, serviceName) { // Check if Type is annotated and use just the given function at n-1 as parameter // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]); - // Object creation: http://jsperf.com/create-constructor/2 - var instance = Object.create((isArray(Type) ? Type[Type.length - 1] : Type).prototype || null); - var returnedValue = invoke(Type, instance, locals, serviceName); - - return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance; + var ctor = (isArray(Type) ? Type[Type.length - 1] : Type); + var args = injectionArgs(Type, locals, serviceName); + // Empty object at position 0 is ignored for invocation with `new`, but required. + args.unshift(null); + return new (Function.prototype.bind.apply(ctor, args))(); } + return { invoke: invoke, instantiate: instantiate, @@ -4508,7 +4789,7 @@ function $AnchorScrollProvider() { * When called, it scrolls to the element related to the specified `hash` or (if omitted) to the * current value of {@link ng.$location#hash $location.hash()}, according to the rules specified * in the - * [HTML5 spec](http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document). + * [HTML5 spec](http://www.w3.org/html/wg/drafts/html/master/browsers.html#an-indicated-part-of-the-document). * * It also watches the {@link ng.$location#hash $location.hash()} and automatically scrolls to * match any anchor whenever it changes. This can be disabled by calling @@ -4791,27 +5072,8 @@ function prepareAnimateOptions(options) { : {}; } -var $$CoreAnimateRunnerProvider = function() { - this.$get = ['$q', '$$rAF', function($q, $$rAF) { - function AnimateRunner() {} - AnimateRunner.all = noop; - AnimateRunner.chain = noop; - AnimateRunner.prototype = { - end: noop, - cancel: noop, - resume: noop, - pause: noop, - complete: noop, - then: function(pass, fail) { - return $q(function(resolve) { - $$rAF(function() { - resolve(); - }); - }).then(pass, fail); - } - }; - return AnimateRunner; - }]; +var $$CoreAnimateJsProvider = function() { + this.$get = noop; }; // this is prefixed with Core since it conflicts with @@ -4839,65 +5101,75 @@ var $$CoreAnimateQueueProvider = function() { addRemoveClassesPostDigest(element, options.addClass, options.removeClass); } - return new $$AnimateRunner(); // jshint ignore:line + var runner = new $$AnimateRunner(); // jshint ignore:line + + // since there are no animations to run the runner needs to be + // notified that the animation call is complete. + runner.complete(); + return runner; } }; - function addRemoveClassesPostDigest(element, add, remove) { - var data = postDigestQueue.get(element); - var classVal; - - if (!data) { - postDigestQueue.put(element, data = {}); - postDigestElements.push(element); - } - if (add) { - forEach(add.split(' '), function(className) { + function updateData(data, classes, value) { + var changed = false; + if (classes) { + classes = isString(classes) ? classes.split(' ') : + isArray(classes) ? classes : []; + forEach(classes, function(className) { if (className) { - data[className] = true; + changed = true; + data[className] = value; } }); } + return changed; + } + + function handleCSSClassChanges() { + forEach(postDigestElements, function(element) { + var data = postDigestQueue.get(element); + if (data) { + var existing = splitClasses(element.attr('class')); + var toAdd = ''; + var toRemove = ''; + forEach(data, function(status, className) { + var hasClass = !!existing[className]; + if (status !== hasClass) { + if (status) { + toAdd += (toAdd.length ? ' ' : '') + className; + } else { + toRemove += (toRemove.length ? ' ' : '') + className; + } + } + }); - if (remove) { - forEach(remove.split(' '), function(className) { - if (className) { - data[className] = false; - } - }); - } + forEach(element, function(elm) { + toAdd && jqLiteAddClass(elm, toAdd); + toRemove && jqLiteRemoveClass(elm, toRemove); + }); + postDigestQueue.remove(element); + } + }); + postDigestElements.length = 0; + } - if (postDigestElements.length > 1) return; - - $rootScope.$$postDigest(function() { - forEach(postDigestElements, function(element) { - var data = postDigestQueue.get(element); - if (data) { - var existing = splitClasses(element.attr('class')); - var toAdd = ''; - var toRemove = ''; - forEach(data, function(status, className) { - var hasClass = !!existing[className]; - if (status !== hasClass) { - if (status) { - toAdd += (toAdd.length ? ' ' : '') + className; - } else { - toRemove += (toRemove.length ? ' ' : '') + className; - } - } - }); - forEach(element, function(elm) { - toAdd && jqLiteAddClass(elm, toAdd); - toRemove && jqLiteRemoveClass(elm, toRemove); - }); - postDigestQueue.remove(element); - } - }); + function addRemoveClassesPostDigest(element, add, remove) { + var data = postDigestQueue.get(element) || {}; - postDigestElements.length = 0; - }); + var classesAdded = updateData(data, add, true); + var classesRemoved = updateData(data, remove, false); + + if (classesAdded || classesRemoved) { + + postDigestQueue.put(element, data); + postDigestElements.push(element); + + if (postDigestElements.length === 1) { + $rootScope.$$postDigest(handleCSSClassChanges); + } + } } }]; }; @@ -5018,7 +5290,7 @@ var $AnimateProvider = ['$provide', function($provide) { * when an animation is detected (and animations are enabled), $animate will do the heavy lifting * to ensure that animation runs with the triggered DOM operation. * - * By default $animate doesn't trigger an animations. This is because the `ngAnimate` module isn't + * By default $animate doesn't trigger any animations. This is because the `ngAnimate` module isn't * included and only when it is active then the animation hooks that `$animate` triggers will be * functional. Once active then all structural `ng-` directives will trigger animations as they perform * their DOM-related operations (enter, leave and move). Other directives such as `ngClass`, @@ -5073,15 +5345,20 @@ var $AnimateProvider = ['$provide', function($provide) { * // remove all the animation event listeners listening for `enter` * $animate.off('enter'); * + * // remove listeners for all animation events from the container element + * $animate.off(container); + * * // remove all the animation event listeners listening for `enter` on the given element and its children * $animate.off('enter', container); * - * // remove the event listener function provided by `listenerFn` that is set - * // to listen for `enter` on the given `element` as well as its children + * // remove the event listener function provided by `callback` that is set + * // to listen for `enter` on the given `container` as well as its children * $animate.off('enter', container, callback); * ``` * - * @param {string} event the animation event (e.g. enter, leave, move, addClass, removeClass, etc...) + * @param {string|DOMElement} event|container the animation event (e.g. enter, leave, move, + * addClass, removeClass, etc...), or the container element. If it is the element, all other + * arguments are ignored. * @param {DOMElement=} container the container element the event listener was placed on * @param {Function=} callback the callback function that was registered as the listener */ @@ -5162,7 +5439,13 @@ var $AnimateProvider = ['$provide', function($provide) { * @param {DOMElement} parent the parent element which will append the element as * a child (so long as the after element is not present) * @param {DOMElement=} after the sibling element after which the element will be appended - * @param {object=} options an optional collection of options/styles that will be applied to the element + * @param {object=} options an optional collection of options/styles that will be applied to the element. + * The object can have the following properties: + * + * - **addClass** - `{string}` - space-separated CSS classes to add to element + * - **from** - `{Object}` - CSS properties & values at the beginning of animation. Must have matching `to` + * - **removeClass** - `{string}` - space-separated CSS classes to remove from element + * - **to** - `{Object}` - CSS properties & values at end of animation. Must have matching `from` * * @return {Promise} the animation callback promise */ @@ -5188,7 +5471,13 @@ var $AnimateProvider = ['$provide', function($provide) { * @param {DOMElement} parent the parent element which will append the element as * a child (so long as the after element is not present) * @param {DOMElement=} after the sibling element after which the element will be appended - * @param {object=} options an optional collection of options/styles that will be applied to the element + * @param {object=} options an optional collection of options/styles that will be applied to the element. + * The object can have the following properties: + * + * - **addClass** - `{string}` - space-separated CSS classes to add to element + * - **from** - `{Object}` - CSS properties & values at the beginning of animation. Must have matching `to` + * - **removeClass** - `{string}` - space-separated CSS classes to remove from element + * - **to** - `{Object}` - CSS properties & values at end of animation. Must have matching `from` * * @return {Promise} the animation callback promise */ @@ -5209,7 +5498,13 @@ var $AnimateProvider = ['$provide', function($provide) { * digest once the animation has completed. * * @param {DOMElement} element the element which will be removed from the DOM - * @param {object=} options an optional collection of options/styles that will be applied to the element + * @param {object=} options an optional collection of options/styles that will be applied to the element. + * The object can have the following properties: + * + * - **addClass** - `{string}` - space-separated CSS classes to add to element + * - **from** - `{Object}` - CSS properties & values at the beginning of animation. Must have matching `to` + * - **removeClass** - `{string}` - space-separated CSS classes to remove from element + * - **to** - `{Object}` - CSS properties & values at end of animation. Must have matching `from` * * @return {Promise} the animation callback promise */ @@ -5233,7 +5528,13 @@ var $AnimateProvider = ['$provide', function($provide) { * * @param {DOMElement} element the element which the CSS classes will be applied to * @param {string} className the CSS class(es) that will be added (multiple classes are separated via spaces) - * @param {object=} options an optional collection of options/styles that will be applied to the element + * @param {object=} options an optional collection of options/styles that will be applied to the element. + * The object can have the following properties: + * + * - **addClass** - `{string}` - space-separated CSS classes to add to element + * - **from** - `{Object}` - CSS properties & values at the beginning of animation. Must have matching `to` + * - **removeClass** - `{string}` - space-separated CSS classes to remove from element + * - **to** - `{Object}` - CSS properties & values at end of animation. Must have matching `from` * * @return {Promise} the animation callback promise */ @@ -5257,7 +5558,13 @@ var $AnimateProvider = ['$provide', function($provide) { * * @param {DOMElement} element the element which the CSS classes will be applied to * @param {string} className the CSS class(es) that will be removed (multiple classes are separated via spaces) - * @param {object=} options an optional collection of options/styles that will be applied to the element + * @param {object=} options an optional collection of options/styles that will be applied to the element. + * The object can have the following properties: + * + * - **addClass** - `{string}` - space-separated CSS classes to add to element + * - **from** - `{Object}` - CSS properties & values at the beginning of animation. Must have matching `to` + * - **removeClass** - `{string}` - space-separated CSS classes to remove from element + * - **to** - `{Object}` - CSS properties & values at end of animation. Must have matching `from` * * @return {Promise} the animation callback promise */ @@ -5282,7 +5589,13 @@ var $AnimateProvider = ['$provide', function($provide) { * @param {DOMElement} element the element which the CSS classes will be applied to * @param {string} add the CSS class(es) that will be added (multiple classes are separated via spaces) * @param {string} remove the CSS class(es) that will be removed (multiple classes are separated via spaces) - * @param {object=} options an optional collection of options/styles that will be applied to the element + * @param {object=} options an optional collection of options/styles that will be applied to the element. + * The object can have the following properties: + * + * - **addClass** - `{string}` - space-separated CSS classes to add to element + * - **from** - `{Object}` - CSS properties & values at the beginning of animation. Must have matching `to` + * - **removeClass** - `{string}` - space-separated CSS classes to remove from element + * - **to** - `{Object}` - CSS properties & values at end of animation. Must have matching `from` * * @return {Promise} the animation callback promise */ @@ -5299,18 +5612,37 @@ var $AnimateProvider = ['$provide', function($provide) { * @kind function * * @description Performs an inline animation on the element which applies the provided to and from CSS styles to the element. - * If any detected CSS transition, keyframe or JavaScript matches the provided className value then the animation will take - * on the provided styles. For example, if a transition animation is set for the given className then the provided from and - * to styles will be applied alongside the given transition. If a JavaScript animation is detected then the provided styles - * will be given in as function paramters into the `animate` method (or as apart of the `options` parameter). + * If any detected CSS transition, keyframe or JavaScript matches the provided className value, then the animation will take + * on the provided styles. For example, if a transition animation is set for the given classNamem, then the provided `from` and + * `to` styles will be applied alongside the given transition. If the CSS style provided in `from` does not have a corresponding + * style in `to`, the style in `from` is applied immediately, and no animation is run. + * If a JavaScript animation is detected then the provided styles will be given in as function parameters into the `animate` + * method (or as part of the `options` parameter): + * + * ```js + * ngModule.animation('.my-inline-animation', function() { + * return { + * animate : function(element, from, to, done, options) { + * //animation + * done(); + * } + * } + * }); + * ``` * * @param {DOMElement} element the element which the CSS styles will be applied to * @param {object} from the from (starting) CSS styles that will be applied to the element and across the animation. * @param {object} to the to (destination) CSS styles that will be applied to the element and across the animation. * @param {string=} className an optional CSS class that will be applied to the element for the duration of the animation. If * this value is left as empty then a CSS class of `ng-inline-animate` will be applied to the element. - * (Note that if no animation is detected then this value will not be appplied to the element.) - * @param {object=} options an optional collection of options/styles that will be applied to the element + * (Note that if no animation is detected then this value will not be applied to the element.) + * @param {object=} options an optional collection of options/styles that will be applied to the element. + * The object can have the following properties: + * + * - **addClass** - `{string}` - space-separated CSS classes to add to element + * - **from** - `{Object}` - CSS properties & values at the beginning of animation. Must have matching `to` + * - **removeClass** - `{string}` - space-separated CSS classes to remove from element + * - **to** - `{Object}` - CSS properties & values at end of animation. Must have matching `from` * * @return {Promise} the animation callback promise */ @@ -5327,15 +5659,261 @@ var $AnimateProvider = ['$provide', function($provide) { }]; }]; -function $$AsyncCallbackProvider() { - this.$get = ['$$rAF', '$timeout', function($$rAF, $timeout) { - return $$rAF.supported - ? function(fn) { return $$rAF(fn); } - : function(fn) { - return $timeout(fn, 0, false); +var $$AnimateAsyncRunFactoryProvider = function() { + this.$get = ['$$rAF', function($$rAF) { + var waitQueue = []; + + function waitForTick(fn) { + waitQueue.push(fn); + if (waitQueue.length > 1) return; + $$rAF(function() { + for (var i = 0; i < waitQueue.length; i++) { + waitQueue[i](); + } + waitQueue = []; + }); + } + + return function() { + var passed = false; + waitForTick(function() { + passed = true; + }); + return function(callback) { + passed ? callback() : waitForTick(callback); }; + }; }]; -} +}; + +var $$AnimateRunnerFactoryProvider = function() { + this.$get = ['$q', '$sniffer', '$$animateAsyncRun', '$document', '$timeout', + function($q, $sniffer, $$animateAsyncRun, $document, $timeout) { + + var INITIAL_STATE = 0; + var DONE_PENDING_STATE = 1; + var DONE_COMPLETE_STATE = 2; + + AnimateRunner.chain = function(chain, callback) { + var index = 0; + + next(); + function next() { + if (index === chain.length) { + callback(true); + return; + } + + chain[index](function(response) { + if (response === false) { + callback(false); + return; + } + index++; + next(); + }); + } + }; + + AnimateRunner.all = function(runners, callback) { + var count = 0; + var status = true; + forEach(runners, function(runner) { + runner.done(onProgress); + }); + + function onProgress(response) { + status = status && response; + if (++count === runners.length) { + callback(status); + } + } + }; + + function AnimateRunner(host) { + this.setHost(host); + + var rafTick = $$animateAsyncRun(); + var timeoutTick = function(fn) { + $timeout(fn, 0, false); + }; + + this._doneCallbacks = []; + this._tick = function(fn) { + var doc = $document[0]; + + // the document may not be ready or attached + // to the module for some internal tests + if (doc && doc.hidden) { + timeoutTick(fn); + } else { + rafTick(fn); + } + }; + this._state = 0; + } + + AnimateRunner.prototype = { + setHost: function(host) { + this.host = host || {}; + }, + + done: function(fn) { + if (this._state === DONE_COMPLETE_STATE) { + fn(); + } else { + this._doneCallbacks.push(fn); + } + }, + + progress: noop, + + getPromise: function() { + if (!this.promise) { + var self = this; + this.promise = $q(function(resolve, reject) { + self.done(function(status) { + status === false ? reject() : resolve(); + }); + }); + } + return this.promise; + }, + + then: function(resolveHandler, rejectHandler) { + return this.getPromise().then(resolveHandler, rejectHandler); + }, + + 'catch': function(handler) { + return this.getPromise()['catch'](handler); + }, + + 'finally': function(handler) { + return this.getPromise()['finally'](handler); + }, + + pause: function() { + if (this.host.pause) { + this.host.pause(); + } + }, + + resume: function() { + if (this.host.resume) { + this.host.resume(); + } + }, + + end: function() { + if (this.host.end) { + this.host.end(); + } + this._resolve(true); + }, + + cancel: function() { + if (this.host.cancel) { + this.host.cancel(); + } + this._resolve(false); + }, + + complete: function(response) { + var self = this; + if (self._state === INITIAL_STATE) { + self._state = DONE_PENDING_STATE; + self._tick(function() { + self._resolve(response); + }); + } + }, + + _resolve: function(response) { + if (this._state !== DONE_COMPLETE_STATE) { + forEach(this._doneCallbacks, function(fn) { + fn(response); + }); + this._doneCallbacks.length = 0; + this._state = DONE_COMPLETE_STATE; + } + } + }; + + return AnimateRunner; + }]; +}; + +/** + * @ngdoc service + * @name $animateCss + * @kind object + * + * @description + * This is the core version of `$animateCss`. By default, only when the `ngAnimate` is included, + * then the `$animateCss` service will actually perform animations. + * + * Click here {@link ngAnimate.$animateCss to read the documentation for $animateCss}. + */ +var $CoreAnimateCssProvider = function() { + this.$get = ['$$rAF', '$q', '$$AnimateRunner', function($$rAF, $q, $$AnimateRunner) { + + return function(element, initialOptions) { + // all of the animation functions should create + // a copy of the options data, however, if a + // parent service has already created a copy then + // we should stick to using that + var options = initialOptions || {}; + if (!options.$$prepared) { + options = copy(options); + } + + // there is no point in applying the styles since + // there is no animation that goes on at all in + // this version of $animateCss. + if (options.cleanupStyles) { + options.from = options.to = null; + } + + if (options.from) { + element.css(options.from); + options.from = null; + } + + /* jshint newcap: false */ + var closed, runner = new $$AnimateRunner(); + return { + start: run, + end: run + }; + + function run() { + $$rAF(function() { + applyAnimationContents(); + if (!closed) { + runner.complete(); + } + closed = true; + }); + return runner; + } + + function applyAnimationContents() { + if (options.addClass) { + element.addClass(options.addClass); + options.addClass = null; + } + if (options.removeClass) { + element.removeClass(options.removeClass); + options.removeClass = null; + } + if (options.to) { + element.css(options.to); + options.to = null; + } + } + }; + }]; +}; /* global stripHash: true */ @@ -5362,7 +5940,6 @@ function $$AsyncCallbackProvider() { */ function Browser(window, document, $log, $sniffer) { var self = this, - rawDocument = document[0], location = window.location, history = window.history, setTimeout = window.setTimeout, @@ -5401,7 +5978,7 @@ function Browser(window, document, $log, $sniffer) { function getHash(url) { var index = url.indexOf('#'); - return index === -1 ? '' : url.substr(index + 1); + return index === -1 ? '' : url.substr(index); } /** @@ -5425,7 +6002,14 @@ function Browser(window, document, $log, $sniffer) { var cachedState, lastHistoryState, lastBrowserUrl = location.href, baseElement = document.find('base'), - reloadLocation = null; + pendingLocation = null, + getCurrentState = !$sniffer.history ? noop : function getCurrentState() { + try { + return history.state; + } catch (e) { + // MSIE can reportedly throw when there is no state (UNCONFIRMED). + } + }; cacheState(); lastHistoryState = cachedState; @@ -5485,8 +6069,8 @@ function Browser(window, document, $log, $sniffer) { // Do the assignment again so that those two variables are referentially identical. lastHistoryState = cachedState; } else { - if (!sameBase || reloadLocation) { - reloadLocation = url; + if (!sameBase) { + pendingLocation = url; } if (replace) { location.replace(url); @@ -5495,14 +6079,21 @@ function Browser(window, document, $log, $sniffer) { } else { location.hash = getHash(url); } + if (location.href !== url) { + pendingLocation = url; + } + } + if (pendingLocation) { + pendingLocation = url; } return self; // getter } else { - // - reloadLocation is needed as browsers don't allow to read out - // the new location.href if a reload happened. + // - pendingLocation is needed as browsers don't allow to read out + // the new location.href if a reload happened or if there is a bug like in iOS 9 (see + // https://openradar.appspot.com/22186109). // - the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172 - return reloadLocation || location.href.replace(/%27/g,"'"); + return pendingLocation || location.href.replace(/%27/g,"'"); } }; @@ -5524,18 +6115,11 @@ function Browser(window, document, $log, $sniffer) { urlChangeInit = false; function cacheStateAndFireUrlChange() { + pendingLocation = null; cacheState(); fireUrlChange(); } - function getCurrentState() { - try { - return history.state; - } catch (e) { - // MSIE can reportedly throw when there is no state (UNCONFIRMED). - } - } - // This variable should be used *only* inside the cacheState function. var lastCachedState = null; function cacheState() { @@ -5759,10 +6343,10 @@ function $BrowserProvider() { $scope.keys = []; $scope.cache = $cacheFactory('cacheId'); $scope.put = function(key, value) { - if ($scope.cache.get(key) === undefined) { + if (angular.isUndefined($scope.cache.get(key))) { $scope.keys.push(key); } - $scope.cache.put(key, value === undefined ? null : value); + $scope.cache.put(key, angular.isUndefined(value) ? null : value); }; }]); @@ -5785,9 +6369,9 @@ function $CacheFactoryProvider() { var size = 0, stats = extend({}, options, {id: cacheId}), - data = {}, + data = createMap(), capacity = (options && options.capacity) || Number.MAX_VALUE, - lruHash = {}, + lruHash = createMap(), freshEnd = null, staleEnd = null; @@ -5915,6 +6499,8 @@ function $CacheFactoryProvider() { delete lruHash[key]; } + if (!(key in data)) return; + delete data[key]; size--; }, @@ -5929,9 +6515,9 @@ function $CacheFactoryProvider() { * Clears the cache object of any entries. */ removeAll: function() { - data = {}; + data = createMap(); size = 0; - lruHash = {}; + lruHash = createMap(); freshEnd = staleEnd = null; }, @@ -6144,8 +6730,9 @@ function $TemplateCacheProvider() { * There are many different options for a directive. * * The difference resides in the return value of the factory function. - * You can either return a "Directive Definition Object" (see below) that defines the directive properties, - * or just the `postLink` function (all other properties will have the default values). + * You can either return a {@link $compile#directive-definition-object Directive Definition Object (see below)} + * that defines the directive properties, or just the `postLink` function (all other properties will have + * the default values). * *
* **Best Practice:** It's recommended to use the "directive definition object" form. @@ -6209,6 +6796,125 @@ function $TemplateCacheProvider() { * }); * ``` * + * ### Life-cycle hooks + * Directive controllers can provide the following methods that are called by Angular at points in the life-cycle of the + * directive: + * * `$onInit()` - Called on each controller after all the controllers on an element have been constructed and + * had their bindings initialized (and before the pre & post linking functions for the directives on + * this element). This is a good place to put initialization code for your controller. + * * `$onChanges(changesObj)` - Called whenever one-way (`<`) or interpolation (`@`) bindings are updated. The + * `changesObj` is a hash whose keys are the names of the bound properties that have changed, and the values are an + * object of the form `{ currentValue, previousValue, isFirstChange() }`. Use this hook to trigger updates within a + * component such as cloning the bound value to prevent accidental mutation of the outer value. + * * `$doCheck()` - Called on each turn of the digest cycle. Provides an opportunity to detect and act on + * changes. Any actions that you wish to take in response to the changes that you detect must be + * invoked from this hook; implementing this has no effect on when `$onChanges` is called. For example, this hook + * could be useful if you wish to perform a deep equality check, or to check a Date object, changes to which would not + * be detected by Angular's change detector and thus not trigger `$onChanges`. This hook is invoked with no arguments; + * if detecting changes, you must store the previous value(s) for comparison to the current values. + * * `$onDestroy()` - Called on a controller when its containing scope is destroyed. Use this hook for releasing + * external resources, watches and event handlers. Note that components have their `$onDestroy()` hooks called in + * the same order as the `$scope.$broadcast` events are triggered, which is top down. This means that parent + * components will have their `$onDestroy()` hook called before child components. + * * `$postLink()` - Called after this controller's element and its children have been linked. Similar to the post-link + * function this hook can be used to set up DOM event handlers and do direct DOM manipulation. + * Note that child elements that contain `templateUrl` directives will not have been compiled and linked since + * they are waiting for their template to load asynchronously and their own compilation and linking has been + * suspended until that occurs. + * + * #### Comparison with Angular 2 life-cycle hooks + * Angular 2 also uses life-cycle hooks for its components. While the Angular 1 life-cycle hooks are similar there are + * some differences that you should be aware of, especially when it comes to moving your code from Angular 1 to Angular 2: + * + * * Angular 1 hooks are prefixed with `$`, such as `$onInit`. Angular 2 hooks are prefixed with `ng`, such as `ngOnInit`. + * * Angular 1 hooks can be defined on the controller prototype or added to the controller inside its constructor. + * In Angular 2 you can only define hooks on the prototype of the Component class. + * * Due to the differences in change-detection, you may get many more calls to `$doCheck` in Angular 1 than you would to + * `ngDoCheck` in Angular 2 + * * Changes to the model inside `$doCheck` will trigger new turns of the digest loop, which will cause the changes to be + * propagated throughout the application. + * Angular 2 does not allow the `ngDoCheck` hook to trigger a change outside of the component. It will either throw an + * error or do nothing depending upon the state of `enableProdMode()`. + * + * #### Life-cycle hook examples + * + * This example shows how you can check for mutations to a Date object even though the identity of the object + * has not changed. + * + * + * + * angular.module('do-check-module', []) + * .component('app', { + * template: + * 'Month: ' + + * 'Date: {{ $ctrl.date }}' + + * '', + * controller: function() { + * this.date = new Date(); + * this.month = this.date.getMonth(); + * this.updateDate = function() { + * this.date.setMonth(this.month); + * }; + * } + * }) + * .component('test', { + * bindings: { date: '<' }, + * template: + * '
{{ $ctrl.log | json }}
', + * controller: function() { + * var previousValue; + * this.log = []; + * this.$doCheck = function() { + * var currentValue = this.date && this.date.valueOf(); + * if (previousValue !== currentValue) { + * this.log.push('doCheck: date mutated: ' + this.date); + * previousValue = currentValue; + * } + * }; + * } + * }); + *
+ * + * + * + *
+ * + * This example show how you might use `$doCheck` to trigger changes in your component's inputs even if the + * actual identity of the component doesn't change. (Be aware that cloning and deep equality checks on large + * arrays or objects can have a negative impact on your application performance) + * + * + * + *
+ * + * + *
{{ items }}
+ * + *
+ *
+ * + * angular.module('do-check-module', []) + * .component('test', { + * bindings: { items: '<' }, + * template: + * '
{{ $ctrl.log | json }}
', + * controller: function() { + * this.log = []; + * + * this.$doCheck = function() { + * if (this.items_ref !== this.items) { + * this.log.push('doCheck: items changed'); + * this.items_ref = this.items; + * } + * if (!angular.equals(this.items_clone, this.items)) { + * this.log.push('doCheck: items mutated'); + * this.items_clone = angular.copy(this.items); + * } + * }; + * } + * }); + *
+ *
* * * ### Directive Definition Object @@ -6220,7 +6926,7 @@ function $TemplateCacheProvider() { * When this property is set to true, the HTML compiler will collect DOM nodes between * nodes with the attributes `directive-name-start` and `directive-name-end`, and group them * together as the directive elements. It is recommended that this feature be used on directives - * which are not strictly behavioural (such as {@link ngClick}), and which + * which are not strictly behavioral (such as {@link ngClick}), and which * do not manipulate or replace child nodes (such as {@link ngInclude}). * * #### `priority` @@ -6238,59 +6944,129 @@ function $TemplateCacheProvider() { * and other directives used in the directive's template will also be excluded from execution. * * #### `scope` - * **If set to `true`,** then a new scope will be created for this directive. If multiple directives on the - * same element request a new scope, only one new scope is created. The new scope rule does not - * apply for the root of the template since the root of the template always gets a new scope. + * The scope property can be `true`, an object or a falsy value: + * + * * **falsy:** No scope will be created for the directive. The directive will use its parent's scope. + * + * * **`true`:** A new child scope that prototypically inherits from its parent will be created for + * the directive's element. If multiple directives on the same element request a new scope, + * only one new scope is created. The new scope rule does not apply for the root of the template + * since the root of the template always gets a new scope. * - * **If set to `{}` (object hash),** then a new "isolate" scope is created. The 'isolate' scope differs from - * normal scope in that it does not prototypically inherit from the parent scope. This is useful - * when creating reusable components, which should not accidentally read or modify data in the - * parent scope. + * * **`{...}` (an object hash):** A new "isolate" scope is created for the directive's element. The + * 'isolate' scope differs from normal scope in that it does not prototypically inherit from its parent + * scope. This is useful when creating reusable components, which should not accidentally read or modify + * data in the parent scope. * - * The 'isolate' scope takes an object hash which defines a set of local scope properties - * derived from the parent scope. These local properties are useful for aliasing values for - * templates. Locals definition is a hash of local scope property to its source: + * The 'isolate' scope object hash defines a set of local scope properties derived from attributes on the + * directive's element. These local properties are useful for aliasing values for templates. The keys in + * the object hash map to the name of the property on the isolate scope; the values define how the property + * is bound to the parent scope, via matching attributes on the directive's element: * * * `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is - * always a string since DOM attributes are strings. If no `attr` name is specified then the - * attribute name is assumed to be the same as the local name. - * Given `` and widget definition - * of `scope: { localName:'@myAttr' }`, then widget scope property `localName` will reflect - * the interpolated value of `hello {{name}}`. As the `name` attribute changes so will the - * `localName` property on the widget scope. The `name` is read from the parent scope (not - * component scope). - * - * * `=` or `=attr` - set up bi-directional binding between a local scope property and the - * parent scope property of name defined via the value of the `attr` attribute. If no `attr` - * name is specified then the attribute name is assumed to be the same as the local name. - * Given `` and widget definition of - * `scope: { localModel:'=myAttr' }`, then widget scope property `localModel` will reflect the + * always a string since DOM attributes are strings. If no `attr` name is specified then the + * attribute name is assumed to be the same as the local name. Given `` and the isolate scope definition `scope: { localName:'@myAttr' }`, + * the directive's scope property `localName` will reflect the interpolated value of `hello + * {{name}}`. As the `name` attribute changes so will the `localName` property on the directive's + * scope. The `name` is read from the parent scope (not the directive's scope). + * + * * `=` or `=attr` - set up a bidirectional binding between a local scope property and an expression + * passed via the attribute `attr`. The expression is evaluated in the context of the parent scope. + * If no `attr` name is specified then the attribute name is assumed to be the same as the local + * name. Given `` and the isolate scope definition `scope: { + * localModel: '=myAttr' }`, the property `localModel` on the directive's scope will reflect the + * value of `parentModel` on the parent scope. Changes to `parentModel` will be reflected in + * `localModel` and vice versa. Optional attributes should be marked as such with a question mark: + * `=?` or `=?attr`. If the binding expression is non-assignable, or if the attribute isn't + * optional and doesn't exist, an exception ({@link error/$compile/nonassign `$compile:nonassign`}) + * will be thrown upon discovering changes to the local value, since it will be impossible to sync + * them back to the parent scope. By default, the {@link ng.$rootScope.Scope#$watch `$watch`} + * method is used for tracking changes, and the equality check is based on object identity. + * However, if an object literal or an array literal is passed as the binding expression, the + * equality check is done by value (using the {@link angular.equals} function). It's also possible + * to watch the evaluated value shallowly with {@link ng.$rootScope.Scope#$watchCollection + * `$watchCollection`}: use `=*` or `=*attr` (`=*?` or `=*?attr` if the attribute is optional). + * + * * `<` or `` and directive definition of + * `scope: { localModel:'` and widget definition of - * `scope: { localFn:'&myAttr' }`, then isolate scope property `localFn` will point to - * a function wrapper for the `count = count + value` expression. Often it's desirable to - * pass data from the isolated scope via an expression to the parent scope, this can be - * done by passing a map of local variable names and values into the expression wrapper fn. - * For example, if the expression is `increment(amount)` then we can specify the amount value - * by calling the `localFn` as `localFn({amount: 22})`. + * in `localModel`, but changes in `localModel` will not reflect in `parentModel`. There are however + * two caveats: + * 1. one-way binding does not copy the value from the parent to the isolate scope, it simply + * sets the same value. That means if your bound value is an object, changes to its properties + * in the isolated scope will be reflected in the parent scope (because both reference the same object). + * 2. one-way binding watches changes to the **identity** of the parent value. That means the + * {@link ng.$rootScope.Scope#$watch `$watch`} on the parent value only fires if the reference + * to the value has changed. In most cases, this should not be of concern, but can be important + * to know if you one-way bind to an object, and then replace that object in the isolated scope. + * If you now change a property of the object in your parent scope, the change will not be + * propagated to the isolated scope, because the identity of the object on the parent scope + * has not changed. Instead you must assign a new object. + * + * One-way binding is useful if you do not plan to propagate changes to your isolated scope bindings + * back to the parent. However, it does not make this completely impossible. + * + * * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope. If + * no `attr` name is specified then the attribute name is assumed to be the same as the local name. + * Given `` and the isolate scope definition `scope: { + * localFn:'&myAttr' }`, the isolate scope property `localFn` will point to a function wrapper for + * the `count = count + value` expression. Often it's desirable to pass data from the isolated scope + * via an expression to the parent scope. This can be done by passing a map of local variable names + * and values into the expression wrapper fn. For example, if the expression is `increment(amount)` + * then we can specify the amount value by calling the `localFn` as `localFn({amount: 22})`. + * + * In general it's possible to apply more than one directive to one element, but there might be limitations + * depending on the type of scope required by the directives. The following points will help explain these limitations. + * For simplicity only two directives are taken into account, but it is also applicable for several directives: + * + * * **no scope** + **no scope** => Two directives which don't require their own scope will use their parent's scope + * * **child scope** + **no scope** => Both directives will share one single child scope + * * **child scope** + **child scope** => Both directives will share one single child scope + * * **isolated scope** + **no scope** => The isolated directive will use it's own created isolated scope. The other directive will use + * its parent's scope + * * **isolated scope** + **child scope** => **Won't work!** Only one scope can be related to one element. Therefore these directives cannot + * be applied to the same element. + * * **isolated scope** + **isolated scope** => **Won't work!** Only one scope can be related to one element. Therefore these directives + * cannot be applied to the same element. * * * #### `bindToController` - * When an isolate scope is used for a component (see above), and `controllerAs` is used, `bindToController: true` will - * allow a component to have its properties bound to the controller, rather than to scope. When the controller - * is instantiated, the initial values of the isolate scope bindings are already available. + * This property is used to bind scope properties directly to the controller. It can be either + * `true` or an object hash with the same format as the `scope` property. Additionally, a controller + * alias must be set, either by using `controllerAs: 'myAlias'` or by specifying the alias in the controller + * definition: `controller: 'myCtrl as myAlias'`. + * + * When an isolate scope is used for a directive (see above), `bindToController: true` will + * allow a component to have its properties bound to the controller, rather than to scope. + * + * After the controller is instantiated, the initial values of the isolate scope bindings will be bound to the controller + * properties. You can access these bindings once they have been initialized by providing a controller method called + * `$onInit`, which is called after all the controllers on an element have been constructed and had their bindings + * initialized. + * + *
+ * **Deprecation warning:** although bindings for non-ES6 class controllers are currently + * bound to `this` before the controller constructor is called, this use is now deprecated. Please place initialization + * code that relies upon bindings inside a `$onInit` method on the controller, instead. + *
+ * + * It is also possible to set `bindToController` to an object hash with the same format as the `scope` property. + * This will set up the scope bindings to the controller directly. Note that `scope` can still be used + * to define which kind of scope is created. By default, no scope is created. Use `scope: {}` to create an isolate + * scope (useful for component directives). + * + * If both `bindToController` and `scope` are defined and have object hashes, `bindToController` overrides `scope`. + * * * #### `controller` * Controller constructor function. The controller is instantiated before the - * pre-linking phase and it is shared with other directives (see + * pre-linking phase and can be accessed by other directives (see * `require` attribute). This allows the directives to communicate with each other and augment * each other's behavior. The controller is injectable (and supports bracket notation) with the following locals: * @@ -6298,10 +7074,10 @@ function $TemplateCacheProvider() { * * `$element` - Current element * * `$attrs` - Current attributes object for the element * * `$transclude` - A transclude linking function pre-bound to the correct transclusion scope: - * `function([scope], cloneLinkingFn, futureParentElement)`. - * * `scope`: optional argument to override the scope. - * * `cloneLinkingFn`: optional argument to create clones of the original transcluded content. - * * `futureParentElement`: + * `function([scope], cloneLinkingFn, futureParentElement, slotName)`: + * * `scope`: (optional) override the scope. + * * `cloneLinkingFn`: (optional) argument to create clones of the original transcluded content. + * * `futureParentElement` (optional): * * defines the parent to which the `cloneLinkingFn` will add the cloned elements. * * default: `$element.parent()` resp. `$element` for `transclude:'element'` resp. `transclude:true`. * * only needed for transcludes that are allowed to contain non html elements (e.g. SVG elements) @@ -6309,14 +7085,30 @@ function $TemplateCacheProvider() { * as those elements need to created and cloned in a special way when they are defined outside their * usual containers (e.g. like ``). * * See also the `directive.templateNamespace` property. - * + * * `slotName`: (optional) the name of the slot to transclude. If falsy (e.g. `null`, `undefined` or `''`) + * then the default translusion is provided. + * The `$transclude` function also has a method on it, `$transclude.isSlotFilled(slotName)`, which returns + * `true` if the specified slot contains content (i.e. one or more DOM nodes). * * #### `require` * Require another directive and inject its controller as the fourth argument to the linking function. The - * `require` takes a string name (or array of strings) of the directive(s) to pass in. If an array is used, the - * injected argument will be an array in corresponding order. If no such directive can be - * found, or if the directive does not have a controller, then an error is raised (unless no link function - * is specified, in which case error checking is skipped). The name can be prefixed with: + * `require` property can be a string, an array or an object: + * * a **string** containing the name of the directive to pass to the linking function + * * an **array** containing the names of directives to pass to the linking function. The argument passed to the + * linking function will be an array of controllers in the same order as the names in the `require` property + * * an **object** whose property values are the names of the directives to pass to the linking function. The argument + * passed to the linking function will also be an object with matching keys, whose values will hold the corresponding + * controllers. + * + * If the `require` property is an object and `bindToController` is truthy, then the required controllers are + * bound to the controller using the keys of the `require` property. This binding occurs after all the controllers + * have been constructed but before `$onInit` is called. + * If the name of the required controller is the same as the local name (the key), the name can be + * omitted. For example, `{parentDir: '^^'}` is equivalent to `{parentDir: '^^parentDir'}`. + * See the {@link $compileProvider#component} helper for an example of how this can be used. + * If no such required directive(s) can be found, or if the directive does not have a controller, then an error is + * raised (unless no link function is specified and the required controllers are not being bound to the directive + * controller, in which case error checking is skipped). The name can be prefixed with: * * * (no prefix) - Locate the required controller on the current element. Throw an error if not found. * * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found. @@ -6330,9 +7122,10 @@ function $TemplateCacheProvider() { * * #### `controllerAs` * Identifier name for a reference to the controller in the directive's scope. - * This allows the controller to be referenced from the directive template. The directive - * needs to define a scope for this configuration to be used. Useful in the case when - * directive is used as component. + * This allows the controller to be referenced from the directive template. This is especially + * useful when a directive is used as component, i.e. with an `isolate` scope. It's also possible + * to use it in a directive without an `isolate` / `new` scope, but you need to be aware that the + * `controllerAs` reference might overwrite a property that already exists on the parent scope. * * * #### `restrict` @@ -6408,14 +7201,6 @@ function $TemplateCacheProvider() { * The contents are compiled and provided to the directive as a **transclusion function**. See the * {@link $compile#transclusion Transclusion} section below. * - * There are two kinds of transclusion depending upon whether you want to transclude just the contents of the - * directive's element or the entire element: - * - * * `true` - transclude the content (i.e. the child nodes) of the directive's element. - * * `'element'` - transclude the whole of the directive's element including any directives on this - * element that defined at a lower priority than this directive. When used, the `template` - * property is ignored. - * * * #### `compile` * @@ -6443,7 +7228,7 @@ function $TemplateCacheProvider() { *
* **Note:** The compile function cannot handle directives that recursively use themselves in their - * own templates or compile functions. Compiling these directives results in an infinite loop and a + * own templates or compile functions. Compiling these directives results in an infinite loop and * stack overflow errors. * * This can be avoided by manually using $compile in the postLink function to imperatively compile @@ -6499,11 +7284,11 @@ function $TemplateCacheProvider() { * otherwise the {@link error:$compile:ctreq Missing Required Controller} error is thrown. * * Note that you can also require the directive's own controller - it will be made available like - * like any other controller. + * any other controller. * * * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope. - * This is the same as the `$transclude` - * parameter of directive controllers, see there for details. + * This is the same as the `$transclude` parameter of directive controllers, + * see {@link ng.$compile#-controller- the controller section for details}. * `function([scope], cloneLinkingFn, futureParentElement)`. * * #### Pre-linking function @@ -6525,7 +7310,7 @@ function $TemplateCacheProvider() { * * ### Transclusion * - * Transclusion is the process of extracting a collection of DOM element from one part of the DOM and + * Transclusion is the process of extracting a collection of DOM elements from one part of the DOM and * copying them to another part of the DOM, while maintaining their connection to the original AngularJS * scope from where they were taken. * @@ -6545,14 +7330,42 @@ function $TemplateCacheProvider() { * Testing Transclusion Directives}. *
* - * #### Transclusion Functions - * - * When a directive requests transclusion, the compiler extracts its contents and provides a **transclusion - * function** to the directive's `link` function and `controller`. This transclusion function is a special - * **linking function** that will return the compiled contents linked to a new transclusion scope. + * There are three kinds of transclusion depending upon whether you want to transclude just the contents of the + * directive's element, the entire element or multiple parts of the element contents: * - *
- * If you are just using {@link ngTransclude} then you don't need to worry about this function, since + * * `true` - transclude the content (i.e. the child nodes) of the directive's element. + * * `'element'` - transclude the whole of the directive's element including any directives on this + * element that defined at a lower priority than this directive. When used, the `template` + * property is ignored. + * * **`{...}` (an object hash):** - map elements of the content onto transclusion "slots" in the template. + * + * **Mult-slot transclusion** is declared by providing an object for the `transclude` property. + * + * This object is a map where the keys are the name of the slot to fill and the value is an element selector + * used to match the HTML to the slot. The element selector should be in normalized form (e.g. `myElement`) + * and will match the standard element variants (e.g. `my-element`, `my:element`, `data-my-element`, etc). + * + * For further information check out the guide on {@link guide/directive#matching-directives Matching Directives} + * + * If the element selector is prefixed with a `?` then that slot is optional. + * + * For example, the transclude object `{ slotA: '?myCustomElement' }` maps `` elements to + * the `slotA` slot, which can be accessed via the `$transclude` function or via the {@link ngTransclude} directive. + * + * Slots that are not marked as optional (`?`) will trigger a compile time error if there are no matching elements + * in the transclude content. If you wish to know if an optional slot was filled with content, then you can call + * `$transclude.isSlotFilled(slotName)` on the transclude function passed to the directive's link function and + * injectable into the directive's controller. + * + * + * #### Transclusion Functions + * + * When a directive requests transclusion, the compiler extracts its contents and provides a **transclusion + * function** to the directive's `link` function and `controller`. This transclusion function is a special + * **linking function** that will return the compiled contents linked to a new transclusion scope. + * + *
+ * If you are just using {@link ngTransclude} then you don't need to worry about this function, since * ngTransclude will deal with it for us. *
* @@ -6565,7 +7378,7 @@ function $TemplateCacheProvider() { * content and the `scope` is the newly created transclusion scope, to which the clone is bound. * *
- * **Best Practice**: Always provide a `cloneFn` (clone attach function) when you call a translude function + * **Best Practice**: Always provide a `cloneFn` (clone attach function) when you call a transclude function * since you then get a fresh clone of the original DOM and also have access to the new transclusion scope. *
* @@ -6597,7 +7410,7 @@ function $TemplateCacheProvider() { *
* * The built-in DOM manipulation directives, such as {@link ngIf}, {@link ngSwitch} and {@link ngRepeat} - * automatically destroy their transluded clones as necessary so you do not need to worry about this if + * automatically destroy their transcluded clones as necessary so you do not need to worry about this if * you are simply using {@link ngTransclude} to inject the transclusion into your directive. * * @@ -6622,19 +7435,19 @@ function $TemplateCacheProvider() { * * The `$parent` scope hierarchy will look like this: * - * ``` - * - $rootScope - * - isolate - * - transclusion - * ``` + ``` + - $rootScope + - isolate + - transclusion + ``` * * but the scopes will inherit prototypically from different scopes to their `$parent`. * - * ``` - * - $rootScope - * - transclusion - * - isolate - * ``` + ``` + - $rootScope + - transclusion + - isolate + ``` * * * ### Attributes @@ -6642,10 +7455,9 @@ function $TemplateCacheProvider() { * The {@link ng.$compile.directive.Attributes Attributes} object - passed as a parameter in the * `link()` or `compile()` functions. It has a variety of uses. * - * accessing *Normalized attribute names:* - * Directives like 'ngBind' can be expressed in many ways: 'ng:bind', `data-ng-bind`, or 'x-ng-bind'. - * the attributes object allows for normalized access to - * the attributes. + * * *Accessing normalized attribute names:* Directives like 'ngBind' can be expressed in many ways: + * 'ng:bind', `data-ng-bind`, or 'x-ng-bind'. The attributes object allows for normalized access + * to the attributes. * * * *Directive inter-communication:* All directives share the same instance of the attributes * object which allows the directives to use the attributes object as inter directive @@ -6766,8 +7578,15 @@ function $TemplateCacheProvider() { * directives; if given, it will be passed through to the link functions of * directives found in `element` during compilation. * * `transcludeControllers` - an object hash with keys that map controller names - * to controller instances; if given, it will make the controllers - * available to directives. + * to a hash with the key `instance`, which maps to the controller instance; + * if given, it will make the controllers available to directives on the compileNode: + * ``` + * { + * parent: { + * instance: parentControllerInstance + * } + * } + * ``` * * `futureParentElement` - defines the parent to which the `cloneAttachFn` will add * the cloned elements; only needed for transcludes that are allowed to contain non html * elements (e.g. SVG elements). See also the directive.controller property. @@ -6807,6 +7626,9 @@ function $TemplateCacheProvider() { var $compileMinErr = minErr('$compile'); +function UNINITIALIZED_VALUE() {} +var _UNINITIALIZED_VALUE = new UNINITIALIZED_VALUE(); + /** * @ngdoc provider * @name $compileProvider @@ -6826,13 +7648,18 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { // The assumption is that future DOM event attribute names will begin with // 'on' and be composed of only English letters. var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/; + var bindingCache = createMap(); function parseIsolateBindings(scope, directiveName, isController) { - var LOCAL_REGEXP = /^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/; + var LOCAL_REGEXP = /^\s*([@&<]|=(\*?))(\??)\s*(\w*)\s*$/; - var bindings = {}; + var bindings = createMap(); forEach(scope, function(definition, scopeName) { + if (definition in bindingCache) { + bindings[scopeName] = bindingCache[definition]; + return; + } var match = definition.match(LOCAL_REGEXP); if (!match) { @@ -6850,6 +7677,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { optional: match[3] === '?', attrName: match[4] || scopeName }; + if (match[4]) { + bindingCache[definition] = bindings[scopeName]; + } }); return bindings; @@ -6895,15 +7725,29 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { function assertValidDirectiveName(name) { var letter = name.charAt(0); if (!letter || letter !== lowercase(letter)) { - throw $compileMinErr('baddir', "Directive name '{0}' is invalid. The first character must be a lowercase letter", name); + throw $compileMinErr('baddir', "Directive/Component name '{0}' is invalid. The first character must be a lowercase letter", name); } if (name !== name.trim()) { throw $compileMinErr('baddir', - "Directive name '{0}' is invalid. The name should not contain leading or trailing whitespaces", + "Directive/Component name '{0}' is invalid. The name should not contain leading or trailing whitespaces", name); } } + function getDirectiveRequire(directive) { + var require = directive.require || (directive.controller && directive.name); + + if (!isArray(require) && isObject(require)) { + forEach(require, function(value, key) { + var match = value.match(REQUIRE_PREFIX_REGEXP); + var name = value.substring(match[0].length); + if (!name) require[key] = match[0] + key; + }); + } + + return require; + } + /** * @ngdoc method * @name $compileProvider#directive @@ -6915,11 +7759,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { * @param {string|Object} name Name of the directive in camel-case (i.e. ngBind which * will match as ng-bind), or an object map of directives where the keys are the * names and the values are the factories. - * @param {Function|Array} directiveFactory An injectable directive factory function. See - * {@link guide/directive} for more info. + * @param {Function|Array} directiveFactory An injectable directive factory function. See the + * {@link guide/directive directive guide} and the {@link $compile compile API} for more info. * @returns {ng.$compileProvider} Self for chaining. */ - this.directive = function registerDirective(name, directiveFactory) { + this.directive = function registerDirective(name, directiveFactory) { assertNotHasOwnProperty(name, 'directive'); if (isString(name)) { assertValidDirectiveName(name); @@ -6940,13 +7784,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { directive.priority = directive.priority || 0; directive.index = index; directive.name = directive.name || name; - directive.require = directive.require || (directive.controller && directive.name); + directive.require = getDirectiveRequire(directive); directive.restrict = directive.restrict || 'EA'; - var bindings = directive.$$bindings = - parseDirectiveBindings(directive, directive.name); - if (isObject(bindings.isolateScope)) { - directive.$$isolateBindings = bindings.isolateScope; - } directive.$$moduleName = directiveFactory.$$moduleName; directives.push(directive); } catch (e) { @@ -6963,6 +7802,147 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { return this; }; + /** + * @ngdoc method + * @name $compileProvider#component + * @module ng + * @param {string} name Name of the component in camelCase (i.e. `myComp` which will match ``) + * @param {Object} options Component definition object (a simplified + * {@link ng.$compile#directive-definition-object directive definition object}), + * with the following properties (all optional): + * + * - `controller` – `{(string|function()=}` – controller constructor function that should be + * associated with newly created scope or the name of a {@link ng.$compile#-controller- + * registered controller} if passed as a string. An empty `noop` function by default. + * - `controllerAs` – `{string=}` – identifier name for to reference the controller in the component's scope. + * If present, the controller will be published to scope under the `controllerAs` name. + * If not present, this will default to be `$ctrl`. + * - `template` – `{string=|function()=}` – html template as a string or a function that + * returns an html template as a string which should be used as the contents of this component. + * Empty string by default. + * + * If `template` is a function, then it is {@link auto.$injector#invoke injected} with + * the following locals: + * + * - `$element` - Current element + * - `$attrs` - Current attributes object for the element + * + * - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html + * template that should be used as the contents of this component. + * + * If `templateUrl` is a function, then it is {@link auto.$injector#invoke injected} with + * the following locals: + * + * - `$element` - Current element + * - `$attrs` - Current attributes object for the element + * + * - `bindings` – `{object=}` – defines bindings between DOM attributes and component properties. + * Component properties are always bound to the component controller and not to the scope. + * See {@link ng.$compile#-bindtocontroller- `bindToController`}. + * - `transclude` – `{boolean=}` – whether {@link $compile#transclusion content transclusion} is enabled. + * Disabled by default. + * - `require` - `{Object=}` - requires the controllers of other directives and binds them to + * this component's controller. The object keys specify the property names under which the required + * controllers (object values) will be bound. See {@link ng.$compile#-require- `require`}. + * - `$...` – additional properties to attach to the directive factory function and the controller + * constructor function. (This is used by the component router to annotate) + * + * @returns {ng.$compileProvider} the compile provider itself, for chaining of function calls. + * @description + * Register a **component definition** with the compiler. This is a shorthand for registering a special + * type of directive, which represents a self-contained UI component in your application. Such components + * are always isolated (i.e. `scope: {}`) and are always restricted to elements (i.e. `restrict: 'E'`). + * + * Component definitions are very simple and do not require as much configuration as defining general + * directives. Component definitions usually consist only of a template and a controller backing it. + * + * In order to make the definition easier, components enforce best practices like use of `controllerAs`, + * `bindToController`. They always have **isolate scope** and are restricted to elements. + * + * Here are a few examples of how you would usually define components: + * + * ```js + * var myMod = angular.module(...); + * myMod.component('myComp', { + * template: '
My name is {{$ctrl.name}}
', + * controller: function() { + * this.name = 'shahar'; + * } + * }); + * + * myMod.component('myComp', { + * template: '
My name is {{$ctrl.name}}
', + * bindings: {name: '@'} + * }); + * + * myMod.component('myComp', { + * templateUrl: 'views/my-comp.html', + * controller: 'MyCtrl', + * controllerAs: 'ctrl', + * bindings: {name: '@'} + * }); + * + * ``` + * For more examples, and an in-depth guide, see the {@link guide/component component guide}. + * + *
+ * See also {@link ng.$compileProvider#directive $compileProvider.directive()}. + */ + this.component = function registerComponent(name, options) { + var controller = options.controller || function() {}; + + function factory($injector) { + function makeInjectable(fn) { + if (isFunction(fn) || isArray(fn)) { + return function(tElement, tAttrs) { + return $injector.invoke(fn, this, {$element: tElement, $attrs: tAttrs}); + }; + } else { + return fn; + } + } + + var template = (!options.template && !options.templateUrl ? '' : options.template); + var ddo = { + controller: controller, + controllerAs: identifierForController(options.controller) || options.controllerAs || '$ctrl', + template: makeInjectable(template), + templateUrl: makeInjectable(options.templateUrl), + transclude: options.transclude, + scope: {}, + bindToController: options.bindings || {}, + restrict: 'E', + require: options.require + }; + + // Copy annotations (starting with $) over to the DDO + forEach(options, function(val, key) { + if (key.charAt(0) === '$') ddo[key] = val; + }); + + return ddo; + } + + // TODO(pete) remove the following `forEach` before we release 1.6.0 + // The component-router@0.2.0 looks for the annotations on the controller constructor + // Nothing in Angular looks for annotations on the factory function but we can't remove + // it from 1.5.x yet. + + // Copy any annotation properties (starting with $) over to the factory and controller constructor functions + // These could be used by libraries such as the new component router + forEach(options, function(val, key) { + if (key.charAt(0) === '$') { + factory[key] = val; + // Don't try to copy over annotations to named controller + if (isFunction(controller)) controller[key] = val; + } + }); + + factory.$inject = ['$injector']; + + return this.directive(name, factory); + }; + /** * @ngdoc method @@ -7054,13 +8034,83 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { return debugInfoEnabled; }; + + var TTL = 10; + /** + * @ngdoc method + * @name $compileProvider#onChangesTtl + * @description + * + * Sets the number of times `$onChanges` hooks can trigger new changes before giving up and + * assuming that the model is unstable. + * + * The current default is 10 iterations. + * + * In complex applications it's possible that dependencies between `$onChanges` hooks and bindings will result + * in several iterations of calls to these hooks. However if an application needs more than the default 10 + * iterations to stabilize then you should investigate what is causing the model to continuously change during + * the `$onChanges` hook execution. + * + * Increasing the TTL could have performance implications, so you should not change it without proper justification. + * + * @param {number} limit The number of `$onChanges` hook iterations. + * @returns {number|object} the current limit (or `this` if called as a setter for chaining) + */ + this.onChangesTtl = function(value) { + if (arguments.length) { + TTL = value; + return this; + } + return TTL; + }; + this.$get = [ '$injector', '$interpolate', '$exceptionHandler', '$templateRequest', '$parse', - '$controller', '$rootScope', '$document', '$sce', '$animate', '$$sanitizeUri', + '$controller', '$rootScope', '$sce', '$animate', '$$sanitizeUri', function($injector, $interpolate, $exceptionHandler, $templateRequest, $parse, - $controller, $rootScope, $document, $sce, $animate, $$sanitizeUri) { + $controller, $rootScope, $sce, $animate, $$sanitizeUri) { + + var SIMPLE_ATTR_NAME = /^\w/; + var specialAttrHolder = window.document.createElement('div'); + + + + var onChangesTtl = TTL; + // The onChanges hooks should all be run together in a single digest + // When changes occur, the call to trigger their hooks will be added to this queue + var onChangesQueue; + + // This function is called in a $$postDigest to trigger all the onChanges hooks in a single digest + function flushOnChangesQueue() { + try { + if (!(--onChangesTtl)) { + // We have hit the TTL limit so reset everything + onChangesQueue = undefined; + throw $compileMinErr('infchng', '{0} $onChanges() iterations reached. Aborting!\n', TTL); + } + // We must run this hook in an apply since the $$postDigest runs outside apply + $rootScope.$apply(function() { + var errors = []; + for (var i = 0, ii = onChangesQueue.length; i < ii; ++i) { + try { + onChangesQueue[i](); + } catch (e) { + errors.push(e); + } + } + // Reset the queue to trigger a new schedule next time there is a change + onChangesQueue = undefined; + if (errors.length) { + throw errors; + } + }); + } finally { + onChangesTtl++; + } + } - var Attributes = function(element, attributesToCopy) { + + function Attributes(element, attributesToCopy) { if (attributesToCopy) { var keys = Object.keys(attributesToCopy); var i, l, key; @@ -7074,7 +8124,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { } this.$$element = element; - }; + } Attributes.prototype = { /** @@ -7169,7 +8219,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { var node = this.$$element[0], booleanKey = getBooleanAttrName(node, key), - aliasedKey = getAliasedAttrName(node, key), + aliasedKey = getAliasedAttrName(key), observer = key, nodeName; @@ -7195,11 +8245,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { nodeName = nodeName_(this.$$element); - if ((nodeName === 'a' && key === 'href') || + if ((nodeName === 'a' && (key === 'href' || key === 'xlinkHref')) || (nodeName === 'img' && key === 'src')) { // sanitize a[href] and img[src] values this[key] = value = $$sanitizeUri(value, key === 'src'); - } else if (nodeName === 'img' && key === 'srcset') { + } else if (nodeName === 'img' && key === 'srcset' && isDefined(value)) { // sanitize img[srcset] values var result = ""; @@ -7236,10 +8286,14 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { } if (writeAttr !== false) { - if (value === null || value === undefined) { + if (value === null || isUndefined(value)) { this.$$element.removeAttr(attrName); } else { - this.$$element.attr(attrName, value); + if (SIMPLE_ATTR_NAME.test(attrName)) { + this.$$element.attr(attrName, value); + } else { + setSpecialAttr(this.$$element[0], attrName, value); + } } } @@ -7270,7 +8324,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { * @param {string} key Normalized key. (ie ngAttribute) . * @param {function(interpolatedValue)} fn Function that will be called whenever the interpolated value of the attribute changes. - * See the {@link guide/directive#text-and-attribute-bindings Directives} guide for more info. + * See the {@link guide/interpolation#how-text-and-attribute-bindings-work Interpolation + * guide} for more info. * @returns {function()} Returns a deregistration function for this observer. */ $observe: function(key, fn) { @@ -7280,7 +8335,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { listeners.push(fn); $rootScope.$evalAsync(function() { - if (!listeners.$$inter && attrs.hasOwnProperty(key)) { + if (!listeners.$$inter && attrs.hasOwnProperty(key) && !isUndefined(attrs[key])) { // no one registered attribute interpolation function, so lets call it manually fn(attrs[key]); } @@ -7292,6 +8347,18 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { } }; + function setSpecialAttr(element, attrName, value) { + // Attributes names that do not start with letters (such as `(click)`) cannot be set using `setAttribute` + // so we have to jump through some hoops to get such an attribute + // https://github.com/angular/angular.js/pull/13318 + specialAttrHolder.innerHTML = ""; + var attributes = specialAttrHolder.firstChild.attributes; + var attribute = attributes[0]; + // We have to remove the attribute from its container element before we can add it to the destination element + attributes.removeNamedItem(attribute.name); + attribute.value = value; + element.attributes.setNamedItem(attribute); + } function safeAddClass($element, className) { try { @@ -7305,12 +8372,13 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { var startSymbol = $interpolate.startSymbol(), endSymbol = $interpolate.endSymbol(), - denormalizeTemplate = (startSymbol == '{{' || endSymbol == '}}') + denormalizeTemplate = (startSymbol == '{{' && endSymbol == '}}') ? identity : function denormalizeTemplate(template) { return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol); }, NG_ATTR_BINDING = /^ngAttr[A-Z]/; + var MULTI_ELEMENT_DIR_RE = /^(.+)Start$/; compile.$$addBindingInfo = debugInfoEnabled ? function $$addBindingInfo($element, binding) { var bindings = $element.data('$binding') || []; @@ -7337,6 +8405,15 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { safeAddClass($element, isolated ? 'ng-isolate-scope' : 'ng-scope'); } : noop; + compile.$$createComment = function(directiveName, comment) { + var content = ''; + if (debugInfoEnabled) { + content = ' ' + (directiveName || '') + ': '; + if (comment) content += comment + ' '; + } + return window.document.createComment(content); + }; + return compile; //================================ @@ -7348,13 +8425,19 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { // modify it. $compileNodes = jqLite($compileNodes); } + + var NOT_EMPTY = /\S+/; + // We can not compile top level text elements since text nodes can be merged and we will // not be able to attach scope data to them, so we will wrap them in - forEach($compileNodes, function(node, index) { - if (node.nodeType == NODE_TYPE_TEXT && node.nodeValue.match(/\S+/) /* non-empty */ ) { - $compileNodes[index] = jqLite(node).wrap('').parent()[0]; + for (var i = 0, len = $compileNodes.length; i < len; i++) { + var domNode = $compileNodes[i]; + + if (domNode.nodeType === NODE_TYPE_TEXT && domNode.nodeValue.match(NOT_EMPTY) /* non-empty */) { + jqLiteWrapNode(domNode, $compileNodes[i] = window.document.createElement('span')); } - }); + } + var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority, ignoreDirective, previousCompileContext); @@ -7363,6 +8446,14 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { return function publicLinkFn(scope, cloneConnectFn, options) { assertArg(scope, 'scope'); + if (previousCompileContext && previousCompileContext.needsNewScope) { + // A parent directive did a replace and a directive on this element asked + // for transclusion, which caused us to lose a layer of element on which + // we could hold the new transclusion scope, so we will create it manually + // here. + scope = scope.$parent.$new(); + } + options = options || {}; var parentBoundTranscludeFn = options.parentBoundTranscludeFn, transcludeControllers = options.transcludeControllers, @@ -7417,7 +8508,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { if (!node) { return 'html'; } else { - return nodeName_(node) !== 'foreignobject' && node.toString().match(/SVG/) ? 'svg' : 'html'; + return nodeName_(node) !== 'foreignobject' && toString.call(node).match(/SVG/) ? 'svg' : 'html'; } } @@ -7508,11 +8599,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { if (nodeLinkFn.scope) { childScope = scope.$new(); compile.$$addScopeInfo(jqLite(node), childScope); - var destroyBindings = nodeLinkFn.$$destroyBindings; - if (destroyBindings) { - nodeLinkFn.$$destroyBindings = null; - childScope.$on('$destroyed', destroyBindings); - } } else { childScope = scope; } @@ -7531,8 +8617,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { childBoundTranscludeFn = null; } - nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn, - nodeLinkFn); + nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn); } else if (childLinkFn) { childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn); @@ -7542,8 +8627,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { } function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn) { - - var boundTranscludeFn = function(transcludedScope, cloneFn, controllers, futureParentElement, containingScope) { + function boundTranscludeFn(transcludedScope, cloneFn, controllers, futureParentElement, containingScope) { if (!transcludedScope) { transcludedScope = scope.$new(false, containingScope); @@ -7555,7 +8639,18 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { transcludeControllers: controllers, futureParentElement: futureParentElement }); - }; + } + + // We need to attach the transclusion slots onto the `boundTranscludeFn` + // so that they are available inside the `controllersBoundTransclude` function + var boundSlots = boundTranscludeFn.$$slots = createMap(); + for (var slotName in transcludeFn.$$slots) { + if (transcludeFn.$$slots[slotName]) { + boundSlots[slotName] = createBoundTranscludeFn(scope, transcludeFn.$$slots[slotName], previousBoundTranscludeFn); + } else { + boundSlots[slotName] = null; + } + } return boundTranscludeFn; } @@ -7601,13 +8696,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { }); } - var directiveNName = ngAttrName.replace(/(Start|End)$/, ''); - if (directiveIsMultiElement(directiveNName)) { - if (ngAttrName === directiveNName + 'Start') { - attrStartName = name; - attrEndName = name.substr(0, name.length - 5) + 'end'; - name = name.substr(0, name.length - 6); - } + var multiElementMatch = ngAttrName.match(MULTI_ELEMENT_DIR_RE); + if (multiElementMatch && directiveIsMultiElement(multiElementMatch[1])) { + attrStartName = name; + attrEndName = name.substr(0, name.length - 5) + 'end'; + name = name.substr(0, name.length - 6); } nName = directiveNormalize(name.toLowerCase()); @@ -7650,19 +8743,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { addTextInterpolateDirective(directives, node.nodeValue); break; case NODE_TYPE_COMMENT: /* Comment */ - try { - match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue); - if (match) { - nName = directiveNormalize(match[1]); - if (addDirective(directives, nName, 'M', maxPriority, ignoreDirective)) { - attrs[nName] = trim(match[2]); - } - } - } catch (e) { - // turns out that under some circumstances IE9 throws errors when one attempts to read - // comment's node value. - // Just ignore it and continue. (Can't seem to reproduce in test case.) - } + collectCommentDirectives(node, directives, attrs, maxPriority, ignoreDirective); break; } @@ -7670,6 +8751,24 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { return directives; } + function collectCommentDirectives(node, directives, attrs, maxPriority, ignoreDirective) { + // function created because of performance, try/catch disables + // the optimization of the whole function #14848 + try { + var match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue); + if (match) { + var nName = directiveNormalize(match[1]); + if (addDirective(directives, nName, 'M', maxPriority, ignoreDirective)) { + attrs[nName] = trim(match[2]); + } + } + } catch (e) { + // turns out that under some circumstances IE9 throws errors when one attempts to read + // comment's node value. + // Just ignore it and continue. (Can't seem to reproduce in test case.) + } + } + /** * Given a node with an directive-start it collects all of the siblings until it finds * directive-end. @@ -7711,12 +8810,41 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { * @returns {Function} */ function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) { - return function(scope, element, attrs, controllers, transcludeFn) { + return function groupedElementsLink(scope, element, attrs, controllers, transcludeFn) { element = groupScan(element[0], attrStart, attrEnd); return linkFn(scope, element, attrs, controllers, transcludeFn); }; } + /** + * A function generator that is used to support both eager and lazy compilation + * linking function. + * @param eager + * @param $compileNodes + * @param transcludeFn + * @param maxPriority + * @param ignoreDirective + * @param previousCompileContext + * @returns {Function} + */ + function compilationGenerator(eager, $compileNodes, transcludeFn, maxPriority, ignoreDirective, previousCompileContext) { + var compiled; + + if (eager) { + return compile($compileNodes, transcludeFn, maxPriority, ignoreDirective, previousCompileContext); + } + return function lazyCompilation() { + if (!compiled) { + compiled = compile($compileNodes, transcludeFn, maxPriority, ignoreDirective, previousCompileContext); + + // Null out all of these references in order to make them eligible for garbage collection + // since this is a potentially long lived closure + $compileNodes = transcludeFn = previousCompileContext = null; + } + return compiled.apply(this, arguments); + }; + } + /** * Once the directives have been collected, their compile functions are executed. This method * is responsible for inlining directive templates as well as terminating the application @@ -7746,7 +8874,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { previousCompileContext = previousCompileContext || {}; var terminalPriority = -Number.MAX_VALUE, - newScopeDirective, + newScopeDirective = previousCompileContext.newScopeDirective, controllerDirectives = previousCompileContext.controllerDirectives, newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective, templateDirective = previousCompileContext.templateDirective, @@ -7761,6 +8889,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { replaceDirective = originalReplaceDirective, childTranscludeFn = transcludeFn, linkFn, + didScanForMultipleTransclusion = false, + mightHaveMultipleTransclusionError = false, directiveValue; // executes all directives on the current element @@ -7803,6 +8933,27 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { directiveName = directive.name; + // If we encounter a condition that can result in transclusion on the directive, + // then scan ahead in the remaining directives for others that may cause a multiple + // transclusion error to be thrown during the compilation process. If a matching directive + // is found, then we know that when we encounter a transcluded directive, we need to eagerly + // compile the `transclude` function rather than doing it lazily in order to throw + // exceptions at the correct time + if (!didScanForMultipleTransclusion && ((directive.replace && (directive.templateUrl || directive.template)) + || (directive.transclude && !directive.$$tlb))) { + var candidateDirective; + + for (var scanningIndex = i + 1; candidateDirective = directives[scanningIndex++];) { + if ((candidateDirective.transclude && !candidateDirective.$$tlb) + || (candidateDirective.replace && (candidateDirective.templateUrl || candidateDirective.template))) { + mightHaveMultipleTransclusionError = true; + break; + } + } + + didScanForMultipleTransclusion = true; + } + if (!directive.templateUrl && directive.controller) { directiveValue = directive.controller; controllerDirectives = controllerDirectives || createMap(); @@ -7827,12 +8978,22 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { terminalPriority = directive.priority; $template = $compileNode; $compileNode = templateAttrs.$$element = - jqLite(document.createComment(' ' + directiveName + ': ' + - templateAttrs[directiveName] + ' ')); + jqLite(compile.$$createComment(directiveName, templateAttrs[directiveName])); compileNode = $compileNode[0]; replaceWith(jqCollection, sliceArgs($template), compileNode); - childTranscludeFn = compile($template, transcludeFn, terminalPriority, + // Support: Chrome < 50 + // https://github.com/angular/angular.js/issues/14041 + + // In the versions of V8 prior to Chrome 50, the document fragment that is created + // in the `replaceWith` function is improperly garbage collected despite still + // being referenced by the `parentNode` property of all of the child nodes. By adding + // a reference to the fragment via a different property, we can avoid that incorrect + // behavior. + // TODO: remove this line after Chrome 50 has been released + $template[0].$$parentNode = $template[0].parentNode; + + childTranscludeFn = compilationGenerator(mightHaveMultipleTransclusionError, $template, transcludeFn, terminalPriority, replaceDirective && replaceDirective.name, { // Don't pass in: // - controllerDirectives - otherwise we'll create duplicates controllers @@ -7844,9 +9005,69 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { nonTlbTranscludeDirective: nonTlbTranscludeDirective }); } else { + + var slots = createMap(); + $template = jqLite(jqLiteClone(compileNode)).contents(); + + if (isObject(directiveValue)) { + + // We have transclusion slots, + // collect them up, compile them and store their transclusion functions + $template = []; + + var slotMap = createMap(); + var filledSlots = createMap(); + + // Parse the element selectors + forEach(directiveValue, function(elementSelector, slotName) { + // If an element selector starts with a ? then it is optional + var optional = (elementSelector.charAt(0) === '?'); + elementSelector = optional ? elementSelector.substring(1) : elementSelector; + + slotMap[elementSelector] = slotName; + + // We explicitly assign `null` since this implies that a slot was defined but not filled. + // Later when calling boundTransclusion functions with a slot name we only error if the + // slot is `undefined` + slots[slotName] = null; + + // filledSlots contains `true` for all slots that are either optional or have been + // filled. This is used to check that we have not missed any required slots + filledSlots[slotName] = optional; + }); + + // Add the matching elements into their slot + forEach($compileNode.contents(), function(node) { + var slotName = slotMap[directiveNormalize(nodeName_(node))]; + if (slotName) { + filledSlots[slotName] = true; + slots[slotName] = slots[slotName] || []; + slots[slotName].push(node); + } else { + $template.push(node); + } + }); + + // Check for required slots that were not filled + forEach(filledSlots, function(filled, slotName) { + if (!filled) { + throw $compileMinErr('reqslot', 'Required transclusion slot `{0}` was not filled.', slotName); + } + }); + + for (var slotName in slots) { + if (slots[slotName]) { + // Only define a transclusion function if the slot was filled + slots[slotName] = compilationGenerator(mightHaveMultipleTransclusionError, slots[slotName], transcludeFn); + } + } + } + $compileNode.empty(); // clear contents - childTranscludeFn = compile($template, transcludeFn); + childTranscludeFn = compilationGenerator(mightHaveMultipleTransclusionError, $template, transcludeFn, undefined, + undefined, { needsNewScope: directive.$$isolateScope || directive.$$newScope}); + childTranscludeFn.$$slots = slots; } } @@ -7888,8 +9109,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs); var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1)); - if (newIsolateScopeDirective) { - markDirectivesAsIsolate(templateDirectives); + if (newIsolateScopeDirective || newScopeDirective) { + // The original directive caused the current element to be replaced but this element + // also needs to have a new scope, so we need to tell the template directives + // that they would need to get their scope from further up, if they require transclusion + markDirectiveScope(templateDirectives, newIsolateScopeDirective, newScopeDirective); } directives = directives.concat(templateDirectives).concat(unprocessedDirectives); mergeTemplateAttributes(templateAttrs, newTemplateAttrs); @@ -7909,9 +9133,12 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { replaceDirective = directive; } + /* jshint -W021 */ nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode, + /* jshint +W021 */ templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, { controllerDirectives: controllerDirectives, + newScopeDirective: (newScopeDirective !== directive) && newScopeDirective, newIsolateScopeDirective: newIsolateScopeDirective, templateDirective: templateDirective, nonTlbTranscludeDirective: nonTlbTranscludeDirective @@ -7920,10 +9147,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { } else if (directive.compile) { try { linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn); + var context = directive.$$originalDirective || directive; if (isFunction(linkFn)) { - addLinkFns(null, linkFn, attrStart, attrEnd); + addLinkFns(null, bind(context, linkFn), attrStart, attrEnd); } else if (linkFn) { - addLinkFns(linkFn.pre, linkFn.post, attrStart, attrEnd); + addLinkFns(bind(context, linkFn.pre), bind(context, linkFn.post), attrStart, attrEnd); } } catch (e) { $exceptionHandler(e, startingTag($compileNode)); @@ -7970,81 +9198,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { } } - - function getControllers(directiveName, require, $element, elementControllers) { - var value; - - if (isString(require)) { - var match = require.match(REQUIRE_PREFIX_REGEXP); - var name = require.substring(match[0].length); - var inheritType = match[1] || match[3]; - var optional = match[2] === '?'; - - //If only parents then start at the parent element - if (inheritType === '^^') { - $element = $element.parent(); - //Otherwise attempt getting the controller from elementControllers in case - //the element is transcluded (and has no data) and to avoid .data if possible - } else { - value = elementControllers && elementControllers[name]; - value = value && value.instance; - } - - if (!value) { - var dataName = '$' + name + 'Controller'; - value = inheritType ? $element.inheritedData(dataName) : $element.data(dataName); - } - - if (!value && !optional) { - throw $compileMinErr('ctreq', - "Controller '{0}', required by directive '{1}', can't be found!", - name, directiveName); - } - } else if (isArray(require)) { - value = []; - for (var i = 0, ii = require.length; i < ii; i++) { - value[i] = getControllers(directiveName, require[i], $element, elementControllers); - } - } - - return value || null; - } - - function setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope) { - var elementControllers = createMap(); - for (var controllerKey in controllerDirectives) { - var directive = controllerDirectives[controllerKey]; - var locals = { - $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope, - $element: $element, - $attrs: attrs, - $transclude: transcludeFn - }; - - var controller = directive.controller; - if (controller == '@') { - controller = attrs[directive.name]; - } - - var controllerInstance = $controller(controller, locals, true, directive.controllerAs); - - // For directives with element transclusion the element is a comment, - // but jQuery .data doesn't support attaching data to comment nodes as it's hard to - // clean up (http://bugs.jquery.com/ticket/8335). - // Instead, we save the controllers for the element in a local hash and attach to .data - // later, once we have the actual element. - elementControllers[directive.name] = controllerInstance; - if (!hasElementTranscludeDirective) { - $element.data('$' + directive.name + 'Controller', controllerInstance.instance); - } - } - return elementControllers; - } - - function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn, - thisLinkFn) { - var i, ii, linkFn, controller, isolateScope, elementControllers, transcludeFn, $element, - attrs; + function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) { + var i, ii, linkFn, isolateScope, controllerScope, elementControllers, transcludeFn, $element, + attrs, scopeBindingInfo; if (compileNode === linkNode) { attrs = templateAttrs; @@ -8054,8 +9210,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { attrs = new Attributes($element, templateAttrs); } + controllerScope = scope; if (newIsolateScopeDirective) { isolateScope = scope.$new(true); + } else if (newScopeDirective) { + controllerScope = scope.$parent; } if (boundTranscludeFn) { @@ -8063,10 +9222,14 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { // is later passed as `parentBoundTranscludeFn` to `publicLinkFn` transcludeFn = controllersBoundTransclude; transcludeFn.$$boundTransclude = boundTranscludeFn; + // expose the slots on the `$transclude` function + transcludeFn.isSlotFilled = function(slotName) { + return !!boundTranscludeFn.$$slots[slotName]; + }; } if (controllerDirectives) { - elementControllers = setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope); + elementControllers = setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope, newIsolateScopeDirective); } if (newIsolateScopeDirective) { @@ -8076,44 +9239,74 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { compile.$$addScopeClass($element, true); isolateScope.$$isolateBindings = newIsolateScopeDirective.$$isolateBindings; - initializeDirectiveBindings(scope, attrs, isolateScope, - isolateScope.$$isolateBindings, - newIsolateScopeDirective, isolateScope); - } - if (elementControllers) { - // Initialize bindToController bindings for new/isolate scopes - var scopeDirective = newIsolateScopeDirective || newScopeDirective; - var bindings; - var controllerForBindings; - if (scopeDirective && elementControllers[scopeDirective.name]) { - bindings = scopeDirective.$$bindings.bindToController; - controller = elementControllers[scopeDirective.name]; - - if (controller && controller.identifier && bindings) { - controllerForBindings = controller; - thisLinkFn.$$destroyBindings = - initializeDirectiveBindings(scope, attrs, controller.instance, - bindings, scopeDirective); + scopeBindingInfo = initializeDirectiveBindings(scope, attrs, isolateScope, + isolateScope.$$isolateBindings, + newIsolateScopeDirective); + if (scopeBindingInfo.removeWatches) { + isolateScope.$on('$destroy', scopeBindingInfo.removeWatches); + } + } + + // Initialize bindToController bindings + for (var name in elementControllers) { + var controllerDirective = controllerDirectives[name]; + var controller = elementControllers[name]; + var bindings = controllerDirective.$$bindings.bindToController; + + if (controller.identifier && bindings) { + controller.bindingInfo = + initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective); + } else { + controller.bindingInfo = {}; + } + + var controllerResult = controller(); + if (controllerResult !== controller.instance) { + // If the controller constructor has a return value, overwrite the instance + // from setupControllers + controller.instance = controllerResult; + $element.data('$' + controllerDirective.name + 'Controller', controllerResult); + controller.bindingInfo.removeWatches && controller.bindingInfo.removeWatches(); + controller.bindingInfo = + initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective); + } + } + + // Bind the required controllers to the controller, if `require` is an object and `bindToController` is truthy + forEach(controllerDirectives, function(controllerDirective, name) { + var require = controllerDirective.require; + if (controllerDirective.bindToController && !isArray(require) && isObject(require)) { + extend(elementControllers[name].instance, getControllers(name, require, $element, elementControllers)); + } + }); + + // Handle the init and destroy lifecycle hooks on all controllers that have them + forEach(elementControllers, function(controller) { + var controllerInstance = controller.instance; + if (isFunction(controllerInstance.$onChanges)) { + try { + controllerInstance.$onChanges(controller.bindingInfo.initialChanges); + } catch (e) { + $exceptionHandler(e); } } - for (i in elementControllers) { - controller = elementControllers[i]; - var controllerResult = controller(); - - if (controllerResult !== controller.instance) { - // If the controller constructor has a return value, overwrite the instance - // from setupControllers and update the element data - controller.instance = controllerResult; - $element.data('$' + i + 'Controller', controllerResult); - if (controller === controllerForBindings) { - // Remove and re-install bindToController bindings - thisLinkFn.$$destroyBindings(); - thisLinkFn.$$destroyBindings = - initializeDirectiveBindings(scope, attrs, controllerResult, bindings, scopeDirective); - } + if (isFunction(controllerInstance.$onInit)) { + try { + controllerInstance.$onInit(); + } catch (e) { + $exceptionHandler(e); } } - } + if (isFunction(controllerInstance.$doCheck)) { + controllerScope.$watch(function() { controllerInstance.$doCheck(); }); + controllerInstance.$doCheck(); + } + if (isFunction(controllerInstance.$onDestroy)) { + controllerScope.$on('$destroy', function callOnDestroyHook() { + controllerInstance.$onDestroy(); + }); + } + }); // PRELINKING for (i = 0, ii = preLinkFns.length; i < ii; i++) { @@ -8148,13 +9341,21 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { ); } + // Trigger $postLink lifecycle hooks + forEach(elementControllers, function(controller) { + var controllerInstance = controller.instance; + if (isFunction(controllerInstance.$postLink)) { + controllerInstance.$postLink(); + } + }); + // This is the function that is injected as `$transclude`. // Note: all arguments are optional! - function controllersBoundTransclude(scope, cloneAttachFn, futureParentElement) { + function controllersBoundTransclude(scope, cloneAttachFn, futureParentElement, slotName) { var transcludeControllers; - // No scope passed in: if (!isScope(scope)) { + slotName = futureParentElement; futureParentElement = cloneAttachFn; cloneAttachFn = scope; scope = undefined; @@ -8166,19 +9367,112 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { if (!futureParentElement) { futureParentElement = hasElementTranscludeDirective ? $element.parent() : $element; } - return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild); + if (slotName) { + // slotTranscludeFn can be one of three things: + // * a transclude function - a filled slot + // * `null` - an optional slot that was not filled + // * `undefined` - a slot that was not declared (i.e. invalid) + var slotTranscludeFn = boundTranscludeFn.$$slots[slotName]; + if (slotTranscludeFn) { + return slotTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild); + } else if (isUndefined(slotTranscludeFn)) { + throw $compileMinErr('noslot', + 'No parent directive that requires a transclusion with slot name "{0}". ' + + 'Element: {1}', + slotName, startingTag($element)); + } + } else { + return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild); + } } } } - function markDirectivesAsIsolate(directives) { - // mark all directives as needing isolate scope. - for (var j = 0, jj = directives.length; j < jj; j++) { - directives[j] = inherit(directives[j], {$$isolateScope: true}); - } - } + function getControllers(directiveName, require, $element, elementControllers) { + var value; - /** + if (isString(require)) { + var match = require.match(REQUIRE_PREFIX_REGEXP); + var name = require.substring(match[0].length); + var inheritType = match[1] || match[3]; + var optional = match[2] === '?'; + + //If only parents then start at the parent element + if (inheritType === '^^') { + $element = $element.parent(); + //Otherwise attempt getting the controller from elementControllers in case + //the element is transcluded (and has no data) and to avoid .data if possible + } else { + value = elementControllers && elementControllers[name]; + value = value && value.instance; + } + + if (!value) { + var dataName = '$' + name + 'Controller'; + value = inheritType ? $element.inheritedData(dataName) : $element.data(dataName); + } + + if (!value && !optional) { + throw $compileMinErr('ctreq', + "Controller '{0}', required by directive '{1}', can't be found!", + name, directiveName); + } + } else if (isArray(require)) { + value = []; + for (var i = 0, ii = require.length; i < ii; i++) { + value[i] = getControllers(directiveName, require[i], $element, elementControllers); + } + } else if (isObject(require)) { + value = {}; + forEach(require, function(controller, property) { + value[property] = getControllers(directiveName, controller, $element, elementControllers); + }); + } + + return value || null; + } + + function setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope, newIsolateScopeDirective) { + var elementControllers = createMap(); + for (var controllerKey in controllerDirectives) { + var directive = controllerDirectives[controllerKey]; + var locals = { + $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope, + $element: $element, + $attrs: attrs, + $transclude: transcludeFn + }; + + var controller = directive.controller; + if (controller == '@') { + controller = attrs[directive.name]; + } + + var controllerInstance = $controller(controller, locals, true, directive.controllerAs); + + // For directives with element transclusion the element is a comment. + // In this case .data will not attach any data. + // Instead, we save the controllers for the element in a local hash and attach to .data + // later, once we have the actual element. + elementControllers[directive.name] = controllerInstance; + $element.data('$' + directive.name + 'Controller', controllerInstance.instance); + } + return elementControllers; + } + + // Depending upon the context in which a directive finds itself it might need to have a new isolated + // or child scope created. For instance: + // * if the directive has been pulled into a template because another directive with a higher priority + // asked for element transclusion + // * if the directive itself asks for transclusion but it is at the root of a template and the original + // element was replaced. See https://github.com/angular/angular.js/issues/12936 + function markDirectiveScope(directives, isolateScope, newScope) { + for (var j = 0, jj = directives.length; j < jj; j++) { + directives[j] = inherit(directives[j], {$$isolateScope: isolateScope, $$newScope: newScope}); + } + } + + /** * looks up the directive and decorates it with exception handling and proper parameters. We * call this the boundDirective. * @@ -8201,11 +9495,18 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { i = 0, ii = directives.length; i < ii; i++) { try { directive = directives[i]; - if ((maxPriority === undefined || maxPriority > directive.priority) && + if ((isUndefined(maxPriority) || maxPriority > directive.priority) && directive.restrict.indexOf(location) != -1) { if (startAttrName) { directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName}); } + if (!directive.$$bindings) { + var bindings = directive.$$bindings = + parseDirectiveBindings(directive, directive.name); + if (isObject(bindings.isolateScope)) { + directive.$$isolateBindings = bindings.isolateScope; + } + } tDirectives.push(directive); match = directive; } @@ -8262,18 +9563,16 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { // copy the new attributes on the old attrs object forEach(src, function(value, key) { - if (key == 'class') { - safeAddClass($element, value); - dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value; - } else if (key == 'style') { - $element.attr('style', $element.attr('style') + ';' + value); - dst['style'] = (dst['style'] ? dst['style'] + ';' : '') + value; - // `dst` will never contain hasOwnProperty as DOM parser won't let it. - // You will get an "InvalidCharacterError: DOM Exception 5" error if you - // have an attribute like "has-own-property" or "data-has-own-property", etc. - } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) { + // Check if we already set this attribute in the loop above. + // `dst` will never contain hasOwnProperty as DOM parser won't let it. + // You will get an "InvalidCharacterError: DOM Exception 5" error if you + // have an attribute like "has-own-property" or "data-has-own-property", etc. + if (!dst.hasOwnProperty(key) && key.charAt(0) !== '$') { dst[key] = value; - dstAttr[key] = srcAttr[key]; + + if (key !== 'class' && key !== 'style') { + dstAttr[key] = srcAttr[key]; + } } }); } @@ -8296,7 +9595,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { $compileNode.empty(); - $templateRequest($sce.getTrustedResourceUrl(templateUrl)) + $templateRequest(templateUrl) .then(function(content) { var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn; @@ -8321,7 +9620,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs); if (isObject(origAsyncDirective.scope)) { - markDirectivesAsIsolate(templateDirectives); + // the original directive that caused the template to be loaded async required + // an isolate scope + markDirectiveScope(templateDirectives, true); } directives = templateDirectives.concat(directives); mergeTemplateAttributes(tAttrs, tempTemplateAttrs); @@ -8370,7 +9671,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { childBoundTranscludeFn = boundTranscludeFn; } afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, - childBoundTranscludeFn, afterTemplateNodeLinkFn); + childBoundTranscludeFn); } linkQueue = null; }); @@ -8387,8 +9688,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { if (afterTemplateNodeLinkFn.transcludeOnThisElement) { childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn); } - afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn, - afterTemplateNodeLinkFn); + afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn); } }; } @@ -8452,7 +9752,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { switch (type) { case 'svg': case 'math': - var wrapper = document.createElement('div'); + var wrapper = window.document.createElement('div'); wrapper.innerHTML = '<' + type + '>' + template + ''; return wrapper.childNodes[0].childNodes; default: @@ -8497,7 +9797,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { compile: function() { return { pre: function attrInterpolatePreLinkFn(scope, element, attr) { - var $$observers = (attr.$$observers || (attr.$$observers = {})); + var $$observers = (attr.$$observers || (attr.$$observers = createMap())); if (EVENT_HANDLER_ATTR_REGEXP.test(name)) { throw $compileMinErr('nodomevents', @@ -8592,41 +9892,33 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { parent.replaceChild(newNode, firstElementToRemove); } - // TODO(perf): what's this document fragment for? is it needed? can we at least reuse it? - var fragment = document.createDocumentFragment(); - fragment.appendChild(firstElementToRemove); + // Append all the `elementsToRemove` to a fragment. This will... + // - remove them from the DOM + // - allow them to still be traversed with .nextSibling + // - allow a single fragment.qSA to fetch all elements being removed + var fragment = window.document.createDocumentFragment(); + for (i = 0; i < removeCount; i++) { + fragment.appendChild(elementsToRemove[i]); + } if (jqLite.hasData(firstElementToRemove)) { // Copy over user data (that includes Angular's $scope etc.). Don't copy private // data here because there's no public interface in jQuery to do that and copying over // event listeners (which is the main use of private data) wouldn't work anyway. - jqLite(newNode).data(jqLite(firstElementToRemove).data()); + jqLite.data(newNode, jqLite.data(firstElementToRemove)); - // Remove data of the replaced element. We cannot just call .remove() - // on the element it since that would deallocate scope that is needed - // for the new node. Instead, remove the data "manually". - if (!jQuery) { - delete jqLite.cache[firstElementToRemove[jqLite.expando]]; - } else { - // jQuery 2.x doesn't expose the data storage. Use jQuery.cleanData to clean up after - // the replaced element. The cleanData version monkey-patched by Angular would cause - // the scope to be trashed and we do need the very same scope to work with the new - // element. However, we cannot just cache the non-patched version and use it here as - // that would break if another library patches the method after Angular does (one - // example is jQuery UI). Instead, set a flag indicating scope destroying should be - // skipped this one time. - skipDestroyOnNextJQueryCleanData = true; - jQuery.cleanData([firstElementToRemove]); - } + // Remove $destroy event listeners from `firstElementToRemove` + jqLite(firstElementToRemove).off('$destroy'); } - for (var k = 1, kk = elementsToRemove.length; k < kk; k++) { - var element = elementsToRemove[k]; - jqLite(element).remove(); // must do this way to clean up expando - fragment.appendChild(element); - delete elementsToRemove[k]; - } + // Cleanup any data/listeners on the elements and children. + // This includes invoking the $destroy event on any elements with listeners. + jqLite.cleanData(fragment.querySelectorAll('*')); + // Update the jqLite collection to only contain the `newNode` + for (i = 1; i < removeCount; i++) { + delete elementsToRemove[i]; + } elementsToRemove[0] = newNode; elementsToRemove.length = 1; } @@ -8648,57 +9940,63 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { // Set up $watches for isolate scope and controller bindings. This process // only occurs for isolate scopes and new scopes with controllerAs. - function initializeDirectiveBindings(scope, attrs, destination, bindings, - directive, newScope) { - var onNewScopeDestroyed; - forEach(bindings, function(definition, scopeName) { + function initializeDirectiveBindings(scope, attrs, destination, bindings, directive) { + var removeWatchCollection = []; + var initialChanges = {}; + var changes; + forEach(bindings, function initializeBinding(definition, scopeName) { var attrName = definition.attrName, optional = definition.optional, - mode = definition.mode, // @, =, or & + mode = definition.mode, // @, =, <, or & lastValue, - parentGet, parentSet, compare; - - if (!hasOwnProperty.call(attrs, attrName)) { - // In the case of user defined a binding with the same name as a method in Object.prototype but didn't set - // the corresponding attribute. We need to make sure subsequent code won't access to the prototype function - attrs[attrName] = undefined; - } + parentGet, parentSet, compare, removeWatch; switch (mode) { case '@': - if (!attrs[attrName] && !optional) { - destination[scopeName] = undefined; + if (!optional && !hasOwnProperty.call(attrs, attrName)) { + destination[scopeName] = attrs[attrName] = void 0; } - attrs.$observe(attrName, function(value) { - destination[scopeName] = value; + if (isString(value) || isBoolean(value)) { + var oldValue = destination[scopeName]; + recordChanges(scopeName, value, oldValue); + destination[scopeName] = value; + } }); attrs.$$observers[attrName].$$scope = scope; - if (attrs[attrName]) { + lastValue = attrs[attrName]; + if (isString(lastValue)) { // If the attribute has been provided then we trigger an interpolation to ensure // the value is there for use in the link fn - destination[scopeName] = $interpolate(attrs[attrName])(scope); + destination[scopeName] = $interpolate(lastValue)(scope); + } else if (isBoolean(lastValue)) { + // If the attributes is one of the BOOLEAN_ATTR then Angular will have converted + // the value to boolean rather than a string, so we special case this situation + destination[scopeName] = lastValue; } + initialChanges[scopeName] = new SimpleChange(_UNINITIALIZED_VALUE, destination[scopeName]); break; case '=': - if (optional && !attrs[attrName]) { - return; + if (!hasOwnProperty.call(attrs, attrName)) { + if (optional) break; + attrs[attrName] = void 0; } - parentGet = $parse(attrs[attrName]); + if (optional && !attrs[attrName]) break; + parentGet = $parse(attrs[attrName]); if (parentGet.literal) { compare = equals; } else { - compare = function(a, b) { return a === b || (a !== a && b !== b); }; + compare = function simpleCompare(a, b) { return a === b || (a !== a && b !== b); }; } parentSet = parentGet.assign || function() { // reset the change, or we will throw this exception on every $digest lastValue = destination[scopeName] = parentGet(scope); throw $compileMinErr('nonassign', - "Expression '{0}' used with directive '{1}' is non-assignable!", - attrs[attrName], directive.name); + "Expression '{0}' in attribute '{1}' used with directive '{2}' is non-assignable!", + attrs[attrName], attrName, directive.name); }; lastValue = destination[scopeName] = parentGet(scope); var parentValueWatch = function parentValueWatch(parentValue) { @@ -8715,19 +10013,42 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { return lastValue = parentValue; }; parentValueWatch.$stateful = true; - var unwatch; if (definition.collection) { - unwatch = scope.$watchCollection(attrs[attrName], parentValueWatch); + removeWatch = scope.$watchCollection(attrs[attrName], parentValueWatch); } else { - unwatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal); + removeWatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal); } - onNewScopeDestroyed = (onNewScopeDestroyed || []); - onNewScopeDestroyed.push(unwatch); + removeWatchCollection.push(removeWatch); break; - case '&': + case '<': + if (!hasOwnProperty.call(attrs, attrName)) { + if (optional) break; + attrs[attrName] = void 0; + } + if (optional && !attrs[attrName]) break; + parentGet = $parse(attrs[attrName]); + var initialValue = destination[scopeName] = parentGet(scope); + initialChanges[scopeName] = new SimpleChange(_UNINITIALIZED_VALUE, destination[scopeName]); + + removeWatch = scope.$watch(parentGet, function parentValueWatchAction(newValue, oldValue) { + if (oldValue === newValue) { + if (oldValue === initialValue) return; + oldValue = initialValue; + } + recordChanges(scopeName, newValue, oldValue); + destination[scopeName] = newValue; + }, parentGet.literal); + + removeWatchCollection.push(removeWatch); + break; + + case '&': + // Don't assign Object.prototype method to scope + parentGet = attrs.hasOwnProperty(attrName) ? $parse(attrs[attrName]) : noop; + // Don't assign noop to destination if expression is not valid if (parentGet === noop && optional) break; @@ -8737,20 +10058,53 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { break; } }); - var destroyBindings = onNewScopeDestroyed ? function destroyBindings() { - for (var i = 0, ii = onNewScopeDestroyed.length; i < ii; ++i) { - onNewScopeDestroyed[i](); + + function recordChanges(key, currentValue, previousValue) { + if (isFunction(destination.$onChanges) && currentValue !== previousValue) { + // If we have not already scheduled the top level onChangesQueue handler then do so now + if (!onChangesQueue) { + scope.$$postDigest(flushOnChangesQueue); + onChangesQueue = []; + } + // If we have not already queued a trigger of onChanges for this controller then do so now + if (!changes) { + changes = {}; + onChangesQueue.push(triggerOnChangesHook); + } + // If the has been a change on this property already then we need to reuse the previous value + if (changes[key]) { + previousValue = changes[key].previousValue; + } + // Store this change + changes[key] = new SimpleChange(previousValue, currentValue); } - } : noop; - if (newScope && destroyBindings !== noop) { - newScope.$on('$destroy', destroyBindings); - return noop; } - return destroyBindings; + + function triggerOnChangesHook() { + destination.$onChanges(changes); + // Now clear the changes so that we schedule onChanges when more changes arrive + changes = undefined; + } + + return { + initialChanges: initialChanges, + removeWatches: removeWatchCollection.length && function removeWatches() { + for (var i = 0, ii = removeWatchCollection.length; i < ii; ++i) { + removeWatchCollection[i](); + } + } + }; } }]; } +function SimpleChange(previous, current) { + this.previousValue = previous; + this.currentValue = current; +} +SimpleChange.prototype.isFirstChange = function() { return this.previousValue === _UNINITIALIZED_VALUE; }; + + var PREFIX_REGEXP = /^((?:x|data)[\:\-_])/i; /** * Converts all accepted directives format into proper directive name. @@ -8856,7 +10210,7 @@ function removeComments(jqNodes) { var $controllerMinErr = minErr('$controller'); -var CNTRL_REG = /^(\S+)(\s+as\s+(\w+))?$/; +var CNTRL_REG = /^(\S+)(\s+as\s+([\w$]+))?$/; function identifierForController(controller, ident) { if (ident && isString(ident)) return ident; if (isString(controller)) { @@ -8880,6 +10234,15 @@ function $ControllerProvider() { var controllers = {}, globals = false; + /** + * @ngdoc method + * @name $controllerProvider#has + * @param {string} name Controller name to check. + */ + this.has = function(name) { + return controllers.hasOwnProperty(name); + }; + /** * @ngdoc method * @name $controllerProvider#register @@ -8936,7 +10299,7 @@ function $ControllerProvider() { * It's just a simple call to {@link auto.$injector $injector}, but extracted into * a service, so that one can override this service with [BC version](https://gist.github.com/1649788). */ - return function(expression, locals, later, ident) { + return function $controller(expression, locals, later, ident) { // PRIVATE API: // param `later` --- indicates that the controller's constructor is invoked at a later time. // If true, $controller will allocate the object with the correct @@ -8987,7 +10350,7 @@ function $ControllerProvider() { } var instantiate; - return instantiate = extend(function() { + return instantiate = extend(function $controllerInit() { var result = $injector.invoke(expression, instance, locals, constructor); if (result !== instance && (isObject(result) || isFunction(result))) { instance = result; @@ -9070,18 +10433,21 @@ function $DocumentProvider() { * * ## Example: * + * The example below will overwrite the default `$exceptionHandler` in order to (a) log uncaught + * errors to the backend for later inspection by the developers and (b) to use `$log.warn()` instead + * of `$log.error()`. + * * ```js - * angular.module('exceptionOverride', []).factory('$exceptionHandler', function() { - * return function(exception, cause) { - * exception.message += ' (caused by "' + cause + '")'; - * throw exception; - * }; - * }); + * angular. + * module('exceptionOverwrite', []). + * factory('$exceptionHandler', ['$log', 'logErrorsToBackend', function($log, logErrorsToBackend) { + * return function myExceptionHandler(exception, cause) { + * logErrorsToBackend(exception, cause); + * $log.warn(exception, cause); + * }; + * }]); * ``` * - * This example will override the normal action of `$exceptionHandler`, to make angular - * exceptions fail hard when they happen, instead of just logging to the console. - * *
* Note, that code executed in event-listeners (even those registered using jqLite's `on`/`bind` * methods) does not delegate exceptions to the {@link ng.$exceptionHandler $exceptionHandler} @@ -9091,7 +10457,7 @@ function $DocumentProvider() { * `try { ... } catch(e) { $exceptionHandler(e); }` * * @param {Error} exception Exception associated with the error. - * @param {string=} cause optional information about the context in which + * @param {string=} cause Optional information about the context in which * the error was thrown. * */ @@ -9103,6 +10469,29 @@ function $ExceptionHandlerProvider() { }]; } +var $$ForceReflowProvider = function() { + this.$get = ['$document', function($document) { + return function(domNode) { + //the line below will force the browser to perform a repaint so + //that all the animated elements within the animation frame will + //be properly updated and drawn on screen. This is required to + //ensure that the preparation animation is properly flushed so that + //the active state picks up from there. DO NOT REMOVE THIS LINE. + //DO NOT OPTIMIZE THIS LINE. THE MINIFIER WILL REMOVE IT OTHERWISE WHICH + //WILL RESULT IN AN UNPREDICTABLE BUG THAT IS VERY HARD TO TRACK DOWN AND + //WILL TAKE YEARS AWAY FROM YOUR LIFE. + if (domNode) { + if (!domNode.nodeType && domNode instanceof jqLite) { + domNode = domNode[0]; + } + } else { + domNode = $document[0].body; + } + return domNode.offsetWidth + 1; + }; + }]; +}; + var APPLICATION_JSON = 'application/json'; var CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': APPLICATION_JSON + ';charset=utf-8'}; var JSON_START = /^\[|^\{(?!\{)/; @@ -9111,6 +10500,12 @@ var JSON_ENDS = { '{': /}$/ }; var JSON_PROTECTION_PREFIX = /^\)\]\}',?\n/; +var $httpMinErr = minErr('$http'); +var $httpMinErrLegacyFn = function(method) { + return function() { + throw $httpMinErr('legacy', 'The method `{0}` on the promise returned from `$http` has been disabled.', method); + }; +}; function serializeValue(v) { if (isObject(v)) { @@ -9132,7 +10527,7 @@ function $HttpParamSerializerProvider() { * * `{'foo': 'bar'}` results in `foo=bar` * * `{'foo': Date.now()}` results in `foo=2015-04-01T09%3A50%3A49.262Z` (`toISOString()` and encoded representation of a Date object) * * `{'foo': ['bar', 'baz']}` results in `foo=bar&foo=baz` (repeated key for each array element) - * * `{'foo': {'bar':'baz'}}` results in `foo=%7B%22bar%22%3A%22baz%22%7D"` (stringified and encoded representation of an object) + * * `{'foo': {'bar':'baz'}}` results in `foo=%7B%22bar%22%3A%22baz%22%7D` (stringified and encoded representation of an object) * * Note that serializer will sort the request parameters alphabetically. * */ @@ -9144,7 +10539,7 @@ function $HttpParamSerializerProvider() { forEachSorted(params, function(value, key) { if (value === null || isUndefined(value)) return; if (isArray(value)) { - forEach(value, function(v, k) { + forEach(value, function(v) { parts.push(encodeUriQuery(key) + '=' + encodeUriQuery(serializeValue(v))); }); } else { @@ -9211,8 +10606,8 @@ function $HttpParamSerializerJQLikeProvider() { function serialize(toSerialize, prefix, topLevel) { if (toSerialize === null || isUndefined(toSerialize)) return; if (isArray(toSerialize)) { - forEach(toSerialize, function(value) { - serialize(value, prefix + '[]'); + forEach(toSerialize, function(value, index) { + serialize(value, prefix + '[' + (isObject(value) ? index : '') + ']'); }); } else if (isObject(toSerialize) && !isDate(toSerialize)) { forEachSorted(toSerialize, function(value, key) { @@ -9354,10 +10749,9 @@ function $HttpProvider() { * * Object containing default values for all {@link ng.$http $http} requests. * - * - **`defaults.cache`** - {Object} - an object built with {@link ng.$cacheFactory `$cacheFactory`} - * that will provide the cache for all requests who set their `cache` property to `true`. - * If you set the `default.cache = false` then only requests that specify their own custom - * cache object will be cached. See {@link $http#caching $http Caching} for more information. + * - **`defaults.cache`** - {boolean|Object} - A boolean value or object created with + * {@link ng.$cacheFactory `$cacheFactory`} to enable or disable caching of HTTP responses + * by default. See {@link $http#caching $http Caching} for more information. * * - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token. * Defaults value is `'XSRF-TOKEN'`. @@ -9433,6 +10827,30 @@ function $HttpProvider() { return useApplyAsync; }; + var useLegacyPromise = true; + /** + * @ngdoc method + * @name $httpProvider#useLegacyPromiseExtensions + * @description + * + * Configure `$http` service to return promises without the shorthand methods `success` and `error`. + * This should be used to make sure that applications work without these methods. + * + * Defaults to true. If no value is specified, returns the current configured value. + * + * @param {boolean=} value If true, `$http` will return a promise with the deprecated legacy `success` and `error` methods. + * + * @returns {boolean|Object} If a value is specified, returns the $httpProvider for chaining. + * otherwise, returns the current configured value. + **/ + this.useLegacyPromiseExtensions = function(value) { + if (isDefined(value)) { + useLegacyPromise = !!value; + return this; + } + return useLegacyPromise; + }; + /** * @ngdoc property * @name $httpProvider#interceptors @@ -9498,66 +10916,50 @@ function $HttpProvider() { * * * ## General usage - * The `$http` service is a function which takes a single argument — a configuration object — - * that is used to generate an HTTP request and returns a {@link ng.$q promise} - * with two $http specific methods: `success` and `error`. - * - * ```js - * // Simple GET request example : - * $http.get('/someUrl'). - * success(function(data, status, headers, config) { - * // this callback will be called asynchronously - * // when the response is available - * }). - * error(function(data, status, headers, config) { - * // called asynchronously if an error occurs - * // or server returns response with an error status. - * }); - * ``` + * The `$http` service is a function which takes a single argument — a {@link $http#usage configuration object} — + * that is used to generate an HTTP request and returns a {@link ng.$q promise}. * * ```js - * // Simple POST request example (passing data) : - * $http.post('/someUrl', {msg:'hello word!'}). - * success(function(data, status, headers, config) { + * // Simple GET request example: + * $http({ + * method: 'GET', + * url: '/someUrl' + * }).then(function successCallback(response) { * // this callback will be called asynchronously * // when the response is available - * }). - * error(function(data, status, headers, config) { + * }, function errorCallback(response) { * // called asynchronously if an error occurs * // or server returns response with an error status. * }); * ``` * + * The response object has these properties: * - * Since the returned value of calling the $http function is a `promise`, you can also use - * the `then` method to register callbacks, and these callbacks will receive a single argument – - * an object representing the response. See the API signature and type info below for more - * details. - * - * A response status code between 200 and 299 is considered a success status and - * will result in the success callback being called. Note that if the response is a redirect, - * XMLHttpRequest will transparently follow it, meaning that the error callback will not be - * called for such responses. + * - **data** – `{string|Object}` – The response body transformed with the transform + * functions. + * - **status** – `{number}` – HTTP status code of the response. + * - **headers** – `{function([headerName])}` – Header getter function. + * - **config** – `{Object}` – The configuration object that was used to generate the request. + * - **statusText** – `{string}` – HTTP status text of the response. * - * ## Writing Unit Tests that use $http - * When unit testing (using {@link ngMock ngMock}), it is necessary to call - * {@link ngMock.$httpBackend#flush $httpBackend.flush()} to flush each pending - * request using trained responses. + * A response status code between 200 and 299 is considered a success status and will result in + * the success callback being called. Any response status code outside of that range is + * considered an error status and will result in the error callback being called. + * Also, status codes less than -1 are normalized to zero. -1 usually means the request was + * aborted, e.g. using a `config.timeout`. + * Note that if the response is a redirect, XMLHttpRequest will transparently follow it, meaning + * that the outcome (success or error) will be determined by the final response status code. * - * ``` - * $httpBackend.expectGET(...); - * $http.get(...); - * $httpBackend.flush(); - * ``` * * ## Shortcut methods * * Shortcut methods are also available. All shortcut methods require passing in the URL, and - * request data must be passed in for POST/PUT requests. + * request data must be passed in for POST/PUT requests. An optional config can be passed as the + * last argument. * * ```js - * $http.get('/someUrl').success(successCallback); - * $http.post('/someUrl', data).success(successCallback); + * $http.get('/someUrl', config).then(successCallback, errorCallback); + * $http.post('/someUrl', data, config).then(successCallback, errorCallback); * ``` * * Complete list of shortcut methods: @@ -9571,6 +10973,25 @@ function $HttpProvider() { * - {@link ng.$http#patch $http.patch} * * + * ## Writing Unit Tests that use $http + * When unit testing (using {@link ngMock ngMock}), it is necessary to call + * {@link ngMock.$httpBackend#flush $httpBackend.flush()} to flush each pending + * request using trained responses. + * + * ``` + * $httpBackend.expectGET(...); + * $http.get(...); + * $httpBackend.flush(); + * ``` + * + * ## Deprecation Notice + *
+ * The `$http` legacy promise methods `success` and `error` have been deprecated. + * Use the standard `then` method instead. + * If {@link $httpProvider#useLegacyPromiseExtensions `$httpProvider.useLegacyPromiseExtensions`} is set to + * `false` then these methods will throw {@link $http:legacy `$http/legacy`} error. + *
+ * * ## Setting HTTP Headers * * The $http service will automatically add certain HTTP headers to all requests. These defaults @@ -9594,7 +11015,7 @@ function $HttpProvider() { * * ``` * module.run(function($http) { - * $http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w' + * $http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w'; * }); * ``` * @@ -9614,7 +11035,7 @@ function $HttpProvider() { * data: { test: 'test' } * } * - * $http(req).success(function(){...}).error(function(){...}); + * $http(req).then(function(){...}, function(){...}); * ``` * * ## Transforming Requests and Responses @@ -9624,6 +11045,15 @@ function $HttpProvider() { * the transformed value (`function(data, headersGetter, status)`) or an array of such transformation functions, * which allows you to `push` or `unshift` a new transformation function into the transformation chain. * + *
+ * **Note:** Angular does not make a copy of the `data` parameter before it is passed into the `transformRequest` pipeline. + * That means changes to the properties of `data` are not local to the transform function (since Javascript passes objects by reference). + * For example, when calling `$http.get(url, $scope.myObject)`, modifications to the object's properties in a transformRequest + * function will be reflected on the scope and in any templates where the object is data-bound. + * To prevent this, transform functions should have no side-effects. + * If you need to modify properties, it is recommended to make a copy of the data, or create new object to return. + *
+ * * ### Default Transformations * * The `$httpProvider` provider and `$http` service expose `defaults.transformRequest` and @@ -9648,7 +11078,7 @@ function $HttpProvider() { * * ### Overriding the Default Transformations Per Request * - * If you wish override the request/response transformations only for a single request then provide + * If you wish to override the request/response transformations only for a single request then provide * `transformRequest` and/or `transformResponse` properties on the configuration object passed * into `$http`. * @@ -9681,26 +11111,35 @@ function $HttpProvider() { * * ## Caching * - * To enable caching, set the request configuration `cache` property to `true` (to use default - * cache) or to a custom cache object (built with {@link ng.$cacheFactory `$cacheFactory`}). - * When the cache is enabled, `$http` stores the response from the server in the specified - * cache. The next time the same request is made, the response is served from the cache without - * sending a request to the server. + * {@link ng.$http `$http`} responses are not cached by default. To enable caching, you must + * set the config.cache value or the default cache value to TRUE or to a cache object (created + * with {@link ng.$cacheFactory `$cacheFactory`}). If defined, the value of config.cache takes + * precedence over the default cache value. + * + * In order to: + * * cache all responses - set the default cache value to TRUE or to a cache object + * * cache a specific response - set config.cache value to TRUE or to a cache object + * + * If caching is enabled, but neither the default cache nor config.cache are set to a cache object, + * then the default `$cacheFactory("$http")` object is used. + * + * The default cache value can be set by updating the + * {@link ng.$http#defaults `$http.defaults.cache`} property or the + * {@link $httpProvider#defaults `$httpProvider.defaults.cache`} property. * - * Note that even if the response is served from cache, delivery of the data is asynchronous in - * the same way that real requests are. + * When caching is enabled, {@link ng.$http `$http`} stores the response from the server using + * the relevant cache object. The next time the same request is made, the response is returned + * from the cache without sending a request to the server. * - * If there are multiple GET requests for the same URL that should be cached using the same - * cache, but the cache is not populated yet, only one request to the server will be made and - * the remaining requests will be fulfilled using the response from the first request. + * Take note that: * - * You can change the default cache to a new object (built with - * {@link ng.$cacheFactory `$cacheFactory`}) by updating the - * {@link ng.$http#defaults `$http.defaults.cache`} property. All requests who set - * their `cache` property to `true` will now use this cache object. + * * Only GET and JSONP requests are cached. + * * The cache key is the request URL including search parameters; headers are not considered. + * * Cached responses are returned asynchronously, in the same way as responses from the server. + * * If multiple identical requests are made using the same cache, which is not yet populated, + * one request will be made to the server and remaining requests will return the same response. + * * A cache-control header on the response does not affect if or how responses are cached. * - * If you set the default cache to `false` then only requests that specify their own custom - * cache object will be cached. * * ## Interceptors * @@ -9720,7 +11159,7 @@ function $HttpProvider() { * * There are two kinds of interceptors (and two kinds of rejection interceptors): * - * * `request`: interceptors get called with a http `config` object. The function is free to + * * `request`: interceptors get called with a http {@link $http#usage config} object. The function is free to * modify the `config` object or create a new one. The function needs to return the `config` * object directly, or a promise containing the `config` or a new `config` object. * * `requestError`: interceptor gets called when a previous interceptor threw an error or @@ -9822,13 +11261,13 @@ function $HttpProvider() { * * ### Cross Site Request Forgery (XSRF) Protection * - * [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) is a technique by which - * an unauthorized site can gain your user's private data. Angular provides a mechanism - * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie - * (by default, `XSRF-TOKEN`) and sets it as an HTTP header (`X-XSRF-TOKEN`). Since only - * JavaScript that runs on your domain could read the cookie, your server can be assured that - * the XHR came from JavaScript running on your domain. The header will not be set for - * cross-domain requests. + * [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) is an attack technique by + * which the attacker can trick an authenticated user into unknowingly executing actions on your + * website. Angular provides a mechanism to counter XSRF. When performing XHR requests, the + * $http service reads a token from a cookie (by default, `XSRF-TOKEN`) and sets it as an HTTP + * header (`X-XSRF-TOKEN`). Since only JavaScript that runs on your domain could read the + * cookie, your server can be assured that the XHR came from JavaScript running on your domain. + * The header will not be set for cross-domain requests. * * To take advantage of this, your server needs to set a token in a JavaScript readable session * cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the @@ -9846,7 +11285,6 @@ function $HttpProvider() { * In order to prevent collisions in environments where multiple Angular apps share the * same domain or subdomain, we recommend that each application uses unique cookie name. * - * * @param {object} config Object describing the request to be made and how it should be * processed. The object has following properties: * @@ -9858,6 +11296,12 @@ function $HttpProvider() { * - **headers** – `{Object}` – Map of strings or functions which return strings representing * HTTP headers to send to the server. If the return value of a function is null, the * header will not be sent. Functions accept a config object as an argument. + * - **eventHandlers** - `{Object}` - Event listeners to be bound to the XMLHttpRequest object. + * To bind events to the XMLHttpRequest upload object, use `uploadEventHandlers`. + * The handler will be called in the context of a `$apply` block. + * - **uploadEventHandlers** - `{Object}` - Event listeners to be bound to the XMLHttpRequest upload + * object. To bind events to the XMLHttpRequest object, use `eventHandlers`. + * The handler will be called in the context of a `$apply` block. * - **xsrfHeaderName** – `{string}` – Name of HTTP header to populate with the XSRF token. * - **xsrfCookieName** – `{string}` – Name of cookie containing the XSRF token. * - **transformRequest** – @@ -9871,7 +11315,7 @@ function $HttpProvider() { * transform function or an array of such functions. The transform function takes the http * response body, headers and status and returns its transformed (typically deserialized) version. * See {@link ng.$http#overriding-the-default-transformations-per-request - * Overriding the Default TransformationjqLiks} + * Overriding the Default Transformations} * - **paramSerializer** - `{string|function(Object):string}` - A function used to * prepare the string representation of request parameters (specified as an object). * If specified as string, it is interpreted as function registered with the @@ -9879,32 +11323,20 @@ function $HttpProvider() { * by registering it as a {@link auto.$provide#service service}. * The default serializer is the {@link $httpParamSerializer $httpParamSerializer}; * alternatively, you can use the {@link $httpParamSerializerJQLike $httpParamSerializerJQLike} - * - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the - * GET request, otherwise if a cache instance built with - * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for - * caching. + * - **cache** – `{boolean|Object}` – A boolean value or object created with + * {@link ng.$cacheFactory `$cacheFactory`} to enable or disable caching of the HTTP response. + * See {@link $http#caching $http Caching} for more information. * - **timeout** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise} * that should abort the request when resolved. * - **withCredentials** - `{boolean}` - whether to set the `withCredentials` flag on the * XHR object. See [requests with credentials](https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials) * for more information. * - **responseType** - `{string}` - see - * [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType). + * [XMLHttpRequest.responseType](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#xmlhttprequest-responsetype). * - * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the - * standard `then` method and two http specific methods: `success` and `error`. The `then` - * method takes two arguments a success and an error callback which will be called with a - * response object. The `success` and `error` methods take a single argument - a function that - * will be called when the request succeeds or fails respectively. The arguments passed into - * these functions are destructured representation of the response object passed into the - * `then` method. The response object has these properties: + * @returns {HttpPromise} Returns a {@link ng.$q `Promise}` that will be resolved to a response object + * when the request succeeds or fails. * - * - **data** – `{string|Object}` – The response body transformed with the transform - * functions. - * - **status** – `{number}` – HTTP status code of the response. - * - **headers** – `{function([headerName])}` – Header getter function. - * - **config** – `{Object}` – The configuration object that was used to generate the request. - * - **statusText** – `{string}` – HTTP status text of the response. * * @property {Array.} pendingRequests Array of config objects for currently pending * requests. This is primarily meant to be used for debugging purposes. @@ -9946,13 +11378,12 @@ function $HttpProvider() { $scope.response = null; $http({method: $scope.method, url: $scope.url, cache: $templateCache}). - success(function(data, status) { - $scope.status = status; - $scope.data = data; - }). - error(function(data, status) { - $scope.data = data || "Request failed"; - $scope.status = status; + then(function(response) { + $scope.status = response.status; + $scope.data = response.data; + }, function(response) { + $scope.data = response.data || "Request failed"; + $scope.status = response.status; }); }; @@ -10000,10 +11431,14 @@ function $HttpProvider() { */ function $http(requestConfig) { - if (!angular.isObject(requestConfig)) { + if (!isObject(requestConfig)) { throw minErr('$http')('badreq', 'Http request configuration must be an object. Received: {0}', requestConfig); } + if (!isString(requestConfig.url)) { + throw minErr('$http')('badreq', 'Http request configuration url must be a string. Received: {0}', requestConfig.url); + } + var config = extend({ method: 'get', transformRequest: defaults.transformRequest, @@ -10014,80 +11449,63 @@ function $HttpProvider() { config.headers = mergeHeaders(requestConfig); config.method = uppercase(config.method); config.paramSerializer = isString(config.paramSerializer) ? - $injector.get(config.paramSerializer) : config.paramSerializer; - - var serverRequest = function(config) { - var headers = config.headers; - var reqData = transformData(config.data, headersGetter(headers), undefined, config.transformRequest); - - // strip content-type if data is undefined - if (isUndefined(reqData)) { - forEach(headers, function(value, header) { - if (lowercase(header) === 'content-type') { - delete headers[header]; - } - }); - } - - if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) { - config.withCredentials = defaults.withCredentials; - } - - // send request - return sendReq(config, reqData).then(transformResponse, transformResponse); - }; + $injector.get(config.paramSerializer) : config.paramSerializer; - var chain = [serverRequest, undefined]; + var requestInterceptors = []; + var responseInterceptors = []; var promise = $q.when(config); // apply interceptors forEach(reversedInterceptors, function(interceptor) { if (interceptor.request || interceptor.requestError) { - chain.unshift(interceptor.request, interceptor.requestError); + requestInterceptors.unshift(interceptor.request, interceptor.requestError); } if (interceptor.response || interceptor.responseError) { - chain.push(interceptor.response, interceptor.responseError); + responseInterceptors.push(interceptor.response, interceptor.responseError); } }); - while (chain.length) { - var thenFn = chain.shift(); - var rejectFn = chain.shift(); - - promise = promise.then(thenFn, rejectFn); - } + promise = chainInterceptors(promise, requestInterceptors); + promise = promise.then(serverRequest); + promise = chainInterceptors(promise, responseInterceptors); - promise.success = function(fn) { - assertArgFn(fn, 'fn'); + if (useLegacyPromise) { + promise.success = function(fn) { + assertArgFn(fn, 'fn'); - promise.then(function(response) { - fn(response.data, response.status, response.headers, config); - }); - return promise; - }; + promise.then(function(response) { + fn(response.data, response.status, response.headers, config); + }); + return promise; + }; - promise.error = function(fn) { - assertArgFn(fn, 'fn'); + promise.error = function(fn) { + assertArgFn(fn, 'fn'); - promise.then(null, function(response) { - fn(response.data, response.status, response.headers, config); - }); - return promise; - }; + promise.then(null, function(response) { + fn(response.data, response.status, response.headers, config); + }); + return promise; + }; + } else { + promise.success = $httpMinErrLegacyFn('success'); + promise.error = $httpMinErrLegacyFn('error'); + } return promise; - function transformResponse(response) { - // make a copy since the response must be cacheable - var resp = extend({}, response); - if (!response.data) { - resp.data = response.data; - } else { - resp.data = transformData(response.data, response.headers, response.status, config.transformResponse); + + function chainInterceptors(promise, interceptors) { + for (var i = 0, ii = interceptors.length; i < ii;) { + var thenFn = interceptors[i++]; + var rejectFn = interceptors[i++]; + + promise = promise.then(thenFn, rejectFn); } - return (isSuccess(response.status)) - ? resp - : $q.reject(resp); + + interceptors.length = 0; + + return promise; } function executeHeaderFns(headers, config) { @@ -10114,7 +11532,7 @@ function $HttpProvider() { defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]); - // using for-in instead of forEach to avoid unecessary iteration after header has been found + // using for-in instead of forEach to avoid unnecessary iteration after header has been found defaultHeadersIteration: for (defHeaderName in defHeaders) { lowercaseDefHeaderName = lowercase(defHeaderName); @@ -10131,6 +11549,37 @@ function $HttpProvider() { // execute if header value is a function for merged headers return executeHeaderFns(reqHeaders, shallowCopy(config)); } + + function serverRequest(config) { + var headers = config.headers; + var reqData = transformData(config.data, headersGetter(headers), undefined, config.transformRequest); + + // strip content-type if data is undefined + if (isUndefined(reqData)) { + forEach(headers, function(value, header) { + if (lowercase(header) === 'content-type') { + delete headers[header]; + } + }); + } + + if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) { + config.withCredentials = defaults.withCredentials; + } + + // send request + return sendReq(config, reqData).then(transformResponse, transformResponse); + } + + function transformResponse(response) { + // make a copy since the response must be cacheable + var resp = extend({}, response); + resp.data = transformData(response.data, response.headers, response.status, + config.transformResponse); + return (isSuccess(response.status)) + ? resp + : $q.reject(resp); + } } $http.pendingRequests = []; @@ -10177,6 +11626,8 @@ function $HttpProvider() { * * @description * Shortcut method to perform `JSONP` request. + * If you would like to customise where and how the callbacks are stored then try overriding + * or decorating the {@link $jsonpCallbacks} service. * * @param {string} url Relative or absolute URL specifying the destination of the request. * The name of the callback should be the string `JSON_CALLBACK`. @@ -10323,11 +11774,35 @@ function $HttpProvider() { } $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout, - config.withCredentials, config.responseType); + config.withCredentials, config.responseType, + createApplyHandlers(config.eventHandlers), + createApplyHandlers(config.uploadEventHandlers)); } return promise; + function createApplyHandlers(eventHandlers) { + if (eventHandlers) { + var applyHandlers = {}; + forEach(eventHandlers, function(eventHandler, key) { + applyHandlers[key] = function(event) { + if (useApplyAsync) { + $rootScope.$applyAsync(callEventHandler); + } else if ($rootScope.$$phase) { + callEventHandler(); + } else { + $rootScope.$apply(callEventHandler); + } + + function callEventHandler() { + eventHandler(event); + } + }; + }); + return applyHandlers; + } + } + /** * Callback registered to $httpBackend(): @@ -10362,8 +11837,8 @@ function $HttpProvider() { * Resolves the raw $http promise. */ function resolvePromise(response, status, headers, statusText) { - // normalize internal statuses to 0 - status = Math.max(status, 0); + //status: HTTP response status code, 0, -1 (aborted by timeout / promise) + status = status >= -1 ? status : 0; (isSuccess(status) ? deferred.resolve : deferred.reject)({ data: response, @@ -10394,15 +11869,41 @@ function $HttpProvider() { }]; } -function createXhr() { - return new window.XMLHttpRequest(); +/** + * @ngdoc service + * @name $xhrFactory + * + * @description + * Factory function used to create XMLHttpRequest objects. + * + * Replace or decorate this service to create your own custom XMLHttpRequest objects. + * + * ``` + * angular.module('myApp', []) + * .factory('$xhrFactory', function() { + * return function createXhr(method, url) { + * return new window.XMLHttpRequest({mozSystem: true}); + * }; + * }); + * ``` + * + * @param {string} method HTTP method of the request (GET, POST, PUT, ..) + * @param {string} url URL of the request. + */ +function $xhrFactoryProvider() { + this.$get = function() { + return function createXhr() { + return new window.XMLHttpRequest(); + }; + }; } /** * @ngdoc service * @name $httpBackend - * @requires $window + * @requires $jsonpCallbacks * @requires $document + * @requires $xhrFactory * * @description * HTTP backend used by the {@link ng.$http service} that delegates to @@ -10415,32 +11916,28 @@ function createXhr() { * $httpBackend} which can be trained with responses. */ function $HttpBackendProvider() { - this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) { - return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]); + this.$get = ['$browser', '$jsonpCallbacks', '$document', '$xhrFactory', function($browser, $jsonpCallbacks, $document, $xhrFactory) { + return createHttpBackend($browser, $xhrFactory, $browser.defer, $jsonpCallbacks, $document[0]); }]; } function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) { // TODO(vojta): fix the signature - return function(method, url, post, callback, headers, timeout, withCredentials, responseType) { + return function(method, url, post, callback, headers, timeout, withCredentials, responseType, eventHandlers, uploadEventHandlers) { $browser.$$incOutstandingRequestCount(); url = url || $browser.url(); - if (lowercase(method) == 'jsonp') { - var callbackId = '_' + (callbacks.counter++).toString(36); - callbacks[callbackId] = function(data) { - callbacks[callbackId].data = data; - callbacks[callbackId].called = true; - }; - - var jsonpDone = jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId), - callbackId, function(status, text) { - completeRequest(callback, status, callbacks[callbackId].data, "", text); - callbacks[callbackId] = noop; + if (lowercase(method) === 'jsonp') { + var callbackPath = callbacks.createCallback(url); + var jsonpDone = jsonpReq(url, callbackPath, function(status, text) { + // jsonpReq only ever sets status to 200 (OK), 404 (ERROR) or -1 (WAITING) + var response = (status === 200) && callbacks.getResponse(callbackPath); + completeRequest(callback, status, response, "", text); + callbacks.removeCallback(callbackPath); }); } else { - var xhr = createXhr(); + var xhr = createXhr(method, url); xhr.open(method, url, true); forEach(headers, function(value, key) { @@ -10452,7 +11949,7 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc xhr.onload = function requestLoaded() { var statusText = xhr.statusText || ''; - // responseText is the old-school way of retrieving response (supported by IE8 & 9) + // responseText is the old-school way of retrieving response (supported by IE9) // response/responseType properties were introduced in XHR Level2 spec (supported by IE10) var response = ('response' in xhr) ? xhr.response : xhr.responseText; @@ -10482,9 +11979,17 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc xhr.onerror = requestError; xhr.onabort = requestError; - if (withCredentials) { - xhr.withCredentials = true; - } + forEach(eventHandlers, function(value, key) { + xhr.addEventListener(key, value); + }); + + forEach(uploadEventHandlers, function(value, key) { + xhr.upload.addEventListener(key, value); + }); + + if (withCredentials) { + xhr.withCredentials = true; + } if (responseType) { try { @@ -10503,7 +12008,7 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc } } - xhr.send(post); + xhr.send(isUndefined(post) ? null : post); } if (timeout > 0) { @@ -10520,7 +12025,7 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc function completeRequest(callback, status, response, headersString, statusText) { // cancel timeout and subsequent timeout promise resolution - if (timeoutId !== undefined) { + if (isDefined(timeoutId)) { $browserDefer.cancel(timeoutId); } jsonpDone = xhr = null; @@ -10530,7 +12035,8 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc } }; - function jsonpReq(url, callbackId, done) { + function jsonpReq(url, callbackPath, done) { + url = url.replace('JSON_CALLBACK', callbackPath); // we can't use jQuery/jqLite here because jQuery does crazy stuff with script elements, e.g.: // - fetches local scripts via XHR and evals them // - adds and immediately removes script elements from the document @@ -10548,7 +12054,7 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc var text = "unknown"; if (event) { - if (event.type === "load" && !callbacks[callbackId].called) { + if (event.type === "load" && !callbacks.wasCalled(callbackPath)) { event = { type: "error" }; } text = event.type; @@ -10587,8 +12093,16 @@ $interpolateMinErr.interr = function(text, err) { * * Used for configuring the interpolation markup. Defaults to `{{` and `}}`. * + *
+ * This feature is sometimes used to mix different markup languages, e.g. to wrap an Angular + * template within a Python Jinja template (or any other template language). Mixing templating + * languages is **very dangerous**. The embedding template language will not safely escape Angular + * expressions, so any user-controlled values in the template will cause Cross Site Scripting (XSS) + * security bugs! + *
+ * * @example - + -
+
//demo.label//
@@ -10687,6 +12201,15 @@ function $InterpolateProvider() { return value; } + //TODO: this is the same as the constantWatchDelegate in parse.js + function constantWatchDelegate(scope, listener, objectEquality, constantInterp) { + var unwatch; + return unwatch = scope.$watch(function constantInterpolateWatch(scope) { + unwatch(); + return constantInterp(scope); + }, listener, objectEquality); + } + /** * @ngdoc service * @name $interpolate @@ -10706,7 +12229,7 @@ function $InterpolateProvider() { * ```js * var $interpolate = ...; // injected * var exp = $interpolate('Hello {{name | uppercase}}!'); - * expect(exp({name:'Angular'}).toEqual('Hello ANGULAR!'); + * expect(exp({name:'Angular'})).toEqual('Hello ANGULAR!'); * ``` * * `$interpolate` takes an optional fourth argument, `allOrNothing`. If `allOrNothing` is @@ -10730,7 +12253,7 @@ function $InterpolateProvider() { * * `allOrNothing` is useful for interpolating URLs. `ngSrc` and `ngSrcset` use this behavior. * - * ####Escaped Interpolation + * #### Escaped Interpolation * $interpolate provides a mechanism for escaping interpolation markers. Start and end markers * can be escaped by preceding each of their characters with a REVERSE SOLIDUS U+005C (backslash). * It will be rendered as a regular start/end marker, and will not be interpreted as an expression @@ -10766,6 +12289,30 @@ function $InterpolateProvider() { * * * + * @knownIssue + * It is currently not possible for an interpolated expression to contain the interpolation end + * symbol. For example, `{{ '}}' }}` will be incorrectly interpreted as `{{ ' }}` + `' }}`, i.e. + * an interpolated expression consisting of a single-quote (`'`) and the `' }}` string. + * + * @knownIssue + * All directives and components must use the standard `{{` `}}` interpolation symbols + * in their templates. If you change the application interpolation symbols the {@link $compile} + * service will attempt to denormalize the standard symbols to the custom symbols. + * The denormalization process is not clever enough to know not to replace instances of the standard + * symbols where they would not normally be treated as interpolation symbols. For example in the following + * code snippet the closing braces of the literal object will get incorrectly denormalized: + * + * ``` + *
+ * ``` + * + * See https://github.com/angular/angular.js/pull/14610#issuecomment-219401099 for more information. + * * @param {string} text The text with markup to interpolate. * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have * embedded expression in order to return an interpolation function. Strings with no @@ -10782,6 +12329,19 @@ function $InterpolateProvider() { * - `context`: evaluation context for all expressions embedded in the interpolated text */ function $interpolate(text, mustHaveExpression, trustedContext, allOrNothing) { + // Provide a quick exit and simplified result function for text with no interpolation + if (!text.length || text.indexOf(startSymbol) === -1) { + var constantInterp; + if (!mustHaveExpression) { + var unescapedText = unescapeText(text); + constantInterp = valueFn(unescapedText); + constantInterp.exp = text; + constantInterp.expressions = []; + constantInterp.$$watchDelegate = constantWatchDelegate; + } + return constantInterp; + } + allOrNothing = !!allOrNothing; var startIndex, endIndex, @@ -10918,8 +12478,8 @@ function $InterpolateProvider() { } function $IntervalProvider() { - this.$get = ['$rootScope', '$window', '$q', '$$q', - function($rootScope, $window, $q, $$q) { + this.$get = ['$rootScope', '$window', '$q', '$$q', '$browser', + function($rootScope, $window, $q, $$q, $browser) { var intervals = {}; @@ -11060,11 +12620,12 @@ function $IntervalProvider() { count = isDefined(count) ? count : 0; - promise.then(null, null, (!hasParams) ? fn : function() { - fn.apply(null, args); - }); - promise.$$intervalId = setInterval(function tick() { + if (skipApply) { + $browser.defer(callback); + } else { + $rootScope.$evalAsync(callback); + } deferred.notify(iteration++); if (count > 0 && iteration >= count) { @@ -11080,6 +12641,14 @@ function $IntervalProvider() { intervals[promise.$$intervalId] = deferred; return promise; + + function callback() { + if (!hasParams) { + fn(iteration); + } else { + fn.apply(null, args); + } + } } @@ -11090,7 +12659,7 @@ function $IntervalProvider() { * @description * Cancels a task associated with the `promise`. * - * @param {promise} promise returned by the `$interval` function. + * @param {Promise=} promise returned by the `$interval` function. * @returns {boolean} Returns `true` if the task was successfully canceled. */ interval.cancel = function(promise) { @@ -11107,6 +12676,87 @@ function $IntervalProvider() { }]; } +/** + * @ngdoc service + * @name $jsonpCallbacks + * @requires $window + * @description + * This service handles the lifecycle of callbacks to handle JSONP requests. + * Override this service if you wish to customise where the callbacks are stored and + * how they vary compared to the requested url. + */ +var $jsonpCallbacksProvider = function() { + this.$get = ['$window', function($window) { + var callbacks = $window.angular.callbacks; + var callbackMap = {}; + + function createCallback(callbackId) { + var callback = function(data) { + callback.data = data; + callback.called = true; + }; + callback.id = callbackId; + return callback; + } + + return { + /** + * @ngdoc method + * @name $jsonpCallbacks#createCallback + * @param {string} url the url of the JSONP request + * @returns {string} the callback path to send to the server as part of the JSONP request + * @description + * {@link $httpBackend} calls this method to create a callback and get hold of the path to the callback + * to pass to the server, which will be used to call the callback with its payload in the JSONP response. + */ + createCallback: function(url) { + var callbackId = '_' + (callbacks.$$counter++).toString(36); + var callbackPath = 'angular.callbacks.' + callbackId; + var callback = createCallback(callbackId); + callbackMap[callbackPath] = callbacks[callbackId] = callback; + return callbackPath; + }, + /** + * @ngdoc method + * @name $jsonpCallbacks#wasCalled + * @param {string} callbackPath the path to the callback that was sent in the JSONP request + * @returns {boolean} whether the callback has been called, as a result of the JSONP response + * @description + * {@link $httpBackend} calls this method to find out whether the JSONP response actually called the + * callback that was passed in the request. + */ + wasCalled: function(callbackPath) { + return callbackMap[callbackPath].called; + }, + /** + * @ngdoc method + * @name $jsonpCallbacks#getResponse + * @param {string} callbackPath the path to the callback that was sent in the JSONP request + * @returns {*} the data received from the response via the registered callback + * @description + * {@link $httpBackend} calls this method to get hold of the data that was provided to the callback + * in the JSONP response. + */ + getResponse: function(callbackPath) { + return callbackMap[callbackPath].data; + }, + /** + * @ngdoc method + * @name $jsonpCallbacks#removeCallback + * @param {string} callbackPath the path to the callback that was sent in the JSONP request + * @description + * {@link $httpBackend} calls this method to remove the callback after the JSONP request has + * completed or timed-out. + */ + removeCallback: function(callbackPath) { + var callback = callbackMap[callbackPath]; + delete callbacks[callback.id]; + delete callbackMap[callbackPath]; + } + }; + }]; +}; + /** * @ngdoc service * @name $locale @@ -11117,75 +12767,6 @@ function $IntervalProvider() { * * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`) */ -function $LocaleProvider() { - this.$get = function() { - return { - id: 'en-us', - - NUMBER_FORMATS: { - DECIMAL_SEP: '.', - GROUP_SEP: ',', - PATTERNS: [ - { // Decimal Pattern - minInt: 1, - minFrac: 0, - maxFrac: 3, - posPre: '', - posSuf: '', - negPre: '-', - negSuf: '', - gSize: 3, - lgSize: 3 - },{ //Currency Pattern - minInt: 1, - minFrac: 2, - maxFrac: 2, - posPre: '\u00A4', - posSuf: '', - negPre: '(\u00A4', - negSuf: ')', - gSize: 3, - lgSize: 3 - } - ], - CURRENCY_SYM: '$' - }, - - DATETIME_FORMATS: { - MONTH: - 'January,February,March,April,May,June,July,August,September,October,November,December' - .split(','), - SHORTMONTH: 'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','), - DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','), - SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','), - AMPMS: ['AM','PM'], - medium: 'MMM d, y h:mm:ss a', - 'short': 'M/d/yy h:mm a', - fullDate: 'EEEE, MMMM d, y', - longDate: 'MMMM d, y', - mediumDate: 'MMM d, y', - shortDate: 'M/d/yy', - mediumTime: 'h:mm:ss a', - shortTime: 'h:mm a', - ERANAMES: [ - "Before Christ", - "Anno Domini" - ], - ERAS: [ - "BC", - "AD" - ] - }, - - pluralCat: function(num) { - if (num === 1) { - return 'one'; - } - return 'other'; - } - }; - }; -} var PATH_MATCH = /^([^\?#]*)(\?([^#]*))?(#(.*))?$/, DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21}; @@ -11235,17 +12816,20 @@ function parseAppUrl(relativeUrl, locationObj) { } } +function startsWith(haystack, needle) { + return haystack.lastIndexOf(needle, 0) === 0; +} /** * - * @param {string} begin - * @param {string} whole - * @returns {string} returns text from whole after begin or undefined if it does not begin with - * expected string. + * @param {string} base + * @param {string} url + * @returns {string} returns text from `url` after `base` or `undefined` if it does not begin with + * the expected string. */ -function beginsWith(begin, whole) { - if (whole.indexOf(begin) === 0) { - return whole.substr(begin.length); +function stripBaseUrl(base, url) { + if (startsWith(url, base)) { + return url.substr(base.length); } } @@ -11276,12 +12860,12 @@ function serverBase(url) { * * @constructor * @param {string} appBase application base URL + * @param {string} appBaseNoFile application base URL stripped of any filename * @param {string} basePrefix url path prefix */ -function LocationHtml5Url(appBase, basePrefix) { +function LocationHtml5Url(appBase, appBaseNoFile, basePrefix) { this.$$html5 = true; basePrefix = basePrefix || ''; - var appBaseNoFile = stripFile(appBase); parseAbsoluteUrl(appBase, this); @@ -11291,7 +12875,7 @@ function LocationHtml5Url(appBase, basePrefix) { * @private */ this.$$parse = function(url) { - var pathUrl = beginsWith(appBaseNoFile, url); + var pathUrl = stripBaseUrl(appBaseNoFile, url); if (!isString(pathUrl)) { throw $locationMinErr('ipthprfx', 'Invalid url "{0}", missing path prefix "{1}".', url, appBaseNoFile); @@ -11328,14 +12912,14 @@ function LocationHtml5Url(appBase, basePrefix) { var appUrl, prevAppUrl; var rewrittenUrl; - if ((appUrl = beginsWith(appBase, url)) !== undefined) { + if (isDefined(appUrl = stripBaseUrl(appBase, url))) { prevAppUrl = appUrl; - if ((appUrl = beginsWith(basePrefix, appUrl)) !== undefined) { - rewrittenUrl = appBaseNoFile + (beginsWith('/', appUrl) || appUrl); + if (isDefined(appUrl = stripBaseUrl(basePrefix, appUrl))) { + rewrittenUrl = appBaseNoFile + (stripBaseUrl('/', appUrl) || appUrl); } else { rewrittenUrl = appBase + prevAppUrl; } - } else if ((appUrl = beginsWith(appBaseNoFile, url)) !== undefined) { + } else if (isDefined(appUrl = stripBaseUrl(appBaseNoFile, url))) { rewrittenUrl = appBaseNoFile + appUrl; } else if (appBaseNoFile == url + '/') { rewrittenUrl = appBaseNoFile; @@ -11355,10 +12939,10 @@ function LocationHtml5Url(appBase, basePrefix) { * * @constructor * @param {string} appBase application base URL + * @param {string} appBaseNoFile application base URL stripped of any filename * @param {string} hashPrefix hashbang prefix */ -function LocationHashbangUrl(appBase, hashPrefix) { - var appBaseNoFile = stripFile(appBase); +function LocationHashbangUrl(appBase, appBaseNoFile, hashPrefix) { parseAbsoluteUrl(appBase, this); @@ -11369,14 +12953,14 @@ function LocationHashbangUrl(appBase, hashPrefix) { * @private */ this.$$parse = function(url) { - var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url); + var withoutBaseUrl = stripBaseUrl(appBase, url) || stripBaseUrl(appBaseNoFile, url); var withoutHashUrl; - if (withoutBaseUrl.charAt(0) === '#') { + if (!isUndefined(withoutBaseUrl) && withoutBaseUrl.charAt(0) === '#') { // The rest of the url starts with a hash so we have // got either a hashbang path or a plain hash fragment - withoutHashUrl = beginsWith(hashPrefix, withoutBaseUrl); + withoutHashUrl = stripBaseUrl(hashPrefix, withoutBaseUrl); if (isUndefined(withoutHashUrl)) { // There was no hashbang prefix so we just have a hash fragment withoutHashUrl = withoutBaseUrl; @@ -11386,7 +12970,15 @@ function LocationHashbangUrl(appBase, hashPrefix) { // There was no hashbang path nor hash fragment: // If we are in HTML5 mode we use what is left as the path; // Otherwise we ignore what is left - withoutHashUrl = this.$$html5 ? withoutBaseUrl : ''; + if (this.$$html5) { + withoutHashUrl = withoutBaseUrl; + } else { + withoutHashUrl = ''; + if (isUndefined(withoutBaseUrl)) { + appBase = url; + this.replace(); + } + } } parseAppUrl(withoutHashUrl, this); @@ -11416,7 +13008,7 @@ function LocationHashbangUrl(appBase, hashPrefix) { var firstPathSegmentMatch; //Get the relative path from the input URL. - if (url.indexOf(base) === 0) { + if (startsWith(url, base)) { url = url.replace(base, ''); } @@ -11459,14 +13051,13 @@ function LocationHashbangUrl(appBase, hashPrefix) { * * @constructor * @param {string} appBase application base URL + * @param {string} appBaseNoFile application base URL stripped of any filename * @param {string} hashPrefix hashbang prefix */ -function LocationHashbangInHtml5Url(appBase, hashPrefix) { +function LocationHashbangInHtml5Url(appBase, appBaseNoFile, hashPrefix) { this.$$html5 = true; LocationHashbangUrl.apply(this, arguments); - var appBaseNoFile = stripFile(appBase); - this.$$parseLinkUrl = function(url, relHref) { if (relHref && relHref[0] === '#') { // special case for links to hash fragments: @@ -11480,7 +13071,7 @@ function LocationHashbangInHtml5Url(appBase, hashPrefix) { if (appBase == stripHash(url)) { rewrittenUrl = url; - } else if ((appUrl = beginsWith(appBaseNoFile, url))) { + } else if ((appUrl = stripBaseUrl(appBaseNoFile, url))) { rewrittenUrl = appBase + hashPrefix + appUrl; } else if (appBaseNoFile === url + '/') { rewrittenUrl = appBaseNoFile; @@ -11496,7 +13087,7 @@ function LocationHashbangInHtml5Url(appBase, hashPrefix) { hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : ''; this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash; - // include hashPrefix in $$absUrl when $$url is empty so IE8 & 9 do not reload page because of removal of '#' + // include hashPrefix in $$absUrl when $$url is empty so IE9 does not reload page because of removal of '#' this.$$absUrl = appBase + hashPrefix + this.$$url; }; @@ -11505,6 +13096,12 @@ function LocationHashbangInHtml5Url(appBase, hashPrefix) { var locationPrototype = { + /** + * Ensure absolute url is initialized. + * @private + */ + $$absUrl:'', + /** * Are we in html5 mode? * @private @@ -11662,7 +13259,7 @@ var locationPrototype = { * ``` * * @param {(string|number)=} path New path - * @return {string} path + * @return {(string|object)} path if called with no parameters, or `$location` if called with a parameter */ path: locationGetterSetter('$$path', function(path) { path = path !== null ? path.toString() : ''; @@ -11754,9 +13351,9 @@ var locationPrototype = { * @description * This method is getter / setter. * - * Return hash fragment when called without any parameter. + * Returns the hash fragment when called without any parameters. * - * Change hash fragment when called with parameter and return `$location`. + * Changes the hash fragment when called with a parameter and returns `$location`. * * * ```js @@ -11777,8 +13374,8 @@ var locationPrototype = { * @name $location#replace * * @description - * If called, all changes to $location during current `$digest` will be replacing current history - * record, instead of adding new one. + * If called, all changes to $location during the current `$digest` will replace the current history + * record, instead of adding a new one. */ replace: function() { this.$$replace = true; @@ -12005,7 +13602,9 @@ function $LocationProvider() { appBase = stripHash(initialUrl); LocationMode = LocationHashbangUrl; } - $location = new LocationMode(appBase, '#' + hashPrefix); + var appBaseNoFile = stripFile(appBase); + + $location = new LocationMode(appBase, appBaseNoFile, '#' + hashPrefix); $location.$$parseLinkUrl(initialUrl, initialUrl); $location.$$state = $browser.state(); @@ -12085,11 +13684,18 @@ function $LocationProvider() { // update $location when $browser url changes $browser.onUrlChange(function(newUrl, newState) { + + if (isUndefined(stripBaseUrl(appBaseNoFile, newUrl))) { + // If we are navigating outside of the app then force a reload + $window.location.href = newUrl; + return; + } + $rootScope.$evalAsync(function() { var oldUrl = $location.absUrl(); var oldState = $location.$$state; var defaultPrevented; - + newUrl = trimEmptyHash(newUrl); $location.$$parse(newUrl); $location.$$state = newState; @@ -12372,6 +13978,24 @@ function ensureSafeMemberName(name, fullExpression) { return name; } +function getStringValue(name) { + // Property names must be strings. This means that non-string objects cannot be used + // as keys in an object. Any non-string object, including a number, is typecasted + // into a string via the toString method. + // -- MDN, https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Property_accessors#Property_names + // + // So, to ensure that we are checking the same `name` that JavaScript would use, we cast it + // to a string. It's not always possible. If `name` is an object and its `toString` method is + // 'broken' (doesn't return a string, isn't a function, etc.), an error will be thrown: + // + // TypeError: Cannot convert object to primitive value + // + // For performance reasons, we don't catch this error here and allow it to propagate up the call + // stack. Note that you'll get the same error in JavaScript if you try to access a property using + // such a 'broken' object as a key. + return name + ''; +} + function ensureSafeObject(obj, fullExpression) { // nifty check if obj is Function that is fast and works across iframes and other contexts if (obj) { @@ -12417,6 +14041,16 @@ function ensureSafeFunction(obj, fullExpression) { } } +function ensureSafeAssignContext(obj, fullExpression) { + if (obj) { + if (obj === (0).constructor || obj === (false).constructor || obj === ''.constructor || + obj === {}.constructor || obj === [].constructor || obj === Function.constructor) { + throw $parseMinErr('isecaf', + 'Assigning to a constructor is disallowed! Expression: {0}', fullExpression); + } + } +} + var OPERATORS = createMap(); forEach('+ - * / % === !== == != < > <= >= && || ! = |'.split(' '), function(operator) { OPERATORS[operator] = true; }); var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'}; @@ -12446,7 +14080,7 @@ Lexer.prototype = { this.readString(ch); } else if (this.isNumber(ch) || ch === '.' && this.isNumber(this.peek())) { this.readNumber(); - } else if (this.isIdent(ch)) { + } else if (this.isIdentifierStart(this.peekMultichar())) { this.readIdent(); } else if (this.is(ch, '(){}[].,;:?')) { this.tokens.push({index: this.index, text: ch}); @@ -12490,12 +14124,49 @@ Lexer.prototype = { ch === '\n' || ch === '\v' || ch === '\u00A0'); }, - isIdent: function(ch) { + isIdentifierStart: function(ch) { + return this.options.isIdentifierStart ? + this.options.isIdentifierStart(ch, this.codePointAt(ch)) : + this.isValidIdentifierStart(ch); + }, + + isValidIdentifierStart: function(ch) { return ('a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || '_' === ch || ch === '$'); }, + isIdentifierContinue: function(ch) { + return this.options.isIdentifierContinue ? + this.options.isIdentifierContinue(ch, this.codePointAt(ch)) : + this.isValidIdentifierContinue(ch); + }, + + isValidIdentifierContinue: function(ch, cp) { + return this.isValidIdentifierStart(ch, cp) || this.isNumber(ch); + }, + + codePointAt: function(ch) { + if (ch.length === 1) return ch.charCodeAt(0); + /*jshint bitwise: false*/ + return (ch.charCodeAt(0) << 10) + ch.charCodeAt(1) - 0x35FDC00; + /*jshint bitwise: true*/ + }, + + peekMultichar: function() { + var ch = this.text.charAt(this.index); + var peek = this.peek(); + if (!peek) { + return ch; + } + var cp1 = ch.charCodeAt(0); + var cp2 = peek.charCodeAt(0); + if (cp1 >= 0xD800 && cp1 <= 0xDBFF && cp2 >= 0xDC00 && cp2 <= 0xDFFF) { + return ch + peek; + } + return ch; + }, + isExpOperator: function(ch) { return (ch === '-' || ch === '+' || this.isNumber(ch)); }, @@ -12544,12 +14215,13 @@ Lexer.prototype = { readIdent: function() { var start = this.index; + this.index += this.peekMultichar().length; while (this.index < this.text.length) { - var ch = this.text.charAt(this.index); - if (!(this.isIdent(ch) || this.isNumber(ch))) { + var ch = this.peekMultichar(); + if (!this.isIdentifierContinue(ch)) { break; } - this.index++; + this.index += ch.length; } this.tokens.push({ index: start, @@ -12620,6 +14292,7 @@ AST.ArrayExpression = 'ArrayExpression'; AST.Property = 'Property'; AST.ObjectExpression = 'ObjectExpression'; AST.ThisExpression = 'ThisExpression'; +AST.LocalsExpression = 'LocalsExpression'; // Internal use only AST.NGValueParameter = 'NGValueParameter'; @@ -12758,8 +14431,10 @@ AST.prototype = { primary = this.arrayDeclaration(); } else if (this.expect('{')) { primary = this.object(); - } else if (this.constants.hasOwnProperty(this.peek().text)) { - primary = copy(this.constants[this.consume().text]); + } else if (this.selfReferential.hasOwnProperty(this.peek().text)) { + primary = copy(this.selfReferential[this.consume().text]); + } else if (this.options.literals.hasOwnProperty(this.peek().text)) { + primary = { type: AST.Literal, value: this.options.literals[this.consume().text]}; } else if (this.peek().identifier) { primary = this.identifier(); } else if (this.peek().constant) { @@ -12800,7 +14475,7 @@ AST.prototype = { var args = []; if (this.peekToken().text !== ')') { do { - args.push(this.expression()); + args.push(this.filterChain()); } while (this.expect(',')); } return args; @@ -12846,13 +14521,28 @@ AST.prototype = { property = {type: AST.Property, kind: 'init'}; if (this.peek().constant) { property.key = this.constant(); + property.computed = false; + this.consume(':'); + property.value = this.expression(); } else if (this.peek().identifier) { property.key = this.identifier(); + property.computed = false; + if (this.peek(':')) { + this.consume(':'); + property.value = this.expression(); + } else { + property.value = property.key; + } + } else if (this.peek('[')) { + this.consume('['); + property.key = this.expression(); + this.consume(']'); + property.computed = true; + this.consume(':'); + property.value = this.expression(); } else { this.throwError("invalid key", this.peek()); } - this.consume(':'); - property.value = this.expression(); properties.push(property); } while (this.expect(',')); } @@ -12911,16 +14601,9 @@ AST.prototype = { return false; }, - - /* `undefined` is not a constant, it is an identifier, - * but using it as an identifier is not supported - */ - constants: { - 'true': { type: AST.Literal, value: true }, - 'false': { type: AST.Literal, value: false }, - 'null': { type: AST.Literal, value: null }, - 'undefined': {type: AST.Literal, value: undefined }, - 'this': {type: AST.ThisExpression } + selfReferential: { + 'this': {type: AST.ThisExpression }, + '$locals': {type: AST.LocalsExpression } } }; @@ -13028,7 +14711,7 @@ function findConstantAndWatchExpressions(ast, $filter) { argsToWatch = []; forEach(ast.properties, function(property) { findConstantAndWatchExpressions(property.value, $filter); - allConstants = allConstants && property.value.constant; + allConstants = allConstants && property.value.constant && !property.computed; if (!property.value.constant) { argsToWatch.push.apply(argsToWatch, property.value.toWatch); } @@ -13040,6 +14723,10 @@ function findConstantAndWatchExpressions(ast, $filter) { ast.constant = false; ast.toWatch = []; break; + case AST.LocalsExpression: + ast.constant = false; + ast.toWatch = []; + break; } } @@ -13098,6 +14785,7 @@ ASTCompiler.prototype = { this.state.computing = 'assign'; var result = this.nextId(); this.recurse(assignable, result); + this.return_(result); extra = 'fn.assign=' + this.generateFunction('assign', 's,v,l'); } var toWatch = getInputs(ast.body); @@ -13130,6 +14818,8 @@ ASTCompiler.prototype = { 'ensureSafeMemberName', 'ensureSafeObject', 'ensureSafeFunction', + 'getStringValue', + 'ensureSafeAssignContext', 'ifDefined', 'plus', 'text', @@ -13138,6 +14828,8 @@ ASTCompiler.prototype = { ensureSafeMemberName, ensureSafeObject, ensureSafeFunction, + getStringValue, + ensureSafeAssignContext, ifDefined, plusFn, expression); @@ -13191,7 +14883,7 @@ ASTCompiler.prototype = { }, recurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) { - var left, right, self = this, args, expression; + var left, right, self = this, args, expression, computed; recursionFn = recursionFn || noop; if (!skipWatchIdCheck && isDefined(ast.watchId)) { intoId = intoId || this.nextId(); @@ -13278,9 +14970,13 @@ ASTCompiler.prototype = { intoId = intoId || this.nextId(); self.recurse(ast.object, left, undefined, function() { self.if_(self.notNull(left), function() { + if (create && create !== 1) { + self.addEnsureSafeAssignContext(left); + } if (ast.computed) { right = self.nextId(); self.recurse(ast.property, right); + self.getStringValue(right); self.addEnsureSafeMemberName(right); if (create && create !== 1) { self.if_(self.not(self.computedMember(left, right)), self.lazyAssign(self.computedMember(left, right), '{}')); @@ -13358,12 +15054,13 @@ ASTCompiler.prototype = { right = this.nextId(); left = {}; if (!isAssignable(ast.left)) { - throw $parseMinErr('lval', 'Trying to assing a value to a non l-value'); + throw $parseMinErr('lval', 'Trying to assign a value to a non l-value'); } this.recurse(ast.left, undefined, left, function() { self.if_(self.notNull(left.context), function() { self.recurse(ast.right, right); self.addEnsureSafeObject(self.member(left.context, left.name, left.computed)); + self.addEnsureSafeAssignContext(left.context); expression = self.member(left.context, left.name, left.computed) + ast.operator + right; self.assign(intoId, expression); recursionFn(intoId || expression); @@ -13383,22 +15080,50 @@ ASTCompiler.prototype = { break; case AST.ObjectExpression: args = []; + computed = false; forEach(ast.properties, function(property) { - self.recurse(property.value, self.nextId(), undefined, function(expr) { - args.push(self.escape( - property.key.type === AST.Identifier ? property.key.name : - ('' + property.key.value)) + - ':' + expr); - }); + if (property.computed) { + computed = true; + } }); - expression = '{' + args.join(',') + '}'; - this.assign(intoId, expression); - recursionFn(expression); + if (computed) { + intoId = intoId || this.nextId(); + this.assign(intoId, '{}'); + forEach(ast.properties, function(property) { + if (property.computed) { + left = self.nextId(); + self.recurse(property.key, left); + } else { + left = property.key.type === AST.Identifier ? + property.key.name : + ('' + property.key.value); + } + right = self.nextId(); + self.recurse(property.value, right); + self.assign(self.member(intoId, left, property.computed), right); + }); + } else { + forEach(ast.properties, function(property) { + self.recurse(property.value, ast.constant ? undefined : self.nextId(), undefined, function(expr) { + args.push(self.escape( + property.key.type === AST.Identifier ? property.key.name : + ('' + property.key.value)) + + ':' + expr); + }); + }); + expression = '{' + args.join(',') + '}'; + this.assign(intoId, expression); + } + recursionFn(intoId || expression); break; case AST.ThisExpression: this.assign(intoId, 's'); recursionFn('s'); break; + case AST.LocalsExpression: + this.assign(intoId, 'l'); + recursionFn('l'); + break; case AST.NGValueParameter: this.assign(intoId, 'v'); recursionFn('v'); @@ -13465,7 +15190,13 @@ ASTCompiler.prototype = { }, nonComputedMember: function(left, right) { - return left + '.' + right; + var SAFE_IDENTIFIER = /[$_a-zA-Z][$_a-zA-Z0-9]*/; + var UNSAFE_CHARACTERS = /[^$_a-zA-Z0-9]/g; + if (SAFE_IDENTIFIER.test(right)) { + return left + '.' + right; + } else { + return left + '["' + right.replace(UNSAFE_CHARACTERS, this.stringEscapeFn) + '"]'; + } }, computedMember: function(left, right) { @@ -13489,6 +15220,10 @@ ASTCompiler.prototype = { this.current().body.push(this.ensureSafeFunction(item), ';'); }, + addEnsureSafeAssignContext: function(item) { + this.current().body.push(this.ensureSafeAssignContext(item), ';'); + }, + ensureSafeObject: function(item) { return 'ensureSafeObject(' + item + ',text)'; }, @@ -13501,6 +15236,14 @@ ASTCompiler.prototype = { return 'ensureSafeFunction(' + item + ',text)'; }, + getStringValue: function(item) { + this.assign(item, 'getStringValue(' + item + ')'); + }, + + ensureSafeAssignContext: function(item) { + return 'ensureSafeAssignContext(' + item + ',text)'; + }, + lazyRecurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) { var self = this; return function() { @@ -13578,7 +15321,7 @@ ASTInterpreter.prototype = { forEach(ast.body, function(expression) { expressions.push(self.recurse(expression.expression)); }); - var fn = ast.body.length === 0 ? function() {} : + var fn = ast.body.length === 0 ? noop : ast.body.length === 1 ? expressions[0] : function(scope, locals) { var lastValue; @@ -13678,6 +15421,7 @@ ASTInterpreter.prototype = { var lhs = left(scope, locals, assign, inputs); var rhs = right(scope, locals, assign, inputs); ensureSafeObject(lhs.value, self.expression); + ensureSafeAssignContext(lhs.context); lhs.context[lhs.name] = rhs; return context ? {value: rhs} : rhs; }; @@ -13696,16 +15440,28 @@ ASTInterpreter.prototype = { case AST.ObjectExpression: args = []; forEach(ast.properties, function(property) { - args.push({key: property.key.type === AST.Identifier ? - property.key.name : - ('' + property.key.value), - value: self.recurse(property.value) - }); + if (property.computed) { + args.push({key: self.recurse(property.key), + computed: true, + value: self.recurse(property.value) + }); + } else { + args.push({key: property.key.type === AST.Identifier ? + property.key.name : + ('' + property.key.value), + computed: false, + value: self.recurse(property.value) + }); + } }); return function(scope, locals, assign, inputs) { var value = {}; for (var i = 0; i < args.length; ++i) { - value[args[i].key] = args[i].value(scope, locals, assign, inputs); + if (args[i].computed) { + value[args[i].key(scope, locals, assign, inputs)] = args[i].value(scope, locals, assign, inputs); + } else { + value[args[i].key] = args[i].value(scope, locals, assign, inputs); + } } return context ? {value: value} : value; }; @@ -13713,8 +15469,12 @@ ASTInterpreter.prototype = { return function(scope) { return context ? {value: scope} : scope; }; + case AST.LocalsExpression: + return function(scope, locals) { + return context ? {value: locals} : locals; + }; case AST.NGValueParameter: - return function(scope, locals, assign, inputs) { + return function(scope, locals, assign) { return context ? {value: assign} : assign; }; } @@ -13875,9 +15635,13 @@ ASTInterpreter.prototype = { var value; if (lhs != null) { rhs = right(scope, locals, assign, inputs); + rhs = getStringValue(rhs); ensureSafeMemberName(rhs, expression); - if (create && create !== 1 && lhs && !(lhs[rhs])) { - lhs[rhs] = {}; + if (create && create !== 1) { + ensureSafeAssignContext(lhs); + if (lhs && !(lhs[rhs])) { + lhs[rhs] = {}; + } } value = lhs[rhs]; ensureSafeObject(value, expression); @@ -13892,8 +15656,11 @@ ASTInterpreter.prototype = { nonComputedMember: function(left, right, expensiveChecks, context, create, expression) { return function(scope, locals, assign, inputs) { var lhs = left(scope, locals, assign, inputs); - if (create && create !== 1 && lhs && !(lhs[right])) { - lhs[right] = {}; + if (create && create !== 1) { + ensureSafeAssignContext(lhs); + if (lhs && !(lhs[right])) { + lhs[right] = {}; + } } var value = lhs != null ? lhs[right] : undefined; if (expensiveChecks || isPossiblyDangerousMemberName(right)) { @@ -13921,7 +15688,7 @@ var Parser = function(lexer, $filter, options) { this.lexer = lexer; this.$filter = $filter; this.options = options; - this.ast = new AST(this.lexer); + this.ast = new AST(lexer, options); this.astCompiler = options.csp ? new ASTInterpreter(this.ast, $filter) : new ASTCompiler(this.ast, $filter); }; @@ -13934,32 +15701,6 @@ Parser.prototype = { } }; -////////////////////////////////////////////////// -// Parser helper functions -////////////////////////////////////////////////// - -function setter(obj, path, setValue, fullExp) { - ensureSafeObject(obj, fullExp); - - var element = path.split('.'), key; - for (var i = 0; element.length > 1; i++) { - key = ensureSafeMemberName(element.shift(), fullExp); - var propertyObj = ensureSafeObject(obj[key], fullExp); - if (!propertyObj) { - propertyObj = {}; - obj[key] = propertyObj; - } - obj = propertyObj; - } - key = ensureSafeMemberName(element.shift(), fullExp); - ensureSafeObject(obj[key], fullExp); - obj[key] = setValue; - return setValue; -} - -var getterFnCacheDefault = createMap(); -var getterFnCacheExpensive = createMap(); - function isPossiblyDangerousMemberName(name) { return name == 'constructor'; } @@ -14024,20 +15765,87 @@ function getValueOf(value) { function $ParseProvider() { var cacheDefault = createMap(); var cacheExpensive = createMap(); + var literals = { + 'true': true, + 'false': false, + 'null': null, + 'undefined': undefined + }; + var identStart, identContinue; + + /** + * @ngdoc method + * @name $parseProvider#addLiteral + * @description + * + * Configure $parse service to add literal values that will be present as literal at expressions. + * + * @param {string} literalName Token for the literal value. The literal name value must be a valid literal name. + * @param {*} literalValue Value for this literal. All literal values must be primitives or `undefined`. + * + **/ + this.addLiteral = function(literalName, literalValue) { + literals[literalName] = literalValue; + }; + + /** + * @ngdoc method + * @name $parseProvider#setIdentifierFns + * @description + * + * Allows defining the set of characters that are allowed in Angular expressions. The function + * `identifierStart` will get called to know if a given character is a valid character to be the + * first character for an identifier. The function `identifierContinue` will get called to know if + * a given character is a valid character to be a follow-up identifier character. The functions + * `identifierStart` and `identifierContinue` will receive as arguments the single character to be + * identifier and the character code point. These arguments will be `string` and `numeric`. Keep in + * mind that the `string` parameter can be two characters long depending on the character + * representation. It is expected for the function to return `true` or `false`, whether that + * character is allowed or not. + * + * Since this function will be called extensivelly, keep the implementation of these functions fast, + * as the performance of these functions have a direct impact on the expressions parsing speed. + * + * @param {function=} identifierStart The function that will decide whether the given character is + * a valid identifier start character. + * @param {function=} identifierContinue The function that will decide whether the given character is + * a valid identifier continue character. + */ + this.setIdentifierFns = function(identifierStart, identifierContinue) { + identStart = identifierStart; + identContinue = identifierContinue; + return this; + }; - this.$get = ['$filter', '$sniffer', function($filter, $sniffer) { + this.$get = ['$filter', function($filter) { + var noUnsafeEval = csp().noUnsafeEval; var $parseOptions = { - csp: $sniffer.csp, - expensiveChecks: false + csp: noUnsafeEval, + expensiveChecks: false, + literals: copy(literals), + isIdentifierStart: isFunction(identStart) && identStart, + isIdentifierContinue: isFunction(identContinue) && identContinue }, $parseOptionsExpensive = { - csp: $sniffer.csp, - expensiveChecks: true + csp: noUnsafeEval, + expensiveChecks: true, + literals: copy(literals), + isIdentifierStart: isFunction(identStart) && identStart, + isIdentifierContinue: isFunction(identContinue) && identContinue }; + var runningChecksEnabled = false; + + $parse.$$runningExpensiveChecks = function() { + return runningChecksEnabled; + }; + + return $parse; - return function $parse(exp, interceptorFn, expensiveChecks) { + function $parse(exp, interceptorFn, expensiveChecks) { var parsedExpression, oneTime, cacheKey; + expensiveChecks = expensiveChecks || runningChecksEnabled; + switch (typeof exp) { case 'string': exp = exp.trim(); @@ -14063,6 +15871,9 @@ function $ParseProvider() { } else if (parsedExpression.inputs) { parsedExpression.$$watchDelegate = inputsWatchDelegate; } + if (expensiveChecks) { + parsedExpression = expensiveChecksInterceptor(parsedExpression); + } cache[cacheKey] = parsedExpression; } return addInterceptor(parsedExpression, interceptorFn); @@ -14071,9 +15882,33 @@ function $ParseProvider() { return addInterceptor(exp, interceptorFn); default: - return noop; + return addInterceptor(noop, interceptorFn); } - }; + } + + function expensiveChecksInterceptor(fn) { + if (!fn) return fn; + expensiveCheckFn.$$watchDelegate = fn.$$watchDelegate; + expensiveCheckFn.assign = expensiveChecksInterceptor(fn.assign); + expensiveCheckFn.constant = fn.constant; + expensiveCheckFn.literal = fn.literal; + for (var i = 0; fn.inputs && i < fn.inputs.length; ++i) { + fn.inputs[i] = expensiveChecksInterceptor(fn.inputs[i]); + } + expensiveCheckFn.inputs = fn.inputs; + + return expensiveCheckFn; + + function expensiveCheckFn(scope, locals, assign, inputs) { + var expensiveCheckOldValue = runningChecksEnabled; + runningChecksEnabled = true; + try { + return fn(scope, locals, assign, inputs); + } finally { + runningChecksEnabled = expensiveCheckOldValue; + } + } + } function expressionInputDirtyCheck(newValue, oldValueOfValue) { @@ -14190,25 +16025,22 @@ function $ParseProvider() { function constantWatchDelegate(scope, listener, objectEquality, parsedExpression) { var unwatch; return unwatch = scope.$watch(function constantWatch(scope) { - return parsedExpression(scope); - }, function constantListener(value, old, scope) { - if (isFunction(listener)) { - listener.apply(this, arguments); - } unwatch(); - }, objectEquality); + return parsedExpression(scope); + }, listener, objectEquality); } function addInterceptor(parsedExpression, interceptorFn) { if (!interceptorFn) return parsedExpression; var watchDelegate = parsedExpression.$$watchDelegate; + var useInputs = false; var regularWatch = watchDelegate !== oneTimeLiteralWatchDelegate && watchDelegate !== oneTimeWatchDelegate; var fn = regularWatch ? function regularInterceptedExpression(scope, locals, assign, inputs) { - var value = parsedExpression(scope, locals, assign, inputs); + var value = useInputs && inputs ? inputs[0] : parsedExpression(scope, locals, assign, inputs); return interceptorFn(value, scope, locals); } : function oneTimeInterceptedExpression(scope, locals, assign, inputs) { var value = parsedExpression(scope, locals, assign, inputs); @@ -14226,6 +16058,7 @@ function $ParseProvider() { // If there is an interceptor, but no watchDelegate then treat the interceptor like // we treat filters - it is assumed to be a pure function unless flagged with $stateful fn.$$watchDelegate = inputsWatchDelegate; + useInputs = !parsedExpression.inputs; fn.inputs = parsedExpression.inputs ? parsedExpression.inputs : [parsedExpression]; } @@ -14247,15 +16080,15 @@ function $ParseProvider() { * [Kris Kowal's Q](https://github.com/kriskowal/q). * * $q can be used in two fashions --- one which is more similar to Kris Kowal's Q or jQuery's Deferred - * implementations, and the other which resembles ES6 promises to some degree. + * implementations, and the other which resembles ES6 (ES2015) promises to some degree. * * # $q constructor * * The streamlined ES6 style promise is essentially just using $q as a constructor which takes a `resolver` - * function as the first argument. This is similar to the native Promise implementation from ES6 Harmony, + * function as the first argument. This is similar to the native Promise implementation from ES6, * see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). * - * While the constructor-style use is supported, not all of the supporting methods from ES6 Harmony promises are + * While the constructor-style use is supported, not all of the supporting methods from ES6 promises are * available yet. * * It can be used like so: @@ -14287,6 +16120,8 @@ function $ParseProvider() { * * Note: progress/notify callbacks are not currently supported via the ES6-style interface. * + * Note: unlike ES6 behavior, an exception thrown in the constructor function will NOT implicitly reject the promise. + * * However, the more traditional CommonJS-style usage is still available, and documented below. * * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an @@ -14367,7 +16202,7 @@ function $ParseProvider() { * * **Methods** * - * - `then(successCallback, errorCallback, notifyCallback)` – regardless of when the promise was or + * - `then(successCallback, [errorCallback], [notifyCallback])` – regardless of when the promise was or * will be resolved or rejected, `then` calls one of the success or error callbacks asynchronously * as soon as the result is available. The callbacks are called with a single argument: the result * or rejection reason. Additionally, the notify callback may be called zero or more times to @@ -14378,7 +16213,8 @@ function $ParseProvider() { * with the value which is resolved in that promise using * [promise chaining](http://www.html5rocks.com/en/tutorials/es6/promises/#toc-promises-queues)). * It also notifies via the return value of the `notifyCallback` method. The promise cannot be - * resolved or rejected from the notifyCallback method. + * resolved or rejected from the notifyCallback method. The errorCallback and notifyCallback + * arguments are optional. * * - `catch(errorCallback)` – shorthand for `promise.then(null, errorCallback)` * @@ -14418,7 +16254,7 @@ function $ParseProvider() { * - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains * all the important functionality needed for common async tasks. * - * # Testing + * # Testing * * ```js * it('should simulate promise', inject(function($q, $rootScope) { @@ -14475,18 +16311,6 @@ function $$QProvider() { */ function qFactory(nextTick, exceptionHandler) { var $qMinErr = minErr('$q', TypeError); - function callOnce(self, resolveFn, rejectFn) { - var called = false; - function wrap(fn) { - return function(value) { - if (called) return; - called = true; - fn.call(self, value); - }; - } - - return [wrap(resolveFn), wrap(rejectFn)]; - } /** * @ngdoc method @@ -14499,15 +16323,23 @@ function qFactory(nextTick, exceptionHandler) { * @returns {Deferred} Returns a new instance of deferred. */ var defer = function() { - return new Deferred(); + var d = new Deferred(); + //Necessary to support unbound execution :/ + d.resolve = simpleBind(d, d.resolve); + d.reject = simpleBind(d, d.reject); + d.notify = simpleBind(d, d.notify); + return d; }; function Promise() { this.$$state = { status: 0 }; } - Promise.prototype = { + extend(Promise.prototype, { then: function(onFulfilled, onRejected, progressBack) { + if (isUndefined(onFulfilled) && isUndefined(onRejected) && isUndefined(progressBack)) { + return this; + } var result = new Deferred(); this.$$state.pending = this.$$state.pending || []; @@ -14528,7 +16360,7 @@ function qFactory(nextTick, exceptionHandler) { return handleCallback(error, false, callback); }, progressBack); } - }; + }); //Faster, more basic than angular.bind http://jsperf.com/angular-bind-vs-custom-vs-native function simpleBind(context, fn) { @@ -14569,13 +16401,9 @@ function qFactory(nextTick, exceptionHandler) { function Deferred() { this.promise = new Promise(); - //Necessary to support unbound execution :/ - this.resolve = simpleBind(this, this.resolve); - this.reject = simpleBind(this, this.reject); - this.notify = simpleBind(this, this.notify); } - Deferred.prototype = { + extend(Deferred.prototype, { resolve: function(val) { if (this.promise.$$state.status) return; if (val === this.promise) { @@ -14590,23 +16418,34 @@ function qFactory(nextTick, exceptionHandler) { }, $$resolve: function(val) { - var then, fns; - - fns = callOnce(this, this.$$resolve, this.$$reject); + var then; + var that = this; + var done = false; try { if ((isObject(val) || isFunction(val))) then = val && val.then; if (isFunction(then)) { this.promise.$$state.status = -1; - then.call(val, fns[0], fns[1], this.notify); + then.call(val, resolvePromise, rejectPromise, simpleBind(this, this.notify)); } else { this.promise.$$state.value = val; this.promise.$$state.status = 1; scheduleProcessQueue(this.promise.$$state); } } catch (e) { - fns[1](e); + rejectPromise(e); exceptionHandler(e); } + + function resolvePromise(val) { + if (done) return; + done = true; + that.$$resolve(val); + } + function rejectPromise(val) { + if (done) return; + done = true; + that.$$reject(val); + } }, reject: function(reason) { @@ -14638,7 +16477,7 @@ function qFactory(nextTick, exceptionHandler) { }); } } - }; + }); /** * @ngdoc method @@ -14721,6 +16560,9 @@ function qFactory(nextTick, exceptionHandler) { * the promise comes from a source that can't be trusted. * * @param {*} value Value or a promise + * @param {Function=} successCallback + * @param {Function=} errorCallback + * @param {Function=} progressCallback * @returns {Promise} Returns a promise of the passed value or promise */ @@ -14740,6 +16582,9 @@ function qFactory(nextTick, exceptionHandler) { * Alias of {@link ng.$q#when when} to maintain naming consistency with ES6. * * @param {*} value Value or a promise + * @param {Function=} successCallback + * @param {Function=} errorCallback + * @param {Function=} progressCallback * @returns {Promise} Returns a promise of the passed value or promise */ var resolve = when; @@ -14784,16 +16629,35 @@ function qFactory(nextTick, exceptionHandler) { return deferred.promise; } + /** + * @ngdoc method + * @name $q#race + * @kind function + * + * @description + * Returns a promise that resolves or rejects as soon as one of those promises + * resolves or rejects, with the value or reason from that promise. + * + * @param {Array.|Object.} promises An array or hash of promises. + * @returns {Promise} a promise that resolves or rejects as soon as one of the `promises` + * resolves or rejects, with the value or reason from that promise. + */ + + function race(promises) { + var deferred = defer(); + + forEach(promises, function(promise) { + when(promise).then(deferred.resolve, deferred.reject); + }); + + return deferred.promise; + } + var $Q = function Q(resolver) { if (!isFunction(resolver)) { throw $qMinErr('norslvr', "Expected resolverFn, got '{0}'", resolver); } - if (!(this instanceof Q)) { - // More useful when $Q is the Promise itself. - return new Q(resolver); - } - var deferred = new Deferred(); function resolveFn(value) { @@ -14809,11 +16673,16 @@ function qFactory(nextTick, exceptionHandler) { return deferred.promise; }; + // Let's make the instanceof operator work for promises, so that + // `new $q(fn) instanceof $q` would evaluate to true. + $Q.prototype = Promise.prototype; + $Q.defer = defer; $Q.reject = reject; $Q.when = when; $Q.resolve = resolve; $Q.all = all; + $Q.race = race; return $Q; } @@ -14828,7 +16697,7 @@ function $$RAFProvider() { //rAF $window.webkitCancelRequestAnimationFrame; var rafSupported = !!requestAnimationFrame; - var rafFn = rafSupported + var raf = rafSupported ? function(fn) { var id = requestAnimationFrame(fn); return function() { @@ -14842,47 +16711,9 @@ function $$RAFProvider() { //rAF }; }; - queueFn.supported = rafSupported; - - var cancelLastRAF; - var taskCount = 0; - var taskQueue = []; - return queueFn; - - function flush() { - for (var i = 0; i < taskQueue.length; i++) { - var task = taskQueue[i]; - if (task) { - taskQueue[i] = null; - task(); - } - } - taskCount = taskQueue.length = 0; - } - - function queueFn(asyncFn) { - var index = taskQueue.length; + raf.supported = rafSupported; - taskCount++; - taskQueue.push(asyncFn); - - if (index === 0) { - cancelLastRAF = rafFn(flush); - } - - return function cancelQueueFn() { - if (index >= 0) { - taskQueue[index] = null; - index = null; - - if (--taskCount === 0 && cancelLastRAF) { - cancelLastRAF(); - cancelLastRAF = null; - taskQueue.length = 0; - } - } - }; - } + return raf; }]; } @@ -14900,15 +16731,15 @@ function $$RAFProvider() { //rAF * exposed as $$____ properties * * Loop operations are optimized by using while(count--) { ... } - * - this means that in order to keep the same order of execution as addition we have to add + * - This means that in order to keep the same order of execution as addition we have to add * items to the array at the beginning (unshift) instead of at the end (push) * * Child scopes are created and removed often - * - Using an array would be slow since inserts in middle are expensive so we use linked list + * - Using an array would be slow since inserts in the middle are expensive; so we use linked lists * - * There are few watches then a lot of observers. This is why you don't want the observer to be - * implemented in the same way as watch. Watch requires return of initialization function which - * are expensive to construct. + * There are fewer watches than observers. This is why you don't want the observer to be implemented + * in the same way as watch. Watch requires return of the initialization function which is expensive + * to construct. */ @@ -14950,7 +16781,7 @@ function $$RAFProvider() { //rAF * Every application has a single root {@link ng.$rootScope.Scope scope}. * All other scopes are descendant scopes of the root scope. Scopes provide separation * between the model and the view, via a mechanism for watching the model for changes. - * They also provide an event emission/broadcast and subscription facility. See the + * They also provide event emission/broadcast and subscription facility. See the * {@link guide/scope developer guide on scopes}. */ function $RootScopeProvider() { @@ -14980,13 +16811,36 @@ function $RootScopeProvider() { return ChildScope; } - this.$get = ['$injector', '$exceptionHandler', '$parse', '$browser', - function($injector, $exceptionHandler, $parse, $browser) { + this.$get = ['$exceptionHandler', '$parse', '$browser', + function($exceptionHandler, $parse, $browser) { function destroyChildScope($event) { $event.currentScope.$$destroyed = true; } + function cleanUpScope($scope) { + + if (msie === 9) { + // There is a memory leak in IE9 if all child scopes are not disconnected + // completely when a scope is destroyed. So this code will recurse up through + // all this scopes children + // + // See issue https://github.com/angular/angular.js/issues/10706 + $scope.$$childHead && cleanUpScope($scope.$$childHead); + $scope.$$nextSibling && cleanUpScope($scope.$$nextSibling); + } + + // The code below works around IE9 and V8's memory leaks + // + // See: + // - https://code.google.com/p/v8/issues/detail?id=2073#c26 + // - https://github.com/angular/angular.js/issues/6794#issuecomment-38648909 + // - https://github.com/angular/angular.js/issues/1313#issuecomment-10378451 + + $scope.$parent = $scope.$$nextSibling = $scope.$$prevSibling = $scope.$$childHead = + $scope.$$childTail = $scope.$root = $scope.$$watchers = null; + } + /** * @ngdoc type * @name $rootScope.Scope @@ -14995,12 +16849,9 @@ function $RootScopeProvider() { * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the * {@link auto.$injector $injector}. Child scopes are created using the * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when - * compiled HTML template is executed.) + * compiled HTML template is executed.) See also the {@link guide/scope Scopes guide} for + * an in-depth introduction and usage examples. * - * Here is a simple scope snippet to show how you can interact with the scope. - * ```html - * - * ``` * * # Inheritance * A scope can inherit from a parent scope, as in this example: @@ -15142,10 +16993,10 @@ function $RootScopeProvider() { * Registers a `listener` callback to be executed whenever the `watchExpression` changes. * * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest - * $digest()} and should return the value that will be watched. (Since - * {@link ng.$rootScope.Scope#$digest $digest()} reruns when it detects changes the - * `watchExpression` can execute multiple times per - * {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.) + * $digest()} and should return the value that will be watched. (`watchExpression` should not change + * its value when executed multiple times with the same input because it may be executed multiple + * times by {@link ng.$rootScope.Scope#$digest $digest()}. That is, `watchExpression` should be + * [idempotent](http://en.wikipedia.org/wiki/Idempotence). * - The `listener` is called only when the value from the current `watchExpression` and the * previous call to `watchExpression` are not equal (with the exception of the initial run, * see below). Inequality is determined according to reference inequality, @@ -15162,9 +17013,9 @@ function $RootScopeProvider() { * * * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called, - * you can register a `watchExpression` function with no `listener`. (Since `watchExpression` - * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a - * change is detected, be prepared for multiple calls to your listener.) + * you can register a `watchExpression` function with no `listener`. (Be prepared for + * multiple calls to your `watchExpression` because it will execute multiple times in a + * single {@link ng.$rootScope.Scope#$digest $digest} cycle if a change is detected.) * * After a watcher is registered with the scope, the `listener` fn is called asynchronously * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the @@ -15245,7 +17096,7 @@ function $RootScopeProvider() { * - `newVal` contains the current value of the `watchExpression` * - `oldVal` contains the previous value of the `watchExpression` * - `scope` refers to the current scope - * @param {boolean=} objectEquality Compare for object equality using {@link angular.equals} instead of + * @param {boolean=} [objectEquality=false] Compare for object equality using {@link angular.equals} instead of * comparing for reference equality. * @returns {function()} Returns a deregistration function for this listener. */ @@ -15494,7 +17345,7 @@ function $RootScopeProvider() { // copy the items to oldValue and look for changes. newLength = 0; for (key in newValue) { - if (newValue.hasOwnProperty(key)) { + if (hasOwnProperty.call(newValue, key)) { newLength++; newItem = newValue[key]; oldItem = oldValue[key]; @@ -15516,7 +17367,7 @@ function $RootScopeProvider() { // we used to have more keys, need to find them and destroy them. changeDetected++; for (key in oldValue) { - if (!newValue.hasOwnProperty(key)) { + if (!hasOwnProperty.call(newValue, key)) { oldLength--; delete oldValue[key]; } @@ -15610,13 +17461,13 @@ function $RootScopeProvider() { * */ $digest: function() { - var watch, value, last, + var watch, value, last, fn, get, watchers, length, dirty, ttl = TTL, next, current, target = this, watchLog = [], - logIdx, logMsg, asyncTask; + logIdx, asyncTask; beginPhase('$digest'); // Check for changes to browser url that happened in sync before the call to $digest @@ -15635,15 +17486,19 @@ function $RootScopeProvider() { dirty = false; current = target; - while (asyncQueue.length) { + // It's safe for asyncQueuePosition to be a local variable here because this loop can't + // be reentered recursively. Calling $digest from a function passed to $applyAsync would + // lead to a '$digest already in progress' error. + for (var asyncQueuePosition = 0; asyncQueuePosition < asyncQueue.length; asyncQueuePosition++) { try { - asyncTask = asyncQueue.shift(); + asyncTask = asyncQueue[asyncQueuePosition]; asyncTask.scope.$eval(asyncTask.expression, asyncTask.locals); } catch (e) { $exceptionHandler(e); } lastDirtyWatch = null; } + asyncQueue.length = 0; traverseScopesLoop: do { // "traverse the scopes" loop @@ -15656,7 +17511,8 @@ function $RootScopeProvider() { // Most common watches are on primitives, in which case we can short // circuit it with === operator, only when === fails do we use .equals if (watch) { - if ((value = watch.get(current)) !== (last = watch.last) && + get = watch.get; + if ((value = get(current)) !== (last = watch.last) && !(watch.eq ? equals(value, last) : (typeof value === 'number' && typeof last === 'number' @@ -15664,7 +17520,8 @@ function $RootScopeProvider() { dirty = true; lastDirtyWatch = watch; watch.last = watch.eq ? copy(value, null) : value; - watch.fn(value, ((last === initWatchVal) ? value : last), current); + fn = watch.fn; + fn(value, ((last === initWatchVal) ? value : last), current); if (ttl < 5) { logIdx = 4 - ttl; if (!watchLog[logIdx]) watchLog[logIdx] = []; @@ -15712,13 +17569,15 @@ function $RootScopeProvider() { clearPhase(); - while (postDigestQueue.length) { + // postDigestQueuePosition isn't local here because this loop can be reentered recursively. + while (postDigestQueuePosition < postDigestQueue.length) { try { - postDigestQueue.shift()(); + postDigestQueue[postDigestQueuePosition++](); } catch (e) { $exceptionHandler(e); } } + postDigestQueue.length = postDigestQueuePosition = 0; }, @@ -15786,16 +17645,9 @@ function $RootScopeProvider() { this.$on = this.$watch = this.$watchGroup = function() { return noop; }; this.$$listeners = {}; - // All of the code below is bogus code that works around V8's memory leak via optimized code - // and inline caches. - // - // see: - // - https://code.google.com/p/v8/issues/detail?id=2073#c26 - // - https://github.com/angular/angular.js/issues/6794#issuecomment-38648909 - // - https://github.com/angular/angular.js/issues/1313#issuecomment-10378451 - - this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead = - this.$$childTail = this.$root = this.$$watchers = null; + // Disconnect the next sibling to prevent `cleanUpScope` destroying those too + this.$$nextSibling = null; + cleanUpScope(this); }, /** @@ -15871,7 +17723,7 @@ function $RootScopeProvider() { }); } - asyncQueue.push({scope: this, expression: expr, locals: locals}); + asyncQueue.push({scope: this, expression: $parse(expr), locals: locals}); }, $$postDigest: function(fn) { @@ -15926,11 +17778,14 @@ function $RootScopeProvider() { $apply: function(expr) { try { beginPhase('$apply'); - return this.$eval(expr); + try { + return this.$eval(expr); + } finally { + clearPhase(); + } } catch (e) { $exceptionHandler(e); } finally { - clearPhase(); try { $rootScope.$digest(); } catch (e) { @@ -15960,6 +17815,7 @@ function $RootScopeProvider() { $applyAsync: function(expr) { var scope = this; expr && applyAsyncQueue.push($applyAsyncExpression); + expr = $parse(expr); scheduleApplyAsync(); function $applyAsyncExpression() { @@ -16176,6 +18032,8 @@ function $RootScopeProvider() { var postDigestQueue = $rootScope.$$postDigestQueue = []; var applyAsyncQueue = $rootScope.$$applyAsyncQueue = []; + var postDigestQueuePosition = 0; + return $rootScope; @@ -16234,6 +18092,21 @@ function $RootScopeProvider() { }]; } +/** + * @ngdoc service + * @name $rootElement + * + * @description + * The root element of Angular application. This is either the element where {@link + * ng.directive:ngApp ngApp} was declared or the element passed into + * {@link angular.bootstrap}. The element represents the root element of application. It is also the + * location where the application's {@link auto.$injector $injector} service gets + * published, and can be retrieved using `$rootElement.injector()`. + */ + + +// the implementation is in angular.bootstrap + /** * @description * Private service to sanitize uris for links and images. Used by $compile and $sanitize. @@ -16448,13 +18321,15 @@ function $SceDelegateProvider() { * @kind function * * @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value - * provided. This must be an array or null. A snapshot of this array is used so further - * changes to the array are ignored. + * provided. This must be an array or null. A snapshot of this array is used so further + * changes to the array are ignored. * - * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items - * allowed in this array. + * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items + * allowed in this array. * - * Note: **an empty whitelist array will block all URLs**! + *
+ * **Note:** an empty whitelist array will block all URLs! + *
* * @return {Array} the currently set whitelist array. * @@ -16477,17 +18352,17 @@ function $SceDelegateProvider() { * @kind function * * @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value - * provided. This must be an array or null. A snapshot of this array is used so further - * changes to the array are ignored. + * provided. This must be an array or null. A snapshot of this array is used so further + * changes to the array are ignored. * - * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items - * allowed in this array. + * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items + * allowed in this array. * - * The typical usage for the blacklist is to **block - * [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as - * these would otherwise be trusted but actually return content from the redirected domain. + * The typical usage for the blacklist is to **block + * [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as + * these would otherwise be trusted but actually return content from the redirected domain. * - * Finally, **the blacklist overrides the whitelist** and has the final say. + * Finally, **the blacklist overrides the whitelist** and has the final say. * * @return {Array} the currently set blacklist array. * @@ -16598,7 +18473,7 @@ function $SceDelegateProvider() { 'Attempted to trust a value in invalid context. Context: {0}; Value: {1}', type, trustedValue); } - if (trustedValue === null || trustedValue === undefined || trustedValue === '') { + if (trustedValue === null || isUndefined(trustedValue) || trustedValue === '') { return trustedValue; } // All the current contexts in SCE_CONTEXTS happen to be strings. In order to avoid trusting @@ -16646,6 +18521,11 @@ function $SceDelegateProvider() { * returns the originally supplied value if the queried context type is a supertype of the * created type. If this condition isn't satisfied, throws an exception. * + *
+ * Disabling auto-escaping is extremely dangerous, it usually creates a Cross Site Scripting + * (XSS) vulnerability in your application. + *
+ * * @param {string} type The kind of context in which this value is to be used. * @param {*} maybeTrusted The result of a prior {@link ng.$sceDelegate#trustAs * `$sceDelegate.trustAs`} call. @@ -16653,7 +18533,7 @@ function $SceDelegateProvider() { * `$sceDelegate.trustAs`} if valid in this context. Otherwise, throws an exception. */ function getTrusted(type, maybeTrusted) { - if (maybeTrusted === null || maybeTrusted === undefined || maybeTrusted === '') { + if (maybeTrusted === null || isUndefined(maybeTrusted) || maybeTrusted === '') { return maybeTrusted; } var constructor = (byType.hasOwnProperty(type) ? byType[type] : null); @@ -16722,7 +18602,7 @@ function $SceDelegateProvider() { * You can ensure your document is in standards mode and not quirks mode by adding `` * to the top of your HTML document. * - * SCE assists in writing code in way that (a) is secure by default and (b) makes auditing for + * SCE assists in writing code in a way that (a) is secure by default and (b) makes auditing for * security vulnerabilities such as XSS, clickjacking, etc. a lot easier. * * Here's an example of a binding in a privileged context: @@ -16788,7 +18668,7 @@ function $SceDelegateProvider() { * By default, Angular only loads templates from the same domain and protocol as the application * document. This is done by calling {@link ng.$sce#getTrustedResourceUrl * $sce.getTrustedResourceUrl} on the template URL. To load templates from other domains and/or - * protocols, you may either either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist + * protocols, you may either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist * them} or {@link ng.$sce#trustAsResourceUrl wrap it} into a trusted value. * * *Please note*: @@ -16846,10 +18726,10 @@ function $SceDelegateProvider() { * - There are exactly **two wildcard sequences** - `*` and `**`. All other characters * match themselves. * - `*`: matches zero or more occurrences of any character other than one of the following 6 - * characters: '`:`', '`/`', '`.`', '`?`', '`&`' and ';'. It's a useful wildcard for use + * characters: '`:`', '`/`', '`.`', '`?`', '`&`' and '`;`'. It's a useful wildcard for use * in a whitelist. * - `**`: matches zero or more occurrences of *any* character. As such, it's not - * not appropriate to use in for a scheme, domain, etc. as it would match too much. (e.g. + * appropriate for use in a scheme, domain, etc. as it would match too much. (e.g. * http://**.example.com/ would match http://evil.com/?ignore=.example.com/ and that might * not have been the intention.) Its usage at the very end of the path is ok. (e.g. * http://foo.example.com/templates/**). @@ -16857,11 +18737,11 @@ function $SceDelegateProvider() { * - *Caveat*: While regular expressions are powerful and offer great flexibility, their syntax * (and all the inevitable escaping) makes them *harder to maintain*. It's easy to * accidentally introduce a bug when one updates a complex expression (imho, all regexes should - * have good test coverage.). For instance, the use of `.` in the regex is correct only in a + * have good test coverage). For instance, the use of `.` in the regex is correct only in a * small number of cases. A `.` character in the regex used when matching the scheme or a * subdomain could be matched against a `:` or literal `.` that was likely not intended. It * is highly recommended to use the string patterns and only fall back to regular expressions - * if they as a last resort. + * as a last resort. * - The regular expression must be an instance of RegExp (i.e. not a string.) It is * matched against the **entire** *normalized / absolute URL* of the resource being tested * (even when the RegExp did not have the `^` and `$` codes.) In addition, any flags @@ -16871,7 +18751,7 @@ function $SceDelegateProvider() { * remember to escape your regular expression (and be aware that you might need more than * one level of escaping depending on your templating engine and the way you interpolated * the value.) Do make use of your platform's escaping mechanism as it might be good - * enough before coding your own. e.g. Ruby has + * enough before coding your own. E.g. Ruby has * [Regexp.escape(str)](http://www.ruby-doc.org/core-2.0.0/Regexp.html#method-c-escape) * and Python has [re.escape](http://docs.python.org/library/re.html#re.escape). * Javascript lacks a similar built in function for escaping. Take a look at Google @@ -17380,6 +19260,10 @@ function $SceProvider() { function $SnifferProvider() { this.$get = ['$window', '$document', function($window, $document) { var eventSupport = {}, + // Chrome Packaged Apps are not allowed to access `history.pushState`. They can be detected by + // the presence of `chrome.app.runtime` (see https://developer.chrome.com/apps/api_index) + isChromePackagedApp = $window.chrome && $window.chrome.app && $window.chrome.app.runtime, + hasHistoryPushState = !isChromePackagedApp && $window.history && $window.history.pushState, android = toInt((/android (\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]), boxee = /Boxee/i.test(($window.navigator || {}).userAgent), @@ -17395,7 +19279,7 @@ function $SnifferProvider() { for (var prop in bodyStyle) { if (match = vendorRegex.exec(prop)) { vendorPrefix = match[0]; - vendorPrefix = vendorPrefix.substr(0, 1).toUpperCase() + vendorPrefix.substr(1); + vendorPrefix = vendorPrefix[0].toUpperCase() + vendorPrefix.substr(1); break; } } @@ -17424,7 +19308,7 @@ function $SnifferProvider() { // so let's not use the history API also // We are purposefully using `!(android < 4)` to cover the case when `android` is undefined // jshint -W018 - history: !!($window.history && $window.history.pushState && !(android < 4) && !boxee), + history: !!(hasHistoryPushState && !(android < 4) && !boxee), // jshint +W018 hasEvent: function(event) { // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have @@ -17450,30 +19334,78 @@ function $SnifferProvider() { }]; } -var $compileMinErr = minErr('$compile'); +var $templateRequestMinErr = minErr('$compile'); /** - * @ngdoc service - * @name $templateRequest - * + * @ngdoc provider + * @name $templateRequestProvider * @description - * The `$templateRequest` service downloads the provided template using `$http` and, upon success, - * stores the contents inside of `$templateCache`. If the HTTP request fails or the response data - * of the HTTP request is empty, a `$compile` error will be thrown (the exception can be thwarted - * by setting the 2nd parameter of the function to true). - * - * @param {string} tpl The HTTP request template URL - * @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty + * Used to configure the options passed to the {@link $http} service when making a template request. * - * @return {Promise} a promise for the HTTP response data of the given URL. - * - * @property {number} totalPendingRequests total amount of pending template requests being downloaded. + * For example, it can be used for specifying the "Accept" header that is sent to the server, when + * requesting a template. */ function $TemplateRequestProvider() { - this.$get = ['$templateCache', '$http', '$q', function($templateCache, $http, $q) { + + var httpOptions; + + /** + * @ngdoc method + * @name $templateRequestProvider#httpOptions + * @description + * The options to be passed to the {@link $http} service when making the request. + * You can use this to override options such as the "Accept" header for template requests. + * + * The {@link $templateRequest} will set the `cache` and the `transformResponse` properties of the + * options if not overridden here. + * + * @param {string=} value new value for the {@link $http} options. + * @returns {string|self} Returns the {@link $http} options when used as getter and self if used as setter. + */ + this.httpOptions = function(val) { + if (val) { + httpOptions = val; + return this; + } + return httpOptions; + }; + + /** + * @ngdoc service + * @name $templateRequest + * + * @description + * The `$templateRequest` service runs security checks then downloads the provided template using + * `$http` and, upon success, stores the contents inside of `$templateCache`. If the HTTP request + * fails or the response data of the HTTP request is empty, a `$compile` error will be thrown (the + * exception can be thwarted by setting the 2nd parameter of the function to true). Note that the + * contents of `$templateCache` are trusted, so the call to `$sce.getTrustedUrl(tpl)` is omitted + * when `tpl` is of type string and `$templateCache` has the matching entry. + * + * If you want to pass custom options to the `$http` service, such as setting the Accept header you + * can configure this via {@link $templateRequestProvider#httpOptions}. + * + * @param {string|TrustedResourceUrl} tpl The HTTP request template URL + * @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty + * + * @return {Promise} a promise for the HTTP response data of the given URL. + * + * @property {number} totalPendingRequests total amount of pending template requests being downloaded. + */ + this.$get = ['$templateCache', '$http', '$q', '$sce', function($templateCache, $http, $q, $sce) { + function handleRequestFn(tpl, ignoreRequestError) { handleRequestFn.totalPendingRequests++; + // We consider the template cache holds only trusted templates, so + // there's no need to go through whitelisting again for keys that already + // are included in there. This also makes Angular accept any script + // directive, no matter its name. However, we still need to unwrap trusted + // types. + if (!isString(tpl) || isUndefined($templateCache.get(tpl))) { + tpl = $sce.getTrustedResourceUrl(tpl); + } + var transformResponse = $http.defaults && $http.defaults.transformResponse; if (isArray(transformResponse)) { @@ -17484,12 +19416,10 @@ function $TemplateRequestProvider() { transformResponse = null; } - var httpOptions = { - cache: $templateCache, - transformResponse: transformResponse - }; - - return $http.get(tpl, httpOptions) + return $http.get(tpl, extend({ + cache: $templateCache, + transformResponse: transformResponse + }, httpOptions)) ['finally'](function() { handleRequestFn.totalPendingRequests--; }) @@ -17500,7 +19430,7 @@ function $TemplateRequestProvider() { function handleError(resp) { if (!ignoreRequestError) { - throw $compileMinErr('tpload', 'Failed to load template: {0} (HTTP status: {1} {2})', + throw $templateRequestMinErr('tpload', 'Failed to load template: {0} (HTTP status: {1} {2})', tpl, resp.status, resp.statusText); } return $q.reject(resp); @@ -17660,8 +19590,8 @@ function $TimeoutProvider() { * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block. * @param {...*=} Pass additional parameters to the executed function. - * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this - * promise will be resolved with is the return value of the `fn` function. + * @returns {Promise} Promise that will be resolved when the timeout is reached. The promise + * will be resolved with the return value of the `fn` function. * */ function timeout(fn, delay, invokeApply) { @@ -17730,7 +19660,7 @@ function $TimeoutProvider() { // doesn't know about mocked locations and resolves URLs to the real document - which is // exactly the behavior needed here. There is little value is mocking these out for this // service. -var urlParsingNode = document.createElement("a"); +var urlParsingNode = window.document.createElement("a"); var originUrl = urlResolve(window.location.href); @@ -17748,20 +19678,13 @@ var originUrl = urlResolve(window.location.href); * * Implementation Notes for IE * --------------------------- - * IE >= 8 and <= 10 normalizes the URL when assigned to the anchor node similar to the other + * IE <= 10 normalizes the URL when assigned to the anchor node similar to the other * browsers. However, the parsed components will not be set if the URL assigned did not specify * them. (e.g. if you assign a.href = "foo", then a.protocol, a.host, etc. will be empty.) We * work around that by performing the parsing in a 2nd step by taking a previously normalized * URL (e.g. by assigning to a.href) and assigning it a.href again. This correctly populates the * properties such as protocol, hostname, port, etc. * - * IE7 does not normalize the URL when assigned to an anchor node. (Apparently, it does, if one - * uses the inner HTML approach to assign the URL as part of an HTML snippet - - * http://stackoverflow.com/a/472729) However, setting img[src] does normalize the URL. - * Unfortunately, setting img[src] to something like "javascript:foo" on IE throws an exception. - * Since the primary usage for normalizing URLs is to sanitize such URLs, we can't use that - * method and IE < 8 is unsupported. - * * References: * http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html @@ -17910,7 +19833,7 @@ function $$CookieReader($document) { // the first value that is seen for a cookie is the most // specific one. values for the same cookie name that // follow are for less specific paths. - if (lastCookies[name] === undefined) { + if (isUndefined(lastCookies[name])) { lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1)); } } @@ -18041,6 +19964,7 @@ function $FilterProvider($provide) { * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores * (`myapp_subsection_filterx`). *
+ * @param {Function} factory If the first argument was a string, a factory function for the filter to be registered. * @returns {Object} Registered filter instance, or if a map of filters was provided then a map * of the registered filter instances. */ @@ -18110,10 +20034,11 @@ function $FilterProvider($provide) { * - `Object`: A pattern object can be used to filter specific properties on objects contained * by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items * which have property `name` containing "M" and property `phone` containing "1". A special - * property name `$` can be used (as in `{$:"text"}`) to accept a match against any - * property of the object or its nested object properties. That's equivalent to the simple - * substring match with a `string` as described above. The predicate can be negated by prefixing - * the string with `!`. + * property name (`$` by default) can be used (e.g. as in `{$: "text"}`) to accept a match + * against any property of the object or its nested object properties. That's equivalent to the + * simple substring match with a `string` as described above. The special property name can be + * overwritten, using the `anyPropertyKey` parameter. + * The predicate can be negated by prefixing the string with `!`. * For example `{name: "!M"}` predicate will return an array of items which have property `name` * not containing "M". * @@ -18147,6 +20072,9 @@ function $FilterProvider($provide) { * Primitive values are converted to strings. Objects are not compared against primitives, * unless they have a custom `toString` method (e.g. `Date` objects). * + * @param {string=} anyPropertyKey The special property name that matches against any property. + * By default `$`. + * * @example @@ -18215,8 +20143,9 @@ function $FilterProvider($provide) { */ + function filterFilter() { - return function(array, expression, comparator) { + return function(array, expression, comparator, anyPropertyKey) { if (!isArrayLike(array)) { if (array == null) { return array; @@ -18225,6 +20154,7 @@ function filterFilter() { } } + anyPropertyKey = anyPropertyKey || '$'; var expressionType = getTypeForFilter(expression); var predicateFn; var matchAgainstAnyProp; @@ -18241,7 +20171,7 @@ function filterFilter() { //jshint -W086 case 'object': //jshint +W086 - predicateFn = createPredicateFn(expression, comparator, matchAgainstAnyProp); + predicateFn = createPredicateFn(expression, comparator, anyPropertyKey, matchAgainstAnyProp); break; default: return array; @@ -18251,13 +20181,9 @@ function filterFilter() { }; } -function hasCustomToString(obj) { - return isFunction(obj.toString) && obj.toString !== Object.prototype.toString; -} - // Helper functions for `filterFilter` -function createPredicateFn(expression, comparator, matchAgainstAnyProp) { - var shouldMatchPrimitives = isObject(expression) && ('$' in expression); +function createPredicateFn(expression, comparator, anyPropertyKey, matchAgainstAnyProp) { + var shouldMatchPrimitives = isObject(expression) && (anyPropertyKey in expression); var predicateFn; if (comparator === true) { @@ -18285,25 +20211,25 @@ function createPredicateFn(expression, comparator, matchAgainstAnyProp) { predicateFn = function(item) { if (shouldMatchPrimitives && !isObject(item)) { - return deepCompare(item, expression.$, comparator, false); + return deepCompare(item, expression[anyPropertyKey], comparator, anyPropertyKey, false); } - return deepCompare(item, expression, comparator, matchAgainstAnyProp); + return deepCompare(item, expression, comparator, anyPropertyKey, matchAgainstAnyProp); }; return predicateFn; } -function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatchWholeObject) { +function deepCompare(actual, expected, comparator, anyPropertyKey, matchAgainstAnyProp, dontMatchWholeObject) { var actualType = getTypeForFilter(actual); var expectedType = getTypeForFilter(expected); if ((expectedType === 'string') && (expected.charAt(0) === '!')) { - return !deepCompare(actual, expected.substring(1), comparator, matchAgainstAnyProp); + return !deepCompare(actual, expected.substring(1), comparator, anyPropertyKey, matchAgainstAnyProp); } else if (isArray(actual)) { // In case `actual` is an array, consider it a match // if ANY of it's items matches `expected` return actual.some(function(item) { - return deepCompare(item, expected, comparator, matchAgainstAnyProp); + return deepCompare(item, expected, comparator, anyPropertyKey, matchAgainstAnyProp); }); } @@ -18312,11 +20238,11 @@ function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatc var key; if (matchAgainstAnyProp) { for (key in actual) { - if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator, true)) { + if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator, anyPropertyKey, true)) { return true; } } - return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, false); + return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, anyPropertyKey, false); } else if (expectedType === 'object') { for (key in expected) { var expectedVal = expected[key]; @@ -18324,9 +20250,9 @@ function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatc continue; } - var matchAnyProperty = key === '$'; + var matchAnyProperty = key === anyPropertyKey; var actualVal = matchAnyProperty ? actual : actual[key]; - if (!deepCompare(actualVal, expectedVal, comparator, matchAnyProperty, matchAnyProperty)) { + if (!deepCompare(actualVal, expectedVal, comparator, anyPropertyKey, matchAnyProperty, matchAnyProperty)) { return false; } } @@ -18347,6 +20273,10 @@ function getTypeForFilter(val) { return (val === null) ? 'null' : typeof val; } +var MAX_DIGITS = 22; +var DECIMAL_SEP = '.'; +var ZERO_CHAR = '0'; + /** * @ngdoc filter * @name currency @@ -18392,9 +20322,9 @@ function getTypeForFilter(val) { } element(by.model('amount')).clear(); element(by.model('amount')).sendKeys('-1234'); - expect(element(by.id('currency-default')).getText()).toBe('($1,234.00)'); - expect(element(by.id('currency-custom')).getText()).toBe('(USD$1,234.00)'); - expect(element(by.id('currency-no-fractions')).getText()).toBe('(USD$1,234)'); + expect(element(by.id('currency-default')).getText()).toBe('-$1,234.00'); + expect(element(by.id('currency-custom')).getText()).toBe('-USD$1,234.00'); + expect(element(by.id('currency-no-fractions')).getText()).toBe('-USD$1,234'); }); @@ -18428,7 +20358,7 @@ function currencyFilter($locale) { * Formats a number as text. * * If the input is null or undefined, it will just be returned. - * If the input is infinite (Infinity/-Infinity) the Infinity symbol '∞' is returned. + * If the input is infinite (Infinity or -Infinity), the Infinity symbol '∞' or '-∞' is returned, respectively. * If the input is not a number an empty string is returned. * * @@ -18436,7 +20366,9 @@ function currencyFilter($locale) { * @param {(number|string)=} fractionSize Number of decimal places to round the number to. * If this is not provided then the fraction size is computed from the current locale's number * formatting pattern. In the case of the default locale, it will be 3. - * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit. + * @returns {string} Number rounded to `fractionSize` appropriately formatted based on the current + * locale (e.g., in the en_US locale it will have "." as the decimal separator and + * include "," group separators after each third digit). * * @example @@ -18471,8 +20403,6 @@ function currencyFilter($locale) { */ - - numberFilter.$inject = ['$locale']; function numberFilter($locale) { var formats = $locale.NUMBER_FORMATS; @@ -18486,102 +20416,227 @@ function numberFilter($locale) { }; } -var DECIMAL_SEP = '.'; -function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) { - if (isObject(number)) return ''; +/** + * Parse a number (as a string) into three components that can be used + * for formatting the number. + * + * (Significant bits of this parse algorithm came from https://github.com/MikeMcl/big.js/) + * + * @param {string} numStr The number to parse + * @return {object} An object describing this number, containing the following keys: + * - d : an array of digits containing leading zeros as necessary + * - i : the number of the digits in `d` that are to the left of the decimal point + * - e : the exponent for numbers that would need more than `MAX_DIGITS` digits in `d` + * + */ +function parse(numStr) { + var exponent = 0, digits, numberOfIntegerDigits; + var i, j, zeros; - var isNegative = number < 0; - number = Math.abs(number); + // Decimal point? + if ((numberOfIntegerDigits = numStr.indexOf(DECIMAL_SEP)) > -1) { + numStr = numStr.replace(DECIMAL_SEP, ''); + } - var isInfinity = number === Infinity; - if (!isInfinity && !isFinite(number)) return ''; + // Exponential form? + if ((i = numStr.search(/e/i)) > 0) { + // Work out the exponent. + if (numberOfIntegerDigits < 0) numberOfIntegerDigits = i; + numberOfIntegerDigits += +numStr.slice(i + 1); + numStr = numStr.substring(0, i); + } else if (numberOfIntegerDigits < 0) { + // There was no decimal point or exponent so it is an integer. + numberOfIntegerDigits = numStr.length; + } - var numStr = number + '', - formatedText = '', - hasExponent = false, - parts = []; + // Count the number of leading zeros. + for (i = 0; numStr.charAt(i) == ZERO_CHAR; i++) {/* jshint noempty: false */} - if (isInfinity) formatedText = '\u221e'; + if (i == (zeros = numStr.length)) { + // The digits are all zero. + digits = [0]; + numberOfIntegerDigits = 1; + } else { + // Count the number of trailing zeros + zeros--; + while (numStr.charAt(zeros) == ZERO_CHAR) zeros--; - if (!isInfinity && numStr.indexOf('e') !== -1) { - var match = numStr.match(/([\d\.]+)e(-?)(\d+)/); - if (match && match[2] == '-' && match[3] > fractionSize + 1) { - number = 0; - } else { - formatedText = numStr; - hasExponent = true; + // Trailing zeros are insignificant so ignore them + numberOfIntegerDigits -= i; + digits = []; + // Convert string to array of digits without leading/trailing zeros. + for (j = 0; i <= zeros; i++, j++) { + digits[j] = +numStr.charAt(i); } } - if (!isInfinity && !hasExponent) { - var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length; + // If the number overflows the maximum allowed digits then use an exponent. + if (numberOfIntegerDigits > MAX_DIGITS) { + digits = digits.splice(0, MAX_DIGITS - 1); + exponent = numberOfIntegerDigits - 1; + numberOfIntegerDigits = 1; + } + + return { d: digits, e: exponent, i: numberOfIntegerDigits }; +} - // determine fractionSize if it is not specified - if (isUndefined(fractionSize)) { - fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac); - } +/** + * Round the parsed number to the specified number of decimal places + * This function changed the parsedNumber in-place + */ +function roundNumber(parsedNumber, fractionSize, minFrac, maxFrac) { + var digits = parsedNumber.d; + var fractionLen = digits.length - parsedNumber.i; - // safely round numbers in JS without hitting imprecisions of floating-point arithmetics - // inspired by: - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round - number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize); + // determine fractionSize if it is not specified; `+fractionSize` converts it to a number + fractionSize = (isUndefined(fractionSize)) ? Math.min(Math.max(minFrac, fractionLen), maxFrac) : +fractionSize; - var fraction = ('' + number).split(DECIMAL_SEP); - var whole = fraction[0]; - fraction = fraction[1] || ''; + // The index of the digit to where rounding is to occur + var roundAt = fractionSize + parsedNumber.i; + var digit = digits[roundAt]; - var i, pos = 0, - lgroup = pattern.lgSize, - group = pattern.gSize; + if (roundAt > 0) { + // Drop fractional digits beyond `roundAt` + digits.splice(Math.max(parsedNumber.i, roundAt)); - if (whole.length >= (lgroup + group)) { - pos = whole.length - lgroup; - for (i = 0; i < pos; i++) { - if ((pos - i) % group === 0 && i !== 0) { - formatedText += groupSep; + // Set non-fractional digits beyond `roundAt` to 0 + for (var j = roundAt; j < digits.length; j++) { + digits[j] = 0; + } + } else { + // We rounded to zero so reset the parsedNumber + fractionLen = Math.max(0, fractionLen); + parsedNumber.i = 1; + digits.length = Math.max(1, roundAt = fractionSize + 1); + digits[0] = 0; + for (var i = 1; i < roundAt; i++) digits[i] = 0; + } + + if (digit >= 5) { + if (roundAt - 1 < 0) { + for (var k = 0; k > roundAt; k--) { + digits.unshift(0); + parsedNumber.i++; } - formatedText += whole.charAt(i); + digits.unshift(1); + parsedNumber.i++; + } else { + digits[roundAt - 1]++; } } - for (i = pos; i < whole.length; i++) { - if ((whole.length - i) % lgroup === 0 && i !== 0) { - formatedText += groupSep; - } - formatedText += whole.charAt(i); - } + // Pad out with zeros to get the required fraction length + for (; fractionLen < Math.max(0, fractionSize); fractionLen++) digits.push(0); + - // format fraction part. - while (fraction.length < fractionSize) { - fraction += '0'; + // Do any carrying, e.g. a digit was rounded up to 10 + var carry = digits.reduceRight(function(carry, d, i, digits) { + d = d + carry; + digits[i] = d % 10; + return Math.floor(d / 10); + }, 0); + if (carry) { + digits.unshift(carry); + parsedNumber.i++; } +} + +/** + * Format a number into a string + * @param {number} number The number to format + * @param {{ + * minFrac, // the minimum number of digits required in the fraction part of the number + * maxFrac, // the maximum number of digits required in the fraction part of the number + * gSize, // number of digits in each group of separated digits + * lgSize, // number of digits in the last group of digits before the decimal separator + * negPre, // the string to go in front of a negative number (e.g. `-` or `(`)) + * posPre, // the string to go in front of a positive number + * negSuf, // the string to go after a negative number (e.g. `)`) + * posSuf // the string to go after a positive number + * }} pattern + * @param {string} groupSep The string to separate groups of number (e.g. `,`) + * @param {string} decimalSep The string to act as the decimal separator (e.g. `.`) + * @param {[type]} fractionSize The size of the fractional part of the number + * @return {string} The number formatted as a string + */ +function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) { + + if (!(isString(number) || isNumber(number)) || isNaN(number)) return ''; - if (fractionSize && fractionSize !== "0") formatedText += decimalSep + fraction.substr(0, fractionSize); + var isInfinity = !isFinite(number); + var isZero = false; + var numStr = Math.abs(number) + '', + formattedText = '', + parsedNumber; + + if (isInfinity) { + formattedText = '\u221e'; } else { - if (fractionSize > 0 && number < 1) { - formatedText = number.toFixed(fractionSize); - number = parseFloat(formatedText); + parsedNumber = parse(numStr); + + roundNumber(parsedNumber, fractionSize, pattern.minFrac, pattern.maxFrac); + + var digits = parsedNumber.d; + var integerLen = parsedNumber.i; + var exponent = parsedNumber.e; + var decimals = []; + isZero = digits.reduce(function(isZero, d) { return isZero && !d; }, true); + + // pad zeros for small numbers + while (integerLen < 0) { + digits.unshift(0); + integerLen++; } - } - if (number === 0) { - isNegative = false; - } + // extract decimals digits + if (integerLen > 0) { + decimals = digits.splice(integerLen, digits.length); + } else { + decimals = digits; + digits = [0]; + } + + // format the integer digits with grouping separators + var groups = []; + if (digits.length >= pattern.lgSize) { + groups.unshift(digits.splice(-pattern.lgSize, digits.length).join('')); + } + while (digits.length > pattern.gSize) { + groups.unshift(digits.splice(-pattern.gSize, digits.length).join('')); + } + if (digits.length) { + groups.unshift(digits.join('')); + } + formattedText = groups.join(groupSep); + + // append the decimal digits + if (decimals.length) { + formattedText += decimalSep + decimals.join(''); + } - parts.push(isNegative ? pattern.negPre : pattern.posPre, - formatedText, - isNegative ? pattern.negSuf : pattern.posSuf); - return parts.join(''); + if (exponent) { + formattedText += 'e+' + exponent; + } + } + if (number < 0 && !isZero) { + return pattern.negPre + formattedText + pattern.negSuf; + } else { + return pattern.posPre + formattedText + pattern.posSuf; + } } -function padNumber(num, digits, trim) { +function padNumber(num, digits, trim, negWrap) { var neg = ''; - if (num < 0) { - neg = '-'; - num = -num; + if (num < 0 || (negWrap && num <= 0)) { + if (negWrap) { + num = -num + 1; + } else { + num = -num; + neg = '-'; + } } num = '' + num; - while (num.length < digits) num = '0' + num; + while (num.length < digits) num = ZERO_CHAR + num; if (trim) { num = num.substr(num.length - digits); } @@ -18589,7 +20644,7 @@ function padNumber(num, digits, trim) { } -function dateGetter(name, size, offset, trim) { +function dateGetter(name, size, offset, trim, negWrap) { offset = offset || 0; return function(date) { var value = date['get' + name](); @@ -18597,14 +20652,15 @@ function dateGetter(name, size, offset, trim) { value += offset; } if (value === 0 && offset == -12) value = 12; - return padNumber(value, size, trim); + return padNumber(value, size, trim, negWrap); }; } -function dateStrGetter(name, shortForm) { +function dateStrGetter(name, shortForm, standAlone) { return function(date, formats) { var value = date['get' + name](); - var get = uppercase(shortForm ? ('SHORT' + name) : name); + var propPrefix = (standAlone ? 'STANDALONE' : '') + (shortForm ? 'SHORT' : ''); + var get = uppercase(propPrefix + name); return formats[get][value]; }; @@ -18659,13 +20715,14 @@ function longEraGetter(date, formats) { } var DATE_FORMATS = { - yyyy: dateGetter('FullYear', 4), - yy: dateGetter('FullYear', 2, 0, true), - y: dateGetter('FullYear', 1), + yyyy: dateGetter('FullYear', 4, 0, false, true), + yy: dateGetter('FullYear', 2, 0, true, true), + y: dateGetter('FullYear', 1, 0, false, true), MMMM: dateStrGetter('Month'), MMM: dateStrGetter('Month', true), MM: dateGetter('Month', 2, 1), M: dateGetter('Month', 1, 1), + LLLL: dateStrGetter('Month', false, true), dd: dateGetter('Date', 2), d: dateGetter('Date', 1), HH: dateGetter('Hours', 2), @@ -18691,7 +20748,7 @@ var DATE_FORMATS = { GGGG: longEraGetter }; -var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/, +var DATE_FORMATS_SPLIT = /((?:[^yMLdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|L+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/, NUMBER_STRING = /^\-?\d+$/; /** @@ -18711,6 +20768,7 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+| * * `'MMM'`: Month in year (Jan-Dec) * * `'MM'`: Month in year, padded (01-12) * * `'M'`: Month in year (1-12) + * * `'LLLL'`: Stand-alone month in year (January-December) * * `'dd'`: Day in month, padded (01-31) * * `'d'`: Day in month (1-31) * * `'EEEE'`: Day in Week,(Sunday-Saturday) @@ -18850,13 +20908,13 @@ function dateFilter($locale) { var dateTimezoneOffset = date.getTimezoneOffset(); if (timezone) { - dateTimezoneOffset = timezoneToOffset(timezone, date.getTimezoneOffset()); + dateTimezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset); date = convertTimezoneToLocal(date, timezone, true); } forEach(parts, function(value) { fn = DATE_FORMATS[value]; text += fn ? fn(date, $locale.DATETIME_FORMATS, dateTimezoneOffset) - : value.replace(/(^'|'$)/g, '').replace(/''/g, "'"); + : value === "''" ? "'" : value.replace(/(^'|'$)/g, '').replace(/''/g, "'"); }); return text; @@ -18932,21 +20990,22 @@ var uppercaseFilter = valueFn(uppercase); * @kind function * * @description - * Creates a new array or string containing only a specified number of elements. The elements - * are taken from either the beginning or the end of the source array, string or number, as specified by - * the value and sign (positive or negative) of `limit`. If a number is used as input, it is - * converted to a string. - * - * @param {Array|string|number} input Source array, string or number to be limited. - * @param {string|number} limit The length of the returned array or string. If the `limit` number + * Creates a new array or string containing only a specified number of elements. The elements are + * taken from either the beginning or the end of the source array, string or number, as specified by + * the value and sign (positive or negative) of `limit`. Other array-like objects are also supported + * (e.g. array subclasses, NodeLists, jqLite/jQuery collections etc). If a number is used as input, + * it is converted to a string. + * + * @param {Array|ArrayLike|string|number} input - Array/array-like, string or number to be limited. + * @param {string|number} limit - The length of the returned array or string. If the `limit` number * is positive, `limit` number of items from the beginning of the source array/string are copied. * If the number is negative, `limit` number of items from the end of the source array/string * are copied. The `limit` will be trimmed if it exceeds `array.length`. If `limit` is undefined, * the input will be returned unchanged. - * @param {(string|number)=} begin Index at which to begin limitation. As a negative index, `begin` - * indicates an offset from the end of `input`. Defaults to `0`. - * @returns {Array|string} A new sub-array or substring of length `limit` or less if input array - * had less than `limit` elements. + * @param {(string|number)=} begin - Index at which to begin limitation. As a negative index, + * `begin` indicates an offset from the end of `input`. Defaults to `0`. + * @returns {Array|string} A new sub-array or substring of length `limit` or less if the input had + * less than `limit` elements. * * @example @@ -19034,77 +21093,157 @@ function limitToFilter() { if (isNaN(limit)) return input; if (isNumber(input)) input = input.toString(); - if (!isArray(input) && !isString(input)) return input; + if (!isArrayLike(input)) return input; begin = (!begin || isNaN(begin)) ? 0 : toInt(begin); - begin = (begin < 0 && begin >= -input.length) ? input.length + begin : begin; + begin = (begin < 0) ? Math.max(0, input.length + begin) : begin; if (limit >= 0) { - return input.slice(begin, begin + limit); + return sliceFn(input, begin, begin + limit); } else { if (begin === 0) { - return input.slice(limit, input.length); + return sliceFn(input, limit, input.length); } else { - return input.slice(Math.max(0, begin + limit), begin); + return sliceFn(input, Math.max(0, begin + limit), begin); } } }; } +function sliceFn(input, begin, end) { + if (isString(input)) return input.slice(begin, end); + + return slice.call(input, begin, end); +} + /** * @ngdoc filter * @name orderBy * @kind function * * @description - * Orders a specified `array` by the `expression` predicate. It is ordered alphabetically - * for strings and numerically for numbers. Note: if you notice numbers are not being sorted - * as expected, make sure they are actually being saved as numbers and not strings. + * Returns an array containing the items from the specified `collection`, ordered by a `comparator` + * function based on the values computed using the `expression` predicate. + * + * For example, `[{id: 'foo'}, {id: 'bar'}] | orderBy:'id'` would result in + * `[{id: 'bar'}, {id: 'foo'}]`. + * + * The `collection` can be an Array or array-like object (e.g. NodeList, jQuery object, TypedArray, + * String, etc). + * + * The `expression` can be a single predicate, or a list of predicates each serving as a tie-breaker + * for the preceeding one. The `expression` is evaluated against each item and the output is used + * for comparing with other items. + * + * You can change the sorting order by setting `reverse` to `true`. By default, items are sorted in + * ascending order. + * + * The comparison is done using the `comparator` function. If none is specified, a default, built-in + * comparator is used (see below for details - in a nutshell, it compares numbers numerically and + * strings alphabetically). + * + * ### Under the hood * - * @param {Array} array The array to sort. - * @param {function(*)|string|Array.<(function(*)|string)>=} expression A predicate to be - * used by the comparator to determine the order of elements. + * Ordering the specified `collection` happens in two phases: + * + * 1. All items are passed through the predicate (or predicates), and the returned values are saved + * along with their type (`string`, `number` etc). For example, an item `{label: 'foo'}`, passed + * through a predicate that extracts the value of the `label` property, would be transformed to: + * ``` + * { + * value: 'foo', + * type: 'string', + * index: ... + * } + * ``` + * 2. The comparator function is used to sort the items, based on the derived values, types and + * indices. + * + * If you use a custom comparator, it will be called with pairs of objects of the form + * `{value: ..., type: '...', index: ...}` and is expected to return `0` if the objects are equal + * (as far as the comparator is concerned), `-1` if the 1st one should be ranked higher than the + * second, or `1` otherwise. + * + * In order to ensure that the sorting will be deterministic across platforms, if none of the + * specified predicates can distinguish between two items, `orderBy` will automatically introduce a + * dummy predicate that returns the item's index as `value`. + * (If you are using a custom comparator, make sure it can handle this predicate as well.) + * + * Finally, in an attempt to simplify things, if a predicate returns an object as the extracted + * value for an item, `orderBy` will try to convert that object to a primitive value, before passing + * it to the comparator. The following rules govern the conversion: + * + * 1. If the object has a `valueOf()` method that returns a primitive, its return value will be + * used instead.
+ * (If the object has a `valueOf()` method that returns another object, then the returned object + * will be used in subsequent steps.) + * 2. If the object has a custom `toString()` method (i.e. not the one inherited from `Object`) that + * returns a primitive, its return value will be used instead.
+ * (If the object has a `toString()` method that returns another object, then the returned object + * will be used in subsequent steps.) + * 3. No conversion; the object itself is used. + * + * ### The default comparator + * + * The default, built-in comparator should be sufficient for most usecases. In short, it compares + * numbers numerically, strings alphabetically (and case-insensitively), for objects falls back to + * using their index in the original collection, and sorts values of different types by type. + * + * More specifically, it follows these steps to determine the relative order of items: + * + * 1. If the compared values are of different types, compare the types themselves alphabetically. + * 2. If both values are of type `string`, compare them alphabetically in a case- and + * locale-insensitive way. + * 3. If both values are objects, compare their indices instead. + * 4. Otherwise, return: + * - `0`, if the values are equal (by strict equality comparison, i.e. using `===`). + * - `-1`, if the 1st value is "less than" the 2nd value (compared using the `<` operator). + * - `1`, otherwise. + * + * **Note:** If you notice numbers not being sorted as expected, make sure they are actually being + * saved as numbers and not strings. + * + * @param {Array|ArrayLike} collection - The collection (array or array-like object) to sort. + * @param {(Function|string|Array.)=} expression - A predicate (or list of + * predicates) to be used by the comparator to determine the order of elements. * * Can be one of: * - * - `function`: Getter function. The result of this function will be sorted using the - * `<`, `===`, `>` operator. - * - `string`: An Angular expression. The result of this expression is used to compare elements - * (for example `name` to sort by a property called `name` or `name.substr(0, 3)` to sort by - * 3 first characters of a property called `name`). The result of a constant expression - * is interpreted as a property name to be used in comparisons (for example `"special name"` - * to sort object by the value of their `special name` property). An expression can be - * optionally prefixed with `+` or `-` to control ascending or descending sort order - * (for example, `+name` or `-name`). If no property is provided, (e.g. `'+'`) then the array - * element itself is used to compare where sorting. - * - `Array`: An array of function or string predicates. The first predicate in the array - * is used for sorting, but when two items are equivalent, the next predicate is used. + * - `Function`: A getter function. This function will be called with each item as argument and + * the return value will be used for sorting. + * - `string`: An Angular expression. This expression will be evaluated against each item and the + * result will be used for sorting. For example, use `'label'` to sort by a property called + * `label` or `'label.substring(0, 3)'` to sort by the first 3 characters of the `label` + * property.
+ * (The result of a constant expression is interpreted as a property name to be used for + * comparison. For example, use `'"special name"'` (note the extra pair of quotes) to sort by a + * property called `special name`.)
+ * An expression can be optionally prefixed with `+` or `-` to control the sorting direction, + * ascending or descending. For example, `'+label'` or `'-label'`. If no property is provided, + * (e.g. `'+'` or `'-'`), the collection element itself is used in comparisons. + * - `Array`: An array of function and/or string predicates. If a predicate cannot determine the + * relative order of two items, the next predicate is used as a tie-breaker. * - * If the predicate is missing or empty then it defaults to `'+'`. + * **Note:** If the predicate is missing or empty then it defaults to `'+'`. * - * @param {boolean=} reverse Reverse the order of the array. - * @returns {Array} Sorted copy of the source array. + * @param {boolean=} reverse - If `true`, reverse the sorting order. + * @param {(Function)=} comparator - The comparator function used to determine the relative order of + * value pairs. If omitted, the built-in comparator will be used. + * + * @returns {Array} - The sorted array. * * * @example - * The example below demonstrates a simple ngRepeat, where the data is sorted - * by age in descending order (predicate is set to `'-age'`). - * `reverse` is not set, which means it defaults to `false`. - + * ### Ordering a table with `ngRepeat` + * + * The example below demonstrates a simple {@link ngRepeat ngRepeat}, where the data is sorted by + * age in descending order (expression is set to `'-age'`). The `comparator` is not set, which means + * it defaults to the built-in comparator. + * + -
- +
@@ -19118,58 +21257,78 @@ function limitToFilter() {
Name Phone Number
+ + angular.module('orderByExample1', []) + .controller('ExampleController', ['$scope', function($scope) { + $scope.friends = [ + {name: 'John', phone: '555-1212', age: 10}, + {name: 'Mary', phone: '555-9876', age: 19}, + {name: 'Mike', phone: '555-4321', age: 21}, + {name: 'Adam', phone: '555-5678', age: 35}, + {name: 'Julie', phone: '555-8765', age: 29} + ]; + }]); + + + .friends { + border-collapse: collapse; + } + + .friends th { + border-bottom: 1px solid; + } + .friends td, .friends th { + border-left: 1px solid; + padding: 5px 10px; + } + .friends td:first-child, .friends th:first-child { + border-left: none; + } + + + // Element locators + var names = element.all(by.repeater('friends').column('friend.name')); + + it('should sort friends by age in reverse order', function() { + expect(names.get(0).getText()).toBe('Adam'); + expect(names.get(1).getText()).toBe('Julie'); + expect(names.get(2).getText()).toBe('Mike'); + expect(names.get(3).getText()).toBe('Mary'); + expect(names.get(4).getText()).toBe('John'); + }); +
+ *
* - * The predicate and reverse parameters can be controlled dynamically through scope properties, - * as shown in the next example. * @example - + * ### Changing parameters dynamically + * + * All parameters can be changed dynamically. The next example shows how you can make the columns of + * a table sortable, by binding the `expression` and `reverse` parameters to scope properties. + * + - -
-
Sorting predicate = {{predicate}}; reverse = {{reverse}}
+
Sort by = {{propertyName}}; reverse = {{reverse}}

- [ unsorted ] - + +
+
- + @@ -19177,172 +21336,507 @@ function limitToFilter() {
- Name - + + - Phone Number - + + - Age - + +
{{friend.name}} {{friend.phone}} {{friend.age}}
-
- * - * It's also possible to call the orderBy filter manually, by injecting `$filter`, retrieving the - * filter routine with `$filter('orderBy')`, and calling the returned filter routine with the - * desired parameters. - * - * Example: - * - * @example - - -
- - - - - - - - - - - -
Name - (^)Phone NumberAge
{{friend.name}}{{friend.phone}}{{friend.age}}
-
-
+ + angular.module('orderByExample2', []) + .controller('ExampleController', ['$scope', function($scope) { + var friends = [ + {name: 'John', phone: '555-1212', age: 10}, + {name: 'Mary', phone: '555-9876', age: 19}, + {name: 'Mike', phone: '555-4321', age: 21}, + {name: 'Adam', phone: '555-5678', age: 35}, + {name: 'Julie', phone: '555-8765', age: 29} + ]; + + $scope.propertyName = 'age'; + $scope.reverse = true; + $scope.friends = friends; + + $scope.sortBy = function(propertyName) { + $scope.reverse = ($scope.propertyName === propertyName) ? !$scope.reverse : false; + $scope.propertyName = propertyName; + }; + }]); + + + .friends { + border-collapse: collapse; + } - - angular.module('orderByExample', []) - .controller('ExampleController', ['$scope', '$filter', function($scope, $filter) { - var orderBy = $filter('orderBy'); - $scope.friends = [ - { name: 'John', phone: '555-1212', age: 10 }, - { name: 'Mary', phone: '555-9876', age: 19 }, - { name: 'Mike', phone: '555-4321', age: 21 }, - { name: 'Adam', phone: '555-5678', age: 35 }, - { name: 'Julie', phone: '555-8765', age: 29 } - ]; - $scope.order = function(predicate, reverse) { - $scope.friends = orderBy($scope.friends, predicate, reverse); - }; - $scope.order('-age',false); - }]); - -
- */ -orderByFilter.$inject = ['$parse']; -function orderByFilter($parse) { - return function(array, sortPredicate, reverseOrder) { - if (!(isArrayLike(array))) return array; - sortPredicate = isArray(sortPredicate) ? sortPredicate : [sortPredicate]; - if (sortPredicate.length === 0) { sortPredicate = ['+']; } - sortPredicate = sortPredicate.map(function(predicate) { - var descending = false, get = predicate || identity; - if (isString(predicate)) { - if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) { - descending = predicate.charAt(0) == '-'; - predicate = predicate.substring(1); - } - if (predicate === '') { - // Effectively no predicate was passed so we compare identity - return reverseComparator(compare, descending); - } - get = $parse(predicate); - if (get.constant) { - var key = get(); - return reverseComparator(function(a, b) { - return compare(a[key], b[key]); - }, descending); - } - } - return reverseComparator(function(a, b) { - return compare(get(a),get(b)); - }, descending); - }); - return slice.call(array).sort(reverseComparator(comparator, reverseOrder)); + .friends th { + border-bottom: 1px solid; + } + .friends td, .friends th { + border-left: 1px solid; + padding: 5px 10px; + } + .friends td:first-child, .friends th:first-child { + border-left: none; + } - function comparator(o1, o2) { - for (var i = 0; i < sortPredicate.length; i++) { - var comp = sortPredicate[i](o1, o2); - if (comp !== 0) return comp; - } - return 0; - } - function reverseComparator(comp, descending) { - return descending - ? function(a, b) {return comp(b,a);} - : comp; - } + .sortorder:after { + content: '\25b2'; // BLACK UP-POINTING TRIANGLE + } + .sortorder.reverse:after { + content: '\25bc'; // BLACK DOWN-POINTING TRIANGLE + } + + + // Element locators + var unsortButton = element(by.partialButtonText('unsorted')); + var nameHeader = element(by.partialButtonText('Name')); + var phoneHeader = element(by.partialButtonText('Phone')); + var ageHeader = element(by.partialButtonText('Age')); + var firstName = element(by.repeater('friends').column('friend.name').row(0)); + var lastName = element(by.repeater('friends').column('friend.name').row(4)); + + it('should sort friends by some property, when clicking on the column header', function() { + expect(firstName.getText()).toBe('Adam'); + expect(lastName.getText()).toBe('John'); + + phoneHeader.click(); + expect(firstName.getText()).toBe('John'); + expect(lastName.getText()).toBe('Mary'); + + nameHeader.click(); + expect(firstName.getText()).toBe('Adam'); + expect(lastName.getText()).toBe('Mike'); + + ageHeader.click(); + expect(firstName.getText()).toBe('John'); + expect(lastName.getText()).toBe('Adam'); + }); - function isPrimitive(value) { - switch (typeof value) { - case 'number': /* falls through */ - case 'boolean': /* falls through */ - case 'string': - return true; - default: - return false; - } - } + it('should sort friends in reverse order, when clicking on the same column', function() { + expect(firstName.getText()).toBe('Adam'); + expect(lastName.getText()).toBe('John'); - function objectToString(value) { - if (value === null) return 'null'; - if (typeof value.valueOf === 'function') { - value = value.valueOf(); - if (isPrimitive(value)) return value; - } - if (typeof value.toString === 'function') { - value = value.toString(); - if (isPrimitive(value)) return value; - } - return ''; - } + ageHeader.click(); + expect(firstName.getText()).toBe('John'); + expect(lastName.getText()).toBe('Adam'); - function compare(v1, v2) { - var t1 = typeof v1; - var t2 = typeof v2; - if (t1 === t2 && t1 === "object") { - v1 = objectToString(v1); - v2 = objectToString(v2); - } - if (t1 === t2) { - if (t1 === "string") { - v1 = v1.toLowerCase(); - v2 = v2.toLowerCase(); - } - if (v1 === v2) return 0; - return v1 < v2 ? -1 : 1; - } else { - return t1 < t2 ? -1 : 1; - } - } - }; -} + ageHeader.click(); + expect(firstName.getText()).toBe('Adam'); + expect(lastName.getText()).toBe('John'); + }); -function ngDirective(directive) { - if (isFunction(directive)) { - directive = { - link: directive - }; - } - directive.restrict = directive.restrict || 'AC'; - return valueFn(directive); -} + it('should restore the original order, when clicking "Set to unsorted"', function() { + expect(firstName.getText()).toBe('Adam'); + expect(lastName.getText()).toBe('John'); -/** - * @ngdoc directive - * @name a - * @restrict E + unsortButton.click(); + expect(firstName.getText()).toBe('John'); + expect(lastName.getText()).toBe('Julie'); + }); + +
+ *
* - * @description - * Modifies the default behavior of the html A tag so that the default action is prevented when - * the href attribute is empty. + * @example + * ### Using `orderBy` inside a controller * - * This change permits the easy creation of action links with the `ngClick` directive - * without changing the location or causing page reloads, e.g.: - * `Add Item` - */ -var htmlAnchorDirective = valueFn({ - restrict: 'E', - compile: function(element, attr) { - if (!attr.href && !attr.xlinkHref) { - return function(scope, element) { - // If the linked element is not an anchor tag anymore, do nothing - if (element[0].nodeName.toLowerCase() !== 'a') return; + * It is also possible to call the `orderBy` filter manually, by injecting `orderByFilter`, and + * calling it with the desired parameters. (Alternatively, you could inject the `$filter` factory + * and retrieve the `orderBy` filter with `$filter('orderBy')`.) + * + + +
+
Sort by = {{propertyName}}; reverse = {{reverse}}
+
+ +
+ + + + + + + + + + + +
+ + + + + + + + +
{{friend.name}}{{friend.phone}}{{friend.age}}
+
+
+ + angular.module('orderByExample3', []) + .controller('ExampleController', ['$scope', 'orderByFilter', function($scope, orderBy) { + var friends = [ + {name: 'John', phone: '555-1212', age: 10}, + {name: 'Mary', phone: '555-9876', age: 19}, + {name: 'Mike', phone: '555-4321', age: 21}, + {name: 'Adam', phone: '555-5678', age: 35}, + {name: 'Julie', phone: '555-8765', age: 29} + ]; + + $scope.propertyName = 'age'; + $scope.reverse = true; + $scope.friends = orderBy(friends, $scope.propertyName, $scope.reverse); + + $scope.sortBy = function(propertyName) { + $scope.reverse = (propertyName !== null && $scope.propertyName === propertyName) + ? !$scope.reverse : false; + $scope.propertyName = propertyName; + $scope.friends = orderBy(friends, $scope.propertyName, $scope.reverse); + }; + }]); + + + .friends { + border-collapse: collapse; + } + + .friends th { + border-bottom: 1px solid; + } + .friends td, .friends th { + border-left: 1px solid; + padding: 5px 10px; + } + .friends td:first-child, .friends th:first-child { + border-left: none; + } + + .sortorder:after { + content: '\25b2'; // BLACK UP-POINTING TRIANGLE + } + .sortorder.reverse:after { + content: '\25bc'; // BLACK DOWN-POINTING TRIANGLE + } + + + // Element locators + var unsortButton = element(by.partialButtonText('unsorted')); + var nameHeader = element(by.partialButtonText('Name')); + var phoneHeader = element(by.partialButtonText('Phone')); + var ageHeader = element(by.partialButtonText('Age')); + var firstName = element(by.repeater('friends').column('friend.name').row(0)); + var lastName = element(by.repeater('friends').column('friend.name').row(4)); + + it('should sort friends by some property, when clicking on the column header', function() { + expect(firstName.getText()).toBe('Adam'); + expect(lastName.getText()).toBe('John'); + + phoneHeader.click(); + expect(firstName.getText()).toBe('John'); + expect(lastName.getText()).toBe('Mary'); + + nameHeader.click(); + expect(firstName.getText()).toBe('Adam'); + expect(lastName.getText()).toBe('Mike'); + + ageHeader.click(); + expect(firstName.getText()).toBe('John'); + expect(lastName.getText()).toBe('Adam'); + }); + + it('should sort friends in reverse order, when clicking on the same column', function() { + expect(firstName.getText()).toBe('Adam'); + expect(lastName.getText()).toBe('John'); + + ageHeader.click(); + expect(firstName.getText()).toBe('John'); + expect(lastName.getText()).toBe('Adam'); + + ageHeader.click(); + expect(firstName.getText()).toBe('Adam'); + expect(lastName.getText()).toBe('John'); + }); + + it('should restore the original order, when clicking "Set to unsorted"', function() { + expect(firstName.getText()).toBe('Adam'); + expect(lastName.getText()).toBe('John'); + + unsortButton.click(); + expect(firstName.getText()).toBe('John'); + expect(lastName.getText()).toBe('Julie'); + }); + +
+ *
+ * + * @example + * ### Using a custom comparator + * + * If you have very specific requirements about the way items are sorted, you can pass your own + * comparator function. For example, you might need to compare some strings in a locale-sensitive + * way. (When specifying a custom comparator, you also need to pass a value for the `reverse` + * argument - passing `false` retains the default sorting order, i.e. ascending.) + * + + +
+
+

Locale-sensitive Comparator

+ + + + + + + + + +
NameFavorite Letter
{{friend.name}}{{friend.favoriteLetter}}
+
+
+

Default Comparator

+ + + + + + + + + +
NameFavorite Letter
{{friend.name}}{{friend.favoriteLetter}}
+
+
+
+ + angular.module('orderByExample4', []) + .controller('ExampleController', ['$scope', function($scope) { + $scope.friends = [ + {name: 'John', favoriteLetter: 'Ä'}, + {name: 'Mary', favoriteLetter: 'Ü'}, + {name: 'Mike', favoriteLetter: 'Ö'}, + {name: 'Adam', favoriteLetter: 'H'}, + {name: 'Julie', favoriteLetter: 'Z'} + ]; + + $scope.localeSensitiveComparator = function(v1, v2) { + // If we don't get strings, just compare by index + if (v1.type !== 'string' || v2.type !== 'string') { + return (v1.index < v2.index) ? -1 : 1; + } + + // Compare strings alphabetically, taking locale into account + return v1.value.localeCompare(v2.value); + }; + }]); + + + .friends-container { + display: inline-block; + margin: 0 30px; + } + + .friends { + border-collapse: collapse; + } + + .friends th { + border-bottom: 1px solid; + } + .friends td, .friends th { + border-left: 1px solid; + padding: 5px 10px; + } + .friends td:first-child, .friends th:first-child { + border-left: none; + } + + + // Element locators + var container = element(by.css('.custom-comparator')); + var names = container.all(by.repeater('friends').column('friend.name')); + + it('should sort friends by favorite letter (in correct alphabetical order)', function() { + expect(names.get(0).getText()).toBe('John'); + expect(names.get(1).getText()).toBe('Adam'); + expect(names.get(2).getText()).toBe('Mike'); + expect(names.get(3).getText()).toBe('Mary'); + expect(names.get(4).getText()).toBe('Julie'); + }); + +
+ * + */ +orderByFilter.$inject = ['$parse']; +function orderByFilter($parse) { + return function(array, sortPredicate, reverseOrder, compareFn) { + + if (array == null) return array; + if (!isArrayLike(array)) { + throw minErr('orderBy')('notarray', 'Expected array but received: {0}', array); + } + + if (!isArray(sortPredicate)) { sortPredicate = [sortPredicate]; } + if (sortPredicate.length === 0) { sortPredicate = ['+']; } + + var predicates = processPredicates(sortPredicate); + + var descending = reverseOrder ? -1 : 1; + + // Define the `compare()` function. Use a default comparator if none is specified. + var compare = isFunction(compareFn) ? compareFn : defaultCompare; + + // The next three lines are a version of a Swartzian Transform idiom from Perl + // (sometimes called the Decorate-Sort-Undecorate idiom) + // See https://en.wikipedia.org/wiki/Schwartzian_transform + var compareValues = Array.prototype.map.call(array, getComparisonObject); + compareValues.sort(doComparison); + array = compareValues.map(function(item) { return item.value; }); + + return array; + + function getComparisonObject(value, index) { + // NOTE: We are adding an extra `tieBreaker` value based on the element's index. + // This will be used to keep the sort stable when none of the input predicates can + // distinguish between two elements. + return { + value: value, + tieBreaker: {value: index, type: 'number', index: index}, + predicateValues: predicates.map(function(predicate) { + return getPredicateValue(predicate.get(value), index); + }) + }; + } + + function doComparison(v1, v2) { + for (var i = 0, ii = predicates.length; i < ii; i++) { + var result = compare(v1.predicateValues[i], v2.predicateValues[i]); + if (result) { + return result * predicates[i].descending * descending; + } + } + + return compare(v1.tieBreaker, v2.tieBreaker) * descending; + } + }; + + function processPredicates(sortPredicates) { + return sortPredicates.map(function(predicate) { + var descending = 1, get = identity; + + if (isFunction(predicate)) { + get = predicate; + } else if (isString(predicate)) { + if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) { + descending = predicate.charAt(0) == '-' ? -1 : 1; + predicate = predicate.substring(1); + } + if (predicate !== '') { + get = $parse(predicate); + if (get.constant) { + var key = get(); + get = function(value) { return value[key]; }; + } + } + } + return {get: get, descending: descending}; + }); + } + + function isPrimitive(value) { + switch (typeof value) { + case 'number': /* falls through */ + case 'boolean': /* falls through */ + case 'string': + return true; + default: + return false; + } + } + + function objectValue(value) { + // If `valueOf` is a valid function use that + if (isFunction(value.valueOf)) { + value = value.valueOf(); + if (isPrimitive(value)) return value; + } + // If `toString` is a valid function and not the one from `Object.prototype` use that + if (hasCustomToString(value)) { + value = value.toString(); + if (isPrimitive(value)) return value; + } + + return value; + } + + function getPredicateValue(value, index) { + var type = typeof value; + if (value === null) { + type = 'string'; + value = 'null'; + } else if (type === 'object') { + value = objectValue(value); + } + return {value: value, type: type, index: index}; + } + + function defaultCompare(v1, v2) { + var result = 0; + var type1 = v1.type; + var type2 = v2.type; + + if (type1 === type2) { + var value1 = v1.value; + var value2 = v2.value; + + if (type1 === 'string') { + // Compare strings case-insensitively + value1 = value1.toLowerCase(); + value2 = value2.toLowerCase(); + } else if (type1 === 'object') { + // For basic objects, use the position of the object + // in the collection instead of the value + if (isObject(value1)) value1 = v1.index; + if (isObject(value2)) value2 = v2.index; + } + + if (value1 !== value2) { + result = value1 < value2 ? -1 : 1; + } + } else { + result = type1 < type2 ? -1 : 1; + } + + return result; + } +} + +function ngDirective(directive) { + if (isFunction(directive)) { + directive = { + link: directive + }; + } + directive.restrict = directive.restrict || 'AC'; + return valueFn(directive); +} + +/** + * @ngdoc directive + * @name a + * @restrict E + * + * @description + * Modifies the default behavior of the html A tag so that the default action is prevented when + * the href attribute is empty. + * + * This change permits the easy creation of action links with the `ngClick` directive + * without changing the location or causing page reloads, e.g.: + * `Add Item` + */ +var htmlAnchorDirective = valueFn({ + restrict: 'E', + compile: function(element, attr) { + if (!attr.href && !attr.xlinkHref) { + return function(scope, element) { + // If the linked element is not an anchor tag anymore, do nothing + if (element[0].nodeName.toLowerCase() !== 'a') return; // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute. var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ? @@ -19521,20 +22015,7 @@ var htmlAnchorDirective = valueFn({ * {@link guide/expression expression} inside `ngDisabled` evaluates to truthy. * * A special directive is necessary because we cannot use interpolation inside the `disabled` - * attribute. The following example would make the button enabled on Chrome/Firefox - * but not on older IEs: - * - * ```html - * - *
- * - *
- * ``` - * - * This is because the HTML specification does not require browsers to preserve the values of - * boolean attributes such as `disabled` (Their presence means true and their absence means false.) - * If we put an Angular interpolation expression into such an attribute then the - * binding information would be lost when the browser removes the attribute. + * attribute. See the {@link guide/interpolation interpolation guide} for more info. * * @example @@ -19564,13 +22045,14 @@ var htmlAnchorDirective = valueFn({ * @priority 100 * * @description - * The HTML specification does not require browsers to preserve the values of boolean attributes - * such as checked. (Their presence means true and their absence means false.) - * If we put an Angular interpolation expression into such an attribute then the - * binding information would be lost when the browser removes the attribute. - * The `ngChecked` directive solves this problem for the `checked` attribute. - * This complementary directive is not removed by the browser and so provides - * a permanent reliable place to store the binding information. + * Sets the `checked` attribute on the element, if the expression inside `ngChecked` is truthy. + * + * Note that this directive should not be used together with {@link ngModel `ngModel`}, + * as this can lead to unexpected behavior. + * + * A special directive is necessary because we cannot use interpolation inside the `checked` + * attribute. See the {@link guide/interpolation interpolation guide} for more info. + * * @example @@ -19588,7 +22070,7 @@ var htmlAnchorDirective = valueFn({ * * @element INPUT * @param {expression} ngChecked If the {@link guide/expression expression} is truthy, - * then special attribute "checked" will be set on the element + * then the `checked` attribute will be set on the element */ @@ -19599,13 +22081,14 @@ var htmlAnchorDirective = valueFn({ * @priority 100 * * @description - * The HTML specification does not require browsers to preserve the values of boolean attributes - * such as readonly. (Their presence means true and their absence means false.) - * If we put an Angular interpolation expression into such an attribute then the - * binding information would be lost when the browser removes the attribute. - * The `ngReadonly` directive solves this problem for the `readonly` attribute. - * This complementary directive is not removed by the browser and so provides - * a permanent reliable place to store the binding information. + * + * Sets the `readonly` attribute on the element, if the expression inside `ngReadonly` is truthy. + * Note that `readonly` applies only to `input` elements with specific types. [See the input docs on + * MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-readonly) for more information. + * + * A special directive is necessary because we cannot use interpolation inside the `readonly` + * attribute. See the {@link guide/interpolation interpolation guide} for more info. + * * @example @@ -19634,13 +22117,18 @@ var htmlAnchorDirective = valueFn({ * @priority 100 * * @description - * The HTML specification does not require browsers to preserve the values of boolean attributes - * such as selected. (Their presence means true and their absence means false.) - * If we put an Angular interpolation expression into such an attribute then the - * binding information would be lost when the browser removes the attribute. - * The `ngSelected` directive solves this problem for the `selected` attribute. - * This complementary directive is not removed by the browser and so provides - * a permanent reliable place to store the binding information. + * + * Sets the `selected` attribute on the element, if the expression inside `ngSelected` is truthy. + * + * A special directive is necessary because we cannot use interpolation inside the `selected` + * attribute. See the {@link guide/interpolation interpolation guide} for more info. + * + *
+ * **Note:** `ngSelected` does not interact with the `select` and `ngModel` directives, it only + * sets the `selected` attribute on the element. If you are using `ngModel` on the select, you + * should not use `ngSelected` on the options, as `ngModel` will set the select value and + * selected options. + *
* * @example @@ -19672,13 +22160,17 @@ var htmlAnchorDirective = valueFn({ * @priority 100 * * @description - * The HTML specification does not require browsers to preserve the values of boolean attributes - * such as open. (Their presence means true and their absence means false.) - * If we put an Angular interpolation expression into such an attribute then the - * binding information would be lost when the browser removes the attribute. - * The `ngOpen` directive solves this problem for the `open` attribute. - * This complementary directive is not removed by the browser and so provides - * a permanent reliable place to store the binding information. + * + * Sets the `open` attribute on the element, if the expression inside `ngOpen` is truthy. + * + * A special directive is necessary because we cannot use interpolation inside the `open` + * attribute. See the {@link guide/interpolation interpolation guide} for more info. + * + * ## A note about browser compatibility + * + * Edge, Firefox, and Internet Explorer do not support the `details` element, it is + * recommended to use {@link ng.ngShow} and {@link ng.ngHide} instead. + * * @example @@ -19822,6 +22314,7 @@ function nullFormRenameControl(control, name) { * @property {boolean} $dirty True if user has already interacted with the form. * @property {boolean} $valid True if all of the containing forms and controls are valid. * @property {boolean} $invalid True if at least one containing control or form is invalid. + * @property {boolean} $pending True if at least one containing control or form is pending. * @property {boolean} $submitted True if user has submitted the form even if its invalid. * * @property {Object} $error Is an object hash, containing references to controls or @@ -19861,8 +22354,6 @@ function FormController(element, attrs, $scope, $animate, $interpolate) { var form = this, controls = []; - var parentForm = form.$$parentForm = element.parent().controller('form') || nullFormCtrl; - // init state form.$error = {}; form.$$success = {}; @@ -19873,8 +22364,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) { form.$valid = true; form.$invalid = false; form.$submitted = false; - - parentForm.$addControl(form); + form.$$parentForm = nullFormCtrl; /** * @ngdoc method @@ -19913,11 +22403,23 @@ function FormController(element, attrs, $scope, $animate, $interpolate) { /** * @ngdoc method * @name form.FormController#$addControl + * @param {object} control control object, either a {@link form.FormController} or an + * {@link ngModel.NgModelController} * * @description - * Register a control with the form. + * Register a control with the form. Input elements using ngModelController do this automatically + * when they are linked. + * + * Note that the current state of the control will not be reflected on the new parent form. This + * is not an issue with normal use, as freshly compiled and linked controls are in a `$pristine` + * state. + * + * However, if the method is used programmatically, for example by adding dynamically created controls, + * or controls that have been previously removed without destroying their corresponding DOM element, + * it's the developers responsibility to make sure the current state propagates to the parent form. * - * Input elements using ngModelController do this automatically when they are linked. + * For example, if an input control is added that is already `$dirty` and has `$error` properties, + * calling `$setDirty()` and `$validate()` afterwards will propagate the state to the parent form. */ form.$addControl = function(control) { // Breaking change - before, inputs whose name was "hasOwnProperty" were quietly ignored @@ -19928,6 +22430,8 @@ function FormController(element, attrs, $scope, $animate, $interpolate) { if (control.$name) { form[control.$name] = control; } + + control.$$parentForm = form; }; // Private API: rename a form control @@ -19944,11 +22448,18 @@ function FormController(element, attrs, $scope, $animate, $interpolate) { /** * @ngdoc method * @name form.FormController#$removeControl + * @param {object} control control object, either a {@link form.FormController} or an + * {@link ngModel.NgModelController} * * @description * Deregister a control from the form. * * Input elements using ngModelController do this automatically when they are destroyed. + * + * Note that only the removed control's validation state (`$errors`etc.) will be removed from the + * form. `$dirty`, `$submitted` states will not be changed, because the expected behavior can be + * different from case to case. For example, removing the only `$dirty` control from a form may or + * may not mean that the form is still `$dirty`. */ form.$removeControl = function(control) { if (control.$name && form[control.$name] === control) { @@ -19965,6 +22476,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) { }); arrayRemove(controls, control); + control.$$parentForm = nullFormCtrl; }; @@ -20001,7 +22513,6 @@ function FormController(element, attrs, $scope, $animate, $interpolate) { delete object[property]; } }, - parentForm: parentForm, $animate: $animate }); @@ -20020,7 +22531,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) { $animate.addClass(element, DIRTY_CLASS); form.$dirty = true; form.$pristine = false; - parentForm.$setDirty(); + form.$$parentForm.$setDirty(); }; /** @@ -20076,7 +22587,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) { form.$setSubmitted = function() { $animate.addClass(element, SUBMITTED_CLASS); form.$submitted = true; - parentForm.$setSubmitted(); + form.$$parentForm.$setSubmitted(); }; } @@ -20115,17 +22626,14 @@ function FormController(element, attrs, $scope, $animate, $interpolate) { * * In Angular, forms can be nested. This means that the outer form is valid when all of the child * forms are valid as well. However, browsers do not allow nesting of `
` elements, so - * Angular provides the {@link ng.directive:ngForm `ngForm`} directive which behaves identically to - * `` but can be nested. This allows you to have nested forms, which is very useful when - * using Angular validation directives in forms that are dynamically generated using the - * {@link ng.directive:ngRepeat `ngRepeat`} directive. Since you cannot dynamically generate the `name` - * attribute of input elements using interpolation, you have to wrap each set of repeated inputs in an - * `ngForm` directive and nest these in an outer `form` element. - * + * Angular provides the {@link ng.directive:ngForm `ngForm`} directive, which behaves identically to + * `form` but can be nested. Nested forms can be useful, for example, if the validity of a sub-group + * of controls needs to be determined. * * # CSS classes * - `ng-valid` is set if the form is valid. * - `ng-invalid` is set if the form is invalid. + * - `ng-pending` is set if the form is pending. * - `ng-pristine` is set if the form is pristine. * - `ng-dirty` is set if the form is dirty. * - `ng-submitted` is set if the form was submitted. @@ -20201,7 +22709,6 @@ function FormController(element, attrs, $scope, $animate, $interpolate) { + *
+ *
+ *
+ * + * {{title}} + *

{{text}}

+ *
+ *
+ * + * + * angular.module('multiSlotTranscludeExample', []) + * .directive('pane', function(){ + * return { + * restrict: 'E', + * transclude: { + * 'title': '?paneTitle', + * 'body': 'paneBody', + * 'footer': '?paneFooter' + * }, + * template: '
' + + * '
Fallback Title
' + + * '
' + + * '' + + * '
' + * }; + * }) + * .controller('ExampleController', ['$scope', function($scope) { + * $scope.title = 'Lorem Ipsum'; + * $scope.link = "https://google.com"; + * $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...'; + * }]); + *
+ * + * it('should have transcluded the title and the body', function() { + * var titleElement = element(by.model('title')); + * titleElement.clear(); + * titleElement.sendKeys('TITLE'); + * var textElement = element(by.model('text')); + * textElement.clear(); + * textElement.sendKeys('TEXT'); + * expect(element(by.css('.title')).getText()).toEqual('TITLE'); + * expect(element(by.binding('text')).getText()).toEqual('TEXT'); + * expect(element(by.css('.footer')).getText()).toEqual('Fallback Footer'); + * }); + * + * */ -var ngTranscludeDirective = ngDirective({ - restrict: 'EAC', - link: function($scope, $element, $attrs, controller, $transclude) { - if (!$transclude) { - throw minErr('ngTransclude')('orphan', - 'Illegal use of ngTransclude directive in the template! ' + - 'No parent directive that requires a transclusion found. ' + - 'Element: {0}', - startingTag($element)); - } - - $transclude(function(clone) { - $element.empty(); - $element.append(clone); - }); - } -}); +var ngTranscludeMinErr = minErr('ngTransclude'); +var ngTranscludeDirective = ['$compile', function($compile) { + return { + restrict: 'EAC', + terminal: true, + compile: function ngTranscludeCompile(tElement) { + + // Remove and cache any original content to act as a fallback + var fallbackLinkFn = $compile(tElement.contents()); + tElement.empty(); + + return function ngTranscludePostLink($scope, $element, $attrs, controller, $transclude) { + + if (!$transclude) { + throw ngTranscludeMinErr('orphan', + 'Illegal use of ngTransclude directive in the template! ' + + 'No parent directive that requires a transclusion found. ' + + 'Element: {0}', + startingTag($element)); + } + + + // If the attribute is of the form: `ng-transclude="ng-transclude"` then treat it like the default + if ($attrs.ngTransclude === $attrs.$attr.ngTransclude) { + $attrs.ngTransclude = ''; + } + var slotName = $attrs.ngTransclude || $attrs.ngTranscludeSlot; + + // If the slot is required and no transclusion content is provided then this call will throw an error + $transclude(ngTranscludeCloneAttachFn, null, slotName); + + // If the slot is optional and no transclusion content is provided then use the fallback content + if (slotName && !$transclude.isSlotFilled(slotName)) { + useFallbackContent(); + } + + function ngTranscludeCloneAttachFn(clone, transcludedScope) { + if (clone.length) { + $element.append(clone); + } else { + useFallbackContent(); + // There is nothing linked against the transcluded scope since no content was available, + // so it should be safe to clean up the generated scope. + transcludedScope.$destroy(); + } + } + + function useFallbackContent() { + // Since this is the fallback content rather than the transcluded content, + // we link against the scope of this directive rather than the transcluded scope + fallbackLinkFn($scope, function(clone) { + $element.append(clone); + }); + } + }; + } + }; +}]; /** * @ngdoc directive @@ -27862,6 +30763,15 @@ var scriptDirective = ['$templateCache', function($templateCache) { var noopNgModelController = { $setViewValue: noop, $render: noop }; +function chromeHack(optionElement) { + // Workaround for https://code.google.com/p/chromium/issues/detail?id=381459 + // Adding an
* - * ### Example (binding `select` to a non-string value) + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} multiple Allows multiple options to be selected. The selected values will be + * bound to the model as an array. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds required attribute and required validation constraint to + * the element when the ngRequired expression evaluates to true. Use ngRequired instead of required + * when you want to data-bind to the required attribute. + * @param {string=} ngChange Angular expression to be executed when selected option(s) changes due to user + * interaction with the select element. + * @param {string=} ngOptions sets the options that the select is populated with and defines what is + * set on the model on selection. See {@link ngOptions `ngOptions`}. + * + * @example + * ### Simple `select` elements with static options + * + * + * + *
+ * + *
+ *
+ * + *
+ *
+ *
+ * singleSelect = {{data.singleSelect}} + * + *
+ *
+ *
+ * multipleSelect = {{data.multipleSelect}}
+ * + *
+ *
+ * + * angular.module('staticSelect', []) + * .controller('ExampleController', ['$scope', function($scope) { + * $scope.data = { + * singleSelect: null, + * multipleSelect: [], + * option1: 'option-1', + * }; + * + * $scope.forceUnknownOption = function() { + * $scope.data.singleSelect = 'nonsense'; + * }; + * }]); + * + *
+ * + * ### Using `ngRepeat` to generate `select` options + * + * + *
+ *
+ * + * + *
+ *
+ * repeatSelect = {{data.repeatSelect}}
+ *
+ *
+ * + * angular.module('ngrepeatSelect', []) + * .controller('ExampleController', ['$scope', function($scope) { + * $scope.data = { + * repeatSelect: null, + * availableOptions: [ + * {id: '1', name: 'Option A'}, + * {id: '2', name: 'Option B'}, + * {id: '3', name: 'Option C'} + * ], + * }; + * }]); + * + *
+ * + * + * ### Using `select` with `ngOptions` and setting a default value + * See the {@link ngOptions ngOptions documentation} for more `ngOptions` usage examples. + * + * + * + *
+ *
+ * + * + *
+ *
+ * option = {{data.selectedOption}}
+ *
+ *
+ * + * angular.module('defaultValueSelect', []) + * .controller('ExampleController', ['$scope', function($scope) { + * $scope.data = { + * availableOptions: [ + * {id: '1', name: 'Option A'}, + * {id: '2', name: 'Option B'}, + * {id: '3', name: 'Option C'} + * ], + * selectedOption: {id: '3', name: 'Option C'} //This sets the default value of the select in the ui + * }; + * }]); + * + *
+ * + * + * ### Binding `select` to a non-string value via `ngModel` parsing / formatting * * * @@ -28037,7 +31118,14 @@ var selectDirective = function() { restrict: 'E', require: ['select', '?ngModel'], controller: SelectController, - link: function(scope, element, attr, ctrls) { + priority: 1, + link: { + pre: selectPreLink, + post: selectPostLink + } + }; + + function selectPreLink(scope, element, attr, ctrls) { // if ngModel is not defined, we don't need to do anything var ngModelCtrl = ctrls[1]; @@ -28047,13 +31135,6 @@ var selectDirective = function() { selectCtrl.ngModelCtrl = ngModelCtrl; - // We delegate rendering to the `writeValue` method, which can be changed - // if the select can have multiple selected values or if the options are being - // generated by `ngOptions` - ngModelCtrl.$render = function() { - selectCtrl.writeValue(ngModelCtrl.$viewValue); - }; - // When the selected item(s) changes we delegate getting the value of the select control // to the `readValue` method, which can be changed if the select can have multiple // selected values or if the options are being generated by `ngOptions` @@ -28107,7 +31188,23 @@ var selectDirective = function() { } } - }; + + function selectPostLink(scope, element, attrs, ctrls) { + // if ngModel is not defined, we don't need to do anything + var ngModelCtrl = ctrls[1]; + if (!ngModelCtrl) return; + + var selectCtrl = ctrls[0]; + + // We delegate rendering to the `writeValue` method, which can be changed + // if the select can have multiple selected values or if the options are being + // generated by `ngOptions`. + // This must be done in the postLink fn to prevent $render to be called before + // all nodes have been linked correctly. + ngModelCtrl.$render = function() { + selectCtrl.writeValue(ngModelCtrl.$viewValue); + }; + } }; @@ -28115,32 +31212,23 @@ var selectDirective = function() { // of dynamically created (and destroyed) option elements to their containing select // directive via its controller. var optionDirective = ['$interpolate', function($interpolate) { - - function chromeHack(optionElement) { - // Workaround for https://code.google.com/p/chromium/issues/detail?id=381459 - // Adding an + * + var required = element(by.binding('form.input.$error.required')); + var model = element(by.binding('model')); + var input = element(by.id('input')); + + it('should set the required error', function() { + expect(required.getText()).toContain('true'); + + input.sendKeys('123'); + expect(required.getText()).not.toContain('true'); + expect(model.getText()).toContain('123'); + }); + * + * + */ var requiredDirective = function() { return { restrict: 'A', @@ -28202,7 +31327,81 @@ var requiredDirective = function() { }; }; +/** + * @ngdoc directive + * @name ngPattern + * + * @description + * + * ngPattern adds the pattern {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}. + * It is most often used for text-based {@link input `input`} controls, but can also be applied to custom text-based controls. + * + * The validator sets the `pattern` error key if the {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`} + * does not match a RegExp which is obtained by evaluating the Angular expression given in the + * `ngPattern` attribute value: + * * If the expression evaluates to a RegExp object, then this is used directly. + * * If the expression evaluates to a string, then it will be converted to a RegExp after wrapping it + * in `^` and `$` characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`. + * + *
+ * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to + * start at the index of the last search's match, thus not taking the whole input value into + * account. + *
+ * + *
+ * **Note:** This directive is also added when the plain `pattern` attribute is used, with two + * differences: + *
    + *
  1. + * `ngPattern` does not set the `pattern` attribute and therefore HTML5 constraint validation is + * not available. + *
  2. + *
  3. + * The `ngPattern` attribute must be an expression, while the `pattern` value must be + * interpolated. + *
  4. + *
+ *
+ * + * @example + * + * + * + *
+ *
+ * + * + *
+ * + *
+ *
+ * input valid? = {{form.input.$valid}}
+ * model = {{model}} + *
+ *
+ *
+ * + var model = element(by.binding('model')); + var input = element(by.id('input')); + + it('should validate the input with the default pattern', function() { + input.sendKeys('aaa'); + expect(model.getText()).not.toContain('aaa'); + input.clear().then(function() { + input.sendKeys('123'); + expect(model.getText()).toContain('123'); + }); + }); + * + *
+ */ var patternDirective = function() { return { restrict: 'A', @@ -28226,14 +31425,80 @@ var patternDirective = function() { ctrl.$validate(); }); - ctrl.$validators.pattern = function(value) { - return ctrl.$isEmpty(value) || isUndefined(regexp) || regexp.test(value); + ctrl.$validators.pattern = function(modelValue, viewValue) { + // HTML5 pattern constraint validates the input value, so we validate the viewValue + return ctrl.$isEmpty(viewValue) || isUndefined(regexp) || regexp.test(viewValue); }; } }; }; +/** + * @ngdoc directive + * @name ngMaxlength + * + * @description + * + * ngMaxlength adds the maxlength {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}. + * It is most often used for text-based {@link input `input`} controls, but can also be applied to custom text-based controls. + * + * The validator sets the `maxlength` error key if the {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`} + * is longer than the integer obtained by evaluating the Angular expression given in the + * `ngMaxlength` attribute value. + * + *
+ * **Note:** This directive is also added when the plain `maxlength` attribute is used, with two + * differences: + *
    + *
  1. + * `ngMaxlength` does not set the `maxlength` attribute and therefore HTML5 constraint + * validation is not available. + *
  2. + *
  3. + * The `ngMaxlength` attribute must be an expression, while the `maxlength` value must be + * interpolated. + *
  4. + *
+ *
+ * + * @example + * + * + * + *
+ *
+ * + * + *
+ * + *
+ *
+ * input valid? = {{form.input.$valid}}
+ * model = {{model}} + *
+ *
+ *
+ * + var model = element(by.binding('model')); + var input = element(by.id('input')); + + it('should validate the input with the default maxlength', function() { + input.sendKeys('abcdef'); + expect(model.getText()).not.toContain('abcdef'); + input.clear().then(function() { + input.sendKeys('abcde'); + expect(model.getText()).toContain('abcde'); + }); + }); + * + *
+ */ var maxlengthDirective = function() { return { restrict: 'A', @@ -28254,6 +31519,70 @@ var maxlengthDirective = function() { }; }; +/** + * @ngdoc directive + * @name ngMinlength + * + * @description + * + * ngMinlength adds the minlength {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}. + * It is most often used for text-based {@link input `input`} controls, but can also be applied to custom text-based controls. + * + * The validator sets the `minlength` error key if the {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`} + * is shorter than the integer obtained by evaluating the Angular expression given in the + * `ngMinlength` attribute value. + * + *
+ * **Note:** This directive is also added when the plain `minlength` attribute is used, with two + * differences: + *
    + *
  1. + * `ngMinlength` does not set the `minlength` attribute and therefore HTML5 constraint + * validation is not available. + *
  2. + *
  3. + * The `ngMinlength` value must be an expression, while the `minlength` value must be + * interpolated. + *
  4. + *
+ *
+ * + * @example + * + * + * + *
+ *
+ * + * + *
+ * + *
+ *
+ * input valid? = {{form.input.$valid}}
+ * model = {{model}} + *
+ *
+ *
+ * + var model = element(by.binding('model')); + var input = element(by.id('input')); + + it('should validate the input with the default minlength', function() { + input.sendKeys('ab'); + expect(model.getText()).not.toContain('ab'); + + input.sendKeys('abc'); + expect(model.getText()).toContain('abc'); + }); + * + *
+ */ var minlengthDirective = function() { return { restrict: 'A', @@ -28273,22 +31602,167 @@ var minlengthDirective = function() { }; }; - if (window.angular.bootstrap) { - //AngularJS is already loaded, so we can return here... +if (window.angular.bootstrap) { + //AngularJS is already loaded, so we can return here... + if (window.console) { console.log('WARNING: Tried to load angular more than once.'); - return; } + return; +} + +//try to bind to jquery now so that one can write jqLite(document).ready() +//but we will rebind on bootstrap again. +bindJQuery(); - //try to bind to jquery now so that one can write jqLite(document).ready() - //but we will rebind on bootstrap again. - bindJQuery(); +publishExternalAPI(angular); + +angular.module("ngLocale", [], ["$provide", function($provide) { +var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; +function getDecimals(n) { + n = n + ''; + var i = n.indexOf('.'); + return (i == -1) ? 0 : n.length - i - 1; +} + +function getVF(n, opt_precision) { + var v = opt_precision; + + if (undefined === v) { + v = Math.min(getDecimals(n), 3); + } - publishExternalAPI(angular); + var base = Math.pow(10, v); + var f = ((n * base) | 0) % base; + return {v: v, f: f}; +} + +$provide.value("$locale", { + "DATETIME_FORMATS": { + "AMPMS": [ + "AM", + "PM" + ], + "DAY": [ + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday" + ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], + "FIRSTDAYOFWEEK": 6, + "MONTH": [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December" + ], + "SHORTDAY": [ + "Sun", + "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat" + ], + "SHORTMONTH": [ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec" + ], + "STANDALONEMONTH": [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December" + ], + "WEEKENDRANGE": [ + 5, + 6 + ], + "fullDate": "EEEE, MMMM d, y", + "longDate": "MMMM d, y", + "medium": "MMM d, y h:mm:ss a", + "mediumDate": "MMM d, y", + "mediumTime": "h:mm:ss a", + "short": "M/d/yy h:mm a", + "shortDate": "M/d/yy", + "shortTime": "h:mm a" + }, + "NUMBER_FORMATS": { + "CURRENCY_SYM": "$", + "DECIMAL_SEP": ".", + "GROUP_SEP": ",", + "PATTERNS": [ + { + "gSize": 3, + "lgSize": 3, + "maxFrac": 3, + "minFrac": 0, + "minInt": 1, + "negPre": "-", + "negSuf": "", + "posPre": "", + "posSuf": "" + }, + { + "gSize": 3, + "lgSize": 3, + "maxFrac": 2, + "minFrac": 2, + "minInt": 1, + "negPre": "-\u00a4", + "negSuf": "", + "posPre": "\u00a4", + "posSuf": "" + } + ] + }, + "id": "en-us", + "localeID": "en_US", + "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;} +}); +}]); - jqLite(document).ready(function() { - angularInit(document, bootstrap); + jqLite(window.document).ready(function() { + angularInit(window.document, bootstrap); }); -})(window, document); +})(window); -!window.angular.$$csp() && window.angular.element(document).find('head').prepend(''); \ No newline at end of file +!window.angular.$$csp().noInlineStyle && window.angular.element(document.head).prepend(''); \ No newline at end of file diff --git a/ui/app/bower_components/angular/angular.min.js b/ui/app/bower_components/angular/angular.min.js index e48ac31..bf50a28 100644 --- a/ui/app/bower_components/angular/angular.min.js +++ b/ui/app/bower_components/angular/angular.min.js @@ -1,290 +1,318 @@ /* - AngularJS v1.4.1 - (c) 2010-2015 Google, Inc. http://angularjs.org + AngularJS v1.5.8 + (c) 2010-2016 Google, Inc. http://angularjs.org License: MIT */ -(function(O,W,s){'use strict';function I(b){return function(){var a=arguments[0],c;c="["+(b?b+":":"")+a+"] http://errors.angularjs.org/1.4.1/"+(b?b+"/":"")+a;for(a=1;a").append(b).html();try{return b[0].nodeType===Na?G(c):c.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/,function(a,b){return"<"+G(b)})}catch(d){return G(c)}}function xc(b){try{return decodeURIComponent(b)}catch(a){}}function yc(b){var a={},c,d;n((b||"").split("&"),function(b){b&&(c=b.replace(/\+/g,"%20").split("="),d=xc(c[0]),z(d)&&(b=z(c[1])?xc(c[1]):!0,Wa.call(a,d)?K(a[d])?a[d].push(b):a[d]=[a[d],b]:a[d]=b))});return a} -function Qb(b){var a=[];n(b,function(b,d){K(b)?n(b,function(b){a.push(ma(d,!0)+(!0===b?"":"="+ma(b,!0)))}):a.push(ma(d,!0)+(!0===b?"":"="+ma(b,!0)))});return a.length?a.join("&"):""}function nb(b){return ma(b,!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+")}function ma(b,a){return encodeURIComponent(b).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%3B/gi,";").replace(/%20/g,a?"%20":"+")}function Xd(b,a){var c,d,e=Oa.length;for(d=0;d< -e;++d)if(c=Oa[d]+a,L(c=b.getAttribute(c)))return c;return null}function Yd(b,a){var c,d,e={};n(Oa,function(a){a+="app";!c&&b.hasAttribute&&b.hasAttribute(a)&&(c=b,d=b.getAttribute(a))});n(Oa,function(a){a+="app";var e;!c&&(e=b.querySelector("["+a.replace(":","\\:")+"]"))&&(c=e,d=e.getAttribute(a))});c&&(e.strictDi=null!==Xd(c,"strict-di"),a(c,d?[d]:[],e))}function zc(b,a,c){F(c)||(c={});c=Q({strictDi:!1},c);var d=function(){b=A(b);if(b.injector()){var d=b[0]===W?"document":va(b);throw Ea("btstrpd", -d.replace(//,">"));}a=a||[];a.unshift(["$provide",function(a){a.value("$rootElement",b)}]);c.debugInfoEnabled&&a.push(["$compileProvider",function(a){a.debugInfoEnabled(!0)}]);a.unshift("ng");d=db(a,c.strictDi);d.invoke(["$rootScope","$rootElement","$compile","$injector",function(a,b,c,d){a.$apply(function(){b.data("$injector",d);c(b)(a)})}]);return d},e=/^NG_ENABLE_DEBUG_INFO!/,f=/^NG_DEFER_BOOTSTRAP!/;O&&e.test(O.name)&&(c.debugInfoEnabled=!0,O.name=O.name.replace(e,"")); -if(O&&!f.test(O.name))return d();O.name=O.name.replace(f,"");$.resumeBootstrap=function(b){n(b,function(b){a.push(b)});return d()};E($.resumeDeferredBootstrap)&&$.resumeDeferredBootstrap()}function Zd(){O.name="NG_ENABLE_DEBUG_INFO!"+O.name;O.location.reload()}function $d(b){b=$.element(b).injector();if(!b)throw Ea("test");return b.get("$$testability")}function Ac(b,a){a=a||"_";return b.replace(ae,function(b,d){return(d?a:"")+b.toLowerCase()})}function be(){var b;if(!Bc){var a=ob();la=O.jQuery;z(a)&& -(la=null===a?s:O[a]);la&&la.fn.on?(A=la,Q(la.fn,{scope:Pa.scope,isolateScope:Pa.isolateScope,controller:Pa.controller,injector:Pa.injector,inheritedData:Pa.inheritedData}),b=la.cleanData,la.cleanData=function(a){var d;if(Rb)Rb=!1;else for(var e=0,f;null!=(f=a[e]);e++)(d=la._data(f,"events"))&&d.$destroy&&la(f).triggerHandler("$destroy");b(a)}):A=R;$.element=A;Bc=!0}}function Sb(b,a,c){if(!b)throw Ea("areq",a||"?",c||"required");return b}function Qa(b,a,c){c&&K(b)&&(b=b[b.length-1]);Sb(E(b),a,"not a function, got "+ -(b&&"object"===typeof b?b.constructor.name||"Object":typeof b));return b}function Ra(b,a){if("hasOwnProperty"===b)throw Ea("badname",a);}function Cc(b,a,c){if(!a)return b;a=a.split(".");for(var d,e=b,f=a.length,g=0;g")+ -d[2];for(d=d[0];d--;)c=c.lastChild;f=bb(f,c.childNodes);c=e.firstChild;c.textContent=""}else f.push(a.createTextNode(b));e.textContent="";e.innerHTML="";n(f,function(a){e.appendChild(a)});return e}function R(b){if(b instanceof R)return b;var a;L(b)&&(b=T(b),a=!0);if(!(this instanceof R)){if(a&&"<"!=b.charAt(0))throw Ub("nosel");return new R(b)}if(a){a=W;var c;b=(c=Cf.exec(b))?[a.createElement(c[1])]:(c=Mc(b,a))?c.childNodes:[]}Nc(this,b)}function Vb(b){return b.cloneNode(!0)}function sb(b,a){a||tb(b); -if(b.querySelectorAll)for(var c=b.querySelectorAll("*"),d=0,e=c.length;dk&&this.remove(t.key);return b}},get:function(a){if(k").parent()[0])});var f=P(a,b,a,c,d,e);S.$$addScopeClass(a); -var g=null;return function(b,c,d){Sb(b,"scope");d=d||{};var e=d.parentBoundTranscludeFn,h=d.transcludeControllers;d=d.futureParentElement;e&&e.$$boundTransclude&&(e=e.$$boundTransclude);g||(g=(d=d&&d[0])?"foreignobject"!==ua(d)&&d.toString().match(/SVG/)?"svg":"html":"html");d="html"!==g?A(Yb(g,A("
").append(a).html())):c?Pa.clone.call(a):a;if(h)for(var l in h)d.data("$"+l+"Controller",h[l].instance);S.$$addScopeInfo(d,b);c&&c(d,b);f&&f(b,d,d,e);return d}}function P(a,b,c,d,e,f){function g(a, -c,d,e){var f,l,k,m,t,B,y;if(p)for(y=Array(c.length),m=0;mJ.priority)break;if(w=J.scope)J.templateUrl||(F(w)?(O("new/isolated scope",u||ba, -J,aa),u=J):O("new/isolated scope",u,J,aa)),ba=ba||J;v=J.name;!J.templateUrl&&J.controller&&(w=J.controller,M=M||ga(),O("'"+v+"' controller",M[v],J,aa),M[v]=J);if(w=J.transclude)x=!0,J.$$tlb||(O("transclusion",n,J,aa),n=J),"element"==w?(r=!0,P=J.priority,w=aa,aa=d.$$element=A(W.createComment(" "+v+": "+d[v]+" ")),b=aa[0],U(f,sa.call(w,0),b),Ja=S(w,e,P,g&&g.name,{nonTlbTranscludeDirective:n})):(w=A(Vb(b)).contents(),aa.empty(),Ja=S(w,e));if(J.template)if(H=!0,O("template",D,J,aa),D=J,w=E(J.template)? -J.template(aa,d):J.template,w=fa(w),J.replace){g=J;w=Tb.test(w)?Zc(Yb(J.templateNamespace,T(w))):[];b=w[0];if(1!=w.length||b.nodeType!==qa)throw ea("tplrt",v,"");U(f,aa,b);G={$attr:{}};w=ha(b,[],G);var R=a.splice(I+1,a.length-(I+1));u&&z(w);a=a.concat(w).concat(R);$c(d,G);G=a.length}else aa.html(w);if(J.templateUrl)H=!0,O("template",D,J,aa),D=J,J.replace&&(g=J),N=Kf(a.splice(I,a.length-I),aa,d,f,x&&Ja,h,k,{controllerDirectives:M,newIsolateScopeDirective:u,templateDirective:D,nonTlbTranscludeDirective:n}), -G=a.length;else if(J.compile)try{za=J.compile(aa,d,Ja),E(za)?t(null,za,Ab,Q):za&&t(za.pre,za.post,Ab,Q)}catch(V){c(V,va(aa))}J.terminal&&(N.terminal=!0,P=Math.max(P,J.priority))}N.scope=ba&&!0===ba.scope;N.transcludeOnThisElement=x;N.templateOnThisElement=H;N.transclude=Ja;m.hasElementTranscludeDirective=r;return N}function z(a){for(var b=0,c=a.length;bm.priority)&&-1!=m.restrict.indexOf(f)&&(l&&(m=Ob(m,{$$start:l,$$end:k})),b.push(m),h=m)}catch(y){c(y)}}return h}function I(b){if(e.hasOwnProperty(b))for(var c=a.get(b+"Directive"),d=0,f=c.length;d"+b+"";return c.childNodes[0].childNodes;default:return b}}function R(a,b){if("srcdoc"==b)return H.HTML;var c=ua(a);if("xlinkHref"==b||"form"==c&&"action"==b||"img"!=c&&("src"==b|| -"ngSrc"==b))return H.RESOURCE_URL}function V(a,c,d,e,f){var g=R(a,e);f=h[e]||f;var l=b(d,!0,g,f);if(l){if("multiple"===e&&"select"===ua(a))throw ea("selmulti",va(a));c.push({priority:100,compile:function(){return{pre:function(a,c,h){c=h.$$observers||(h.$$observers={});if(k.test(e))throw ea("nodomevents");var m=h[e];m!==d&&(l=m&&b(m,!0,g,f),d=m);l&&(h[e]=l(a),(c[e]||(c[e]=[])).$$inter=!0,(h.$$observers&&h.$$observers[e].$$scope||a).$watch(l,function(a,b){"class"===e&&a!=b?h.$updateClass(a,b):h.$set(e, -a)}))}}}})}}function U(a,b,c){var d=b[0],e=b.length,f=d.parentNode,g,h;if(a)for(g=0,h=a.length;g=a)return b;for(;a--;)8=== -b[a].nodeType&&Lf.call(b,a,1);return b}function We(){var b={},a=!1;this.register=function(a,d){Ra(a,"controller");F(a)?Q(b,a):b[a]=d};this.allowGlobals=function(){a=!0};this.$get=["$injector","$window",function(c,d){function e(a,b,c,d){if(!a||!F(a.$scope))throw I("$controller")("noscp",d,b);a.$scope[b]=c}return function(f,g,h,l){var k,m,q;h=!0===h;l&&L(l)&&(q=l);if(L(f)){l=f.match(Wc);if(!l)throw Mf("ctrlfmt",f);m=l[1];q=q||l[3];f=b.hasOwnProperty(m)?b[m]:Cc(g.$scope,m,!0)||(a?Cc(d,m,!0):s);Qa(f, -m,!0)}if(h)return h=(K(f)?f[f.length-1]:f).prototype,k=Object.create(h||null),q&&e(g,q,k,m||f.name),Q(function(){var a=c.invoke(f,k,g,m);a!==k&&(F(a)||E(a))&&(k=a,q&&e(g,q,k,m||f.name));return k},{instance:k,identifier:q});k=c.instantiate(f,g,m);q&&e(g,q,k,m||f.name);return k}}]}function Xe(){this.$get=["$window",function(b){return A(b.document)}]}function Ye(){this.$get=["$log",function(b){return function(a,c){b.error.apply(b,arguments)}}]}function Zb(b){return F(b)?da(b)?b.toISOString():cb(b):b} -function bf(){this.$get=function(){return function(b){if(!b)return"";var a=[];oc(b,function(b,d){null===b||w(b)||(K(b)?n(b,function(b,c){a.push(ma(d)+"="+ma(Zb(b)))}):a.push(ma(d)+"="+ma(Zb(b))))});return a.join("&")}}}function cf(){this.$get=function(){return function(b){function a(b,e,f){null===b||w(b)||(K(b)?n(b,function(b){a(b,e+"[]")}):F(b)&&!da(b)?oc(b,function(b,c){a(b,e+(f?"":"[")+c+(f?"":"]"))}):c.push(ma(e)+"="+ma(Zb(b))))}if(!b)return"";var c=[];a(b,"",!0);return c.join("&")}}}function $b(b, -a){if(L(b)){var c=b.replace(Nf,"").trim();if(c){var d=a("Content-Type");(d=d&&0===d.indexOf(bd))||(d=(d=c.match(Of))&&Pf[d[0]].test(c));d&&(b=vc(c))}}return b}function cd(b){var a=ga(),c;L(b)?n(b.split("\n"),function(b){c=b.indexOf(":");var e=G(T(b.substr(0,c)));b=T(b.substr(c+1));e&&(a[e]=a[e]?a[e]+", "+b:b)}):F(b)&&n(b,function(b,c){var f=G(c),g=T(b);f&&(a[f]=a[f]?a[f]+", "+g:g)});return a}function dd(b){var a;return function(c){a||(a=cd(b));return c?(c=a[G(c)],void 0===c&&(c=null),c):a}}function ed(b, -a,c,d){if(E(d))return d(b,a,c);n(d,function(d){b=d(b,a,c)});return b}function af(){var b=this.defaults={transformResponse:[$b],transformRequest:[function(a){return F(a)&&"[object File]"!==ta.call(a)&&"[object Blob]"!==ta.call(a)&&"[object FormData]"!==ta.call(a)?cb(a):a}],headers:{common:{Accept:"application/json, text/plain, */*"},post:ia(ac),put:ia(ac),patch:ia(ac)},xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",paramSerializer:"$httpParamSerializer"},a=!1;this.useApplyAsync=function(b){return z(b)? -(a=!!b,this):a};var c=this.interceptors=[];this.$get=["$httpBackend","$$cookieReader","$cacheFactory","$rootScope","$q","$injector",function(d,e,f,g,h,l){function k(a){function c(a){var b=Q({},a);b.data=a.data?ed(a.data,a.headers,a.status,e.transformResponse):a.data;a=a.status;return 200<=a&&300>a?b:h.reject(b)}function d(a,b){var c,e={};n(a,function(a,d){E(a)?(c=a(b),null!=c&&(e[d]=c)):e[d]=a});return e}if(!$.isObject(a))throw I("$http")("badreq",a);var e=Q({method:"get",transformRequest:b.transformRequest, -transformResponse:b.transformResponse,paramSerializer:b.paramSerializer},a);e.headers=function(a){var c=b.headers,e=Q({},a.headers),f,g,h,c=Q({},c.common,c[G(a.method)]);a:for(f in c){g=G(f);for(h in e)if(G(h)===g)continue a;e[f]=c[f]}return d(e,ia(a))}(a);e.method=qb(e.method);e.paramSerializer=L(e.paramSerializer)?l.get(e.paramSerializer):e.paramSerializer;var f=[function(a){var d=a.headers,e=ed(a.data,dd(d),s,a.transformRequest);w(e)&&n(d,function(a,b){"content-type"===G(b)&&delete d[b]});w(a.withCredentials)&& -!w(b.withCredentials)&&(a.withCredentials=b.withCredentials);return m(a,e).then(c,c)},s],g=h.when(e);for(n(y,function(a){(a.request||a.requestError)&&f.unshift(a.request,a.requestError);(a.response||a.responseError)&&f.push(a.response,a.responseError)});f.length;){a=f.shift();var k=f.shift(),g=g.then(a,k)}g.success=function(a){Qa(a,"fn");g.then(function(b){a(b.data,b.status,b.headers,e)});return g};g.error=function(a){Qa(a,"fn");g.then(null,function(b){a(b.data,b.status,b.headers,e)});return g};return g} -function m(c,f){function l(b,c,d,e){function f(){m(c,b,d,e)}M&&(200<=b&&300>b?M.put(P,[b,c,cd(d),e]):M.remove(P));a?g.$applyAsync(f):(f(),g.$$phase||g.$apply())}function m(a,b,d,e){b=Math.max(b,0);(200<=b&&300>b?H.resolve:H.reject)({data:a,status:b,headers:dd(d),config:c,statusText:e})}function y(a){m(a.data,a.status,ia(a.headers()),a.statusText)}function n(){var a=k.pendingRequests.indexOf(c);-1!==a&&k.pendingRequests.splice(a,1)}var H=h.defer(),B=H.promise,M,D,S=c.headers,P=q(c.url,c.paramSerializer(c.params)); -k.pendingRequests.push(c);B.then(n,n);!c.cache&&!b.cache||!1===c.cache||"GET"!==c.method&&"JSONP"!==c.method||(M=F(c.cache)?c.cache:F(b.cache)?b.cache:t);M&&(D=M.get(P),z(D)?D&&E(D.then)?D.then(y,y):K(D)?m(D[1],D[0],ia(D[2]),D[3]):m(D,200,{},"OK"):M.put(P,B));w(D)&&((D=fd(c.url)?e()[c.xsrfCookieName||b.xsrfCookieName]:s)&&(S[c.xsrfHeaderName||b.xsrfHeaderName]=D),d(c.method,P,f,l,S,c.timeout,c.withCredentials,c.responseType));return B}function q(a,b){0=l&&(u.resolve(C),y(p.$$intervalId),delete f[p.$$intervalId]);N||b.$apply()},h);f[p.$$intervalId]=u;return p}var f={};e.cancel=function(b){return b&&b.$$intervalId in f?(f[b.$$intervalId].reject("canceled"),a.clearInterval(b.$$intervalId),delete f[b.$$intervalId],!0):!1};return e}]}function fe(){this.$get=function(){return{id:"en-us",NUMBER_FORMATS:{DECIMAL_SEP:".", -GROUP_SEP:",",PATTERNS:[{minInt:1,minFrac:0,maxFrac:3,posPre:"",posSuf:"",negPre:"-",negSuf:"",gSize:3,lgSize:3},{minInt:1,minFrac:2,maxFrac:2,posPre:"\u00a4",posSuf:"",negPre:"(\u00a4",negSuf:")",gSize:3,lgSize:3}],CURRENCY_SYM:"$"},DATETIME_FORMATS:{MONTH:"January February March April May June July August September October November December".split(" "),SHORTMONTH:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),DAY:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "), -SHORTDAY:"Sun Mon Tue Wed Thu Fri Sat".split(" "),AMPMS:["AM","PM"],medium:"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a",fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",mediumDate:"MMM d, y",shortDate:"M/d/yy",mediumTime:"h:mm:ss a",shortTime:"h:mm a",ERANAMES:["Before Christ","Anno Domini"],ERAS:["BC","AD"]},pluralCat:function(b){return 1===b?"one":"other"}}}}function bc(b){b=b.split("/");for(var a=b.length;a--;)b[a]=nb(b[a]);return b.join("/")}function gd(b,a){var c=Aa(b);a.$$protocol=c.protocol; -a.$$host=c.hostname;a.$$port=X(c.port)||Sf[c.protocol]||null}function hd(b,a){var c="/"!==b.charAt(0);c&&(b="/"+b);var d=Aa(b);a.$$path=decodeURIComponent(c&&"/"===d.pathname.charAt(0)?d.pathname.substring(1):d.pathname);a.$$search=yc(d.search);a.$$hash=decodeURIComponent(d.hash);a.$$path&&"/"!=a.$$path.charAt(0)&&(a.$$path="/"+a.$$path)}function ya(b,a){if(0===a.indexOf(b))return a.substr(b.length)}function Ia(b){var a=b.indexOf("#");return-1==a?b:b.substr(0,a)}function Bb(b){return b.replace(/(#.+)|#$/, -"$1")}function cc(b){return b.substr(0,Ia(b).lastIndexOf("/")+1)}function dc(b,a){this.$$html5=!0;a=a||"";var c=cc(b);gd(b,this);this.$$parse=function(a){var b=ya(c,a);if(!L(b))throw Cb("ipthprfx",a,c);hd(b,this);this.$$path||(this.$$path="/");this.$$compose()};this.$$compose=function(){var a=Qb(this.$$search),b=this.$$hash?"#"+nb(this.$$hash):"";this.$$url=bc(this.$$path)+(a?"?"+a:"")+b;this.$$absUrl=c+this.$$url.substr(1)};this.$$parseLinkUrl=function(d,e){if(e&&"#"===e[0])return this.hash(e.slice(1)), -!0;var f,g;(f=ya(b,d))!==s?(g=f,g=(f=ya(a,f))!==s?c+(ya("/",f)||f):b+g):(f=ya(c,d))!==s?g=c+f:c==d+"/"&&(g=c);g&&this.$$parse(g);return!!g}}function ec(b,a){var c=cc(b);gd(b,this);this.$$parse=function(d){d=ya(b,d)||ya(c,d);var e;"#"===d.charAt(0)?(e=ya(a,d),w(e)&&(e=d)):e=this.$$html5?d:"";hd(e,this);d=this.$$path;var f=/^\/[A-Z]:(\/.*)/;0===e.indexOf(b)&&(e=e.replace(b,""));f.exec(e)||(d=(e=f.exec(d))?e[1]:d);this.$$path=d;this.$$compose()};this.$$compose=function(){var c=Qb(this.$$search),e=this.$$hash? -"#"+nb(this.$$hash):"";this.$$url=bc(this.$$path)+(c?"?"+c:"")+e;this.$$absUrl=b+(this.$$url?a+this.$$url:"")};this.$$parseLinkUrl=function(a,c){return Ia(b)==Ia(a)?(this.$$parse(a),!0):!1}}function id(b,a){this.$$html5=!0;ec.apply(this,arguments);var c=cc(b);this.$$parseLinkUrl=function(d,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),!0;var f,g;b==Ia(d)?f=d:(g=ya(c,d))?f=b+a+g:c===d+"/"&&(f=c);f&&this.$$parse(f);return!!f};this.$$compose=function(){var c=Qb(this.$$search),e=this.$$hash?"#"+nb(this.$$hash): -"";this.$$url=bc(this.$$path)+(c?"?"+c:"")+e;this.$$absUrl=b+a+this.$$url}}function Db(b){return function(){return this[b]}}function jd(b,a){return function(c){if(w(c))return this[b];this[b]=a(c);this.$$compose();return this}}function ef(){var b="",a={enabled:!1,requireBase:!0,rewriteLinks:!0};this.hashPrefix=function(a){return z(a)?(b=a,this):b};this.html5Mode=function(b){return $a(b)?(a.enabled=b,this):F(b)?($a(b.enabled)&&(a.enabled=b.enabled),$a(b.requireBase)&&(a.requireBase=b.requireBase),$a(b.rewriteLinks)&& -(a.rewriteLinks=b.rewriteLinks),this):a};this.$get=["$rootScope","$browser","$sniffer","$rootElement","$window",function(c,d,e,f,g){function h(a,b,c){var e=k.url(),f=k.$$state;try{d.url(a,b,c),k.$$state=d.state()}catch(g){throw k.url(e),k.$$state=f,g;}}function l(a,b){c.$broadcast("$locationChangeSuccess",k.absUrl(),a,k.$$state,b)}var k,m;m=d.baseHref();var q=d.url(),t;if(a.enabled){if(!m&&a.requireBase)throw Cb("nobase");t=q.substring(0,q.indexOf("/",q.indexOf("//")+2))+(m||"/");m=e.history?dc:id}else t= -Ia(q),m=ec;k=new m(t,"#"+b);k.$$parseLinkUrl(q,q);k.$$state=d.state();var y=/^\s*(javascript|mailto):/i;f.on("click",function(b){if(a.rewriteLinks&&!b.ctrlKey&&!b.metaKey&&!b.shiftKey&&2!=b.which&&2!=b.button){for(var e=A(b.target);"a"!==ua(e[0]);)if(e[0]===f[0]||!(e=e.parent())[0])return;var h=e.prop("href"),l=e.attr("href")||e.attr("xlink:href");F(h)&&"[object SVGAnimatedString]"===h.toString()&&(h=Aa(h.animVal).href);y.test(h)||!h||e.attr("target")||b.isDefaultPrevented()||!k.$$parseLinkUrl(h, -l)||(b.preventDefault(),k.absUrl()!=d.url()&&(c.$apply(),g.angular["ff-684208-preventDefault"]=!0))}});Bb(k.absUrl())!=Bb(q)&&d.url(k.absUrl(),!0);var C=!0;d.onUrlChange(function(a,b){c.$evalAsync(function(){var d=k.absUrl(),e=k.$$state,f;k.$$parse(a);k.$$state=b;f=c.$broadcast("$locationChangeStart",a,d,b,e).defaultPrevented;k.absUrl()===a&&(f?(k.$$parse(d),k.$$state=e,h(d,!1,e)):(C=!1,l(d,e)))});c.$$phase||c.$digest()});c.$watch(function(){var a=Bb(d.url()),b=Bb(k.absUrl()),f=d.state(),g=k.$$replace, -m=a!==b||k.$$html5&&e.history&&f!==k.$$state;if(C||m)C=!1,c.$evalAsync(function(){var b=k.absUrl(),d=c.$broadcast("$locationChangeStart",b,a,k.$$state,f).defaultPrevented;k.absUrl()===b&&(d?(k.$$parse(a),k.$$state=f):(m&&h(b,g,f===k.$$state?null:k.$$state),l(a,f)))});k.$$replace=!1});return k}]}function ff(){var b=!0,a=this;this.debugEnabled=function(a){return z(a)?(b=a,this):b};this.$get=["$window",function(c){function d(a){a instanceof Error&&(a.stack?a=a.message&&-1===a.stack.indexOf(a.message)? -"Error: "+a.message+"\n"+a.stack:a.stack:a.sourceURL&&(a=a.message+"\n"+a.sourceURL+":"+a.line));return a}function e(a){var b=c.console||{},e=b[a]||b.log||v;a=!1;try{a=!!e.apply}catch(l){}return a?function(){var a=[];n(arguments,function(b){a.push(d(b))});return e.apply(b,a)}:function(a,b){e(a,null==b?"":b)}}return{log:e("log"),info:e("info"),warn:e("warn"),error:e("error"),debug:function(){var c=e("debug");return function(){b&&c.apply(a,arguments)}}()}}]}function Ba(b,a){if("__defineGetter__"=== -b||"__defineSetter__"===b||"__lookupGetter__"===b||"__lookupSetter__"===b||"__proto__"===b)throw ca("isecfld",a);return b}function oa(b,a){if(b){if(b.constructor===b)throw ca("isecfn",a);if(b.window===b)throw ca("isecwindow",a);if(b.children&&(b.nodeName||b.prop&&b.attr&&b.find))throw ca("isecdom",a);if(b===Object)throw ca("isecobj",a);}return b}function kd(b,a){if(b){if(b.constructor===b)throw ca("isecfn",a);if(b===Tf||b===Uf||b===Vf)throw ca("isecff",a);}}function Wf(b,a){return"undefined"!==typeof b? -b:a}function ld(b,a){return"undefined"===typeof b?a:"undefined"===typeof a?b:b+a}function U(b,a){var c,d;switch(b.type){case r.Program:c=!0;n(b.body,function(b){U(b.expression,a);c=c&&b.expression.constant});b.constant=c;break;case r.Literal:b.constant=!0;b.toWatch=[];break;case r.UnaryExpression:U(b.argument,a);b.constant=b.argument.constant;b.toWatch=b.argument.toWatch;break;case r.BinaryExpression:U(b.left,a);U(b.right,a);b.constant=b.left.constant&&b.right.constant;b.toWatch=b.left.toWatch.concat(b.right.toWatch); -break;case r.LogicalExpression:U(b.left,a);U(b.right,a);b.constant=b.left.constant&&b.right.constant;b.toWatch=b.constant?[]:[b];break;case r.ConditionalExpression:U(b.test,a);U(b.alternate,a);U(b.consequent,a);b.constant=b.test.constant&&b.alternate.constant&&b.consequent.constant;b.toWatch=b.constant?[]:[b];break;case r.Identifier:b.constant=!1;b.toWatch=[b];break;case r.MemberExpression:U(b.object,a);b.computed&&U(b.property,a);b.constant=b.object.constant&&(!b.computed||b.property.constant);b.toWatch= -[b];break;case r.CallExpression:c=b.filter?!a(b.callee.name).$stateful:!1;d=[];n(b.arguments,function(b){U(b,a);c=c&&b.constant;b.constant||d.push.apply(d,b.toWatch)});b.constant=c;b.toWatch=b.filter&&!a(b.callee.name).$stateful?d:[b];break;case r.AssignmentExpression:U(b.left,a);U(b.right,a);b.constant=b.left.constant&&b.right.constant;b.toWatch=[b];break;case r.ArrayExpression:c=!0;d=[];n(b.elements,function(b){U(b,a);c=c&&b.constant;b.constant||d.push.apply(d,b.toWatch)});b.constant=c;b.toWatch= -d;break;case r.ObjectExpression:c=!0;d=[];n(b.properties,function(b){U(b.value,a);c=c&&b.value.constant;b.value.constant||d.push.apply(d,b.value.toWatch)});b.constant=c;b.toWatch=d;break;case r.ThisExpression:b.constant=!1,b.toWatch=[]}}function md(b){if(1==b.length){b=b[0].expression;var a=b.toWatch;return 1!==a.length?a:a[0]!==b?a:s}}function nd(b){return b.type===r.Identifier||b.type===r.MemberExpression}function od(b){if(1===b.body.length&&nd(b.body[0].expression))return{type:r.AssignmentExpression, -left:b.body[0].expression,right:{type:r.NGValueParameter},operator:"="}}function pd(b){return 0===b.body.length||1===b.body.length&&(b.body[0].expression.type===r.Literal||b.body[0].expression.type===r.ArrayExpression||b.body[0].expression.type===r.ObjectExpression)}function qd(b,a){this.astBuilder=b;this.$filter=a}function rd(b,a){this.astBuilder=b;this.$filter=a}function Eb(b,a,c,d){oa(b,d);a=a.split(".");for(var e,f=0;1=this.promise.$$state.status&&d&&d.length&&b(function(){for(var b,e,f=0,g=d.length;fa)for(b in k++,f)e.hasOwnProperty(b)||(n--,delete f[b])}else f!==e&&(f=e,k++);return k}}c.$stateful=!0;var d=this,e,f,g,l=1< -b.length,k=0,m=h(a,c),q=[],t={},p=!0,n=0;return this.$watch(m,function(){p?(p=!1,b(e,e,d)):b(e,g,d);if(l)if(F(e))if(Da(e)){g=Array(e.length);for(var a=0;an&&(H=4-n,u[H]||(u[H]=[]),u[H].push({msg:E(b.exp)?"fn: "+(b.exp.name||b.exp.toString()):b.exp,newVal:f,oldVal:h}));else if(b===d){t=!1;break a}}catch(A){g(A)}if(!(k=y.$$watchersCount&&y.$$childHead||y!==this&&y.$$nextSibling))for(;y!==this&&!(k=y.$$nextSibling);)y=y.$parent}while(y=k);if((t||x.length)&&!n--)throw p.$$phase= -null,c("infdig",a,u);}while(t||x.length);for(p.$$phase=null;z.length;)try{z.shift()()}catch(F){g(F)}},$destroy:function(){if(!this.$$destroyed){var a=this.$parent;this.$broadcast("$destroy");this.$$destroyed=!0;this===p&&l.$$applicationDestroyed();t(this,-this.$$watchersCount);for(var b in this.$$listenerCount)y(this,this.$$listenerCount[b],b);a&&a.$$childHead==this&&(a.$$childHead=this.$$nextSibling);a&&a.$$childTail==this&&(a.$$childTail=this.$$prevSibling);this.$$prevSibling&&(this.$$prevSibling.$$nextSibling= -this.$$nextSibling);this.$$nextSibling&&(this.$$nextSibling.$$prevSibling=this.$$prevSibling);this.$destroy=this.$digest=this.$apply=this.$evalAsync=this.$applyAsync=v;this.$on=this.$watch=this.$watchGroup=function(){return v};this.$$listeners={};this.$parent=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=this.$root=this.$$watchers=null}},$eval:function(a,b){return h(a)(this,b)},$evalAsync:function(a,b){p.$$phase||x.length||l.defer(function(){x.length&&p.$digest()});x.push({scope:this, -expression:a,locals:b})},$$postDigest:function(a){z.push(a)},$apply:function(a){try{return q("$apply"),this.$eval(a)}catch(b){g(b)}finally{p.$$phase=null;try{p.$digest()}catch(c){throw g(c),c;}}},$applyAsync:function(a){function b(){c.$eval(a)}var c=this;a&&H.push(b);u()},$on:function(a,b){var c=this.$$listeners[a];c||(this.$$listeners[a]=c=[]);c.push(b);var d=this;do d.$$listenerCount[a]||(d.$$listenerCount[a]=0),d.$$listenerCount[a]++;while(d=d.$parent);var e=this;return function(){var d=c.indexOf(b); --1!==d&&(c[d]=null,y(e,1,a))}},$emit:function(a,b){var c=[],d,e=this,f=!1,h={name:a,targetScope:e,stopPropagation:function(){f=!0},preventDefault:function(){h.defaultPrevented=!0},defaultPrevented:!1},l=bb([h],arguments,1),k,m;do{d=e.$$listeners[a]||c;h.currentScope=e;k=0;for(m=d.length;kTa)throw Ca("iequirks");var d=ia(pa);d.isEnabled=function(){return b};d.trustAs=c.trustAs;d.getTrusted=c.getTrusted;d.valueOf=c.valueOf;b||(d.trustAs=d.getTrusted=function(a,b){return b},d.valueOf=Xa);d.parseAs=function(b,c){var e=a(c);return e.literal&&e.constant?e:a(c,function(a){return d.getTrusted(b, -a)})};var e=d.parseAs,f=d.getTrusted,g=d.trustAs;n(pa,function(a,b){var c=G(b);d[gb("parse_as_"+c)]=function(b){return e(a,b)};d[gb("get_trusted_"+c)]=function(b){return f(a,b)};d[gb("trust_as_"+c)]=function(b){return g(a,b)}});return d}]}function nf(){this.$get=["$window","$document",function(b,a){var c={},d=X((/android (\d+)/.exec(G((b.navigator||{}).userAgent))||[])[1]),e=/Boxee/i.test((b.navigator||{}).userAgent),f=a[0]||{},g,h=/^(Moz|webkit|ms)(?=[A-Z])/,l=f.body&&f.body.style,k=!1,m=!1;if(l){for(var q in l)if(k= -h.exec(q)){g=k[0];g=g.substr(0,1).toUpperCase()+g.substr(1);break}g||(g="WebkitOpacity"in l&&"webkit");k=!!("transition"in l||g+"Transition"in l);m=!!("animation"in l||g+"Animation"in l);!d||k&&m||(k=L(l.webkitTransition),m=L(l.webkitAnimation))}return{history:!(!b.history||!b.history.pushState||4>d||e),hasEvent:function(a){if("input"===a&&11>=Ta)return!1;if(w(c[a])){var b=f.createElement("div");c[a]="on"+a in b}return c[a]},csp:eb(),vendorPrefix:g,transitions:k,animations:m,android:d}}]}function pf(){this.$get= -["$templateCache","$http","$q",function(b,a,c){function d(e,f){d.totalPendingRequests++;var g=a.defaults&&a.defaults.transformResponse;K(g)?g=g.filter(function(a){return a!==$b}):g===$b&&(g=null);return a.get(e,{cache:b,transformResponse:g})["finally"](function(){d.totalPendingRequests--}).then(function(a){b.put(e,a.data);return a.data},function(a){if(!f)throw ea("tpload",e,a.status,a.statusText);return c.reject(a)})}d.totalPendingRequests=0;return d}]}function qf(){this.$get=["$rootScope","$browser", -"$location",function(b,a,c){return{findBindings:function(a,b,c){a=a.getElementsByClassName("ng-binding");var g=[];n(a,function(a){var d=$.element(a).data("$binding");d&&n(d,function(d){c?(new RegExp("(^|\\s)"+td(b)+"(\\s|\\||$)")).test(d)&&g.push(a):-1!=d.indexOf(b)&&g.push(a)})});return g},findModels:function(a,b,c){for(var g=["ng-","data-ng-","ng\\:"],h=0;hb;b=Math.abs(b);var g=Infinity===b;if(!g&&!isFinite(b))return"";var h=b+"",l="",k=!1,m=[];g&&(l="\u221e");if(!g&&-1!==h.indexOf("e")){var q=h.match(/([\d\.]+)e(-?)(\d+)/);q&&"-"==q[2]&&q[3]>e+1?b=0:(l=h,k=!0)}if(g||k)0< -e&&1>b&&(l=b.toFixed(e),b=parseFloat(l));else{g=(h.split(Cd)[1]||"").length;w(e)&&(e=Math.min(Math.max(a.minFrac,g),a.maxFrac));b=+(Math.round(+(b.toString()+"e"+e)).toString()+"e"+-e);var g=(""+b).split(Cd),h=g[0],g=g[1]||"",q=0,t=a.lgSize,n=a.gSize;if(h.length>=t+n)for(q=h.length-t,k=0;kb&&(d="-",b=-b);for(b=""+b;b.length-c)e+=c;0===e&&-12==c&&(e=12);return Gb(e,a,d)}}function Hb(b,a){return function(c,d){var e=c["get"+b](),f=qb(a?"SHORT"+b:b);return d[f][e]}}function Dd(b){var a=(new Date(b,0,1)).getDay();return new Date(b,0,(4>=a?5:12)-a)}function Ed(b){return function(a){var c=Dd(a.getFullYear()); -a=+new Date(a.getFullYear(),a.getMonth(),a.getDate()+(4-a.getDay()))-+c;a=1+Math.round(a/6048E5);return Gb(a,b)}}function jc(b,a){return 0>=b.getFullYear()?a.ERAS[0]:a.ERAS[1]}function yd(b){function a(a){var b;if(b=a.match(c)){a=new Date(0);var f=0,g=0,h=b[8]?a.setUTCFullYear:a.setFullYear,l=b[8]?a.setUTCHours:a.setHours;b[9]&&(f=X(b[9]+b[10]),g=X(b[9]+b[11]));h.call(a,X(b[1]),X(b[2])-1,X(b[3]));f=X(b[4]||0)-f;g=X(b[5]||0)-g;h=X(b[6]||0);b=Math.round(1E3*parseFloat("0."+(b[7]||0)));l.call(a,f,g, -h,b)}return a}var c=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(c,e,f){var g="",h=[],l,k;e=e||"mediumDate";e=b.DATETIME_FORMATS[e]||e;L(c)&&(c=eg.test(c)?X(c):a(c));V(c)&&(c=new Date(c));if(!da(c)||!isFinite(c.getTime()))return c;for(;e;)(k=fg.exec(e))?(h=bb(h,k,1),e=h.pop()):(h.push(e),e=null);var m=c.getTimezoneOffset();f&&(m=wc(f,c.getTimezoneOffset()),c=Pb(c,f,!0));n(h,function(a){l=gg[a];g+=l?l(c,b.DATETIME_FORMATS,m): -a.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return g}}function $f(){return function(b,a){w(a)&&(a=2);return cb(b,a)}}function ag(){return function(b,a,c){a=Infinity===Math.abs(Number(a))?Number(a):X(a);if(isNaN(a))return b;V(b)&&(b=b.toString());if(!K(b)&&!L(b))return b;c=!c||isNaN(c)?0:X(c);c=0>c&&c>=-b.length?b.length+c:c;return 0<=a?b.slice(c,c+a):0===c?b.slice(a,b.length):b.slice(Math.max(0,c+a),c)}}function Ad(b){return function(a,c,d){function e(a,b){return b?function(b,c){return a(c,b)}: -a}function f(a){switch(typeof a){case "number":case "boolean":case "string":return!0;default:return!1}}function g(a){return null===a?"null":"function"===typeof a.valueOf&&(a=a.valueOf(),f(a))||"function"===typeof a.toString&&(a=a.toString(),f(a))?a:""}function h(a,b){var c=typeof a,d=typeof b;c===d&&"object"===c&&(a=g(a),b=g(b));return c===d?("string"===c&&(a=a.toLowerCase(),b=b.toLowerCase()),a===b?0:ab||37<=b&&40>=b||m(a,this,this.value)});if(e.hasEvent("paste"))a.on("paste cut",m)}a.on("change", -l);d.$render=function(){a.val(d.$isEmpty(d.$viewValue)?"":d.$viewValue)}}function Kb(b,a){return function(c,d){var e,f;if(da(c))return c;if(L(c)){'"'==c.charAt(0)&&'"'==c.charAt(c.length-1)&&(c=c.substring(1,c.length-1));if(hg.test(c))return new Date(c);b.lastIndex=0;if(e=b.exec(c))return e.shift(),f=d?{yyyy:d.getFullYear(),MM:d.getMonth()+1,dd:d.getDate(),HH:d.getHours(),mm:d.getMinutes(),ss:d.getSeconds(),sss:d.getMilliseconds()/1E3}:{yyyy:1970,MM:1,dd:1,HH:0,mm:0,ss:0,sss:0},n(e,function(b,c){c< -a.length&&(f[a[c]]=+b)}),new Date(f.yyyy,f.MM-1,f.dd,f.HH,f.mm,f.ss||0,1E3*f.sss||0)}return NaN}}function kb(b,a,c,d){return function(e,f,g,h,l,k,m){function q(a){return a&&!(a.getTime&&a.getTime()!==a.getTime())}function t(a){return z(a)?da(a)?a:c(a):s}Hd(e,f,g,h);jb(e,f,g,h,l,k);var n=h&&h.$options&&h.$options.timezone,r;h.$$parserName=b;h.$parsers.push(function(b){return h.$isEmpty(b)?null:a.test(b)?(b=c(b,r),n&&(b=Pb(b,n)),b):s});h.$formatters.push(function(a){if(a&&!da(a))throw Lb("datefmt", -a);if(q(a))return(r=a)&&n&&(r=Pb(r,n,!0)),m("date")(a,d,n);r=null;return""});if(z(g.min)||g.ngMin){var N;h.$validators.min=function(a){return!q(a)||w(N)||c(a)>=N};g.$observe("min",function(a){N=t(a);h.$validate()})}if(z(g.max)||g.ngMax){var u;h.$validators.max=function(a){return!q(a)||w(u)||c(a)<=u};g.$observe("max",function(a){u=t(a);h.$validate()})}}}function Hd(b,a,c,d){(d.$$hasNativeValidators=F(a[0].validity))&&d.$parsers.push(function(b){var c=a.prop("validity")||{};return c.badInput&&!c.typeMismatch? -s:b})}function Id(b,a,c,d,e){if(z(d)){b=b(d);if(!b.constant)throw I("ngModel")("constexpr",c,d);return b(a)}return e}function lc(b,a){b="ngClass"+b;return["$animate",function(c){function d(a,b){var c=[],d=0;a:for(;d(?:<\/\1>|)$/,Tb=/<|&#?\w+;/,Af=/<([\w:]+)/,Bf=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,na={option:[1,'"],thead:[1,"","
"],col:[2, -"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};na.optgroup=na.option;na.tbody=na.tfoot=na.colgroup=na.caption=na.thead;na.th=na.td;var Pa=R.prototype={ready:function(b){function a(){c||(c=!0,b())}var c=!1;"complete"===W.readyState?setTimeout(a):(this.on("DOMContentLoaded",a),R(O).on("load",a))},toString:function(){var b=[];n(this,function(a){b.push(""+a)});return"["+b.join(", ")+"]"},eq:function(b){return 0<= -b?A(this[b]):A(this[this.length+b])},length:0,push:jg,sort:[].sort,splice:[].splice},zb={};n("multiple selected checked disabled readOnly required open".split(" "),function(b){zb[G(b)]=b});var Sc={};n("input select option textarea button form details".split(" "),function(b){Sc[b]=!0});var Tc={ngMinlength:"minlength",ngMaxlength:"maxlength",ngMin:"min",ngMax:"max",ngPattern:"pattern"};n({data:Wb,removeData:tb,hasData:function(b){for(var a in hb[b.ng339])return!0;return!1}},function(b,a){R[a]=b});n({data:Wb, -inheritedData:yb,scope:function(b){return A.data(b,"$scope")||yb(b.parentNode||b,["$isolateScope","$scope"])},isolateScope:function(b){return A.data(b,"$isolateScope")||A.data(b,"$isolateScopeNoTemplate")},controller:Pc,injector:function(b){return yb(b,"$injector")},removeAttr:function(b,a){b.removeAttribute(a)},hasClass:vb,css:function(b,a,c){a=gb(a);if(z(c))b.style[a]=c;else return b.style[a]},attr:function(b,a,c){var d=b.nodeType;if(d!==Na&&2!==d&&8!==d)if(d=G(a),zb[d])if(z(c))c?(b[a]=!0,b.setAttribute(a, -d)):(b[a]=!1,b.removeAttribute(d));else return b[a]||(b.attributes.getNamedItem(a)||v).specified?d:s;else if(z(c))b.setAttribute(a,c);else if(b.getAttribute)return b=b.getAttribute(a,2),null===b?s:b},prop:function(b,a,c){if(z(c))b[a]=c;else return b[a]},text:function(){function b(a,b){if(w(b)){var d=a.nodeType;return d===qa||d===Na?a.textContent:""}a.textContent=b}b.$dv="";return b}(),val:function(b,a){if(w(a)){if(b.multiple&&"select"===ua(b)){var c=[];n(b.options,function(a){a.selected&&c.push(a.value|| -a.text)});return 0===c.length?null:c}return b.value}b.value=a},html:function(b,a){if(w(a))return b.innerHTML;sb(b,!0);b.innerHTML=a},empty:Qc},function(b,a){R.prototype[a]=function(a,d){var e,f,g=this.length;if(b!==Qc&&(2==b.length&&b!==vb&&b!==Pc?a:d)===s){if(F(a)){for(e=0;e <= >= && || ! = |".split(" "),function(a){Mb[a]=!0});var pg={n:"\n",f:"\f",r:"\r",t:"\t",v:"\v","'":"'",'"':'"'},gc=function(a){this.options=a};gc.prototype={constructor:gc,lex:function(a){this.text=a;this.index=0;for(this.tokens=[];this.index=a&&"string"===typeof a},isWhitespace:function(a){return" "===a||"\r"===a||"\t"===a||"\n"===a||"\v"===a||"\u00a0"===a},isIdent:function(a){return"a"<=a&&"z">=a||"A"<=a&&"Z">=a||"_"===a||"$"===a},isExpOperator:function(a){return"-"===a||"+"===a||this.isNumber(a)},throwError:function(a,c,d){d=d||this.index;c=z(c)?"s "+c+"-"+ -this.index+" ["+this.text.substring(c,d)+"]":" "+d;throw ca("lexerr",a,c,this.text);},readNumber:function(){for(var a="",c=this.index;this.index","<=",">=");)a={type:r.BinaryExpression,operator:c.text,left:a,right:this.additive()};return a},additive:function(){for(var a=this.multiplicative(), -c;c=this.expect("+","-");)a={type:r.BinaryExpression,operator:c.text,left:a,right:this.multiplicative()};return a},multiplicative:function(){for(var a=this.unary(),c;c=this.expect("*","/","%");)a={type:r.BinaryExpression,operator:c.text,left:a,right:this.unary()};return a},unary:function(){var a;return(a=this.expect("+","-","!"))?{type:r.UnaryExpression,operator:a.text,prefix:!0,argument:this.unary()}:this.primary()},primary:function(){var a;this.expect("(")?(a=this.filterChain(),this.consume(")")): -this.expect("[")?a=this.arrayDeclaration():this.expect("{")?a=this.object():this.constants.hasOwnProperty(this.peek().text)?a=fa(this.constants[this.consume().text]):this.peek().identifier?a=this.identifier():this.peek().constant?a=this.constant():this.throwError("not a primary expression",this.peek());for(var c;c=this.expect("(","[",".");)"("===c.text?(a={type:r.CallExpression,callee:a,arguments:this.parseArguments()},this.consume(")")):"["===c.text?(a={type:r.MemberExpression,object:a,property:this.expression(), -computed:!0},this.consume("]")):"."===c.text?a={type:r.MemberExpression,object:a,property:this.identifier(),computed:!1}:this.throwError("IMPOSSIBLE");return a},filter:function(a){a=[a];for(var c={type:r.CallExpression,callee:this.identifier(),arguments:a,filter:!0};this.expect(":");)a.push(this.expression());return c},parseArguments:function(){var a=[];if(")"!==this.peekToken().text){do a.push(this.expression());while(this.expect(","))}return a},identifier:function(){var a=this.consume();a.identifier|| -this.throwError("is not a valid identifier",a);return{type:r.Identifier,name:a.text}},constant:function(){return{type:r.Literal,value:this.consume().value}},arrayDeclaration:function(){var a=[];if("]"!==this.peekToken().text){do{if(this.peek("]"))break;a.push(this.expression())}while(this.expect(","))}this.consume("]");return{type:r.ArrayExpression,elements:a}},object:function(){var a=[],c;if("}"!==this.peekToken().text){do{if(this.peek("}"))break;c={type:r.Property,kind:"init"};this.peek().constant? -c.key=this.constant():this.peek().identifier?c.key=this.identifier():this.throwError("invalid key",this.peek());this.consume(":");c.value=this.expression();a.push(c)}while(this.expect(","))}this.consume("}");return{type:r.ObjectExpression,properties:a}},throwError:function(a,c){throw ca("syntax",c.text,a,c.index+1,this.text,this.text.substring(c.index));},consume:function(a){if(0===this.tokens.length)throw ca("ueoe",this.text);var c=this.expect(a);c||this.throwError("is unexpected, expecting ["+a+ -"]",this.peek());return c},peekToken:function(){if(0===this.tokens.length)throw ca("ueoe",this.text);return this.tokens[0]},peek:function(a,c,d,e){return this.peekAhead(0,a,c,d,e)},peekAhead:function(a,c,d,e,f){if(this.tokens.length>a){a=this.tokens[a];var g=a.text;if(g===c||g===d||g===e||g===f||!(c||d||e||f))return a}return!1},expect:function(a,c,d,e){return(a=this.peek(a,c,d,e))?(this.tokens.shift(),a):!1},constants:{"true":{type:r.Literal,value:!0},"false":{type:r.Literal,value:!1},"null":{type:r.Literal, -value:null},undefined:{type:r.Literal,value:s},"this":{type:r.ThisExpression}}};qd.prototype={compile:function(a,c){var d=this,e=this.astBuilder.ast(a);this.state={nextId:0,filters:{},expensiveChecks:c,fn:{vars:[],body:[],own:{}},assign:{vars:[],body:[],own:{}},inputs:[]};U(e,d.$filter);var f="",g;this.stage="assign";if(g=od(e))this.state.computing="assign",f=this.nextId(),this.recurse(g,f),f="fn.assign="+this.generateFunction("assign","s,v,l");g=md(e.body);d.stage="inputs";n(g,function(a,c){var e= -"fn"+c;d.state[e]={vars:[],body:[],own:{}};d.state.computing=e;var f=d.nextId();d.recurse(a,f);d.return_(f);d.state.inputs.push(e);a.watchId=c});this.state.computing="fn";this.stage="main";this.recurse(e);f='"'+this.USE+" "+this.STRICT+'";\n'+this.filterPrefix()+"var fn="+this.generateFunction("fn","s,l,a,i")+f+this.watchFns()+"return fn;";f=(new Function("$filter","ensureSafeMemberName","ensureSafeObject","ensureSafeFunction","ifDefined","plus","text",f))(this.$filter,Ba,oa,kd,Wf,ld,a);this.state= -this.stage=s;f.literal=pd(e);f.constant=e.constant;return f},USE:"use",STRICT:"strict",watchFns:function(){var a=[],c=this.state.inputs,d=this;n(c,function(c){a.push("var "+c+"="+d.generateFunction(c,"s"))});c.length&&a.push("fn.inputs=["+c.join(",")+"];");return a.join("")},generateFunction:function(a,c){return"function("+c+"){"+this.varsPrefix(a)+this.body(a)+"};"},filterPrefix:function(){var a=[],c=this;n(this.state.filters,function(d,e){a.push(d+"=$filter("+c.escape(e)+")")});return a.length? -"var "+a.join(",")+";":""},varsPrefix:function(a){return this.state[a].vars.length?"var "+this.state[a].vars.join(",")+";":""},body:function(a){return this.state[a].body.join("")},recurse:function(a,c,d,e,f,g){var h,l,k=this,m,q;e=e||v;if(!g&&z(a.watchId))c=c||this.nextId(),this.if_("i",this.lazyAssign(c,this.computedMember("i",a.watchId)),this.lazyRecurse(a,c,d,e,f,!0));else switch(a.type){case r.Program:n(a.body,function(c,d){k.recurse(c.expression,s,s,function(a){l=a});d!==a.body.length-1?k.current().body.push(l, -";"):k.return_(l)});break;case r.Literal:q=this.escape(a.value);this.assign(c,q);e(q);break;case r.UnaryExpression:this.recurse(a.argument,s,s,function(a){l=a});q=a.operator+"("+this.ifDefined(l,0)+")";this.assign(c,q);e(q);break;case r.BinaryExpression:this.recurse(a.left,s,s,function(a){h=a});this.recurse(a.right,s,s,function(a){l=a});q="+"===a.operator?this.plus(h,l):"-"===a.operator?this.ifDefined(h,0)+a.operator+this.ifDefined(l,0):"("+h+")"+a.operator+"("+l+")";this.assign(c,q);e(q);break;case r.LogicalExpression:c= -c||this.nextId();k.recurse(a.left,c);k.if_("&&"===a.operator?c:k.not(c),k.lazyRecurse(a.right,c));e(c);break;case r.ConditionalExpression:c=c||this.nextId();k.recurse(a.test,c);k.if_(c,k.lazyRecurse(a.alternate,c),k.lazyRecurse(a.consequent,c));e(c);break;case r.Identifier:c=c||this.nextId();d&&(d.context="inputs"===k.stage?"s":this.assign(this.nextId(),this.getHasOwnProperty("l",a.name)+"?l:s"),d.computed=!1,d.name=a.name);Ba(a.name);k.if_("inputs"===k.stage||k.not(k.getHasOwnProperty("l",a.name)), -function(){k.if_("inputs"===k.stage||"s",function(){f&&1!==f&&k.if_(k.not(k.nonComputedMember("s",a.name)),k.lazyAssign(k.nonComputedMember("s",a.name),"{}"));k.assign(c,k.nonComputedMember("s",a.name))})},c&&k.lazyAssign(c,k.nonComputedMember("l",a.name)));(k.state.expensiveChecks||Fb(a.name))&&k.addEnsureSafeObject(c);e(c);break;case r.MemberExpression:h=d&&(d.context=this.nextId())||this.nextId();c=c||this.nextId();k.recurse(a.object,h,s,function(){k.if_(k.notNull(h),function(){if(a.computed)l= -k.nextId(),k.recurse(a.property,l),k.addEnsureSafeMemberName(l),f&&1!==f&&k.if_(k.not(k.computedMember(h,l)),k.lazyAssign(k.computedMember(h,l),"{}")),q=k.ensureSafeObject(k.computedMember(h,l)),k.assign(c,q),d&&(d.computed=!0,d.name=l);else{Ba(a.property.name);f&&1!==f&&k.if_(k.not(k.nonComputedMember(h,a.property.name)),k.lazyAssign(k.nonComputedMember(h,a.property.name),"{}"));q=k.nonComputedMember(h,a.property.name);if(k.state.expensiveChecks||Fb(a.property.name))q=k.ensureSafeObject(q);k.assign(c, -q);d&&(d.computed=!1,d.name=a.property.name)}},function(){k.assign(c,"undefined")});e(c)},!!f);break;case r.CallExpression:c=c||this.nextId();a.filter?(l=k.filter(a.callee.name),m=[],n(a.arguments,function(a){var c=k.nextId();k.recurse(a,c);m.push(c)}),q=l+"("+m.join(",")+")",k.assign(c,q),e(c)):(l=k.nextId(),h={},m=[],k.recurse(a.callee,l,h,function(){k.if_(k.notNull(l),function(){k.addEnsureSafeFunction(l);n(a.arguments,function(a){k.recurse(a,k.nextId(),s,function(a){m.push(k.ensureSafeObject(a))})}); -h.name?(k.state.expensiveChecks||k.addEnsureSafeObject(h.context),q=k.member(h.context,h.name,h.computed)+"("+m.join(",")+")"):q=l+"("+m.join(",")+")";q=k.ensureSafeObject(q);k.assign(c,q)},function(){k.assign(c,"undefined")});e(c)}));break;case r.AssignmentExpression:l=this.nextId();h={};if(!nd(a.left))throw ca("lval");this.recurse(a.left,s,h,function(){k.if_(k.notNull(h.context),function(){k.recurse(a.right,l);k.addEnsureSafeObject(k.member(h.context,h.name,h.computed));q=k.member(h.context,h.name, -h.computed)+a.operator+l;k.assign(c,q);e(c||q)})},1);break;case r.ArrayExpression:m=[];n(a.elements,function(a){k.recurse(a,k.nextId(),s,function(a){m.push(a)})});q="["+m.join(",")+"]";this.assign(c,q);e(q);break;case r.ObjectExpression:m=[];n(a.properties,function(a){k.recurse(a.value,k.nextId(),s,function(c){m.push(k.escape(a.key.type===r.Identifier?a.key.name:""+a.key.value)+":"+c)})});q="{"+m.join(",")+"}";this.assign(c,q);e(q);break;case r.ThisExpression:this.assign(c,"s");e("s");break;case r.NGValueParameter:this.assign(c, -"v"),e("v")}},getHasOwnProperty:function(a,c){var d=a+"."+c,e=this.current().own;e.hasOwnProperty(d)||(e[d]=this.nextId(!1,a+"&&("+this.escape(c)+" in "+a+")"));return e[d]},assign:function(a,c){if(a)return this.current().body.push(a,"=",c,";"),a},filter:function(a){this.state.filters.hasOwnProperty(a)||(this.state.filters[a]=this.nextId(!0));return this.state.filters[a]},ifDefined:function(a,c){return"ifDefined("+a+","+this.escape(c)+")"},plus:function(a,c){return"plus("+a+","+c+")"},return_:function(a){this.current().body.push("return ", -a,";")},if_:function(a,c,d){if(!0===a)c();else{var e=this.current().body;e.push("if(",a,"){");c();e.push("}");d&&(e.push("else{"),d(),e.push("}"))}},not:function(a){return"!("+a+")"},notNull:function(a){return a+"!=null"},nonComputedMember:function(a,c){return a+"."+c},computedMember:function(a,c){return a+"["+c+"]"},member:function(a,c,d){return d?this.computedMember(a,c):this.nonComputedMember(a,c)},addEnsureSafeObject:function(a){this.current().body.push(this.ensureSafeObject(a),";")},addEnsureSafeMemberName:function(a){this.current().body.push(this.ensureSafeMemberName(a), -";")},addEnsureSafeFunction:function(a){this.current().body.push(this.ensureSafeFunction(a),";")},ensureSafeObject:function(a){return"ensureSafeObject("+a+",text)"},ensureSafeMemberName:function(a){return"ensureSafeMemberName("+a+",text)"},ensureSafeFunction:function(a){return"ensureSafeFunction("+a+",text)"},lazyRecurse:function(a,c,d,e,f,g){var h=this;return function(){h.recurse(a,c,d,e,f,g)}},lazyAssign:function(a,c){var d=this;return function(){d.assign(a,c)}},stringEscapeRegex:/[^ a-zA-Z0-9]/g, -stringEscapeFn:function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)},escape:function(a){if(L(a))return"'"+a.replace(this.stringEscapeRegex,this.stringEscapeFn)+"'";if(V(a))return a.toString();if(!0===a)return"true";if(!1===a)return"false";if(null===a)return"null";if("undefined"===typeof a)return"undefined";throw ca("esc");},nextId:function(a,c){var d="v"+this.state.nextId++;a||this.current().vars.push(d+(c?"="+c:""));return d},current:function(){return this.state[this.state.computing]}}; -rd.prototype={compile:function(a,c){var d=this,e=this.astBuilder.ast(a);this.expression=a;this.expensiveChecks=c;U(e,d.$filter);var f,g;if(f=od(e))g=this.recurse(f);f=md(e.body);var h;f&&(h=[],n(f,function(a,c){var e=d.recurse(a);a.input=e;h.push(e);a.watchId=c}));var l=[];n(e.body,function(a){l.push(d.recurse(a.expression))});f=0===e.body.length?function(){}:1===e.body.length?l[0]:function(a,c){var d;n(l,function(e){d=e(a,c)});return d};g&&(f.assign=function(a,c,d){return g(a,d,c)});h&&(f.inputs= -h);f.literal=pd(e);f.constant=e.constant;return f},recurse:function(a,c,d){var e,f,g=this,h;if(a.input)return this.inputs(a.input,a.watchId);switch(a.type){case r.Literal:return this.value(a.value,c);case r.UnaryExpression:return f=this.recurse(a.argument),this["unary"+a.operator](f,c);case r.BinaryExpression:return e=this.recurse(a.left),f=this.recurse(a.right),this["binary"+a.operator](e,f,c);case r.LogicalExpression:return e=this.recurse(a.left),f=this.recurse(a.right),this["binary"+a.operator](e, -f,c);case r.ConditionalExpression:return this["ternary?:"](this.recurse(a.test),this.recurse(a.alternate),this.recurse(a.consequent),c);case r.Identifier:return Ba(a.name,g.expression),g.identifier(a.name,g.expensiveChecks||Fb(a.name),c,d,g.expression);case r.MemberExpression:return e=this.recurse(a.object,!1,!!d),a.computed||(Ba(a.property.name,g.expression),f=a.property.name),a.computed&&(f=this.recurse(a.property)),a.computed?this.computedMember(e,f,c,d,g.expression):this.nonComputedMember(e,f, -g.expensiveChecks,c,d,g.expression);case r.CallExpression:return h=[],n(a.arguments,function(a){h.push(g.recurse(a))}),a.filter&&(f=this.$filter(a.callee.name)),a.filter||(f=this.recurse(a.callee,!0)),a.filter?function(a,d,e,g){for(var n=[],r=0;r":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)>c(e,f,g,h);return d?{value:e}:e}},"binary<=":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)<=c(e,f,g,h);return d?{value:e}:e}},"binary>=":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)>=c(e,f,g,h);return d?{value:e}:e}},"binary&&":function(a,c,d){return function(e,f,g,h){e= -a(e,f,g,h)&&c(e,f,g,h);return d?{value:e}:e}},"binary||":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)||c(e,f,g,h);return d?{value:e}:e}},"ternary?:":function(a,c,d,e){return function(f,g,h,l){f=a(f,g,h,l)?c(f,g,h,l):d(f,g,h,l);return e?{value:f}:f}},value:function(a,c){return function(){return c?{context:s,name:s,value:a}:a}},identifier:function(a,c,d,e,f){return function(g,h,l,k){g=h&&a in h?h:g;e&&1!==e&&g&&!g[a]&&(g[a]={});h=g?g[a]:s;c&&oa(h,f);return d?{context:g,name:a,value:h}:h}}, -computedMember:function(a,c,d,e,f){return function(g,h,l,k){var m=a(g,h,l,k),n,t;null!=m&&(n=c(g,h,l,k),Ba(n,f),e&&1!==e&&m&&!m[n]&&(m[n]={}),t=m[n],oa(t,f));return d?{context:m,name:n,value:t}:t}},nonComputedMember:function(a,c,d,e,f,g){return function(h,l,k,m){h=a(h,l,k,m);f&&1!==f&&h&&!h[c]&&(h[c]={});l=null!=h?h[c]:s;(d||Fb(c))&&oa(l,g);return e?{context:h,name:c,value:l}:l}},inputs:function(a,c){return function(d,e,f,g){return g?g[c]:a(d,e,f)}}};var hc=function(a,c,d){this.lexer=a;this.$filter= -c;this.options=d;this.ast=new r(this.lexer);this.astCompiler=d.csp?new rd(this.ast,c):new qd(this.ast,c)};hc.prototype={constructor:hc,parse:function(a){return this.astCompiler.compile(a,this.options.expensiveChecks)}};ga();ga();var Xf=Object.prototype.valueOf,Ca=I("$sce"),pa={HTML:"html",CSS:"css",URL:"url",RESOURCE_URL:"resourceUrl",JS:"js"},ea=I("$compile"),Y=W.createElement("a"),vd=Aa(O.location.href);wd.$inject=["$document"];Kc.$inject=["$provide"];xd.$inject=["$locale"];zd.$inject=["$locale"]; -var Cd=".",gg={yyyy:Z("FullYear",4),yy:Z("FullYear",2,0,!0),y:Z("FullYear",1),MMMM:Hb("Month"),MMM:Hb("Month",!0),MM:Z("Month",2,1),M:Z("Month",1,1),dd:Z("Date",2),d:Z("Date",1),HH:Z("Hours",2),H:Z("Hours",1),hh:Z("Hours",2,-12),h:Z("Hours",1,-12),mm:Z("Minutes",2),m:Z("Minutes",1),ss:Z("Seconds",2),s:Z("Seconds",1),sss:Z("Milliseconds",3),EEEE:Hb("Day"),EEE:Hb("Day",!0),a:function(a,c){return 12>a.getHours()?c.AMPMS[0]:c.AMPMS[1]},Z:function(a,c,d){a=-1*d;return a=(0<=a?"+":"")+(Gb(Math[0=a.getFullYear()?c.ERANAMES[0]:c.ERANAMES[1]}},fg=/((?:[^yMdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/,eg=/^\-?\d+$/;yd.$inject=["$locale"];var bg=ra(G),cg=ra(qb);Ad.$inject=["$parse"];var he=ra({restrict:"E",compile:function(a,c){if(!c.href&&!c.xlinkHref)return function(a,c){if("a"===c[0].nodeName.toLowerCase()){var f="[object SVGAnimatedString]"===ta.call(c.prop("href"))? -"xlink:href":"href";c.on("click",function(a){c.attr(f)||a.preventDefault()})}}}}),rb={};n(zb,function(a,c){function d(a,d,f){a.$watch(f[e],function(a){f.$set(c,!!a)})}if("multiple"!=a){var e=xa("ng-"+c),f=d;"checked"===a&&(f=function(a,c,f){f.ngModel!==f[e]&&d(a,c,f)});rb[e]=function(){return{restrict:"A",priority:100,link:f}}}});n(Tc,function(a,c){rb[c]=function(){return{priority:100,link:function(a,e,f){if("ngPattern"===c&&"/"==f.ngPattern.charAt(0)&&(e=f.ngPattern.match(ig))){f.$set("ngPattern", -new RegExp(e[1],e[2]));return}a.$watch(f[c],function(a){f.$set(c,a)})}}}});n(["src","srcset","href"],function(a){var c=xa("ng-"+a);rb[c]=function(){return{priority:99,link:function(d,e,f){var g=a,h=a;"href"===a&&"[object SVGAnimatedString]"===ta.call(e.prop("href"))&&(h="xlinkHref",f.$attr[h]="xlink:href",g=null);f.$observe(c,function(c){c?(f.$set(h,c),Ta&&g&&e.prop(g,f[h])):"href"===a&&f.$set(h,null)})}}}});var Ib={$addControl:v,$$renameControl:function(a,c){a.$name=c},$removeControl:v,$setValidity:v, -$setDirty:v,$setPristine:v,$setSubmitted:v};Fd.$inject=["$element","$attrs","$scope","$animate","$interpolate"];var Nd=function(a){return["$timeout",function(c){return{name:"form",restrict:a?"EAC":"E",controller:Fd,compile:function(d,e){d.addClass(Ua).addClass(lb);var f=e.name?"name":a&&e.ngForm?"ngForm":!1;return{pre:function(a,d,e,k){if(!("action"in e)){var m=function(c){a.$apply(function(){k.$commitViewValue();k.$setSubmitted()});c.preventDefault()};d[0].addEventListener("submit",m,!1);d.on("$destroy", -function(){c(function(){d[0].removeEventListener("submit",m,!1)},0,!1)})}var n=k.$$parentForm;f&&(Eb(a,k.$name,k,k.$name),e.$observe(f,function(c){k.$name!==c&&(Eb(a,k.$name,s,k.$name),n.$$renameControl(k,c),Eb(a,k.$name,k,k.$name))}));d.on("$destroy",function(){n.$removeControl(k);f&&Eb(a,e[f],s,k.$name);Q(k,Ib)})}}}}}]},ie=Nd(),ve=Nd(!0),hg=/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/,qg=/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/, -rg=/^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i,sg=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/,Od=/^(\d{4})-(\d{2})-(\d{2})$/,Pd=/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,mc=/^(\d{4})-W(\d\d)$/,Qd=/^(\d{4})-(\d\d)$/,Rd=/^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,Sd={text:function(a,c,d,e,f,g){jb(a,c,d,e,f,g);kc(e)},date:kb("date",Od,Kb(Od,["yyyy","MM","dd"]),"yyyy-MM-dd"),"datetime-local":kb("datetimelocal",Pd,Kb(Pd, -"yyyy MM dd HH mm ss sss".split(" ")),"yyyy-MM-ddTHH:mm:ss.sss"),time:kb("time",Rd,Kb(Rd,["HH","mm","ss","sss"]),"HH:mm:ss.sss"),week:kb("week",mc,function(a,c){if(da(a))return a;if(L(a)){mc.lastIndex=0;var d=mc.exec(a);if(d){var e=+d[1],f=+d[2],g=d=0,h=0,l=0,k=Dd(e),f=7*(f-1);c&&(d=c.getHours(),g=c.getMinutes(),h=c.getSeconds(),l=c.getMilliseconds());return new Date(e,0,k.getDate()+f,d,g,h,l)}}return NaN},"yyyy-Www"),month:kb("month",Qd,Kb(Qd,["yyyy","MM"]),"yyyy-MM"),number:function(a,c,d,e,f,g){Hd(a, -c,d,e);jb(a,c,d,e,f,g);e.$$parserName="number";e.$parsers.push(function(a){return e.$isEmpty(a)?null:sg.test(a)?parseFloat(a):s});e.$formatters.push(function(a){if(!e.$isEmpty(a)){if(!V(a))throw Lb("numfmt",a);a=a.toString()}return a});if(z(d.min)||d.ngMin){var h;e.$validators.min=function(a){return e.$isEmpty(a)||w(h)||a>=h};d.$observe("min",function(a){z(a)&&!V(a)&&(a=parseFloat(a,10));h=V(a)&&!isNaN(a)?a:s;e.$validate()})}if(z(d.max)||d.ngMax){var l;e.$validators.max=function(a){return e.$isEmpty(a)|| -w(l)||a<=l};d.$observe("max",function(a){z(a)&&!V(a)&&(a=parseFloat(a,10));l=V(a)&&!isNaN(a)?a:s;e.$validate()})}},url:function(a,c,d,e,f,g){jb(a,c,d,e,f,g);kc(e);e.$$parserName="url";e.$validators.url=function(a,c){var d=a||c;return e.$isEmpty(d)||qg.test(d)}},email:function(a,c,d,e,f,g){jb(a,c,d,e,f,g);kc(e);e.$$parserName="email";e.$validators.email=function(a,c){var d=a||c;return e.$isEmpty(d)||rg.test(d)}},radio:function(a,c,d,e){w(d.name)&&c.attr("name",++mb);c.on("click",function(a){c[0].checked&& -e.$setViewValue(d.value,a&&a.type)});e.$render=function(){c[0].checked=d.value==e.$viewValue};d.$observe("value",e.$render)},checkbox:function(a,c,d,e,f,g,h,l){var k=Id(l,a,"ngTrueValue",d.ngTrueValue,!0),m=Id(l,a,"ngFalseValue",d.ngFalseValue,!1);c.on("click",function(a){e.$setViewValue(c[0].checked,a&&a.type)});e.$render=function(){c[0].checked=e.$viewValue};e.$isEmpty=function(a){return!1===a};e.$formatters.push(function(a){return ka(a,k)});e.$parsers.push(function(a){return a?k:m})},hidden:v, -button:v,submit:v,reset:v,file:v},Ec=["$browser","$sniffer","$filter","$parse",function(a,c,d,e){return{restrict:"E",require:["?ngModel"],link:{pre:function(f,g,h,l){l[0]&&(Sd[G(h.type)]||Sd.text)(f,g,h,l[0],c,a,d,e)}}}}],tg=/^(true|false|\d+)$/,Ne=function(){return{restrict:"A",priority:100,compile:function(a,c){return tg.test(c.ngValue)?function(a,c,f){f.$set("value",a.$eval(f.ngValue))}:function(a,c,f){a.$watch(f.ngValue,function(a){f.$set("value",a)})}}}},ne=["$compile",function(a){return{restrict:"AC", -compile:function(c){a.$$addBindingClass(c);return function(c,e,f){a.$$addBindingInfo(e,f.ngBind);e=e[0];c.$watch(f.ngBind,function(a){e.textContent=a===s?"":a})}}}}],pe=["$interpolate","$compile",function(a,c){return{compile:function(d){c.$$addBindingClass(d);return function(d,f,g){d=a(f.attr(g.$attr.ngBindTemplate));c.$$addBindingInfo(f,d.expressions);f=f[0];g.$observe("ngBindTemplate",function(a){f.textContent=a===s?"":a})}}}}],oe=["$sce","$parse","$compile",function(a,c,d){return{restrict:"A", -compile:function(e,f){var g=c(f.ngBindHtml),h=c(f.ngBindHtml,function(a){return(a||"").toString()});d.$$addBindingClass(e);return function(c,e,f){d.$$addBindingInfo(e,f.ngBindHtml);c.$watch(h,function(){e.html(a.getTrustedHtml(g(c))||"")})}}}}],Me=ra({restrict:"A",require:"ngModel",link:function(a,c,d,e){e.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}),qe=lc("",!0),se=lc("Odd",0),re=lc("Even",1),te=Ma({compile:function(a,c){c.$set("ngCloak",s);a.removeClass("ng-cloak")}}),ue=[function(){return{restrict:"A", -scope:!0,controller:"@",priority:500}}],Jc={},ug={blur:!0,focus:!0};n("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "),function(a){var c=xa("ng-"+a);Jc[c]=["$parse","$rootScope",function(d,e){return{restrict:"A",compile:function(f,g){var h=d(g[c],null,!0);return function(c,d){d.on(a,function(d){var f=function(){h(c,{$event:d})};ug[a]&&e.$$phase?c.$evalAsync(f):c.$apply(f)})}}}}]});var xe=["$animate", -function(a){return{multiElement:!0,transclude:"element",priority:600,terminal:!0,restrict:"A",$$tlb:!0,link:function(c,d,e,f,g){var h,l,k;c.$watch(e.ngIf,function(c){c?l||g(function(c,f){l=f;c[c.length++]=W.createComment(" end ngIf: "+e.ngIf+" ");h={clone:c};a.enter(c,d.parent(),d)}):(k&&(k.remove(),k=null),l&&(l.$destroy(),l=null),h&&(k=pb(h.clone),a.leave(k).then(function(){k=null}),h=null))})}}}],ye=["$templateRequest","$anchorScroll","$animate","$sce",function(a,c,d,e){return{restrict:"ECA",priority:400, -terminal:!0,transclude:"element",controller:$.noop,compile:function(f,g){var h=g.ngInclude||g.src,l=g.onload||"",k=g.autoscroll;return function(f,g,n,r,s){var w=0,u,p,x,v=function(){p&&(p.remove(),p=null);u&&(u.$destroy(),u=null);x&&(d.leave(x).then(function(){p=null}),p=x,x=null)};f.$watch(e.parseAsResourceUrl(h),function(e){var h=function(){!z(k)||k&&!f.$eval(k)||c()},n=++w;e?(a(e,!0).then(function(a){if(n===w){var c=f.$new();r.template=a;a=s(c,function(a){v();d.enter(a,null,g).then(h)});u=c;x= -a;u.$emit("$includeContentLoaded",e);f.$eval(l)}},function(){n===w&&(v(),f.$emit("$includeContentError",e))}),f.$emit("$includeContentRequested",e)):(v(),r.template=null)})}}}}],Pe=["$compile",function(a){return{restrict:"ECA",priority:-400,require:"ngInclude",link:function(c,d,e,f){/SVG/.test(d[0].toString())?(d.empty(),a(Mc(f.template,W).childNodes)(c,function(a){d.append(a)},{futureParentElement:d})):(d.html(f.template),a(d.contents())(c))}}}],ze=Ma({priority:450,compile:function(){return{pre:function(a, -c,d){a.$eval(d.ngInit)}}}}),Le=function(){return{restrict:"A",priority:100,require:"ngModel",link:function(a,c,d,e){var f=c.attr(d.$attr.ngList)||", ",g="false"!==d.ngTrim,h=g?T(f):f;e.$parsers.push(function(a){if(!w(a)){var c=[];a&&n(a.split(h),function(a){a&&c.push(g?T(a):a)});return c}});e.$formatters.push(function(a){return K(a)?a.join(f):s});e.$isEmpty=function(a){return!a||!a.length}}}},lb="ng-valid",Jd="ng-invalid",Ua="ng-pristine",Jb="ng-dirty",Ld="ng-pending",Lb=new I("ngModel"),vg=["$scope", -"$exceptionHandler","$attrs","$element","$parse","$animate","$timeout","$rootScope","$q","$interpolate",function(a,c,d,e,f,g,h,l,k,m){this.$modelValue=this.$viewValue=Number.NaN;this.$$rawModelValue=s;this.$validators={};this.$asyncValidators={};this.$parsers=[];this.$formatters=[];this.$viewChangeListeners=[];this.$untouched=!0;this.$touched=!1;this.$pristine=!0;this.$dirty=!1;this.$valid=!0;this.$invalid=!1;this.$error={};this.$$success={};this.$pending=s;this.$name=m(d.name||"",!1)(a);var q=f(d.ngModel), -r=q.assign,y=q,C=r,N=null,u,p=this;this.$$setOptions=function(a){if((p.$options=a)&&a.getterSetter){var c=f(d.ngModel+"()"),g=f(d.ngModel+"($$$p)");y=function(a){var d=q(a);E(d)&&(d=c(a));return d};C=function(a,c){E(q(a))?g(a,{$$$p:p.$modelValue}):r(a,p.$modelValue)}}else if(!q.assign)throw Lb("nonassign",d.ngModel,va(e));};this.$render=v;this.$isEmpty=function(a){return w(a)||""===a||null===a||a!==a};var x=e.inheritedData("$formController")||Ib,A=0;Gd({ctrl:this,$element:e,set:function(a,c){a[c]= -!0},unset:function(a,c){delete a[c]},parentForm:x,$animate:g});this.$setPristine=function(){p.$dirty=!1;p.$pristine=!0;g.removeClass(e,Jb);g.addClass(e,Ua)};this.$setDirty=function(){p.$dirty=!0;p.$pristine=!1;g.removeClass(e,Ua);g.addClass(e,Jb);x.$setDirty()};this.$setUntouched=function(){p.$touched=!1;p.$untouched=!0;g.setClass(e,"ng-untouched","ng-touched")};this.$setTouched=function(){p.$touched=!0;p.$untouched=!1;g.setClass(e,"ng-touched","ng-untouched")};this.$rollbackViewValue=function(){h.cancel(N); -p.$viewValue=p.$$lastCommittedViewValue;p.$render()};this.$validate=function(){if(!V(p.$modelValue)||!isNaN(p.$modelValue)){var a=p.$$rawModelValue,c=p.$valid,d=p.$modelValue,e=p.$options&&p.$options.allowInvalid;p.$$runValidators(a,p.$$lastCommittedViewValue,function(f){e||c===f||(p.$modelValue=f?a:s,p.$modelValue!==d&&p.$$writeModelToScope())})}};this.$$runValidators=function(a,c,d){function e(){var d=!0;n(p.$validators,function(e,f){var h=e(a,c);d=d&&h;g(f,h)});return d?!0:(n(p.$asyncValidators, -function(a,c){g(c,null)}),!1)}function f(){var d=[],e=!0;n(p.$asyncValidators,function(f,h){var k=f(a,c);if(!k||!E(k.then))throw Lb("$asyncValidators",k);g(h,s);d.push(k.then(function(){g(h,!0)},function(a){e=!1;g(h,!1)}))});d.length?k.all(d).then(function(){h(e)},v):h(!0)}function g(a,c){l===A&&p.$setValidity(a,c)}function h(a){l===A&&d(a)}A++;var l=A;(function(){var a=p.$$parserName||"parse";if(u===s)g(a,null);else return u||(n(p.$validators,function(a,c){g(c,null)}),n(p.$asyncValidators,function(a, -c){g(c,null)})),g(a,u),u;return!0})()?e()?f():h(!1):h(!1)};this.$commitViewValue=function(){var a=p.$viewValue;h.cancel(N);if(p.$$lastCommittedViewValue!==a||""===a&&p.$$hasNativeValidators)p.$$lastCommittedViewValue=a,p.$pristine&&this.$setDirty(),this.$$parseAndValidate()};this.$$parseAndValidate=function(){var c=p.$$lastCommittedViewValue;if(u=w(c)?s:!0)for(var d=0;df||e.$isEmpty(c)||c.length<=f}}}}},Hc=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){if(e){var f=0;d.$observe("minlength",function(a){f=X(a)||0;e.$validate()});e.$validators.minlength=function(a, -c){return e.$isEmpty(c)||c.length>=f}}}}};O.angular.bootstrap?console.log("WARNING: Tried to load angular more than once."):(be(),de($),A(W).ready(function(){Yd(W,zc)}))})(window,document);!window.angular.$$csp()&&window.angular.element(document).find("head").prepend(''); +(function(C){'use strict';function N(a){return function(){var b=arguments[0],d;d="["+(a?a+":":"")+b+"] http://errors.angularjs.org/1.5.8/"+(a?a+"/":"")+b;for(b=1;b").append(a).html();try{return a[0].nodeType===Ma?Q(d):d.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/,function(a,b){return"<"+Q(b)})}catch(c){return Q(d)}}function zc(a){try{return decodeURIComponent(a)}catch(b){}}function Ac(a){var b={};q((a||"").split("&"),function(a){var c,e,f;a&&(e=a=a.replace(/\+/g,"%20"), +c=a.indexOf("="),-1!==c&&(e=a.substring(0,c),f=a.substring(c+1)),e=zc(e),w(e)&&(f=w(f)?zc(f):!0,ua.call(b,e)?L(b[e])?b[e].push(f):b[e]=[b[e],f]:b[e]=f))});return b}function Tb(a){var b=[];q(a,function(a,c){L(a)?q(a,function(a){b.push(ea(c,!0)+(!0===a?"":"="+ea(a,!0)))}):b.push(ea(c,!0)+(!0===a?"":"="+ea(a,!0)))});return b.length?b.join("&"):""}function qb(a){return ea(a,!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+")}function ea(a,b){return encodeURIComponent(a).replace(/%40/gi, +"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%3B/gi,";").replace(/%20/g,b?"%20":"+")}function ee(a,b){var d,c,e=Na.length;for(c=0;c/,">"));}b=b||[];b.unshift(["$provide",function(b){b.value("$rootElement",a)}]);d.debugInfoEnabled&&b.push(["$compileProvider",function(a){a.debugInfoEnabled(!0)}]);b.unshift("ng");c=cb(b,d.strictDi);c.invoke(["$rootScope","$rootElement","$compile","$injector",function(a,b,c,d){a.$apply(function(){b.data("$injector", +d);c(b)(a)})}]);return c},e=/^NG_ENABLE_DEBUG_INFO!/,f=/^NG_DEFER_BOOTSTRAP!/;C&&e.test(C.name)&&(d.debugInfoEnabled=!0,C.name=C.name.replace(e,""));if(C&&!f.test(C.name))return c();C.name=C.name.replace(f,"");ca.resumeBootstrap=function(a){q(a,function(a){b.push(a)});return c()};z(ca.resumeDeferredBootstrap)&&ca.resumeDeferredBootstrap()}function ge(){C.name="NG_ENABLE_DEBUG_INFO!"+C.name;C.location.reload()}function he(a){a=ca.element(a).injector();if(!a)throw xa("test");return a.get("$$testability")} +function Cc(a,b){b=b||"_";return a.replace(ie,function(a,c){return(c?b:"")+a.toLowerCase()})}function je(){var a;if(!Dc){var b=rb();(qa=y(b)?C.jQuery:b?C[b]:void 0)&&qa.fn.on?(F=qa,S(qa.fn,{scope:Oa.scope,isolateScope:Oa.isolateScope,controller:Oa.controller,injector:Oa.injector,inheritedData:Oa.inheritedData}),a=qa.cleanData,qa.cleanData=function(b){for(var c,e=0,f;null!=(f=b[e]);e++)(c=qa._data(f,"events"))&&c.$destroy&&qa(f).triggerHandler("$destroy");a(b)}):F=O;ca.element=F;Dc=!0}}function sb(a, +b,d){if(!a)throw xa("areq",b||"?",d||"required");return a}function Pa(a,b,d){d&&L(a)&&(a=a[a.length-1]);sb(z(a),b,"not a function, got "+(a&&"object"===typeof a?a.constructor.name||"Object":typeof a));return a}function Qa(a,b){if("hasOwnProperty"===a)throw xa("badname",b);}function Ec(a,b,d){if(!b)return a;b=b.split(".");for(var c,e=a,f=b.length,g=0;g")+c[2];for(c=c[0];c--;)d=d.lastChild;f=$a(f,d.childNodes);d=e.firstChild; +d.textContent=""}else f.push(b.createTextNode(a));e.textContent="";e.innerHTML="";q(f,function(a){e.appendChild(a)});return e}function Pc(a,b){var d=a.parentNode;d&&d.replaceChild(b,a);b.appendChild(a)}function O(a){if(a instanceof O)return a;var b;G(a)&&(a=W(a),b=!0);if(!(this instanceof O)){if(b&&"<"!=a.charAt(0))throw Wb("nosel");return new O(a)}if(b){b=C.document;var d;a=(d=Of.exec(a))?[b.createElement(d[1])]:(d=Oc(a,b))?d.childNodes:[]}Qc(this,a)}function Xb(a){return a.cloneNode(!0)}function wb(a, +b){b||eb(a);if(a.querySelectorAll)for(var d=a.querySelectorAll("*"),c=0,e=d.length;c=Ea?!1:"function"===typeof a&&/^(?:class\b|constructor\()/.test(Function.prototype.toString.call(a)+" ");return d?(c.unshift(null),new (Function.prototype.bind.apply(a,c))):a.apply(b,c)},instantiate:function(a,b,c){var d= +L(a)?a[a.length-1]:a;a=e(a,b,c);a.unshift(null);return new (Function.prototype.bind.apply(d,a))},get:d,annotate:cb.$$annotate,has:function(b){return n.hasOwnProperty(b+"Provider")||a.hasOwnProperty(b)}}}b=!0===b;var k={},l=[],m=new Ra([],!0),n={$provide:{provider:d(c),factory:d(f),service:d(function(a,b){return f(a,["$injector",function(a){return a.instantiate(b)}])}),value:d(function(a,b){return f(a,ha(b),!1)}),constant:d(function(a,b){Qa(a,"constant");n[a]=b;u[a]=b}),decorator:function(a,b){var c= +p.get(a+"Provider"),d=c.$get;c.$get=function(){var a=B.invoke(d,c);return B.invoke(b,null,{$delegate:a})}}}},p=n.$injector=h(n,function(a,b){ca.isString(b)&&l.push(b);throw Ha("unpr",l.join(" <- "));}),u={},R=h(u,function(a,b){var c=p.get(a+"Provider",b);return B.invoke(c.$get,c,void 0,a)}),B=R;n.$injectorProvider={$get:ha(R)};var r=g(a),B=R.get("$injector");B.strictDi=b;q(r,function(a){a&&B.invoke(a)});return B}function Xe(){var a=!0;this.disableAutoScrolling=function(){a=!1};this.$get=["$window", +"$location","$rootScope",function(b,d,c){function e(a){var b=null;Array.prototype.some.call(a,function(a){if("a"===wa(a))return b=a,!0});return b}function f(a){if(a){a.scrollIntoView();var c;c=g.yOffset;z(c)?c=c():Qb(c)?(c=c[0],c="fixed"!==b.getComputedStyle(c).position?0:c.getBoundingClientRect().bottom):T(c)||(c=0);c&&(a=a.getBoundingClientRect().top,b.scrollBy(0,a-c))}else b.scrollTo(0,0)}function g(a){a=G(a)?a:d.hash();var b;a?(b=h.getElementById(a))?f(b):(b=e(h.getElementsByName(a)))?f(b):"top"=== +a&&f(null):f(null)}var h=b.document;a&&c.$watch(function(){return d.hash()},function(a,b){a===b&&""===a||Qf(function(){c.$evalAsync(g)})});return g}]}function gb(a,b){if(!a&&!b)return"";if(!a)return b;if(!b)return a;L(a)&&(a=a.join(" "));L(b)&&(b=b.join(" "));return a+" "+b}function Zf(a){G(a)&&(a=a.split(" "));var b=U();q(a,function(a){a.length&&(b[a]=!0)});return b}function Ia(a){return D(a)?a:{}}function $f(a,b,d,c){function e(a){try{a.apply(null,va.call(arguments,1))}finally{if(R--,0===R)for(;B.length;)try{B.pop()()}catch(b){d.error(b)}}} +function f(){t=null;g();h()}function g(){r=K();r=y(r)?null:r;na(r,E)&&(r=E);E=r}function h(){if(v!==k.url()||J!==r)v=k.url(),J=r,q(M,function(a){a(k.url(),r)})}var k=this,l=a.location,m=a.history,n=a.setTimeout,p=a.clearTimeout,u={};k.isMock=!1;var R=0,B=[];k.$$completeOutstandingRequest=e;k.$$incOutstandingRequestCount=function(){R++};k.notifyWhenNoOutstandingRequests=function(a){0===R?a():B.push(a)};var r,J,v=l.href,fa=b.find("base"),t=null,K=c.history?function(){try{return m.state}catch(a){}}: +A;g();J=r;k.url=function(b,d,e){y(e)&&(e=null);l!==a.location&&(l=a.location);m!==a.history&&(m=a.history);if(b){var f=J===e;if(v===b&&(!c.history||f))return k;var h=v&&Ja(v)===Ja(b);v=b;J=e;!c.history||h&&f?(h||(t=b),d?l.replace(b):h?(d=l,e=b.indexOf("#"),e=-1===e?"":b.substr(e),d.hash=e):l.href=b,l.href!==b&&(t=b)):(m[d?"replaceState":"pushState"](e,"",b),g(),J=r);t&&(t=b);return k}return t||l.href.replace(/%27/g,"'")};k.state=function(){return r};var M=[],H=!1,E=null;k.onUrlChange=function(b){if(!H){if(c.history)F(a).on("popstate", +f);F(a).on("hashchange",f);H=!0}M.push(b);return b};k.$$applicationDestroyed=function(){F(a).off("hashchange popstate",f)};k.$$checkUrlChange=h;k.baseHref=function(){var a=fa.attr("href");return a?a.replace(/^(https?\:)?\/\/[^\/]*/,""):""};k.defer=function(a,b){var c;R++;c=n(function(){delete u[c];e(a)},b||0);u[c]=!0;return c};k.defer.cancel=function(a){return u[a]?(delete u[a],p(a),e(A),!0):!1}}function df(){this.$get=["$window","$log","$sniffer","$document",function(a,b,d,c){return new $f(a,c,b, +d)}]}function ef(){this.$get=function(){function a(a,c){function e(a){a!=n&&(p?p==a&&(p=a.n):p=a,f(a.n,a.p),f(a,n),n=a,n.n=null)}function f(a,b){a!=b&&(a&&(a.p=b),b&&(b.n=a))}if(a in b)throw N("$cacheFactory")("iid",a);var g=0,h=S({},c,{id:a}),k=U(),l=c&&c.capacity||Number.MAX_VALUE,m=U(),n=null,p=null;return b[a]={put:function(a,b){if(!y(b)){if(ll&&this.remove(p.key);return b}},get:function(a){if(l";b=pa.firstChild.attributes;var d=b[0];b.removeNamedItem(d.name);d.value=c;a.attributes.setNamedItem(d)}function x(a,b){try{a.addClass(b)}catch(c){}}function aa(a,b,c,d,e){a instanceof F||(a=F(a));for(var f=/\S+/,g=0,h=a.length;g< +h;g++){var k=a[g];k.nodeType===Ma&&k.nodeValue.match(f)&&Pc(k,a[g]=C.document.createElement("span"))}var l=s(a,b,a,c,d,e);aa.$$addScopeClass(a);var m=null;return function(b,c,d){sb(b,"scope");e&&e.needsNewScope&&(b=b.$parent.$new());d=d||{};var f=d.parentBoundTranscludeFn,g=d.transcludeControllers;d=d.futureParentElement;f&&f.$$boundTransclude&&(f=f.$$boundTransclude);m||(m=(d=d&&d[0])?"foreignobject"!==wa(d)&&ma.call(d).match(/SVG/)?"svg":"html":"html");d="html"!==m?F(da(m,F("
").append(a).html())): +c?Oa.clone.call(a):a;if(g)for(var h in g)d.data("$"+h+"Controller",g[h].instance);aa.$$addScopeInfo(d,b);c&&c(d,b);l&&l(b,d,d,f);return d}}function s(a,b,c,d,e,f){function g(a,c,d,e){var f,k,l,m,p,r,v;if(n)for(v=Array(c.length),m=0;mx.priority)break;if(w=x.scope)x.templateUrl||(D(w)?(X("new/isolated scope",u||r,x,t),u=x):X("new/isolated scope",u,x,t)),r=r||x;I=x.name;if(!Fa&&(x.replace&&(x.templateUrl||x.template)||x.transclude&& +!x.$$tlb)){for(w=A+1;Fa=a[w++];)if(Fa.transclude&&!Fa.$$tlb||Fa.replace&&(Fa.templateUrl||Fa.template)){za=!0;break}Fa=!0}!x.templateUrl&&x.controller&&(w=x.controller,v=v||U(),X("'"+I+"' controller",v[I],x,t),v[I]=x);if(w=x.transclude)if(M=!0,x.$$tlb||(X("transclusion",E,x,t),E=x),"element"==w)fa=!0,n=x.priority,P=t,t=d.$$element=F(aa.$$createComment(I,d[I])),b=t[0],ea(f,va.call(P,0),b),P[0].$$parentNode=P[0].parentNode,K=ac(za,P,e,n,g&&g.name,{nonTlbTranscludeDirective:E});else{var oa=U();P=F(Xb(b)).contents(); +if(D(w)){P=[];var Q=U(),O=U();q(w,function(a,b){var c="?"===a.charAt(0);a=c?a.substring(1):a;Q[a]=b;oa[b]=null;O[b]=c});q(t.contents(),function(a){var b=Q[Aa(wa(a))];b?(O[b]=!0,oa[b]=oa[b]||[],oa[b].push(a)):P.push(a)});q(O,function(a,b){if(!a)throw ga("reqslot",b);});for(var V in oa)oa[V]&&(oa[V]=ac(za,oa[V],e))}t.empty();K=ac(za,P,e,void 0,void 0,{needsNewScope:x.$$isolateScope||x.$$newScope});K.$$slots=oa}if(x.template)if(B=!0,X("template",H,x,t),H=x,w=z(x.template)?x.template(t,d):x.template, +w=xa(w),x.replace){g=x;P=Vb.test(w)?$c(da(x.templateNamespace,W(w))):[];b=P[0];if(1!=P.length||1!==b.nodeType)throw ga("tplrt",I,"");ea(f,t,b);C={$attr:{}};w=$b(b,[],C);var Z=a.splice(A+1,a.length-(A+1));(u||r)&&T(w,u,r);a=a.concat(w).concat(Z);$(d,C);C=a.length}else t.html(w);if(x.templateUrl)B=!0,X("template",H,x,t),H=x,x.replace&&(g=x),p=ba(a.splice(A,a.length-A),t,d,f,M&&K,h,k,{controllerDirectives:v,newScopeDirective:r!==x&&r,newIsolateScopeDirective:u,templateDirective:H,nonTlbTranscludeDirective:E}), +C=a.length;else if(x.compile)try{s=x.compile(t,d,K);var Y=x.$$originalDirective||x;z(s)?m(null,ab(Y,s),G,hb):s&&m(ab(Y,s.pre),ab(Y,s.post),G,hb)}catch(ca){c(ca,ya(t))}x.terminal&&(p.terminal=!0,n=Math.max(n,x.priority))}p.scope=r&&!0===r.scope;p.transcludeOnThisElement=M;p.templateOnThisElement=B;p.transclude=K;l.hasElementTranscludeDirective=fa;return p}function ib(a,b,c,d){var e;if(G(b)){var f=b.match(l);b=b.substring(f[0].length);var g=f[1]||f[3],f="?"===f[2];"^^"===g?c=c.parent():e=(e=d&&d[b])&& +e.instance;if(!e){var h="$"+b+"Controller";e=g?c.inheritedData(h):c.data(h)}if(!e&&!f)throw ga("ctreq",b,a);}else if(L(b))for(e=[],g=0,f=b.length;gp.priority)&&-1!=p.restrict.indexOf(g)){l&&(p=Rb(p,{$$start:l,$$end:m}));if(!p.$$bindings){var u=p,v=p,x=p.name,H={isolateScope:null,bindToController:null};D(v.scope)&&(!0===v.bindToController?(H.bindToController=d(v.scope,x,!0),H.isolateScope={}): +H.isolateScope=d(v.scope,x,!1));D(v.bindToController)&&(H.bindToController=d(v.bindToController,x,!0));if(D(H.bindToController)){var E=v.controller,M=v.controllerAs;if(!E)throw ga("noctrl",x);if(!Xc(E,M))throw ga("noident",x);}var t=u.$$bindings=H;D(t.isolateScope)&&(p.$$isolateBindings=t.isolateScope)}b.push(p);k=p}}catch(I){c(I)}}return k}function V(b){if(f.hasOwnProperty(b))for(var c=a.get(b+"Directive"),d=0,e=c.length;d"+b+"";return c.childNodes[0].childNodes;default:return b}}function ha(a,b){if("srcdoc"==b)return M.HTML;var c=wa(a);if("xlinkHref"==b||"form"==c&&"action"==b||"img"!= +c&&("src"==b||"ngSrc"==b))return M.RESOURCE_URL}function ia(a,c,d,e,f){var g=ha(a,e);f=k[e]||f;var h=b(d,!0,g,f);if(h){if("multiple"===e&&"select"===wa(a))throw ga("selmulti",ya(a));c.push({priority:100,compile:function(){return{pre:function(a,c,k){c=k.$$observers||(k.$$observers=U());if(m.test(e))throw ga("nodomevents");var l=k[e];l!==d&&(h=l&&b(l,!0,g,f),d=l);h&&(k[e]=h(a),(c[e]||(c[e]=[])).$$inter=!0,(k.$$observers&&k.$$observers[e].$$scope||a).$watch(h,function(a,b){"class"===e&&a!=b?k.$updateClass(a, +b):k.$set(e,a)}))}}}})}}function ea(a,b,c){var d=b[0],e=b.length,f=d.parentNode,g,h;if(a)for(g=0,h=a.length;g=b)return a;for(;b--;)8===a[b].nodeType&&bg.call(a,b,1);return a}function Xc(a,b){if(b&&G(b))return b;if(G(a)){var d=cd.exec(a);if(d)return d[3]}}function ff(){var a={},b=!1;this.has=function(b){return a.hasOwnProperty(b)};this.register=function(b,c){Qa(b,"controller");D(b)?S(a,b):a[b]=c};this.allowGlobals=function(){b=!0};this.$get=["$injector", +"$window",function(d,c){function e(a,b,c,d){if(!a||!D(a.$scope))throw N("$controller")("noscp",d,b);a.$scope[b]=c}return function(f,g,h,k){var l,m,n;h=!0===h;k&&G(k)&&(n=k);if(G(f)){k=f.match(cd);if(!k)throw cg("ctrlfmt",f);m=k[1];n=n||k[3];f=a.hasOwnProperty(m)?a[m]:Ec(g.$scope,m,!0)||(b?Ec(c,m,!0):void 0);Pa(f,m,!0)}if(h)return h=(L(f)?f[f.length-1]:f).prototype,l=Object.create(h||null),n&&e(g,n,l,m||f.name),S(function(){var a=d.invoke(f,l,g,m);a!==l&&(D(a)||z(a))&&(l=a,n&&e(g,n,l,m||f.name));return l}, +{instance:l,identifier:n});l=d.instantiate(f,g,m);n&&e(g,n,l,m||f.name);return l}}]}function gf(){this.$get=["$window",function(a){return F(a.document)}]}function hf(){this.$get=["$log",function(a){return function(b,d){a.error.apply(a,arguments)}}]}function cc(a){return D(a)?da(a)?a.toISOString():bb(a):a}function nf(){this.$get=function(){return function(a){if(!a)return"";var b=[];tc(a,function(a,c){null===a||y(a)||(L(a)?q(a,function(a){b.push(ea(c)+"="+ea(cc(a)))}):b.push(ea(c)+"="+ea(cc(a))))}); +return b.join("&")}}}function of(){this.$get=function(){return function(a){function b(a,e,f){null===a||y(a)||(L(a)?q(a,function(a,c){b(a,e+"["+(D(a)?c:"")+"]")}):D(a)&&!da(a)?tc(a,function(a,c){b(a,e+(f?"":"[")+c+(f?"":"]"))}):d.push(ea(e)+"="+ea(cc(a))))}if(!a)return"";var d=[];b(a,"",!0);return d.join("&")}}}function dc(a,b){if(G(a)){var d=a.replace(dg,"").trim();if(d){var c=b("Content-Type");(c=c&&0===c.indexOf(dd))||(c=(c=d.match(eg))&&fg[c[0]].test(d));c&&(a=xc(d))}}return a}function ed(a){var b= +U(),d;G(a)?q(a.split("\n"),function(a){d=a.indexOf(":");var e=Q(W(a.substr(0,d)));a=W(a.substr(d+1));e&&(b[e]=b[e]?b[e]+", "+a:a)}):D(a)&&q(a,function(a,d){var f=Q(d),g=W(a);f&&(b[f]=b[f]?b[f]+", "+g:g)});return b}function fd(a){var b;return function(d){b||(b=ed(a));return d?(d=b[Q(d)],void 0===d&&(d=null),d):b}}function gd(a,b,d,c){if(z(c))return c(a,b,d);q(c,function(c){a=c(a,b,d)});return a}function mf(){var a=this.defaults={transformResponse:[dc],transformRequest:[function(a){return D(a)&&"[object File]"!== +ma.call(a)&&"[object Blob]"!==ma.call(a)&&"[object FormData]"!==ma.call(a)?bb(a):a}],headers:{common:{Accept:"application/json, text/plain, */*"},post:ia(ec),put:ia(ec),patch:ia(ec)},xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",paramSerializer:"$httpParamSerializer"},b=!1;this.useApplyAsync=function(a){return w(a)?(b=!!a,this):b};var d=!0;this.useLegacyPromiseExtensions=function(a){return w(a)?(d=!!a,this):d};var c=this.interceptors=[];this.$get=["$httpBackend","$$cookieReader","$cacheFactory", +"$rootScope","$q","$injector",function(e,f,g,h,k,l){function m(b){function c(a,b){for(var d=0,e=b.length;da?b:k.reject(b)}if(!D(b))throw N("$http")("badreq",b);if(!G(b.url))throw N("$http")("badreq",b.url);var g=S({method:"get",transformRequest:a.transformRequest, +transformResponse:a.transformResponse,paramSerializer:a.paramSerializer},b);g.headers=function(b){var c=a.headers,d=S({},b.headers),f,g,h,c=S({},c.common,c[Q(b.method)]);a:for(f in c){g=Q(f);for(h in d)if(Q(h)===g)continue a;d[f]=c[f]}return e(d,ia(b))}(b);g.method=ub(g.method);g.paramSerializer=G(g.paramSerializer)?l.get(g.paramSerializer):g.paramSerializer;var h=[],m=[],p=k.when(g);q(R,function(a){(a.request||a.requestError)&&h.unshift(a.request,a.requestError);(a.response||a.responseError)&&m.push(a.response, +a.responseError)});p=c(p,h);p=p.then(function(b){var c=b.headers,d=gd(b.data,fd(c),void 0,b.transformRequest);y(d)&&q(c,function(a,b){"content-type"===Q(b)&&delete c[b]});y(b.withCredentials)&&!y(a.withCredentials)&&(b.withCredentials=a.withCredentials);return n(b,d).then(f,f)});p=c(p,m);d?(p.success=function(a){Pa(a,"fn");p.then(function(b){a(b.data,b.status,b.headers,g)});return p},p.error=function(a){Pa(a,"fn");p.then(null,function(b){a(b.data,b.status,b.headers,g)});return p}):(p.success=hd("success"), +p.error=hd("error"));return p}function n(c,d){function g(a){if(a){var c={};q(a,function(a,d){c[d]=function(c){function d(){a(c)}b?h.$applyAsync(d):h.$$phase?d():h.$apply(d)}});return c}}function l(a,c,d,e){function f(){n(c,a,d,e)}E&&(200<=a&&300>a?E.put(P,[a,c,ed(d),e]):E.remove(P));b?h.$applyAsync(f):(f(),h.$$phase||h.$apply())}function n(a,b,d,e){b=-1<=b?b:0;(200<=b&&300>b?M.resolve:M.reject)({data:a,status:b,headers:fd(d),config:c,statusText:e})}function t(a){n(a.data,a.status,ia(a.headers()), +a.statusText)}function R(){var a=m.pendingRequests.indexOf(c);-1!==a&&m.pendingRequests.splice(a,1)}var M=k.defer(),H=M.promise,E,I,Da=c.headers,P=p(c.url,c.paramSerializer(c.params));m.pendingRequests.push(c);H.then(R,R);!c.cache&&!a.cache||!1===c.cache||"GET"!==c.method&&"JSONP"!==c.method||(E=D(c.cache)?c.cache:D(a.cache)?a.cache:u);E&&(I=E.get(P),w(I)?I&&z(I.then)?I.then(t,t):L(I)?n(I[1],I[0],ia(I[2]),I[3]):n(I,200,{},"OK"):E.put(P,H));y(I)&&((I=id(c.url)?f()[c.xsrfCookieName||a.xsrfCookieName]: +void 0)&&(Da[c.xsrfHeaderName||a.xsrfHeaderName]=I),e(c.method,P,d,l,Da,c.timeout,c.withCredentials,c.responseType,g(c.eventHandlers),g(c.uploadEventHandlers)));return H}function p(a,b){0=l&&(v.resolve(r),q(fa.$$intervalId),delete g[fa.$$intervalId]);J||a.$apply()},k);g[fa.$$intervalId]=v;return fa}var g={};f.cancel=function(a){return a&&a.$$intervalId in g?(g[a.$$intervalId].reject("canceled"),b.clearInterval(a.$$intervalId), +delete g[a.$$intervalId],!0):!1};return f}]}function fc(a){a=a.split("/");for(var b=a.length;b--;)a[b]=qb(a[b]);return a.join("/")}function jd(a,b){var d=Y(a);b.$$protocol=d.protocol;b.$$host=d.hostname;b.$$port=Z(d.port)||hg[d.protocol]||null}function kd(a,b){var d="/"!==a.charAt(0);d&&(a="/"+a);var c=Y(a);b.$$path=decodeURIComponent(d&&"/"===c.pathname.charAt(0)?c.pathname.substring(1):c.pathname);b.$$search=Ac(c.search);b.$$hash=decodeURIComponent(c.hash);b.$$path&&"/"!=b.$$path.charAt(0)&&(b.$$path= +"/"+b.$$path)}function ka(a,b){if(0===b.lastIndexOf(a,0))return b.substr(a.length)}function Ja(a){var b=a.indexOf("#");return-1==b?a:a.substr(0,b)}function jb(a){return a.replace(/(#.+)|#$/,"$1")}function gc(a,b,d){this.$$html5=!0;d=d||"";jd(a,this);this.$$parse=function(a){var d=ka(b,a);if(!G(d))throw Gb("ipthprfx",a,b);kd(d,this);this.$$path||(this.$$path="/");this.$$compose()};this.$$compose=function(){var a=Tb(this.$$search),d=this.$$hash?"#"+qb(this.$$hash):"";this.$$url=fc(this.$$path)+(a?"?"+ +a:"")+d;this.$$absUrl=b+this.$$url.substr(1)};this.$$parseLinkUrl=function(c,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),!0;var f,g;w(f=ka(a,c))?(g=f,g=w(f=ka(d,f))?b+(ka("/",f)||f):a+g):w(f=ka(b,c))?g=b+f:b==c+"/"&&(g=b);g&&this.$$parse(g);return!!g}}function hc(a,b,d){jd(a,this);this.$$parse=function(c){var e=ka(a,c)||ka(b,c),f;y(e)||"#"!==e.charAt(0)?this.$$html5?f=e:(f="",y(e)&&(a=c,this.replace())):(f=ka(d,e),y(f)&&(f=e));kd(f,this);c=this.$$path;var e=a,g=/^\/[A-Z]:(\/.*)/;0===f.lastIndexOf(e, +0)&&(f=f.replace(e,""));g.exec(f)||(c=(f=g.exec(c))?f[1]:c);this.$$path=c;this.$$compose()};this.$$compose=function(){var b=Tb(this.$$search),e=this.$$hash?"#"+qb(this.$$hash):"";this.$$url=fc(this.$$path)+(b?"?"+b:"")+e;this.$$absUrl=a+(this.$$url?d+this.$$url:"")};this.$$parseLinkUrl=function(b,d){return Ja(a)==Ja(b)?(this.$$parse(b),!0):!1}}function ld(a,b,d){this.$$html5=!0;hc.apply(this,arguments);this.$$parseLinkUrl=function(c,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),!0;var f,g;a==Ja(c)? +f=c:(g=ka(b,c))?f=a+d+g:b===c+"/"&&(f=b);f&&this.$$parse(f);return!!f};this.$$compose=function(){var b=Tb(this.$$search),e=this.$$hash?"#"+qb(this.$$hash):"";this.$$url=fc(this.$$path)+(b?"?"+b:"")+e;this.$$absUrl=a+d+this.$$url}}function Hb(a){return function(){return this[a]}}function md(a,b){return function(d){if(y(d))return this[a];this[a]=b(d);this.$$compose();return this}}function sf(){var a="",b={enabled:!1,requireBase:!0,rewriteLinks:!0};this.hashPrefix=function(b){return w(b)?(a=b,this): +a};this.html5Mode=function(a){return Ga(a)?(b.enabled=a,this):D(a)?(Ga(a.enabled)&&(b.enabled=a.enabled),Ga(a.requireBase)&&(b.requireBase=a.requireBase),Ga(a.rewriteLinks)&&(b.rewriteLinks=a.rewriteLinks),this):b};this.$get=["$rootScope","$browser","$sniffer","$rootElement","$window",function(d,c,e,f,g){function h(a,b,d){var e=l.url(),f=l.$$state;try{c.url(a,b,d),l.$$state=c.state()}catch(g){throw l.url(e),l.$$state=f,g;}}function k(a,b){d.$broadcast("$locationChangeSuccess",l.absUrl(),a,l.$$state, +b)}var l,m;m=c.baseHref();var n=c.url(),p;if(b.enabled){if(!m&&b.requireBase)throw Gb("nobase");p=n.substring(0,n.indexOf("/",n.indexOf("//")+2))+(m||"/");m=e.history?gc:ld}else p=Ja(n),m=hc;var u=p.substr(0,Ja(p).lastIndexOf("/")+1);l=new m(p,u,"#"+a);l.$$parseLinkUrl(n,n);l.$$state=c.state();var R=/^\s*(javascript|mailto):/i;f.on("click",function(a){if(b.rewriteLinks&&!a.ctrlKey&&!a.metaKey&&!a.shiftKey&&2!=a.which&&2!=a.button){for(var e=F(a.target);"a"!==wa(e[0]);)if(e[0]===f[0]||!(e=e.parent())[0])return; +var h=e.prop("href"),k=e.attr("href")||e.attr("xlink:href");D(h)&&"[object SVGAnimatedString]"===h.toString()&&(h=Y(h.animVal).href);R.test(h)||!h||e.attr("target")||a.isDefaultPrevented()||!l.$$parseLinkUrl(h,k)||(a.preventDefault(),l.absUrl()!=c.url()&&(d.$apply(),g.angular["ff-684208-preventDefault"]=!0))}});jb(l.absUrl())!=jb(n)&&c.url(l.absUrl(),!0);var q=!0;c.onUrlChange(function(a,b){y(ka(u,a))?g.location.href=a:(d.$evalAsync(function(){var c=l.absUrl(),e=l.$$state,f;a=jb(a);l.$$parse(a);l.$$state= +b;f=d.$broadcast("$locationChangeStart",a,c,b,e).defaultPrevented;l.absUrl()===a&&(f?(l.$$parse(c),l.$$state=e,h(c,!1,e)):(q=!1,k(c,e)))}),d.$$phase||d.$digest())});d.$watch(function(){var a=jb(c.url()),b=jb(l.absUrl()),f=c.state(),g=l.$$replace,m=a!==b||l.$$html5&&e.history&&f!==l.$$state;if(q||m)q=!1,d.$evalAsync(function(){var b=l.absUrl(),c=d.$broadcast("$locationChangeStart",b,a,l.$$state,f).defaultPrevented;l.absUrl()===b&&(c?(l.$$parse(a),l.$$state=f):(m&&h(b,g,f===l.$$state?null:l.$$state), +k(a,f)))});l.$$replace=!1});return l}]}function tf(){var a=!0,b=this;this.debugEnabled=function(b){return w(b)?(a=b,this):a};this.$get=["$window",function(d){function c(a){a instanceof Error&&(a.stack?a=a.message&&-1===a.stack.indexOf(a.message)?"Error: "+a.message+"\n"+a.stack:a.stack:a.sourceURL&&(a=a.message+"\n"+a.sourceURL+":"+a.line));return a}function e(a){var b=d.console||{},e=b[a]||b.log||A;a=!1;try{a=!!e.apply}catch(k){}return a?function(){var a=[];q(arguments,function(b){a.push(c(b))}); +return e.apply(b,a)}:function(a,b){e(a,null==b?"":b)}}return{log:e("log"),info:e("info"),warn:e("warn"),error:e("error"),debug:function(){var c=e("debug");return function(){a&&c.apply(b,arguments)}}()}}]}function Sa(a,b){if("__defineGetter__"===a||"__defineSetter__"===a||"__lookupGetter__"===a||"__lookupSetter__"===a||"__proto__"===a)throw X("isecfld",b);return a}function ig(a){return a+""}function ra(a,b){if(a){if(a.constructor===a)throw X("isecfn",b);if(a.window===a)throw X("isecwindow",b);if(a.children&& +(a.nodeName||a.prop&&a.attr&&a.find))throw X("isecdom",b);if(a===Object)throw X("isecobj",b);}return a}function nd(a,b){if(a){if(a.constructor===a)throw X("isecfn",b);if(a===jg||a===kg||a===lg)throw X("isecff",b);}}function Ib(a,b){if(a&&(a===(0).constructor||a===(!1).constructor||a==="".constructor||a==={}.constructor||a===[].constructor||a===Function.constructor))throw X("isecaf",b);}function mg(a,b){return"undefined"!==typeof a?a:b}function od(a,b){return"undefined"===typeof a?b:"undefined"=== +typeof b?a:a+b}function V(a,b){var d,c;switch(a.type){case s.Program:d=!0;q(a.body,function(a){V(a.expression,b);d=d&&a.expression.constant});a.constant=d;break;case s.Literal:a.constant=!0;a.toWatch=[];break;case s.UnaryExpression:V(a.argument,b);a.constant=a.argument.constant;a.toWatch=a.argument.toWatch;break;case s.BinaryExpression:V(a.left,b);V(a.right,b);a.constant=a.left.constant&&a.right.constant;a.toWatch=a.left.toWatch.concat(a.right.toWatch);break;case s.LogicalExpression:V(a.left,b);V(a.right, +b);a.constant=a.left.constant&&a.right.constant;a.toWatch=a.constant?[]:[a];break;case s.ConditionalExpression:V(a.test,b);V(a.alternate,b);V(a.consequent,b);a.constant=a.test.constant&&a.alternate.constant&&a.consequent.constant;a.toWatch=a.constant?[]:[a];break;case s.Identifier:a.constant=!1;a.toWatch=[a];break;case s.MemberExpression:V(a.object,b);a.computed&&V(a.property,b);a.constant=a.object.constant&&(!a.computed||a.property.constant);a.toWatch=[a];break;case s.CallExpression:d=a.filter?!b(a.callee.name).$stateful: +!1;c=[];q(a.arguments,function(a){V(a,b);d=d&&a.constant;a.constant||c.push.apply(c,a.toWatch)});a.constant=d;a.toWatch=a.filter&&!b(a.callee.name).$stateful?c:[a];break;case s.AssignmentExpression:V(a.left,b);V(a.right,b);a.constant=a.left.constant&&a.right.constant;a.toWatch=[a];break;case s.ArrayExpression:d=!0;c=[];q(a.elements,function(a){V(a,b);d=d&&a.constant;a.constant||c.push.apply(c,a.toWatch)});a.constant=d;a.toWatch=c;break;case s.ObjectExpression:d=!0;c=[];q(a.properties,function(a){V(a.value, +b);d=d&&a.value.constant&&!a.computed;a.value.constant||c.push.apply(c,a.value.toWatch)});a.constant=d;a.toWatch=c;break;case s.ThisExpression:a.constant=!1;a.toWatch=[];break;case s.LocalsExpression:a.constant=!1,a.toWatch=[]}}function pd(a){if(1==a.length){a=a[0].expression;var b=a.toWatch;return 1!==b.length?b:b[0]!==a?b:void 0}}function qd(a){return a.type===s.Identifier||a.type===s.MemberExpression}function rd(a){if(1===a.body.length&&qd(a.body[0].expression))return{type:s.AssignmentExpression, +left:a.body[0].expression,right:{type:s.NGValueParameter},operator:"="}}function sd(a){return 0===a.body.length||1===a.body.length&&(a.body[0].expression.type===s.Literal||a.body[0].expression.type===s.ArrayExpression||a.body[0].expression.type===s.ObjectExpression)}function td(a,b){this.astBuilder=a;this.$filter=b}function ud(a,b){this.astBuilder=a;this.$filter=b}function Jb(a){return"constructor"==a}function ic(a){return z(a.valueOf)?a.valueOf():ng.call(a)}function uf(){var a=U(),b=U(),d={"true":!0, +"false":!1,"null":null,undefined:void 0},c,e;this.addLiteral=function(a,b){d[a]=b};this.setIdentifierFns=function(a,b){c=a;e=b;return this};this.$get=["$filter",function(f){function g(c,d,e){var g,k,H;e=e||J;switch(typeof c){case "string":H=c=c.trim();var E=e?b:a;g=E[H];if(!g){":"===c.charAt(0)&&":"===c.charAt(1)&&(k=!0,c=c.substring(2));g=e?r:B;var q=new jc(g);g=(new kc(q,f,g)).parse(c);g.constant?g.$$watchDelegate=p:k?g.$$watchDelegate=g.literal?n:m:g.inputs&&(g.$$watchDelegate=l);e&&(g=h(g));E[H]= +g}return u(g,d);case "function":return u(c,d);default:return u(A,d)}}function h(a){function b(c,d,e,f){var g=J;J=!0;try{return a(c,d,e,f)}finally{J=g}}if(!a)return a;b.$$watchDelegate=a.$$watchDelegate;b.assign=h(a.assign);b.constant=a.constant;b.literal=a.literal;for(var c=0;a.inputs&&c=this.promise.$$state.status&&d&&d.length&&a(function(){for(var a,e,f=0,g=d.length;fa)for(b in l++,f)ua.call(e,b)||(u--,delete f[b])}else f!==e&&(f=e,l++);return l}}c.$stateful=!0;var d=this,e,f,h,k=1q&&(A=4-q,y[A]||(y[A]=[]),y[A].push({msg:z(a.exp)?"fn: "+(a.exp.name||a.exp.toString()):a.exp,newVal:g,oldVal:k}));else if(a===c){r=!1;break a}}catch(G){f(G)}if(!(p=t.$$watchersCount&&t.$$childHead||t!==this&&t.$$nextSibling))for(;t!==this&&!(p=t.$$nextSibling);)t=t.$parent}while(t=p);if((r||v.length)&& +!q--)throw J.$$phase=null,d("infdig",b,y);}while(r||v.length);for(J.$$phase=null;KEa)throw sa("iequirks");var c=ia(la);c.isEnabled=function(){return a};c.trustAs=d.trustAs;c.getTrusted=d.getTrusted;c.valueOf=d.valueOf;a||(c.trustAs=c.getTrusted=function(a,b){return b},c.valueOf=Xa);c.parseAs=function(a,d){var e=b(d);return e.literal&&e.constant?e:b(d,function(b){return c.getTrusted(a,b)})};var e=c.parseAs, +f=c.getTrusted,g=c.trustAs;q(la,function(a,b){var d=Q(b);c[db("parse_as_"+d)]=function(b){return e(a,b)};c[db("get_trusted_"+d)]=function(b){return f(a,b)};c[db("trust_as_"+d)]=function(b){return g(a,b)}});return c}]}function Af(){this.$get=["$window","$document",function(a,b){var d={},c=!(a.chrome&&a.chrome.app&&a.chrome.app.runtime)&&a.history&&a.history.pushState,e=Z((/android (\d+)/.exec(Q((a.navigator||{}).userAgent))||[])[1]),f=/Boxee/i.test((a.navigator||{}).userAgent),g=b[0]||{},h,k=/^(Moz|webkit|ms)(?=[A-Z])/, +l=g.body&&g.body.style,m=!1,n=!1;if(l){for(var p in l)if(m=k.exec(p)){h=m[0];h=h[0].toUpperCase()+h.substr(1);break}h||(h="WebkitOpacity"in l&&"webkit");m=!!("transition"in l||h+"Transition"in l);n=!!("animation"in l||h+"Animation"in l);!e||m&&n||(m=G(l.webkitTransition),n=G(l.webkitAnimation))}return{history:!(!c||4>e||f),hasEvent:function(a){if("input"===a&&11>=Ea)return!1;if(y(d[a])){var b=g.createElement("div");d[a]="on"+a in b}return d[a]},csp:Ba(),vendorPrefix:h,transitions:m,animations:n,android:e}}]} +function Cf(){var a;this.httpOptions=function(b){return b?(a=b,this):a};this.$get=["$templateCache","$http","$q","$sce",function(b,d,c,e){function f(g,h){f.totalPendingRequests++;if(!G(g)||y(b.get(g)))g=e.getTrustedResourceUrl(g);var k=d.defaults&&d.defaults.transformResponse;L(k)?k=k.filter(function(a){return a!==dc}):k===dc&&(k=null);return d.get(g,S({cache:b,transformResponse:k},a))["finally"](function(){f.totalPendingRequests--}).then(function(a){b.put(g,a.data);return a.data},function(a){if(!h)throw pg("tpload", +g,a.status,a.statusText);return c.reject(a)})}f.totalPendingRequests=0;return f}]}function Df(){this.$get=["$rootScope","$browser","$location",function(a,b,d){return{findBindings:function(a,b,d){a=a.getElementsByClassName("ng-binding");var g=[];q(a,function(a){var c=ca.element(a).data("$binding");c&&q(c,function(c){d?(new RegExp("(^|\\s)"+wd(b)+"(\\s|\\||$)")).test(c)&&g.push(a):-1!=c.indexOf(b)&&g.push(a)})});return g},findModels:function(a,b,d){for(var g=["ng-","data-ng-","ng\\:"],h=0;hc&&(c=e),c+=+a.slice(e+1),a=a.substring(0,e)):0>c&&(c=a.length);for(e=0;a.charAt(e)==mc;e++); +if(e==(g=a.length))d=[0],c=1;else{for(g--;a.charAt(g)==mc;)g--;c-=e;d=[];for(f=0;e<=g;e++,f++)d[f]=+a.charAt(e)}c>Gd&&(d=d.splice(0,Gd-1),b=c-1,c=1);return{d:d,e:b,i:c}}function xg(a,b,d,c){var e=a.d,f=e.length-a.i;b=y(b)?Math.min(Math.max(d,f),c):+b;d=b+a.i;c=e[d];if(0d-1){for(c=0;c>d;c--)e.unshift(0),a.i++;e.unshift(1);a.i++}else e[d-1]++; +for(;fh;)k.unshift(0),h++;0=b.lgSize&&h.unshift(k.splice(-b.lgSize,k.length).join(""));k.length> +b.gSize;)h.unshift(k.splice(-b.gSize,k.length).join(""));k.length&&h.unshift(k.join(""));k=h.join(d);f.length&&(k+=c+f.join(""));e&&(k+="e+"+e)}return 0>a&&!g?b.negPre+k+b.negSuf:b.posPre+k+b.posSuf}function Kb(a,b,d,c){var e="";if(0>a||c&&0>=a)c?a=-a+1:(a=-a,e="-");for(a=""+a;a.length-d)f+=d;0===f&&-12==d&&(f=12);return Kb(f,b,c,e)}}function kb(a,b,d){return function(c,e){var f= +c["get"+a](),g=ub((d?"STANDALONE":"")+(b?"SHORT":"")+a);return e[g][f]}}function Hd(a){var b=(new Date(a,0,1)).getDay();return new Date(a,0,(4>=b?5:12)-b)}function Id(a){return function(b){var d=Hd(b.getFullYear());b=+new Date(b.getFullYear(),b.getMonth(),b.getDate()+(4-b.getDay()))-+d;b=1+Math.round(b/6048E5);return Kb(b,a)}}function nc(a,b){return 0>=a.getFullYear()?b.ERAS[0]:b.ERAS[1]}function Bd(a){function b(a){var b;if(b=a.match(d)){a=new Date(0);var f=0,g=0,h=b[8]?a.setUTCFullYear:a.setFullYear, +k=b[8]?a.setUTCHours:a.setHours;b[9]&&(f=Z(b[9]+b[10]),g=Z(b[9]+b[11]));h.call(a,Z(b[1]),Z(b[2])-1,Z(b[3]));f=Z(b[4]||0)-f;g=Z(b[5]||0)-g;h=Z(b[6]||0);b=Math.round(1E3*parseFloat("0."+(b[7]||0)));k.call(a,f,g,h,b)}return a}var d=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(c,d,f){var g="",h=[],k,l;d=d||"mediumDate";d=a.DATETIME_FORMATS[d]||d;G(c)&&(c=yg.test(c)?Z(c):b(c));T(c)&&(c=new Date(c));if(!da(c)||!isFinite(c.getTime()))return c; +for(;d;)(l=zg.exec(d))?(h=$a(h,l,1),d=h.pop()):(h.push(d),d=null);var m=c.getTimezoneOffset();f&&(m=yc(f,m),c=Sb(c,f,!0));q(h,function(b){k=Ag[b];g+=k?k(c,a.DATETIME_FORMATS,m):"''"===b?"'":b.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return g}}function rg(){return function(a,b){y(b)&&(b=2);return bb(a,b)}}function sg(){return function(a,b,d){b=Infinity===Math.abs(Number(b))?Number(b):Z(b);if(isNaN(b))return a;T(a)&&(a=a.toString());if(!ta(a))return a;d=!d||isNaN(d)?0:Z(d);d=0>d?Math.max(0,a.length+ +d):d;return 0<=b?oc(a,d,d+b):0===d?oc(a,b,a.length):oc(a,Math.max(0,d+b),d)}}function oc(a,b,d){return G(a)?a.slice(b,d):va.call(a,b,d)}function Dd(a){function b(b){return b.map(function(b){var c=1,d=Xa;if(z(b))d=b;else if(G(b)){if("+"==b.charAt(0)||"-"==b.charAt(0))c="-"==b.charAt(0)?-1:1,b=b.substring(1);if(""!==b&&(d=a(b),d.constant))var e=d(),d=function(a){return a[e]}}return{get:d,descending:c}})}function d(a){switch(typeof a){case "number":case "boolean":case "string":return!0;default:return!1}} +function c(a,b){var c=0,d=a.type,k=b.type;if(d===k){var k=a.value,l=b.value;"string"===d?(k=k.toLowerCase(),l=l.toLowerCase()):"object"===d&&(D(k)&&(k=a.index),D(l)&&(l=b.index));k!==l&&(c=kb||37<=b&&40>=b|| +m(a,this,this.value)});if(e.hasEvent("paste"))b.on("paste cut",m)}b.on("change",l);if(Ld[g]&&c.$$hasNativeValidators&&g===d.type)b.on("keydown wheel mousedown",function(a){if(!k){var b=this.validity,c=b.badInput,d=b.typeMismatch;k=f.defer(function(){k=null;b.badInput===c&&b.typeMismatch===d||l(a)})}});c.$render=function(){var a=c.$isEmpty(c.$viewValue)?"":c.$viewValue;b.val()!==a&&b.val(a)}}function Nb(a,b){return function(d,c){var e,f;if(da(d))return d;if(G(d)){'"'==d.charAt(0)&&'"'==d.charAt(d.length- +1)&&(d=d.substring(1,d.length-1));if(Bg.test(d))return new Date(d);a.lastIndex=0;if(e=a.exec(d))return e.shift(),f=c?{yyyy:c.getFullYear(),MM:c.getMonth()+1,dd:c.getDate(),HH:c.getHours(),mm:c.getMinutes(),ss:c.getSeconds(),sss:c.getMilliseconds()/1E3}:{yyyy:1970,MM:1,dd:1,HH:0,mm:0,ss:0,sss:0},q(e,function(a,c){c=s};g.$observe("min", +function(a){s=p(a);h.$validate()})}if(w(g.max)||g.ngMax){var r;h.$validators.max=function(a){return!n(a)||y(r)||d(a)<=r};g.$observe("max",function(a){r=p(a);h.$validate()})}}}function Md(a,b,d,c){(c.$$hasNativeValidators=D(b[0].validity))&&c.$parsers.push(function(a){var c=b.prop("validity")||{};return c.badInput||c.typeMismatch?void 0:a})}function Nd(a,b,d,c,e){if(w(c)){a=a(c);if(!a.constant)throw nb("constexpr",d,c);return a(b)}return e}function qc(a,b){a="ngClass"+a;return["$animate",function(d){function c(a, +b){var c=[],d=0;a:for(;d(?:<\/\1>|)$/,Vb=/<|&#?\w+;/,Mf=/<([\w:-]+)/,Nf=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi, +ja={option:[1,'"],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ja.optgroup=ja.option;ja.tbody=ja.tfoot=ja.colgroup=ja.caption=ja.thead;ja.th=ja.td;var Uf=C.Node.prototype.contains||function(a){return!!(this.compareDocumentPosition(a)&16)},Oa=O.prototype={ready:function(a){function b(){d||(d=!0,a())}var d=!1;"complete"=== +C.document.readyState?C.setTimeout(b):(this.on("DOMContentLoaded",b),O(C).on("load",b))},toString:function(){var a=[];q(this,function(b){a.push(""+b)});return"["+a.join(", ")+"]"},eq:function(a){return 0<=a?F(this[a]):F(this[this.length+a])},length:0,push:Dg,sort:[].sort,splice:[].splice},Eb={};q("multiple selected checked disabled readOnly required open".split(" "),function(a){Eb[Q(a)]=a});var Vc={};q("input select option textarea button form details".split(" "),function(a){Vc[a]=!0});var bd={ngMinlength:"minlength", +ngMaxlength:"maxlength",ngMin:"min",ngMax:"max",ngPattern:"pattern"};q({data:Yb,removeData:eb,hasData:function(a){for(var b in fb[a.ng339])return!0;return!1},cleanData:function(a){for(var b=0,d=a.length;b/,Xf=/^[^\(]*\(\s*([^\)]*)\)/m,Eg=/,/,Fg=/^\s*(_?)(\S+?)\1\s*$/,Vf=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg,Ha=N("$injector");cb.$$annotate=function(a,b,d){var c;if("function"===typeof a){if(!(c=a.$inject)){c=[];if(a.length){if(b)throw G(d)&&d||(d=a.name||Yf(a)),Ha("strictdi",d); +b=Wc(a);q(b[1].split(Eg),function(a){a.replace(Fg,function(a,b,d){c.push(d)})})}a.$inject=c}}else L(a)?(b=a.length-1,Pa(a[b],"fn"),c=a.slice(0,b)):Pa(a,"fn",!0);return c};var Rd=N("$animate"),$e=function(){this.$get=A},af=function(){var a=new Ra,b=[];this.$get=["$$AnimateRunner","$rootScope",function(d,c){function e(a,b,c){var d=!1;b&&(b=G(b)?b.split(" "):L(b)?b:[],q(b,function(b){b&&(d=!0,a[b]=c)}));return d}function f(){q(b,function(b){var c=a.get(b);if(c){var d=Zf(b.attr("class")),e="",f="";q(c, +function(a,b){a!==!!d[b]&&(a?e+=(e.length?" ":"")+b:f+=(f.length?" ":"")+b)});q(b,function(a){e&&Bb(a,e);f&&Ab(a,f)});a.remove(b)}});b.length=0}return{enabled:A,on:A,off:A,pin:A,push:function(g,h,k,l){l&&l();k=k||{};k.from&&g.css(k.from);k.to&&g.css(k.to);if(k.addClass||k.removeClass)if(h=k.addClass,l=k.removeClass,k=a.get(g)||{},h=e(k,h,!0),l=e(k,l,!1),h||l)a.put(g,k),b.push(g),1===b.length&&c.$$postDigest(f);g=new d;g.complete();return g}}}]},Ye=["$provide",function(a){var b=this;this.$$registeredAnimations= +Object.create(null);this.register=function(d,c){if(d&&"."!==d.charAt(0))throw Rd("notcsel",d);var e=d+"-animation";b.$$registeredAnimations[d.substr(1)]=e;a.factory(e,c)};this.classNameFilter=function(a){if(1===arguments.length&&(this.$$classNameFilter=a instanceof RegExp?a:null)&&/(\s+|\/)ng-animate(\s+|\/)/.test(this.$$classNameFilter.toString()))throw Rd("nongcls","ng-animate");return this.$$classNameFilter};this.$get=["$$animateQueue",function(a){function b(a,c,d){if(d){var h;a:{for(h=0;h <= >= && || ! = |".split(" "),function(a){Ob[a]=!0});var Jg={n:"\n",f:"\f",r:"\r",t:"\t",v:"\v","'":"'",'"':'"'},jc=function(a){this.options=a};jc.prototype={constructor:jc, +lex:function(a){this.text=a;this.index=0;for(this.tokens=[];this.index=a&&"string"===typeof a},isWhitespace:function(a){return" "===a||"\r"===a||"\t"===a||"\n"===a||"\v"===a||"\u00a0"===a},isIdentifierStart:function(a){return this.options.isIdentifierStart? +this.options.isIdentifierStart(a,this.codePointAt(a)):this.isValidIdentifierStart(a)},isValidIdentifierStart:function(a){return"a"<=a&&"z">=a||"A"<=a&&"Z">=a||"_"===a||"$"===a},isIdentifierContinue:function(a){return this.options.isIdentifierContinue?this.options.isIdentifierContinue(a,this.codePointAt(a)):this.isValidIdentifierContinue(a)},isValidIdentifierContinue:function(a,b){return this.isValidIdentifierStart(a,b)||this.isNumber(a)},codePointAt:function(a){return 1===a.length?a.charCodeAt(0): +(a.charCodeAt(0)<<10)+a.charCodeAt(1)-56613888},peekMultichar:function(){var a=this.text.charAt(this.index),b=this.peek();if(!b)return a;var d=a.charCodeAt(0),c=b.charCodeAt(0);return 55296<=d&&56319>=d&&56320<=c&&57343>=c?a+b:a},isExpOperator:function(a){return"-"===a||"+"===a||this.isNumber(a)},throwError:function(a,b,d){d=d||this.index;b=w(b)?"s "+b+"-"+this.index+" ["+this.text.substring(b,d)+"]":" "+d;throw X("lexerr",a,b,this.text);},readNumber:function(){for(var a="",b=this.index;this.index< +this.text.length;){var d=Q(this.text.charAt(this.index));if("."==d||this.isNumber(d))a+=d;else{var c=this.peek();if("e"==d&&this.isExpOperator(c))a+=d;else if(this.isExpOperator(d)&&c&&this.isNumber(c)&&"e"==a.charAt(a.length-1))a+=d;else if(!this.isExpOperator(d)||c&&this.isNumber(c)||"e"!=a.charAt(a.length-1))break;else this.throwError("Invalid exponent")}this.index++}this.tokens.push({index:b,text:a,constant:!0,value:Number(a)})},readIdent:function(){var a=this.index;for(this.index+=this.peekMultichar().length;this.index< +this.text.length;){var b=this.peekMultichar();if(!this.isIdentifierContinue(b))break;this.index+=b.length}this.tokens.push({index:a,text:this.text.slice(a,this.index),identifier:!0})},readString:function(a){var b=this.index;this.index++;for(var d="",c=a,e=!1;this.index","<=",">=");)a={type:s.BinaryExpression,operator:b.text,left:a,right:this.additive()};return a},additive:function(){for(var a=this.multiplicative(),b;b=this.expect("+","-");)a={type:s.BinaryExpression,operator:b.text, +left:a,right:this.multiplicative()};return a},multiplicative:function(){for(var a=this.unary(),b;b=this.expect("*","/","%");)a={type:s.BinaryExpression,operator:b.text,left:a,right:this.unary()};return a},unary:function(){var a;return(a=this.expect("+","-","!"))?{type:s.UnaryExpression,operator:a.text,prefix:!0,argument:this.unary()}:this.primary()},primary:function(){var a;this.expect("(")?(a=this.filterChain(),this.consume(")")):this.expect("[")?a=this.arrayDeclaration():this.expect("{")?a=this.object(): +this.selfReferential.hasOwnProperty(this.peek().text)?a=pa(this.selfReferential[this.consume().text]):this.options.literals.hasOwnProperty(this.peek().text)?a={type:s.Literal,value:this.options.literals[this.consume().text]}:this.peek().identifier?a=this.identifier():this.peek().constant?a=this.constant():this.throwError("not a primary expression",this.peek());for(var b;b=this.expect("(","[",".");)"("===b.text?(a={type:s.CallExpression,callee:a,arguments:this.parseArguments()},this.consume(")")): +"["===b.text?(a={type:s.MemberExpression,object:a,property:this.expression(),computed:!0},this.consume("]")):"."===b.text?a={type:s.MemberExpression,object:a,property:this.identifier(),computed:!1}:this.throwError("IMPOSSIBLE");return a},filter:function(a){a=[a];for(var b={type:s.CallExpression,callee:this.identifier(),arguments:a,filter:!0};this.expect(":");)a.push(this.expression());return b},parseArguments:function(){var a=[];if(")"!==this.peekToken().text){do a.push(this.filterChain());while(this.expect(",")) +}return a},identifier:function(){var a=this.consume();a.identifier||this.throwError("is not a valid identifier",a);return{type:s.Identifier,name:a.text}},constant:function(){return{type:s.Literal,value:this.consume().value}},arrayDeclaration:function(){var a=[];if("]"!==this.peekToken().text){do{if(this.peek("]"))break;a.push(this.expression())}while(this.expect(","))}this.consume("]");return{type:s.ArrayExpression,elements:a}},object:function(){var a=[],b;if("}"!==this.peekToken().text){do{if(this.peek("}"))break; +b={type:s.Property,kind:"init"};this.peek().constant?(b.key=this.constant(),b.computed=!1,this.consume(":"),b.value=this.expression()):this.peek().identifier?(b.key=this.identifier(),b.computed=!1,this.peek(":")?(this.consume(":"),b.value=this.expression()):b.value=b.key):this.peek("[")?(this.consume("["),b.key=this.expression(),this.consume("]"),b.computed=!0,this.consume(":"),b.value=this.expression()):this.throwError("invalid key",this.peek());a.push(b)}while(this.expect(","))}this.consume("}"); +return{type:s.ObjectExpression,properties:a}},throwError:function(a,b){throw X("syntax",b.text,a,b.index+1,this.text,this.text.substring(b.index));},consume:function(a){if(0===this.tokens.length)throw X("ueoe",this.text);var b=this.expect(a);b||this.throwError("is unexpected, expecting ["+a+"]",this.peek());return b},peekToken:function(){if(0===this.tokens.length)throw X("ueoe",this.text);return this.tokens[0]},peek:function(a,b,d,c){return this.peekAhead(0,a,b,d,c)},peekAhead:function(a,b,d,c,e){if(this.tokens.length> +a){a=this.tokens[a];var f=a.text;if(f===b||f===d||f===c||f===e||!(b||d||c||e))return a}return!1},expect:function(a,b,d,c){return(a=this.peek(a,b,d,c))?(this.tokens.shift(),a):!1},selfReferential:{"this":{type:s.ThisExpression},$locals:{type:s.LocalsExpression}}};td.prototype={compile:function(a,b){var d=this,c=this.astBuilder.ast(a);this.state={nextId:0,filters:{},expensiveChecks:b,fn:{vars:[],body:[],own:{}},assign:{vars:[],body:[],own:{}},inputs:[]};V(c,d.$filter);var e="",f;this.stage="assign"; +if(f=rd(c))this.state.computing="assign",e=this.nextId(),this.recurse(f,e),this.return_(e),e="fn.assign="+this.generateFunction("assign","s,v,l");f=pd(c.body);d.stage="inputs";q(f,function(a,b){var c="fn"+b;d.state[c]={vars:[],body:[],own:{}};d.state.computing=c;var e=d.nextId();d.recurse(a,e);d.return_(e);d.state.inputs.push(c);a.watchId=b});this.state.computing="fn";this.stage="main";this.recurse(c);e='"'+this.USE+" "+this.STRICT+'";\n'+this.filterPrefix()+"var fn="+this.generateFunction("fn","s,l,a,i")+ +e+this.watchFns()+"return fn;";e=(new Function("$filter","ensureSafeMemberName","ensureSafeObject","ensureSafeFunction","getStringValue","ensureSafeAssignContext","ifDefined","plus","text",e))(this.$filter,Sa,ra,nd,ig,Ib,mg,od,a);this.state=this.stage=void 0;e.literal=sd(c);e.constant=c.constant;return e},USE:"use",STRICT:"strict",watchFns:function(){var a=[],b=this.state.inputs,d=this;q(b,function(b){a.push("var "+b+"="+d.generateFunction(b,"s"))});b.length&&a.push("fn.inputs=["+b.join(",")+"];"); +return a.join("")},generateFunction:function(a,b){return"function("+b+"){"+this.varsPrefix(a)+this.body(a)+"};"},filterPrefix:function(){var a=[],b=this;q(this.state.filters,function(d,c){a.push(d+"=$filter("+b.escape(c)+")")});return a.length?"var "+a.join(",")+";":""},varsPrefix:function(a){return this.state[a].vars.length?"var "+this.state[a].vars.join(",")+";":""},body:function(a){return this.state[a].body.join("")},recurse:function(a,b,d,c,e,f){var g,h,k=this,l,m,n;c=c||A;if(!f&&w(a.watchId))b= +b||this.nextId(),this.if_("i",this.lazyAssign(b,this.computedMember("i",a.watchId)),this.lazyRecurse(a,b,d,c,e,!0));else switch(a.type){case s.Program:q(a.body,function(b,c){k.recurse(b.expression,void 0,void 0,function(a){h=a});c!==a.body.length-1?k.current().body.push(h,";"):k.return_(h)});break;case s.Literal:m=this.escape(a.value);this.assign(b,m);c(m);break;case s.UnaryExpression:this.recurse(a.argument,void 0,void 0,function(a){h=a});m=a.operator+"("+this.ifDefined(h,0)+")";this.assign(b,m); +c(m);break;case s.BinaryExpression:this.recurse(a.left,void 0,void 0,function(a){g=a});this.recurse(a.right,void 0,void 0,function(a){h=a});m="+"===a.operator?this.plus(g,h):"-"===a.operator?this.ifDefined(g,0)+a.operator+this.ifDefined(h,0):"("+g+")"+a.operator+"("+h+")";this.assign(b,m);c(m);break;case s.LogicalExpression:b=b||this.nextId();k.recurse(a.left,b);k.if_("&&"===a.operator?b:k.not(b),k.lazyRecurse(a.right,b));c(b);break;case s.ConditionalExpression:b=b||this.nextId();k.recurse(a.test, +b);k.if_(b,k.lazyRecurse(a.alternate,b),k.lazyRecurse(a.consequent,b));c(b);break;case s.Identifier:b=b||this.nextId();d&&(d.context="inputs"===k.stage?"s":this.assign(this.nextId(),this.getHasOwnProperty("l",a.name)+"?l:s"),d.computed=!1,d.name=a.name);Sa(a.name);k.if_("inputs"===k.stage||k.not(k.getHasOwnProperty("l",a.name)),function(){k.if_("inputs"===k.stage||"s",function(){e&&1!==e&&k.if_(k.not(k.nonComputedMember("s",a.name)),k.lazyAssign(k.nonComputedMember("s",a.name),"{}"));k.assign(b,k.nonComputedMember("s", +a.name))})},b&&k.lazyAssign(b,k.nonComputedMember("l",a.name)));(k.state.expensiveChecks||Jb(a.name))&&k.addEnsureSafeObject(b);c(b);break;case s.MemberExpression:g=d&&(d.context=this.nextId())||this.nextId();b=b||this.nextId();k.recurse(a.object,g,void 0,function(){k.if_(k.notNull(g),function(){e&&1!==e&&k.addEnsureSafeAssignContext(g);if(a.computed)h=k.nextId(),k.recurse(a.property,h),k.getStringValue(h),k.addEnsureSafeMemberName(h),e&&1!==e&&k.if_(k.not(k.computedMember(g,h)),k.lazyAssign(k.computedMember(g, +h),"{}")),m=k.ensureSafeObject(k.computedMember(g,h)),k.assign(b,m),d&&(d.computed=!0,d.name=h);else{Sa(a.property.name);e&&1!==e&&k.if_(k.not(k.nonComputedMember(g,a.property.name)),k.lazyAssign(k.nonComputedMember(g,a.property.name),"{}"));m=k.nonComputedMember(g,a.property.name);if(k.state.expensiveChecks||Jb(a.property.name))m=k.ensureSafeObject(m);k.assign(b,m);d&&(d.computed=!1,d.name=a.property.name)}},function(){k.assign(b,"undefined")});c(b)},!!e);break;case s.CallExpression:b=b||this.nextId(); +a.filter?(h=k.filter(a.callee.name),l=[],q(a.arguments,function(a){var b=k.nextId();k.recurse(a,b);l.push(b)}),m=h+"("+l.join(",")+")",k.assign(b,m),c(b)):(h=k.nextId(),g={},l=[],k.recurse(a.callee,h,g,function(){k.if_(k.notNull(h),function(){k.addEnsureSafeFunction(h);q(a.arguments,function(a){k.recurse(a,k.nextId(),void 0,function(a){l.push(k.ensureSafeObject(a))})});g.name?(k.state.expensiveChecks||k.addEnsureSafeObject(g.context),m=k.member(g.context,g.name,g.computed)+"("+l.join(",")+")"):m= +h+"("+l.join(",")+")";m=k.ensureSafeObject(m);k.assign(b,m)},function(){k.assign(b,"undefined")});c(b)}));break;case s.AssignmentExpression:h=this.nextId();g={};if(!qd(a.left))throw X("lval");this.recurse(a.left,void 0,g,function(){k.if_(k.notNull(g.context),function(){k.recurse(a.right,h);k.addEnsureSafeObject(k.member(g.context,g.name,g.computed));k.addEnsureSafeAssignContext(g.context);m=k.member(g.context,g.name,g.computed)+a.operator+h;k.assign(b,m);c(b||m)})},1);break;case s.ArrayExpression:l= +[];q(a.elements,function(a){k.recurse(a,k.nextId(),void 0,function(a){l.push(a)})});m="["+l.join(",")+"]";this.assign(b,m);c(m);break;case s.ObjectExpression:l=[];n=!1;q(a.properties,function(a){a.computed&&(n=!0)});n?(b=b||this.nextId(),this.assign(b,"{}"),q(a.properties,function(a){a.computed?(g=k.nextId(),k.recurse(a.key,g)):g=a.key.type===s.Identifier?a.key.name:""+a.key.value;h=k.nextId();k.recurse(a.value,h);k.assign(k.member(b,g,a.computed),h)})):(q(a.properties,function(b){k.recurse(b.value, +a.constant?void 0:k.nextId(),void 0,function(a){l.push(k.escape(b.key.type===s.Identifier?b.key.name:""+b.key.value)+":"+a)})}),m="{"+l.join(",")+"}",this.assign(b,m));c(b||m);break;case s.ThisExpression:this.assign(b,"s");c("s");break;case s.LocalsExpression:this.assign(b,"l");c("l");break;case s.NGValueParameter:this.assign(b,"v"),c("v")}},getHasOwnProperty:function(a,b){var d=a+"."+b,c=this.current().own;c.hasOwnProperty(d)||(c[d]=this.nextId(!1,a+"&&("+this.escape(b)+" in "+a+")"));return c[d]}, +assign:function(a,b){if(a)return this.current().body.push(a,"=",b,";"),a},filter:function(a){this.state.filters.hasOwnProperty(a)||(this.state.filters[a]=this.nextId(!0));return this.state.filters[a]},ifDefined:function(a,b){return"ifDefined("+a+","+this.escape(b)+")"},plus:function(a,b){return"plus("+a+","+b+")"},return_:function(a){this.current().body.push("return ",a,";")},if_:function(a,b,d){if(!0===a)b();else{var c=this.current().body;c.push("if(",a,"){");b();c.push("}");d&&(c.push("else{"), +d(),c.push("}"))}},not:function(a){return"!("+a+")"},notNull:function(a){return a+"!=null"},nonComputedMember:function(a,b){var d=/[^$_a-zA-Z0-9]/g;return/[$_a-zA-Z][$_a-zA-Z0-9]*/.test(b)?a+"."+b:a+'["'+b.replace(d,this.stringEscapeFn)+'"]'},computedMember:function(a,b){return a+"["+b+"]"},member:function(a,b,d){return d?this.computedMember(a,b):this.nonComputedMember(a,b)},addEnsureSafeObject:function(a){this.current().body.push(this.ensureSafeObject(a),";")},addEnsureSafeMemberName:function(a){this.current().body.push(this.ensureSafeMemberName(a), +";")},addEnsureSafeFunction:function(a){this.current().body.push(this.ensureSafeFunction(a),";")},addEnsureSafeAssignContext:function(a){this.current().body.push(this.ensureSafeAssignContext(a),";")},ensureSafeObject:function(a){return"ensureSafeObject("+a+",text)"},ensureSafeMemberName:function(a){return"ensureSafeMemberName("+a+",text)"},ensureSafeFunction:function(a){return"ensureSafeFunction("+a+",text)"},getStringValue:function(a){this.assign(a,"getStringValue("+a+")")},ensureSafeAssignContext:function(a){return"ensureSafeAssignContext("+ +a+",text)"},lazyRecurse:function(a,b,d,c,e,f){var g=this;return function(){g.recurse(a,b,d,c,e,f)}},lazyAssign:function(a,b){var d=this;return function(){d.assign(a,b)}},stringEscapeRegex:/[^ a-zA-Z0-9]/g,stringEscapeFn:function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)},escape:function(a){if(G(a))return"'"+a.replace(this.stringEscapeRegex,this.stringEscapeFn)+"'";if(T(a))return a.toString();if(!0===a)return"true";if(!1===a)return"false";if(null===a)return"null";if("undefined"=== +typeof a)return"undefined";throw X("esc");},nextId:function(a,b){var d="v"+this.state.nextId++;a||this.current().vars.push(d+(b?"="+b:""));return d},current:function(){return this.state[this.state.computing]}};ud.prototype={compile:function(a,b){var d=this,c=this.astBuilder.ast(a);this.expression=a;this.expensiveChecks=b;V(c,d.$filter);var e,f;if(e=rd(c))f=this.recurse(e);e=pd(c.body);var g;e&&(g=[],q(e,function(a,b){var c=d.recurse(a);a.input=c;g.push(c);a.watchId=b}));var h=[];q(c.body,function(a){h.push(d.recurse(a.expression))}); +e=0===c.body.length?A:1===c.body.length?h[0]:function(a,b){var c;q(h,function(d){c=d(a,b)});return c};f&&(e.assign=function(a,b,c){return f(a,c,b)});g&&(e.inputs=g);e.literal=sd(c);e.constant=c.constant;return e},recurse:function(a,b,d){var c,e,f=this,g;if(a.input)return this.inputs(a.input,a.watchId);switch(a.type){case s.Literal:return this.value(a.value,b);case s.UnaryExpression:return e=this.recurse(a.argument),this["unary"+a.operator](e,b);case s.BinaryExpression:return c=this.recurse(a.left), +e=this.recurse(a.right),this["binary"+a.operator](c,e,b);case s.LogicalExpression:return c=this.recurse(a.left),e=this.recurse(a.right),this["binary"+a.operator](c,e,b);case s.ConditionalExpression:return this["ternary?:"](this.recurse(a.test),this.recurse(a.alternate),this.recurse(a.consequent),b);case s.Identifier:return Sa(a.name,f.expression),f.identifier(a.name,f.expensiveChecks||Jb(a.name),b,d,f.expression);case s.MemberExpression:return c=this.recurse(a.object,!1,!!d),a.computed||(Sa(a.property.name, +f.expression),e=a.property.name),a.computed&&(e=this.recurse(a.property)),a.computed?this.computedMember(c,e,b,d,f.expression):this.nonComputedMember(c,e,f.expensiveChecks,b,d,f.expression);case s.CallExpression:return g=[],q(a.arguments,function(a){g.push(f.recurse(a))}),a.filter&&(e=this.$filter(a.callee.name)),a.filter||(e=this.recurse(a.callee,!0)),a.filter?function(a,c,d,f){for(var n=[],p=0;p":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)>b(c,e,f,g);return d?{value:c}:c}},"binary<=":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)<=b(c,e,f,g);return d?{value:c}:c}},"binary>=":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)>=b(c,e,f,g);return d?{value:c}:c}},"binary&&":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)&&b(c,e,f,g);return d?{value:c}:c}},"binary||":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)|| +b(c,e,f,g);return d?{value:c}:c}},"ternary?:":function(a,b,d,c){return function(e,f,g,h){e=a(e,f,g,h)?b(e,f,g,h):d(e,f,g,h);return c?{value:e}:e}},value:function(a,b){return function(){return b?{context:void 0,name:void 0,value:a}:a}},identifier:function(a,b,d,c,e){return function(f,g,h,k){f=g&&a in g?g:f;c&&1!==c&&f&&!f[a]&&(f[a]={});g=f?f[a]:void 0;b&&ra(g,e);return d?{context:f,name:a,value:g}:g}},computedMember:function(a,b,d,c,e){return function(f,g,h,k){var l=a(f,g,h,k),m,n;null!=l&&(m=b(f, +g,h,k),m+="",Sa(m,e),c&&1!==c&&(Ib(l),l&&!l[m]&&(l[m]={})),n=l[m],ra(n,e));return d?{context:l,name:m,value:n}:n}},nonComputedMember:function(a,b,d,c,e,f){return function(g,h,k,l){g=a(g,h,k,l);e&&1!==e&&(Ib(g),g&&!g[b]&&(g[b]={}));h=null!=g?g[b]:void 0;(d||Jb(b))&&ra(h,f);return c?{context:g,name:b,value:h}:h}},inputs:function(a,b){return function(d,c,e,f){return f?f[b]:a(d,c,e)}}};var kc=function(a,b,d){this.lexer=a;this.$filter=b;this.options=d;this.ast=new s(a,d);this.astCompiler=d.csp?new ud(this.ast, +b):new td(this.ast,b)};kc.prototype={constructor:kc,parse:function(a){return this.astCompiler.compile(a,this.options.expensiveChecks)}};var ng=Object.prototype.valueOf,sa=N("$sce"),la={HTML:"html",CSS:"css",URL:"url",RESOURCE_URL:"resourceUrl",JS:"js"},pg=N("$compile"),$=C.document.createElement("a"),yd=Y(C.location.href);zd.$inject=["$document"];Mc.$inject=["$provide"];var Gd=22,Fd=".",mc="0";Ad.$inject=["$locale"];Cd.$inject=["$locale"];var Ag={yyyy:ba("FullYear",4,0,!1,!0),yy:ba("FullYear",2,0, +!0,!0),y:ba("FullYear",1,0,!1,!0),MMMM:kb("Month"),MMM:kb("Month",!0),MM:ba("Month",2,1),M:ba("Month",1,1),LLLL:kb("Month",!1,!0),dd:ba("Date",2),d:ba("Date",1),HH:ba("Hours",2),H:ba("Hours",1),hh:ba("Hours",2,-12),h:ba("Hours",1,-12),mm:ba("Minutes",2),m:ba("Minutes",1),ss:ba("Seconds",2),s:ba("Seconds",1),sss:ba("Milliseconds",3),EEEE:kb("Day"),EEE:kb("Day",!0),a:function(a,b){return 12>a.getHours()?b.AMPMS[0]:b.AMPMS[1]},Z:function(a,b,d){a=-1*d;return a=(0<=a?"+":"")+(Kb(Math[0=a.getFullYear()?b.ERANAMES[0]:b.ERANAMES[1]}},zg=/((?:[^yMLdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|L+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/,yg=/^\-?\d+$/;Bd.$inject=["$locale"];var tg=ha(Q),ug=ha(ub);Dd.$inject=["$parse"];var oe=ha({restrict:"E",compile:function(a,b){if(!b.href&&!b.xlinkHref)return function(a,b){if("a"===b[0].nodeName.toLowerCase()){var e="[object SVGAnimatedString]"===ma.call(b.prop("href"))? +"xlink:href":"href";b.on("click",function(a){b.attr(e)||a.preventDefault()})}}}}),vb={};q(Eb,function(a,b){function d(a,d,e){a.$watch(e[c],function(a){e.$set(b,!!a)})}if("multiple"!=a){var c=Aa("ng-"+b),e=d;"checked"===a&&(e=function(a,b,e){e.ngModel!==e[c]&&d(a,b,e)});vb[c]=function(){return{restrict:"A",priority:100,link:e}}}});q(bd,function(a,b){vb[b]=function(){return{priority:100,link:function(a,c,e){if("ngPattern"===b&&"/"==e.ngPattern.charAt(0)&&(c=e.ngPattern.match(Cg))){e.$set("ngPattern", +new RegExp(c[1],c[2]));return}a.$watch(e[b],function(a){e.$set(b,a)})}}}});q(["src","srcset","href"],function(a){var b=Aa("ng-"+a);vb[b]=function(){return{priority:99,link:function(d,c,e){var f=a,g=a;"href"===a&&"[object SVGAnimatedString]"===ma.call(c.prop("href"))&&(g="xlinkHref",e.$attr[g]="xlink:href",f=null);e.$observe(b,function(b){b?(e.$set(g,b),Ea&&f&&c.prop(f,e[g])):"href"===a&&e.$set(g,null)})}}}});var Lb={$addControl:A,$$renameControl:function(a,b){a.$name=b},$removeControl:A,$setValidity:A, +$setDirty:A,$setPristine:A,$setSubmitted:A};Jd.$inject=["$element","$attrs","$scope","$animate","$interpolate"];var Sd=function(a){return["$timeout","$parse",function(b,d){function c(a){return""===a?d('this[""]').assign:d(a).assign||A}return{name:"form",restrict:a?"EAC":"E",require:["form","^^?form"],controller:Jd,compile:function(d,f){d.addClass(Ua).addClass(ob);var g=f.name?"name":a&&f.ngForm?"ngForm":!1;return{pre:function(a,d,e,f){var n=f[0];if(!("action"in e)){var p=function(b){a.$apply(function(){n.$commitViewValue(); +n.$setSubmitted()});b.preventDefault()};d[0].addEventListener("submit",p,!1);d.on("$destroy",function(){b(function(){d[0].removeEventListener("submit",p,!1)},0,!1)})}(f[1]||n.$$parentForm).$addControl(n);var q=g?c(n.$name):A;g&&(q(a,n),e.$observe(g,function(b){n.$name!==b&&(q(a,void 0),n.$$parentForm.$$renameControl(n,b),q=c(n.$name),q(a,n))}));d.on("$destroy",function(){n.$$parentForm.$removeControl(n);q(a,void 0);S(n,Lb)})}}}}}]},pe=Sd(),Ce=Sd(!0),Bg=/^\d{4,}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+(?:[+-][0-2]\d:[0-5]\d|Z)$/, +Kg=/^[a-z][a-z\d.+-]*:\/*(?:[^:@]+(?::[^@]+)?@)?(?:[^\s:/?#]+|\[[a-f\d:]+\])(?::\d+)?(?:\/[^?#]*)?(?:\?[^#]*)?(?:#.*)?$/i,Lg=/^(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+\/0-9=?A-Z^_`a-z{|}~]+(\.[-!#$%&'*+\/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/,Mg=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/,Td=/^(\d{4,})-(\d{2})-(\d{2})$/,Ud=/^(\d{4,})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,rc=/^(\d{4,})-W(\d\d)$/,Vd=/^(\d{4,})-(\d\d)$/, +Wd=/^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,Ld=U();q(["date","datetime-local","month","time","week"],function(a){Ld[a]=!0});var Xd={text:function(a,b,d,c,e,f){lb(a,b,d,c,e,f);pc(c)},date:mb("date",Td,Nb(Td,["yyyy","MM","dd"]),"yyyy-MM-dd"),"datetime-local":mb("datetimelocal",Ud,Nb(Ud,"yyyy MM dd HH mm ss sss".split(" ")),"yyyy-MM-ddTHH:mm:ss.sss"),time:mb("time",Wd,Nb(Wd,["HH","mm","ss","sss"]),"HH:mm:ss.sss"),week:mb("week",rc,function(a,b){if(da(a))return a;if(G(a)){rc.lastIndex=0;var d=rc.exec(a); +if(d){var c=+d[1],e=+d[2],f=d=0,g=0,h=0,k=Hd(c),e=7*(e-1);b&&(d=b.getHours(),f=b.getMinutes(),g=b.getSeconds(),h=b.getMilliseconds());return new Date(c,0,k.getDate()+e,d,f,g,h)}}return NaN},"yyyy-Www"),month:mb("month",Vd,Nb(Vd,["yyyy","MM"]),"yyyy-MM"),number:function(a,b,d,c,e,f){Md(a,b,d,c);lb(a,b,d,c,e,f);c.$$parserName="number";c.$parsers.push(function(a){if(c.$isEmpty(a))return null;if(Mg.test(a))return parseFloat(a)});c.$formatters.push(function(a){if(!c.$isEmpty(a)){if(!T(a))throw nb("numfmt", +a);a=a.toString()}return a});if(w(d.min)||d.ngMin){var g;c.$validators.min=function(a){return c.$isEmpty(a)||y(g)||a>=g};d.$observe("min",function(a){w(a)&&!T(a)&&(a=parseFloat(a));g=T(a)&&!isNaN(a)?a:void 0;c.$validate()})}if(w(d.max)||d.ngMax){var h;c.$validators.max=function(a){return c.$isEmpty(a)||y(h)||a<=h};d.$observe("max",function(a){w(a)&&!T(a)&&(a=parseFloat(a));h=T(a)&&!isNaN(a)?a:void 0;c.$validate()})}},url:function(a,b,d,c,e,f){lb(a,b,d,c,e,f);pc(c);c.$$parserName="url";c.$validators.url= +function(a,b){var d=a||b;return c.$isEmpty(d)||Kg.test(d)}},email:function(a,b,d,c,e,f){lb(a,b,d,c,e,f);pc(c);c.$$parserName="email";c.$validators.email=function(a,b){var d=a||b;return c.$isEmpty(d)||Lg.test(d)}},radio:function(a,b,d,c){y(d.name)&&b.attr("name",++pb);b.on("click",function(a){b[0].checked&&c.$setViewValue(d.value,a&&a.type)});c.$render=function(){b[0].checked=d.value==c.$viewValue};d.$observe("value",c.$render)},checkbox:function(a,b,d,c,e,f,g,h){var k=Nd(h,a,"ngTrueValue",d.ngTrueValue, +!0),l=Nd(h,a,"ngFalseValue",d.ngFalseValue,!1);b.on("click",function(a){c.$setViewValue(b[0].checked,a&&a.type)});c.$render=function(){b[0].checked=c.$viewValue};c.$isEmpty=function(a){return!1===a};c.$formatters.push(function(a){return na(a,k)});c.$parsers.push(function(a){return a?k:l})},hidden:A,button:A,submit:A,reset:A,file:A},Gc=["$browser","$sniffer","$filter","$parse",function(a,b,d,c){return{restrict:"E",require:["?ngModel"],link:{pre:function(e,f,g,h){h[0]&&(Xd[Q(g.type)]||Xd.text)(e,f, +g,h[0],b,a,d,c)}}}}],Ng=/^(true|false|\d+)$/,Ue=function(){return{restrict:"A",priority:100,compile:function(a,b){return Ng.test(b.ngValue)?function(a,b,e){e.$set("value",a.$eval(e.ngValue))}:function(a,b,e){a.$watch(e.ngValue,function(a){e.$set("value",a)})}}}},ue=["$compile",function(a){return{restrict:"AC",compile:function(b){a.$$addBindingClass(b);return function(b,c,e){a.$$addBindingInfo(c,e.ngBind);c=c[0];b.$watch(e.ngBind,function(a){c.textContent=y(a)?"":a})}}}}],we=["$interpolate","$compile", +function(a,b){return{compile:function(d){b.$$addBindingClass(d);return function(c,d,f){c=a(d.attr(f.$attr.ngBindTemplate));b.$$addBindingInfo(d,c.expressions);d=d[0];f.$observe("ngBindTemplate",function(a){d.textContent=y(a)?"":a})}}}}],ve=["$sce","$parse","$compile",function(a,b,d){return{restrict:"A",compile:function(c,e){var f=b(e.ngBindHtml),g=b(e.ngBindHtml,function(b){return a.valueOf(b)});d.$$addBindingClass(c);return function(b,c,e){d.$$addBindingInfo(c,e.ngBindHtml);b.$watch(g,function(){var d= +f(b);c.html(a.getTrustedHtml(d)||"")})}}}}],Te=ha({restrict:"A",require:"ngModel",link:function(a,b,d,c){c.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}),xe=qc("",!0),ze=qc("Odd",0),ye=qc("Even",1),Ae=Ta({compile:function(a,b){b.$set("ngCloak",void 0);a.removeClass("ng-cloak")}}),Be=[function(){return{restrict:"A",scope:!0,controller:"@",priority:500}}],Lc={},Og={blur:!0,focus:!0};q("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "), +function(a){var b=Aa("ng-"+a);Lc[b]=["$parse","$rootScope",function(d,c){return{restrict:"A",compile:function(e,f){var g=d(f[b],null,!0);return function(b,d){d.on(a,function(d){var e=function(){g(b,{$event:d})};Og[a]&&c.$$phase?b.$evalAsync(e):b.$apply(e)})}}}}]});var Ee=["$animate","$compile",function(a,b){return{multiElement:!0,transclude:"element",priority:600,terminal:!0,restrict:"A",$$tlb:!0,link:function(d,c,e,f,g){var h,k,l;d.$watch(e.ngIf,function(d){d?k||g(function(d,f){k=f;d[d.length++]= +b.$$createComment("end ngIf",e.ngIf);h={clone:d};a.enter(d,c.parent(),c)}):(l&&(l.remove(),l=null),k&&(k.$destroy(),k=null),h&&(l=tb(h.clone),a.leave(l).then(function(){l=null}),h=null))})}}}],Fe=["$templateRequest","$anchorScroll","$animate",function(a,b,d){return{restrict:"ECA",priority:400,terminal:!0,transclude:"element",controller:ca.noop,compile:function(c,e){var f=e.ngInclude||e.src,g=e.onload||"",h=e.autoscroll;return function(c,e,m,n,p){var q=0,s,B,r,y=function(){B&&(B.remove(),B=null);s&& +(s.$destroy(),s=null);r&&(d.leave(r).then(function(){B=null}),B=r,r=null)};c.$watch(f,function(f){var m=function(){!w(h)||h&&!c.$eval(h)||b()},t=++q;f?(a(f,!0).then(function(a){if(!c.$$destroyed&&t===q){var b=c.$new();n.template=a;a=p(b,function(a){y();d.enter(a,null,e).then(m)});s=b;r=a;s.$emit("$includeContentLoaded",f);c.$eval(g)}},function(){c.$$destroyed||t!==q||(y(),c.$emit("$includeContentError",f))}),c.$emit("$includeContentRequested",f)):(y(),n.template=null)})}}}}],We=["$compile",function(a){return{restrict:"ECA", +priority:-400,require:"ngInclude",link:function(b,d,c,e){ma.call(d[0]).match(/SVG/)?(d.empty(),a(Oc(e.template,C.document).childNodes)(b,function(a){d.append(a)},{futureParentElement:d})):(d.html(e.template),a(d.contents())(b))}}}],Ge=Ta({priority:450,compile:function(){return{pre:function(a,b,d){a.$eval(d.ngInit)}}}}),Se=function(){return{restrict:"A",priority:100,require:"ngModel",link:function(a,b,d,c){var e=b.attr(d.$attr.ngList)||", ",f="false"!==d.ngTrim,g=f?W(e):e;c.$parsers.push(function(a){if(!y(a)){var b= +[];a&&q(a.split(g),function(a){a&&b.push(f?W(a):a)});return b}});c.$formatters.push(function(a){if(L(a))return a.join(e)});c.$isEmpty=function(a){return!a||!a.length}}}},ob="ng-valid",Od="ng-invalid",Ua="ng-pristine",Mb="ng-dirty",Qd="ng-pending",nb=N("ngModel"),Pg=["$scope","$exceptionHandler","$attrs","$element","$parse","$animate","$timeout","$rootScope","$q","$interpolate",function(a,b,d,c,e,f,g,h,k,l){this.$modelValue=this.$viewValue=Number.NaN;this.$$rawModelValue=void 0;this.$validators={}; +this.$asyncValidators={};this.$parsers=[];this.$formatters=[];this.$viewChangeListeners=[];this.$untouched=!0;this.$touched=!1;this.$pristine=!0;this.$dirty=!1;this.$valid=!0;this.$invalid=!1;this.$error={};this.$$success={};this.$pending=void 0;this.$name=l(d.name||"",!1)(a);this.$$parentForm=Lb;var m=e(d.ngModel),n=m.assign,p=m,u=n,s=null,B,r=this;this.$$setOptions=function(a){if((r.$options=a)&&a.getterSetter){var b=e(d.ngModel+"()"),f=e(d.ngModel+"($$$p)");p=function(a){var c=m(a);z(c)&&(c=b(a)); +return c};u=function(a,b){z(m(a))?f(a,{$$$p:b}):n(a,b)}}else if(!m.assign)throw nb("nonassign",d.ngModel,ya(c));};this.$render=A;this.$isEmpty=function(a){return y(a)||""===a||null===a||a!==a};this.$$updateEmptyClasses=function(a){r.$isEmpty(a)?(f.removeClass(c,"ng-not-empty"),f.addClass(c,"ng-empty")):(f.removeClass(c,"ng-empty"),f.addClass(c,"ng-not-empty"))};var J=0;Kd({ctrl:this,$element:c,set:function(a,b){a[b]=!0},unset:function(a,b){delete a[b]},$animate:f});this.$setPristine=function(){r.$dirty= +!1;r.$pristine=!0;f.removeClass(c,Mb);f.addClass(c,Ua)};this.$setDirty=function(){r.$dirty=!0;r.$pristine=!1;f.removeClass(c,Ua);f.addClass(c,Mb);r.$$parentForm.$setDirty()};this.$setUntouched=function(){r.$touched=!1;r.$untouched=!0;f.setClass(c,"ng-untouched","ng-touched")};this.$setTouched=function(){r.$touched=!0;r.$untouched=!1;f.setClass(c,"ng-touched","ng-untouched")};this.$rollbackViewValue=function(){g.cancel(s);r.$viewValue=r.$$lastCommittedViewValue;r.$render()};this.$validate=function(){if(!T(r.$modelValue)|| +!isNaN(r.$modelValue)){var a=r.$$rawModelValue,b=r.$valid,c=r.$modelValue,d=r.$options&&r.$options.allowInvalid;r.$$runValidators(a,r.$$lastCommittedViewValue,function(e){d||b===e||(r.$modelValue=e?a:void 0,r.$modelValue!==c&&r.$$writeModelToScope())})}};this.$$runValidators=function(a,b,c){function d(){var c=!0;q(r.$validators,function(d,e){var g=d(a,b);c=c&&g;f(e,g)});return c?!0:(q(r.$asyncValidators,function(a,b){f(b,null)}),!1)}function e(){var c=[],d=!0;q(r.$asyncValidators,function(e,g){var h= +e(a,b);if(!h||!z(h.then))throw nb("nopromise",h);f(g,void 0);c.push(h.then(function(){f(g,!0)},function(){d=!1;f(g,!1)}))});c.length?k.all(c).then(function(){g(d)},A):g(!0)}function f(a,b){h===J&&r.$setValidity(a,b)}function g(a){h===J&&c(a)}J++;var h=J;(function(){var a=r.$$parserName||"parse";if(y(B))f(a,null);else return B||(q(r.$validators,function(a,b){f(b,null)}),q(r.$asyncValidators,function(a,b){f(b,null)})),f(a,B),B;return!0})()?d()?e():g(!1):g(!1)};this.$commitViewValue=function(){var a= +r.$viewValue;g.cancel(s);if(r.$$lastCommittedViewValue!==a||""===a&&r.$$hasNativeValidators)r.$$updateEmptyClasses(a),r.$$lastCommittedViewValue=a,r.$pristine&&this.$setDirty(),this.$$parseAndValidate()};this.$$parseAndValidate=function(){var b=r.$$lastCommittedViewValue;if(B=y(b)?void 0:!0)for(var c=0;ce||c.$isEmpty(b)||b.length<=e}}}}},Jc=function(){return{restrict:"A",require:"?ngModel",link:function(a,b,d,c){if(c){var e=0;d.$observe("minlength",function(a){e=Z(a)||0;c.$validate()});c.$validators.minlength=function(a,b){return c.$isEmpty(b)||b.length>=e}}}}};C.angular.bootstrap? +C.console&&console.log("WARNING: Tried to load angular more than once."):(je(),le(ca),ca.module("ngLocale",[],["$provide",function(a){function b(a){a+="";var b=a.indexOf(".");return-1==b?0:a.length-b-1}a.value("$locale",{DATETIME_FORMATS:{AMPMS:["AM","PM"],DAY:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),ERANAMES:["Before Christ","Anno Domini"],ERAS:["BC","AD"],FIRSTDAYOFWEEK:6,MONTH:"January February March April May June July August September October November December".split(" "), +SHORTDAY:"Sun Mon Tue Wed Thu Fri Sat".split(" "),SHORTMONTH:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),STANDALONEMONTH:"January February March April May June July August September October November December".split(" "),WEEKENDRANGE:[5,6],fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",medium:"MMM d, y h:mm:ss a",mediumDate:"MMM d, y",mediumTime:"h:mm:ss a","short":"M/d/yy h:mm a",shortDate:"M/d/yy",shortTime:"h:mm a"},NUMBER_FORMATS:{CURRENCY_SYM:"$",DECIMAL_SEP:".",GROUP_SEP:",", +PATTERNS:[{gSize:3,lgSize:3,maxFrac:3,minFrac:0,minInt:1,negPre:"-",negSuf:"",posPre:"",posSuf:""},{gSize:3,lgSize:3,maxFrac:2,minFrac:2,minInt:1,negPre:"-\u00a4",negSuf:"",posPre:"\u00a4",posSuf:""}]},id:"en-us",localeID:"en_US",pluralCat:function(a,c){var e=a|0,f=c;void 0===f&&(f=Math.min(b(a),3));Math.pow(10,f);return 1==e&&0==f?"one":"other"}})}]),F(C.document).ready(function(){fe(C.document,Bc)}))})(window);!window.angular.$$csp().noInlineStyle&&window.angular.element(document.head).prepend(''); //# sourceMappingURL=angular.min.js.map diff --git a/ui/app/bower_components/angular/angular.min.js.gzip b/ui/app/bower_components/angular/angular.min.js.gzip index 3bec206eb48a037c884811117cf9b8c4337d5d47..dc10f045a8b53cac4a6c07acc8e2cc6fcb3b76dd 100644 GIT binary patch literal 56905 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 literal 51566 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","binary<=","binary>=","binary&&","binary||","ternary?:","base","astCompiler","yy","y","MMMM","MMM","M","H","hh","EEEE","EEE","ampmGetter","Z","timeZoneGetter","zone","paddedZone","ww","w","G","GG","GGG","GGGG","longEraGetter","xlinkHref","propName","defaultLinkFn","normalized","ngBooleanAttrWatchAction","htmlAttr","ngAttrAliasWatchAction","nullFormRenameControl","formDirectiveFactory","isNgForm","ngFormCompile","formElement","nameAttr","ngFormPreLink","handleFormSubmission","parentFormCtrl","URL_REGEXP","EMAIL_REGEXP","NUMBER_REGEXP","DATE_REGEXP","DATETIMELOCAL_REGEXP","WEEK_REGEXP","MONTH_REGEXP","TIME_REGEXP","inputType","textInputType","weekParser","isoWeek","existingDate","week","hours","seconds","milliseconds","addDays","numberInputType","urlInputType","ctrl.$validators.url","modelValue","viewValue","emailInputType","email","ctrl.$validators.email","radioInputType","checked","checkboxInputType","trueValue","ngTrueValue","falseValue","ngFalseValue","ctrl.$isEmpty","ctrls","CONSTANT_VALUE_REGEXP","tplAttr","ngValueConstantLink","ngValueLink","valueWatchAction","$compile","ngBindCompile","templateElement","ngBindLink","ngBindWatchAction","ngBindTemplateCompile","ngBindTemplateLink","ngBindHtmlCompile","tElement","ngBindHtmlGetter","ngBindHtmlWatch","getStringValue","ngBindHtmlLink","ngBindHtmlWatchAction","getTrustedHtml","$viewChangeListeners","forceAsyncEvents","ngEventHandler","previousElements","ngIfWatchAction","srcExp","onloadExp","autoScrollExp","autoscroll","changeCounter","previousElement","currentElement","cleanupLastIncludeContent","parseAsResourceUrl","ngIncludeWatchAction","afterAnimation","thisChangeId","namespaceAdaptedClone","trimValues","NgModelController","$modelValue","$$rawModelValue","$asyncValidators","$untouched","$touched","parsedNgModel","parsedNgModelAssign","ngModelGet","ngModelSet","pendingDebounce","parserValid","$$setOptions","this.$$setOptions","getterSetter","invokeModelGetter","invokeModelSetter","$$$p","this.$isEmpty","currentValidationRunId","this.$setPristine","this.$setDirty","this.$setUntouched","UNTOUCHED_CLASS","TOUCHED_CLASS","$setTouched","this.$setTouched","this.$rollbackViewValue","$$lastCommittedViewValue","this.$validate","prevValid","prevModelValue","allowInvalid","$$runValidators","allValid","$$writeModelToScope","this.$$runValidators","doneCallback","processSyncValidators","syncValidatorsValid","validator","processAsyncValidators","validatorPromises","validationDone","localValidationRunId","processParseErrors","errorKey","this.$commitViewValue","$$parseAndValidate","this.$$parseAndValidate","this.$$writeModelToScope","this.$setViewValue","updateOnDefault","$$debounceViewValueCommit","this.$$debounceViewValueCommit","debounceDelay","debounce","ngModelWatch","formatters","ngModelCompile","ngModelPreLink","modelCtrl","formCtrl","ngModelPostLink","updateOn","DEFAULT_REGEXP","that","ngOptionsMinErr","NG_OPTIONS_REGEXP","parseOptionsExpression","optionsExp","selectElement","Option","selectValue","label","disabled","valueName","keyName","selectAs","trackBy","viewValueFn","trackByFn","getTrackByValueFn","getHashOfValue","getTrackByValue","getLocals","displayFn","groupByFn","disableWhenFn","valuesFn","getWatchables","watchedArray","getWatchable","disableWhen","getOptions","optionItems","selectValueMap","optionValues","optionValuesKeys","itemKey","optionValuesLength","optionItem","getOptionFromViewValue","getViewValueFromOption","optionTemplate","optGroupTemplate","updateOptionElement","addOrReuseElement","removeExcessElements","skipEmptyAndUnknownOptions","emptyOption_","emptyOption","unknownOption_","unknownOption","updateOptions","previousValue","selectCtrl","readValue","groupMap","providedEmptyOption","updateOption","optionElement","groupElement","currentOptionElement","ngModelCtrl","nextValue","ngModelCtrl.$isEmpty","writeValue","selectCtrl.writeValue","selectCtrl.readValue","selectedValues","selections","selectedOption","BRACE","IS_WHEN","updateElementText","newText","numberExp","whenExp","whens","whensExpFns","braceReplacement","watchRemover","lastCount","attributeName","tmpMatch","whenKey","ngPluralizeWatchAction","countIsNaN","whenExpFn","ngRepeatMinErr","updateScope","valueIdentifier","keyIdentifier","arrayLength","$first","$last","$middle","$odd","$even","ngRepeatCompile","ngRepeatEndComment","aliasAs","trackByExp","trackByExpGetter","trackByIdExpFn","trackByIdArrayFn","trackByIdObjFn","hashFnLocals","ngRepeatLink","lastBlockMap","ngRepeatAction","previousNode","nextNode","nextBlockMap","collectionLength","trackById","collectionKeys","nextBlockOrder","trackByIdFn","blockKey","ngRepeatTransclude","ngShowWatchAction","NG_HIDE_CLASS","NG_HIDE_IN_PROGRESS_CLASS","ngHideWatchAction","ngStyleWatchAction","newStyles","oldStyles","ngSwitchController","cases","selectedTranscludes","selectedElements","previousLeaveAnimations","selectedScopes","spliceFactory","ngSwitchWatchAction","selectedTransclude","caseElement","selectedScope","anchor","noopNgModelController","SelectController","optionsMap","renderUnknownOption","self.renderUnknownOption","unknownVal","removeUnknownOption","self.removeUnknownOption","self.readValue","self.writeValue","hasOption","addOption","self.addOption","removeOption","self.removeOption","self.hasOption","ngModelCtrl.$render","lastView","lastViewRef","selectMultipleWatch","chromeHack","selectCtrlName","interpolateWatchAction","ctrl.$validators.required","patternExp","ctrl.$validators.pattern","intVal","ctrl.$validators.maxlength","ctrl.$validators.minlength","$$csp"] +"names":["window","minErr","isArrayLike","obj","isWindow","isArray","isString","jqLite","length","Object","isNumber","Array","item","forEach","iterator","context","key","isFunction","hasOwnProperty","call","isPrimitive","isBlankObject","forEachSorted","keys","sort","i","reverseParams","iteratorFn","value","nextUid","uid","baseExtend","dst","objs","deep","h","$$hashKey","ii","isObject","j","jj","src","isDate","Date","valueOf","isRegExp","RegExp","nodeName","cloneNode","isElement","clone","extend","slice","arguments","merge","toInt","str","parseInt","inherit","parent","extra","create","noop","identity","$","valueFn","valueRef","hasCustomToString","toString","isUndefined","isDefined","getPrototypeOf","isScope","$evalAsync","$watch","isBoolean","isTypedArray","TYPED_ARRAY_REGEXP","test","node","prop","attr","find","makeMap","items","split","nodeName_","element","lowercase","arrayRemove","array","index","indexOf","splice","copy","source","destination","copyRecurse","push","copyElement","stackSource","stackDest","ngMinErr","needsRecurse","copyType","undefined","constructor","buffer","byteOffset","copied","ArrayBuffer","byteLength","set","Uint8Array","re","match","lastIndex","type","equals","o1","o2","t1","t2","getTime","keySet","createMap","charAt","concat","array1","array2","bind","self","fn","curryArgs","startIndex","apply","toJsonReplacer","val","document","toJson","pretty","JSON","stringify","fromJson","json","parse","timezoneToOffset","timezone","fallback","replace","ALL_COLONS","requestedTimezoneOffset","isNaN","convertTimezoneToLocal","date","reverse","dateTimezoneOffset","getTimezoneOffset","timezoneOffset","setMinutes","getMinutes","minutes","startingTag","empty","e","elemHtml","append","html","nodeType","NODE_TYPE_TEXT","tryDecodeURIComponent","decodeURIComponent","parseKeyValue","keyValue","splitPoint","substring","toKeyValue","parts","arrayValue","encodeUriQuery","join","encodeUriSegment","pctEncodeSpaces","encodeURIComponent","getNgAttribute","ngAttr","ngAttrPrefixes","getAttribute","angularInit","bootstrap","appElement","module","config","prefix","name","hasAttribute","candidate","querySelector","strictDi","modules","defaultConfig","doBootstrap","injector","tag","unshift","$provide","debugInfoEnabled","$compileProvider","createInjector","invoke","bootstrapApply","scope","compile","$apply","data","NG_ENABLE_DEBUG_INFO","NG_DEFER_BOOTSTRAP","angular","resumeBootstrap","angular.resumeBootstrap","extraModules","resumeDeferredBootstrap","reloadWithDebugInfo","location","reload","getTestability","rootElement","get","snake_case","separator","SNAKE_CASE_REGEXP","letter","pos","toLowerCase","bindJQuery","originalCleanData","bindJQueryFired","jqName","jq","jQuery","on","JQLitePrototype","isolateScope","controller","inheritedData","cleanData","jQuery.cleanData","elems","events","elem","_data","$destroy","triggerHandler","JQLite","assertArg","arg","reason","assertArgFn","acceptArrayAnnotation","assertNotHasOwnProperty","getter","path","bindFnToScope","lastInstance","len","getBlockNodes","nodes","endNode","blockNodes","nextSibling","setupModuleLoader","ensure","factory","$injectorMinErr","$$minErr","requires","configFn","invokeLater","provider","method","insertMethod","queue","invokeQueue","moduleInstance","invokeLaterAndSetModuleName","recipeName","factoryFunction","$$moduleName","configBlocks","runBlocks","_invokeQueue","_configBlocks","_runBlocks","service","constant","decorator","animation","filter","directive","component","run","block","shallowCopy","publishExternalAPI","version","uppercase","$$counter","csp","angularModule","ngModule","$$sanitizeUri","$$SanitizeUriProvider","$CompileProvider","a","htmlAnchorDirective","input","inputDirective","textarea","form","formDirective","script","scriptDirective","select","selectDirective","style","styleDirective","option","optionDirective","ngBind","ngBindDirective","ngBindHtml","ngBindHtmlDirective","ngBindTemplate","ngBindTemplateDirective","ngClass","ngClassDirective","ngClassEven","ngClassEvenDirective","ngClassOdd","ngClassOddDirective","ngCloak","ngCloakDirective","ngController","ngControllerDirective","ngForm","ngFormDirective","ngHide","ngHideDirective","ngIf","ngIfDirective","ngInclude","ngIncludeDirective","ngInit","ngInitDirective","ngNonBindable","ngNonBindableDirective","ngPluralize","ngPluralizeDirective","ngRepeat","ngRepeatDirective","ngShow","ngShowDirective","ngStyle","ngStyleDirective","ngSwitch","ngSwitchDirective","ngSwitchWhen","ngSwitchWhenDirective","ngSwitchDefault","ngSwitchDefaultDirective","ngOptions","ngOptionsDirective","ngTransclude","ngTranscludeDirective","ngModel","ngModelDirective","ngList","ngListDirective","ngChange","ngChangeDirective","pattern","patternDirective","ngPattern","required","requiredDirective","ngRequired","minlength","minlengthDirective","ngMinlength","maxlength","maxlengthDirective","ngMaxlength","ngValue","ngValueDirective","ngModelOptions","ngModelOptionsDirective","ngIncludeFillContentDirective","ngAttributeAliasDirectives","ngEventDirectives","$anchorScroll","$AnchorScrollProvider","$animate","$AnimateProvider","$animateCss","$CoreAnimateCssProvider","$$animateJs","$$CoreAnimateJsProvider","$$animateQueue","$$CoreAnimateQueueProvider","$$AnimateRunner","$$AnimateRunnerFactoryProvider","$$animateAsyncRun","$$AnimateAsyncRunFactoryProvider","$browser","$BrowserProvider","$cacheFactory","$CacheFactoryProvider","$controller","$ControllerProvider","$document","$DocumentProvider","$exceptionHandler","$ExceptionHandlerProvider","$filter","$FilterProvider","$$forceReflow","$$ForceReflowProvider","$interpolate","$InterpolateProvider","$interval","$IntervalProvider","$http","$HttpProvider","$httpParamSerializer","$HttpParamSerializerProvider","$httpParamSerializerJQLike","$HttpParamSerializerJQLikeProvider","$httpBackend","$HttpBackendProvider","$xhrFactory","$xhrFactoryProvider","$jsonpCallbacks","$jsonpCallbacksProvider","$location","$LocationProvider","$log","$LogProvider","$parse","$ParseProvider","$rootScope","$RootScopeProvider","$q","$QProvider","$$q","$$QProvider","$sce","$SceProvider","$sceDelegate","$SceDelegateProvider","$sniffer","$SnifferProvider","$templateCache","$TemplateCacheProvider","$templateRequest","$TemplateRequestProvider","$$testability","$$TestabilityProvider","$timeout","$TimeoutProvider","$window","$WindowProvider","$$rAF","$$RAFProvider","$$jqLite","$$jqLiteProvider","$$HashMap","$$HashMapProvider","$$cookieReader","$$CookieReaderProvider","camelCase","SPECIAL_CHARS_REGEXP","_","offset","toUpperCase","MOZ_HACK_REGEXP","jqLiteAcceptsData","NODE_TYPE_ELEMENT","NODE_TYPE_DOCUMENT","jqLiteBuildFragment","tmp","fragment","createDocumentFragment","HTML_REGEXP","appendChild","createElement","TAG_NAME_REGEXP","exec","wrap","wrapMap","_default","innerHTML","XHTML_TAG_REGEXP","lastChild","childNodes","firstChild","textContent","createTextNode","jqLiteWrapNode","wrapper","parentNode","replaceChild","argIsString","trim","jqLiteMinErr","parsed","SINGLE_TAG_REGEXP","jqLiteAddNodes","jqLiteClone","jqLiteDealoc","onlyDescendants","jqLiteRemoveData","querySelectorAll","descendants","l","jqLiteOff","unsupported","expandoStore","jqLiteExpandoStore","handle","removeHandler","listenerFns","removeEventListener","MOUSE_EVENT_MAP","expandoId","ng339","jqCache","createIfNecessary","jqId","jqLiteData","isSimpleSetter","isSimpleGetter","massGetter","jqLiteHasClass","selector","jqLiteRemoveClass","cssClasses","setAttribute","cssClass","jqLiteAddClass","existingClasses","root","elements","jqLiteController","jqLiteInheritedData","documentElement","names","NODE_TYPE_DOCUMENT_FRAGMENT","host","jqLiteEmpty","removeChild","jqLiteRemove","keepData","jqLiteDocumentLoaded","action","win","readyState","setTimeout","getBooleanAttrName","booleanAttr","BOOLEAN_ATTR","BOOLEAN_ELEMENTS","createEventHandler","eventHandler","event","isDefaultPrevented","event.isDefaultPrevented","defaultPrevented","eventFns","eventFnsLength","immediatePropagationStopped","originalStopImmediatePropagation","stopImmediatePropagation","event.stopImmediatePropagation","stopPropagation","isImmediatePropagationStopped","event.isImmediatePropagationStopped","handlerWrapper","specialHandlerWrapper","defaultHandlerWrapper","handler","specialMouseHandlerWrapper","target","related","relatedTarget","jqLiteContains","$get","this.$get","hasClass","classes","addClass","removeClass","hashKey","nextUidFn","objType","HashMap","isolatedUid","this.nextUid","put","extractArgs","fnText","Function","prototype","STRIP_COMMENTS","ARROW_ARG","FN_ARGS","anonFn","args","modulesToLoad","supportObject","delegate","provider_","providerInjector","instantiate","providerCache","providerSuffix","enforceReturnValue","enforcedReturnValue","result","instanceInjector","factoryFn","enforce","loadModules","moduleFn","runInvokeQueue","invokeArgs","loadedModules","message","stack","createInternalInjector","cache","getService","serviceName","caller","INSTANTIATING","err","shift","injectionArgs","locals","$inject","$$annotate","msie","Type","ctor","annotate","has","$injector","instanceCache","decorFn","origProvider","orig$get","origProvider.$get","origInstance","$delegate","protoInstanceInjector","autoScrollingEnabled","disableAutoScrolling","this.disableAutoScrolling","getFirstAnchor","list","some","scrollTo","scrollIntoView","scroll","yOffset","getComputedStyle","position","getBoundingClientRect","bottom","elemTop","top","scrollBy","hash","elm","getElementById","getElementsByName","autoScrollWatch","autoScrollWatchAction","newVal","oldVal","mergeClasses","b","splitClasses","klass","prepareAnimateOptions","options","Browser","completeOutstandingRequest","outstandingRequestCount","outstandingRequestCallbacks","pop","error","cacheStateAndFireUrlChange","pendingLocation","cacheState","fireUrlChange","cachedState","getCurrentState","lastCachedState","lastBrowserUrl","url","lastHistoryState","urlChangeListeners","listener","history","clearTimeout","pendingDeferIds","isMock","$$completeOutstandingRequest","$$incOutstandingRequestCount","self.$$incOutstandingRequestCount","notifyWhenNoOutstandingRequests","self.notifyWhenNoOutstandingRequests","callback","href","baseElement","state","self.url","sameState","sameBase","stripHash","substr","self.state","urlChangeInit","onUrlChange","self.onUrlChange","$$applicationDestroyed","self.$$applicationDestroyed","off","$$checkUrlChange","baseHref","self.baseHref","defer","self.defer","delay","timeoutId","cancel","self.defer.cancel","deferId","cacheFactory","cacheId","refresh","entry","freshEnd","staleEnd","n","link","p","nextEntry","prevEntry","caches","size","stats","id","capacity","Number","MAX_VALUE","lruHash","lruEntry","remove","removeAll","destroy","info","cacheFactory.info","cacheFactory.get","$$sanitizeUriProvider","parseIsolateBindings","directiveName","isController","LOCAL_REGEXP","bindings","definition","scopeName","bindingCache","$compileMinErr","mode","collection","optional","attrName","assertValidDirectiveName","getDirectiveRequire","require","REQUIRE_PREFIX_REGEXP","hasDirectives","COMMENT_DIRECTIVE_REGEXP","CLASS_DIRECTIVE_REGEXP","ALL_OR_NOTHING_ATTRS","EVENT_HANDLER_ATTR_REGEXP","this.directive","registerDirective","directiveFactory","Suffix","directives","priority","restrict","this.component","makeInjectable","tElement","tAttrs","$element","$attrs","template","templateUrl","ddo","controllerAs","identifierForController","transclude","bindToController","aHrefSanitizationWhitelist","this.aHrefSanitizationWhitelist","regexp","imgSrcSanitizationWhitelist","this.imgSrcSanitizationWhitelist","this.debugInfoEnabled","enabled","TTL","onChangesTtl","this.onChangesTtl","flushOnChangesQueue","onChangesQueue","errors","Attributes","attributesToCopy","$attr","$$element","setSpecialAttr","specialAttrHolder","attributes","attribute","removeNamedItem","setNamedItem","safeAddClass","className","$compileNodes","transcludeFn","maxPriority","ignoreDirective","previousCompileContext","NOT_EMPTY","domNode","nodeValue","compositeLinkFn","compileNodes","$$addScopeClass","namespace","publicLinkFn","cloneConnectFn","needsNewScope","$parent","$new","parentBoundTranscludeFn","transcludeControllers","futureParentElement","$$boundTransclude","$linkNode","wrapTemplate","controllerName","instance","$$addScopeInfo","nodeList","$rootElement","childLinkFn","childScope","childBoundTranscludeFn","stableNodeList","nodeLinkFnFound","linkFns","idx","nodeLinkFn","transcludeOnThisElement","createBoundTranscludeFn","templateOnThisElement","attrs","linkFnFound","collectDirectives","applyDirectivesToNode","terminal","previousBoundTranscludeFn","boundTranscludeFn","transcludedScope","cloneFn","controllers","containingScope","$$transcluded","boundSlots","$$slots","slotName","attrsMap","addDirective","directiveNormalize","isNgAttr","nAttrs","attrStartName","attrEndName","ngAttrName","NG_ATTR_BINDING","PREFIX_REGEXP","multiElementMatch","MULTI_ELEMENT_DIR_RE","directiveIsMultiElement","nName","addAttrInterpolateDirective","animVal","addTextInterpolateDirective","NODE_TYPE_COMMENT","collectCommentDirectives","byPriority","groupScan","attrStart","attrEnd","depth","groupElementsLinkFnWrapper","linkFn","groupedElementsLink","compilationGenerator","eager","compiled","lazyCompilation","compileNode","templateAttrs","jqCollection","originalReplaceDirective","preLinkFns","postLinkFns","addLinkFns","pre","post","newIsolateScopeDirective","$$isolateScope","cloneAndAnnotateFn","linkNode","controllersBoundTransclude","cloneAttachFn","hasElementTranscludeDirective","elementControllers","slotTranscludeFn","scopeToChild","controllerScope","newScopeDirective","isSlotFilled","transcludeFn.isSlotFilled","controllerDirectives","setupControllers","templateDirective","$$originalDirective","$$isolateBindings","scopeBindingInfo","initializeDirectiveBindings","removeWatches","$on","controllerDirective","$$bindings","bindingInfo","identifier","controllerResult","getControllers","controllerInstance","$onChanges","initialChanges","$onInit","$doCheck","$onDestroy","callOnDestroyHook","invokeLinkFn","$postLink","terminalPriority","nonTlbTranscludeDirective","hasTranscludeDirective","hasTemplate","$compileNode","$template","childTranscludeFn","didScanForMultipleTransclusion","mightHaveMultipleTransclusionError","directiveValue","$$start","$$end","assertNoDuplicate","$$tlb","scanningIndex","candidateDirective","$$createComment","replaceWith","$$parentNode","replaceDirective","slots","contents","slotMap","filledSlots","elementSelector","filled","$$newScope","denormalizeTemplate","removeComments","templateNamespace","newTemplateAttrs","templateDirectives","unprocessedDirectives","markDirectiveScope","mergeTemplateAttributes","compileTemplateUrl","Math","max","inheritType","dataName","property","controllerKey","$scope","$transclude","newScope","tDirectives","startAttrName","endAttrName","multiElement","srcAttr","dstAttr","$set","linkQueue","afterTemplateNodeLinkFn","afterTemplateChildLinkFn","beforeTemplateCompileNode","origAsyncDirective","derivedSyncDirective","then","content","tempTemplateAttrs","beforeTemplateLinkNode","linkRootElement","$$destroyed","oldClasses","delayedNodeLinkFn","ignoreChildLinkFn","diff","what","previousDirective","wrapModuleNameIfDefined","moduleName","text","interpolateFn","textInterpolateCompileFn","templateNode","templateNodeParent","hasCompileParent","$$addBindingClass","textInterpolateLinkFn","$$addBindingInfo","expressions","interpolateFnWatchAction","getTrustedContext","attrNormalizedName","HTML","RESOURCE_URL","allOrNothing","trustedContext","attrInterpolatePreLinkFn","$$observers","newValue","$$inter","$$scope","oldValue","$updateClass","elementsToRemove","newNode","firstElementToRemove","removeCount","j2","hasData","annotation","recordChanges","currentValue","previousValue","$$postDigest","changes","triggerOnChangesHook","SimpleChange","removeWatchCollection","initializeBinding","lastValue","parentGet","parentSet","compare","$observe","_UNINITIALIZED_VALUE","literal","assign","parentValueWatch","parentValue","$stateful","removeWatch","$watchCollection","initialValue","parentValueWatchAction","SIMPLE_ATTR_NAME","$normalize","$addClass","classVal","$removeClass","newClasses","toAdd","tokenDifference","toRemove","writeAttr","booleanKey","aliasedKey","ALIASED_ATTR","observer","trimmedSrcset","srcPattern","rawUris","nbrUrisWith2parts","floor","innerIdx","lastTuple","removeAttr","listeners","startSymbol","endSymbol","binding","isolated","noTemplate","compile.$$createComment","comment","createComment","previous","current","str1","str2","values","tokens1","tokens2","token","jqNodes","ident","CNTRL_REG","globals","this.has","register","this.register","allowGlobals","this.allowGlobals","addIdentifier","expression","later","$controllerMinErr","controllerPrototype","$controllerInit","exception","cause","serializeValue","v","toISOString","ngParamSerializer","params","jQueryLikeParamSerializer","serialize","toSerialize","topLevel","defaultHttpResponseTransform","headers","tempData","JSON_PROTECTION_PREFIX","contentType","jsonStart","JSON_START","JSON_ENDS","parseHeaders","line","headerVal","headerKey","headersGetter","headersObj","transformData","status","fns","defaults","transformResponse","transformRequest","d","common","CONTENT_TYPE_APPLICATION_JSON","patch","xsrfCookieName","xsrfHeaderName","paramSerializer","useApplyAsync","this.useApplyAsync","useLegacyPromise","useLegacyPromiseExtensions","this.useLegacyPromiseExtensions","interceptorFactories","interceptors","requestConfig","chainInterceptors","promise","thenFn","rejectFn","executeHeaderFns","headerContent","processedHeaders","headerFn","header","response","resp","reject","mergeHeaders","defHeaders","reqHeaders","defHeaderName","lowercaseDefHeaderName","reqHeaderName","requestInterceptors","responseInterceptors","when","reversedInterceptors","interceptor","request","requestError","responseError","serverRequest","reqData","withCredentials","sendReq","success","promise.success","promise.error","$httpMinErrLegacyFn","createApplyHandlers","eventHandlers","applyHandlers","callEventHandler","$applyAsync","$$phase","done","headersString","statusText","resolveHttpPromise","resolvePromise","deferred","resolve","resolvePromiseWithResult","removePendingReq","pendingRequests","cachedResp","buildUrl","defaultCache","xsrfValue","urlIsSameOrigin","timeout","responseType","uploadEventHandlers","serializedParams","interceptorFactory","createShortMethods","createShortMethodsWithData","createXhr","XMLHttpRequest","createHttpBackend","$browserDefer","callbacks","rawDocument","jsonpReq","callbackPath","async","body","wasCalled","addEventListener","timeoutRequest","jsonpDone","xhr","abort","completeRequest","createCallback","getResponse","removeCallback","open","setRequestHeader","onload","xhr.onload","responseText","urlResolve","protocol","getAllResponseHeaders","onerror","onabort","upload","send","this.startSymbol","this.endSymbol","escape","ch","unescapeText","escapedStartRegexp","escapedEndRegexp","constantWatchDelegate","objectEquality","constantInterp","unwatch","constantInterpolateWatch","mustHaveExpression","parseStringifyInterceptor","getTrusted","$interpolateMinErr","interr","unescapedText","exp","$$watchDelegate","endIndex","parseFns","textLength","expressionPositions","startSymbolLength","endSymbolLength","throwNoconcat","compute","interpolationFn","$watchGroup","interpolateFnWatcher","oldValues","currValue","$interpolate.startSymbol","$interpolate.endSymbol","interval","count","invokeApply","hasParams","iteration","setInterval","clearInterval","skipApply","$$intervalId","tick","notify","intervals","interval.cancel","encodePath","segments","parseAbsoluteUrl","absoluteUrl","locationObj","parsedUrl","$$protocol","$$host","hostname","$$port","port","DEFAULT_PORTS","parseAppUrl","relativeUrl","prefixed","$$path","pathname","$$search","search","$$hash","stripBaseUrl","base","lastIndexOf","trimEmptyHash","LocationHtml5Url","appBase","appBaseNoFile","basePrefix","$$html5","$$parse","this.$$parse","pathUrl","$locationMinErr","$$compose","this.$$compose","$$url","$$absUrl","$$parseLinkUrl","this.$$parseLinkUrl","relHref","appUrl","prevAppUrl","rewrittenUrl","LocationHashbangUrl","hashPrefix","withoutBaseUrl","withoutHashUrl","windowsFilePathExp","firstPathSegmentMatch","LocationHashbangInHtml5Url","locationGetter","locationGetterSetter","preprocess","html5Mode","requireBase","rewriteLinks","this.hashPrefix","this.html5Mode","setBrowserUrlWithFallback","oldUrl","oldState","$$state","afterLocationChange","$broadcast","absUrl","LocationMode","initialUrl","IGNORE_URI_REGEXP","ctrlKey","metaKey","shiftKey","which","button","absHref","preventDefault","initializing","newUrl","newState","$digest","$locationWatch","currentReplace","$$replace","urlOrStateChanged","debug","debugEnabled","this.debugEnabled","flag","formatError","Error","sourceURL","consoleLog","console","logFn","log","hasApply","arg1","arg2","warn","ensureSafeMemberName","fullExpression","$parseMinErr","getStringValue","ensureSafeObject","children","ensureSafeFunction","CALL","APPLY","BIND","ensureSafeAssignContext","ifDefined","plusFn","r","findConstantAndWatchExpressions","ast","allConstants","argsToWatch","AST","Program","expr","Literal","toWatch","UnaryExpression","argument","BinaryExpression","left","right","LogicalExpression","ConditionalExpression","alternate","consequent","Identifier","MemberExpression","object","computed","CallExpression","callee","AssignmentExpression","ArrayExpression","ObjectExpression","properties","ThisExpression","LocalsExpression","getInputs","lastExpression","isAssignable","assignableAST","NGValueParameter","operator","isLiteral","ASTCompiler","astBuilder","ASTInterpreter","isPossiblyDangerousMemberName","getValueOf","objectValueOf","cacheDefault","cacheExpensive","literals","identStart","identContinue","addLiteral","this.addLiteral","literalName","literalValue","setIdentifierFns","this.setIdentifierFns","identifierStart","identifierContinue","interceptorFn","expensiveChecks","parsedExpression","oneTime","cacheKey","runningChecksEnabled","parseOptions","$parseOptionsExpensive","$parseOptions","lexer","Lexer","parser","Parser","oneTimeLiteralWatchDelegate","oneTimeWatchDelegate","inputs","inputsWatchDelegate","expensiveChecksInterceptor","addInterceptor","expensiveCheckFn","expensiveCheckOldValue","expressionInputDirtyCheck","oldValueOfValue","prettyPrintExpression","inputExpressions","lastResult","oldInputValueOf","expressionInputWatch","newInputValue","oldInputValueOfValues","oldInputValues","expressionInputsWatch","changed","oneTimeWatch","oneTimeListener","old","isAllDefined","allDefined","constantWatch","watchDelegate","useInputs","regularInterceptedExpression","oneTimeInterceptedExpression","noUnsafeEval","isIdentifierStart","isIdentifierContinue","$$runningExpensiveChecks","$parse.$$runningExpensiveChecks","qFactory","nextTick","exceptionHandler","Promise","simpleBind","scheduleProcessQueue","processScheduled","pending","Deferred","$qMinErr","TypeError","onFulfilled","onRejected","progressBack","catch","finally","handleCallback","$$reject","$$resolve","that","rejectPromise","progress","makePromise","resolved","isResolved","callbackOutput","errback","$Q","resolver","resolveFn","all","promises","counter","results","race","requestAnimationFrame","webkitRequestAnimationFrame","cancelAnimationFrame","webkitCancelAnimationFrame","webkitCancelRequestAnimationFrame","rafSupported","raf","timer","supported","createChildScopeClass","ChildScope","$$watchers","$$nextSibling","$$childHead","$$childTail","$$listeners","$$listenerCount","$$watchersCount","$id","$$ChildScope","$rootScopeMinErr","lastDirtyWatch","applyAsyncId","digestTtl","this.digestTtl","destroyChildScope","$event","currentScope","cleanUpScope","$$prevSibling","$root","Scope","beginPhase","phase","incrementWatchersCount","decrementListenerCount","initWatchVal","flushApplyAsync","applyAsyncQueue","scheduleApplyAsync","isolate","child","watchExp","watcher","last","eq","deregisterWatch","watchExpressions","watchGroupAction","changeReactionScheduled","firstRun","newValues","deregisterFns","shouldCall","deregisterWatchGroup","unwatchFn","watchGroupSubAction","$watchCollectionInterceptor","_value","bothNaN","newItem","oldItem","internalArray","oldLength","changeDetected","newLength","internalObject","veryOldValue","trackVeryOldValue","changeDetector","initRun","$watchCollectionAction","watch","watchers","dirty","ttl","watchLog","logIdx","asyncTask","asyncQueuePosition","asyncQueue","$eval","msg","next","postDigestQueuePosition","postDigestQueue","eventName","this.$watchGroup","$applyAsyncExpression","namedListeners","indexOfListener","$emit","targetScope","listenerArgs","$$asyncQueue","$$postDigestQueue","$$applyAsyncQueue","sanitizeUri","uri","isImage","regex","normalizedVal","adjustMatcher","matcher","$sceMinErr","escapeForRegexp","adjustMatchers","matchers","adjustedMatchers","SCE_CONTEXTS","resourceUrlWhitelist","resourceUrlBlacklist","this.resourceUrlWhitelist","this.resourceUrlBlacklist","matchUrl","generateHolderType","Base","holderType","trustedValue","$$unwrapTrustedValue","this.$$unwrapTrustedValue","holderType.prototype.valueOf","holderType.prototype.toString","htmlSanitizer","trustedValueHolderBase","byType","CSS","URL","JS","trustAs","Constructor","maybeTrusted","allowed","this.enabled","sce","isEnabled","sce.isEnabled","sce.getTrusted","parseAs","sce.parseAs","enumValue","lName","eventSupport","hasHistoryPushState","chrome","app","runtime","pushState","android","userAgent","navigator","boxee","vendorPrefix","vendorRegex","bodyStyle","transitions","animations","webkitTransition","webkitAnimation","hasEvent","divElm","httpOptions","this.httpOptions","handleRequestFn","tpl","ignoreRequestError","totalPendingRequests","getTrustedResourceUrl","transformer","handleError","$templateRequestMinErr","testability","testability.findBindings","opt_exactMatch","getElementsByClassName","matches","dataBinding","bindingName","testability.findModels","prefixes","attributeEquals","testability.getLocation","testability.setLocation","testability.whenStable","deferreds","$$timeoutId","timeout.cancel","urlParsingNode","requestUrl","originUrl","$$CookieReader","safeDecodeURIComponent","lastCookies","lastCookieString","cookieArray","cookie","currentCookieString","filters","suffix","currencyFilter","dateFilter","filterFilter","jsonFilter","limitToFilter","lowercaseFilter","numberFilter","orderByFilter","uppercaseFilter","comparator","anyPropertyKey","matchAgainstAnyProp","getTypeForFilter","expressionType","predicateFn","createPredicateFn","shouldMatchPrimitives","actual","expected","deepCompare","dontMatchWholeObject","actualType","expectedType","expectedVal","matchAnyProperty","actualVal","$locale","formats","NUMBER_FORMATS","amount","currencySymbol","fractionSize","CURRENCY_SYM","PATTERNS","maxFrac","formatNumber","GROUP_SEP","DECIMAL_SEP","number","numStr","exponent","digits","numberOfIntegerDigits","zeros","ZERO_CHAR","MAX_DIGITS","roundNumber","parsedNumber","minFrac","fractionLen","min","roundAt","digit","k","carry","reduceRight","groupSep","decimalSep","isInfinity","isFinite","isZero","abs","formattedText","integerLen","decimals","reduce","groups","lgSize","gSize","negPre","negSuf","posPre","posSuf","padNumber","num","negWrap","neg","dateGetter","dateStrGetter","shortForm","standAlone","getFirstThursdayOfYear","year","dayOfWeekOnFirst","getDay","weekGetter","firstThurs","getFullYear","thisThurs","getMonth","getDate","round","eraGetter","ERAS","jsonStringToDate","string","R_ISO8601_STR","tzHour","tzMin","dateSetter","setUTCFullYear","setFullYear","timeSetter","setUTCHours","setHours","m","s","ms","parseFloat","format","DATETIME_FORMATS","NUMBER_STRING","DATE_FORMATS_SPLIT","DATE_FORMATS","spacing","limit","begin","Infinity","sliceFn","end","processPredicates","sortPredicates","map","predicate","descending","defaultCompare","v1","v2","type1","type2","value1","value2","sortPredicate","reverseOrder","compareFn","predicates","compareValues","getComparisonObject","tieBreaker","predicateValues","doComparison","ngDirective","FormController","controls","$error","$$success","$pending","$name","$dirty","$pristine","$valid","$invalid","$submitted","$$parentForm","nullFormCtrl","$rollbackViewValue","form.$rollbackViewValue","control","$commitViewValue","form.$commitViewValue","$addControl","form.$addControl","$$renameControl","form.$$renameControl","newName","oldName","$removeControl","form.$removeControl","$setValidity","addSetValidityMethod","ctrl","unset","$setDirty","form.$setDirty","PRISTINE_CLASS","DIRTY_CLASS","$setPristine","form.$setPristine","setClass","SUBMITTED_CLASS","$setUntouched","form.$setUntouched","$setSubmitted","form.$setSubmitted","stringBasedInputType","$formatters","$isEmpty","baseInputType","composing","ev","ngTrim","$viewValue","$$hasNativeValidators","$setViewValue","deferListener","origValue","keyCode","PARTIAL_VALIDATION_TYPES","PARTIAL_VALIDATION_EVENTS","validity","origBadInput","badInput","origTypeMismatch","typeMismatch","$render","ctrl.$render","createDateParser","mapping","iso","ISO_DATE_REGEXP","yyyy","MM","dd","HH","getHours","mm","ss","getSeconds","sss","getMilliseconds","part","NaN","createDateInputType","parseDate","dynamicDateInputType","isValidDate","parseObservedDateValue","badInputChecker","$options","previousDate","$$parserName","$parsers","parsedDate","ngModelMinErr","ngMin","minVal","$validators","ctrl.$validators.min","$validate","ngMax","maxVal","ctrl.$validators.max","VALIDITY_STATE_PROPERTY","parseConstantExpr","parseFn","classDirective","arrayDifference","arrayClasses","addClasses","digestClassCounts","classCounts","classesToUpdate","updateClasses","ngClassWatchAction","$index","old$index","mod","cachedToggleClass","switchValue","classCache","toggleValidationCss","validationErrorKey","isValid","VALID_CLASS","INVALID_CLASS","setValidity","isObjectEmpty","PENDING_CLASS","combinedState","REGEX_STRING_REGEXP","documentMode","rules","ngCspElement","ngCspAttribute","noInlineStyle","name_","el","full","major","minor","dot","codeName","expando","JQLite._data","mouseleave","mouseenter","optgroup","tbody","tfoot","colgroup","caption","thead","th","td","Node","contains","compareDocumentPosition","ready","trigger","fired","removeData","jqLiteHasData","jqLiteCleanData","removeAttribute","css","NODE_TYPE_ATTRIBUTE","lowercasedName","specified","getNamedItem","ret","getText","$dv","multiple","selected","nodeCount","jqLiteOn","types","addHandler","noEventListener","one","onFn","replaceNode","insertBefore","contentDocument","prepend","wrapNode","detach","after","newElement","toggleClass","condition","classCondition","nextElementSibling","getElementsByTagName","extraParameters","dummyEvent","handlerArgs","eventFnsCopy","arg3","unbind","FN_ARG_SPLIT","FN_ARG","argDecl","underscore","$animateMinErr","postDigestElements","updateData","handleCSSClassChanges","existing","pin","domOperation","from","to","classesAdded","add","classesRemoved","runner","complete","$$registeredAnimations","classNameFilter","this.classNameFilter","$$classNameFilter","reservedRegex","NG_ANIMATE_CLASSNAME","domInsert","parentElement","afterElement","afterNode","ELEMENT_NODE","previousElementSibling","enter","move","leave","addclass","animate","tempClasses","waitForTick","waitQueue","passed","AnimateRunner","setHost","rafTick","_doneCallbacks","_tick","this._tick","doc","hidden","_state","chain","AnimateRunner.chain","AnimateRunner.all","runners","onProgress","DONE_COMPLETE_STATE","getPromise","resolveHandler","rejectHandler","pause","resume","_resolve","INITIAL_STATE","DONE_PENDING_STATE","initialOptions","closed","$$prepared","cleanupStyles","start","UNINITIALIZED_VALUE","isFirstChange","SimpleChange.prototype.isFirstChange","offsetWidth","APPLICATION_JSON","$httpMinErr","$interpolateMinErr.throwNoconcat","$interpolateMinErr.interr","callbackId","called","callbackMap","PATH_MATCH","locationPrototype","paramValue","Location","Location.prototype.state","OPERATORS","ESCAPE","lex","tokens","readString","peek","readNumber","peekMultichar","readIdent","is","isWhitespace","ch2","ch3","op2","op3","op1","throwError","chars","codePointAt","isValidIdentifierStart","isValidIdentifierContinue","cp","charCodeAt","cp1","cp2","isExpOperator","colStr","peekCh","quote","rawString","hex","String","fromCharCode","rep","ExpressionStatement","Property","program","expressionStatement","expect","filterChain","assignment","ternary","logicalOR","consume","logicalAND","equality","relational","additive","multiplicative","unary","primary","arrayDeclaration","selfReferential","parseArguments","baseExpression","peekToken","kind","e1","e2","e3","e4","peekAhead","t","nextId","vars","own","assignable","stage","computing","recurse","return_","generateFunction","fnKey","intoId","watchId","fnString","USE","STRICT","filterPrefix","watchFns","varsPrefix","section","nameId","recursionFn","skipWatchIdCheck","if_","lazyAssign","computedMember","lazyRecurse","plus","not","getHasOwnProperty","nonComputedMember","addEnsureSafeObject","notNull","addEnsureSafeAssignContext","addEnsureSafeMemberName","addEnsureSafeFunction","member","filterName","defaultValue","UNSAFE_CHARACTERS","SAFE_IDENTIFIER","stringEscapeFn","stringEscapeRegex","c","skip","init","fn.assign","rhs","lhs","unary+","unary-","unary!","binary+","binary-","binary*","binary/","binary%","binary===","binary!==","binary==","binary!=","binary<","binary>","binary<=","binary>=","binary&&","binary||","ternary?:","astCompiler","yy","y","MMMM","MMM","M","LLLL","H","hh","EEEE","EEE","ampmGetter","AMPMS","Z","timeZoneGetter","zone","paddedZone","ww","w","G","GG","GGG","GGGG","longEraGetter","ERANAMES","xlinkHref","propName","defaultLinkFn","normalized","ngBooleanAttrWatchAction","htmlAttr","ngAttrAliasWatchAction","nullFormRenameControl","formDirectiveFactory","isNgForm","getSetter","ngFormCompile","formElement","nameAttr","ngFormPreLink","ctrls","handleFormSubmission","setter","URL_REGEXP","EMAIL_REGEXP","NUMBER_REGEXP","DATE_REGEXP","DATETIMELOCAL_REGEXP","WEEK_REGEXP","MONTH_REGEXP","TIME_REGEXP","inputType","textInputType","weekParser","isoWeek","existingDate","week","hours","seconds","milliseconds","addDays","numberInputType","urlInputType","ctrl.$validators.url","modelValue","viewValue","emailInputType","email","ctrl.$validators.email","radioInputType","checked","checkboxInputType","trueValue","ngTrueValue","falseValue","ngFalseValue","ctrl.$isEmpty","CONSTANT_VALUE_REGEXP","tplAttr","ngValueConstantLink","ngValueLink","valueWatchAction","$compile","ngBindCompile","templateElement","ngBindLink","ngBindWatchAction","ngBindTemplateCompile","ngBindTemplateLink","ngBindHtmlCompile","ngBindHtmlGetter","ngBindHtmlWatch","sceValueOf","ngBindHtmlLink","ngBindHtmlWatchAction","getTrustedHtml","$viewChangeListeners","forceAsyncEvents","ngEventHandler","previousElements","ngIfWatchAction","srcExp","onloadExp","autoScrollExp","autoscroll","changeCounter","previousElement","currentElement","cleanupLastIncludeContent","ngIncludeWatchAction","afterAnimation","thisChangeId","namespaceAdaptedClone","trimValues","NgModelController","$modelValue","$$rawModelValue","$asyncValidators","$untouched","$touched","parsedNgModel","parsedNgModelAssign","ngModelGet","ngModelSet","pendingDebounce","parserValid","$$setOptions","this.$$setOptions","getterSetter","invokeModelGetter","invokeModelSetter","$$$p","this.$isEmpty","$$updateEmptyClasses","this.$$updateEmptyClasses","NOT_EMPTY_CLASS","EMPTY_CLASS","currentValidationRunId","this.$setPristine","this.$setDirty","this.$setUntouched","UNTOUCHED_CLASS","TOUCHED_CLASS","$setTouched","this.$setTouched","this.$rollbackViewValue","$$lastCommittedViewValue","this.$validate","prevValid","prevModelValue","allowInvalid","$$runValidators","allValid","$$writeModelToScope","this.$$runValidators","doneCallback","processSyncValidators","syncValidatorsValid","validator","processAsyncValidators","validatorPromises","validationDone","localValidationRunId","processParseErrors","errorKey","this.$commitViewValue","$$parseAndValidate","this.$$parseAndValidate","this.$$writeModelToScope","this.$setViewValue","updateOnDefault","$$debounceViewValueCommit","this.$$debounceViewValueCommit","debounceDelay","debounce","ngModelWatch","formatters","ngModelCompile","ngModelPreLink","modelCtrl","formCtrl","ngModelPostLink","updateOn","DEFAULT_REGEXP","ngOptionsMinErr","NG_OPTIONS_REGEXP","parseOptionsExpression","optionsExp","selectElement","Option","selectValue","label","group","disabled","getOptionValuesKeys","optionValues","optionValuesKeys","keyName","itemKey","valueName","selectAs","trackBy","viewValueFn","trackByFn","getTrackByValueFn","getHashOfValue","getTrackByValue","getLocals","displayFn","groupByFn","disableWhenFn","valuesFn","getWatchables","watchedArray","optionValuesLength","disableWhen","getOptions","optionItems","selectValueMap","optionItem","getOptionFromViewValue","getViewValueFromOption","optionTemplate","optGroupTemplate","ngOptionsPreLink","registerOption","ngOptionsPostLink","updateOptionElement","updateOptions","selectCtrl","readValue","groupElementMap","providedEmptyOption","emptyOption","addOption","groupElement","listFragment","optionElement","ngModelCtrl","nextValue","unknownOption","ngModelCtrl.$isEmpty","writeValue","selectCtrl.writeValue","selectCtrl.readValue","selectedValues","selections","selectedOption","BRACE","IS_WHEN","updateElementText","newText","numberExp","whenExp","whens","whensExpFns","braceReplacement","watchRemover","lastCount","attributeName","tmpMatch","whenKey","ngPluralizeWatchAction","countIsNaN","pluralCat","whenExpFn","ngRepeatMinErr","updateScope","valueIdentifier","keyIdentifier","arrayLength","$first","$last","$middle","$odd","$even","ngRepeatCompile","ngRepeatEndComment","aliasAs","trackByExp","trackByExpGetter","trackByIdExpFn","trackByIdArrayFn","trackByIdObjFn","hashFnLocals","ngRepeatLink","lastBlockMap","ngRepeatAction","previousNode","nextNode","nextBlockMap","collectionLength","trackById","collectionKeys","nextBlockOrder","trackByIdFn","blockKey","ngRepeatTransclude","ngShowWatchAction","NG_HIDE_CLASS","NG_HIDE_IN_PROGRESS_CLASS","ngHideWatchAction","ngStyleWatchAction","newStyles","oldStyles","ngSwitchController","cases","selectedTranscludes","selectedElements","previousLeaveAnimations","selectedScopes","spliceFactory","ngSwitchWatchAction","selectedTransclude","caseElement","selectedScope","anchor","ngTranscludeMinErr","ngTranscludeCompile","fallbackLinkFn","ngTranscludePostLink","useFallbackContent","ngTranscludeSlot","ngTranscludeCloneAttachFn","noopNgModelController","SelectController","optionsMap","renderUnknownOption","self.renderUnknownOption","unknownVal","removeUnknownOption","self.removeUnknownOption","self.readValue","self.writeValue","hasOption","self.addOption","removeOption","self.removeOption","self.hasOption","self.registerOption","optionScope","optionAttrs","interpolateValueFn","interpolateTextFn","valueAttributeObserveAction","interpolateWatchAction","selectPreLink","lastView","lastViewRef","selectMultipleWatch","selectPostLink","ngModelCtrl.$render","selectCtrlName","ctrl.$validators.required","patternExp","ctrl.$validators.pattern","intVal","ctrl.$validators.maxlength","ctrl.$validators.minlength","getDecimals","opt_precision","pow","ONE","OTHER","$$csp","head"] } diff --git a/ui/app/bower_components/angular/bower.json b/ui/app/bower_components/angular/bower.json index 7474c97..1d1b272 100644 --- a/ui/app/bower_components/angular/bower.json +++ b/ui/app/bower_components/angular/bower.json @@ -1,6 +1,7 @@ { "name": "angular", - "version": "1.4.1", + "version": "1.5.8", + "license": "MIT", "main": "./angular.js", "ignore": [], "dependencies": { diff --git a/ui/app/bower_components/angular/package.json b/ui/app/bower_components/angular/package.json index 16910cf..fe0bb7e 100644 --- a/ui/app/bower_components/angular/package.json +++ b/ui/app/bower_components/angular/package.json @@ -1,6 +1,6 @@ { "name": "angular", - "version": "1.4.1", + "version": "1.5.8", "description": "HTML enhanced for web apps", "main": "index.js", "scripts": { From 4debd735516f32ca6794446cc171db55f2aea449 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Mon, 7 Nov 2016 11:34:52 +0100 Subject: [PATCH 24/35] implemented PUT DC in NS Manager --- ns-manager/routes/config.rb | 78 +----------------------------------- ns-manager/routes/dc.rb | 15 ++++++- ns-manager/spec/auth_spec.rb | 8 ---- ns-manager/spec/dc_spec.rb | 55 +++++++++++++++++++++++++ 4 files changed, 70 insertions(+), 86 deletions(-) diff --git a/ns-manager/routes/config.rb b/ns-manager/routes/config.rb index 0b4e9cd..6fc6a20 100644 --- a/ns-manager/routes/config.rb +++ b/ns-manager/routes/config.rb @@ -75,7 +75,6 @@ class ServiceConfiguration < TnovaManager post '/services' do return 415 unless request.content_type == 'application/json' serv_reg, errors = parse_json(request.body.read) - logger.info "POST SERVICE REQUEST -------------------------------------------------------------- " + serv_reg['name'] @token = JWT.encode({ service_name: serv_reg['name'] }, serv_reg['secret'], 'HS256') serv = { @@ -87,7 +86,7 @@ class ServiceConfiguration < TnovaManager depends_on: serv_reg['depends_on'], type: serv_reg['type'] } - logger.debug serv + logger.debug 'Registring a new service: ' + serv_reg['name'] begin s = Service.find_by(name: serv_reg['name']) s.update_attributes!(host: serv_reg['host'], port: serv_reg['port'], token: @token, depends_on: serv_reg['depends_on'], type: serv_reg['type']) @@ -147,79 +146,4 @@ class ServiceConfiguration < TnovaManager halt 200 end - # DEPRECATED.............. - - # @method post_configs_registerService - # @overload post '/configs/registerService' - # Register a microservice - post '/registerService' do - return registerService(request.body.read) - end - - # @method post_configs_registerExternalService - # @overload post '/configs/registerExternalService' - # Register a external service - post '/registerExternalService' do - return registerExternalService(request.body.read) - end - - # @method post_configs_unRegisterService - # @overload post '/configs/unRegisterService/:service_id' - # Unregister a service - post '/unRegisterService/:microservice' do - logger.info('Unregister service ' + params['microservice']) - unregisterService(params['microservice']) - logger.info('Service ' + @json['name'] + ' unregistred correctly') - end - - # @method delete_configs_services - # @overload delete '/configs/services/:microservice' - # Delete a registered service - delete '/services/:microservice' do - ServiceModel.find_by(name: params['microservice']).delete - end - - # @method get_configs_services - # @overload get '/configs/services' - # Get all available services - get '/services' do - if params['name'] - return ServiceModel.find_by(name: params['name']).to_json - else - return ServiceModel.all.to_json - end - end - - # @method put_configs_services - # @overload put '/configs/services' - # Update service information - put '/services' do - updateService(request.body.read) - return 'Correct update.' - end - - # @method put_configs_services - # @overload put '/configs/services/:name/status' - # Update service status - put '/services/:name/status' do - @service = ServiceModel.find_by(name: params['name']) - @service.update_attribute(:status, request.body.read) - return 'Correct update.' - end - - # @method get_configs_services_publish_microservice - # @overload get '/configs/services/:name/status' - # Get dependencies for specific microservice, asyncrhonous call - post '/services/publish/:microservice' do - name = params[:microservice] - - registerService(request.body.read) - - Thread.new do - logger.debug 'Publishing `' + name + '` to other services services...' - ServiceConfigurationHelper.publishServices - end - - return 200 - end end diff --git a/ns-manager/routes/dc.rb b/ns-manager/routes/dc.rb index cab24a3..6b21c2d 100644 --- a/ns-manager/routes/dc.rb +++ b/ns-manager/routes/dc.rb @@ -100,7 +100,20 @@ class DcController < TnovaManager halt 201, { id: dc._id }.to_json end - put '/services' do + put '/dc/:id' do |id| + return 415 unless request.content_type == 'application/json' + pop_info, errors = parse_json(request.body.read) + + begin + dc = Dc.find(id.to_i) + rescue Mongoid::Errors::DocumentNotFound => e + logger.error 'DC not found' + return 404 + end + + dc.update_attributes(pop_info) + + halt 200 end # @method delete_pops_dc_id diff --git a/ns-manager/spec/auth_spec.rb b/ns-manager/spec/auth_spec.rb index 704c177..130bb3d 100644 --- a/ns-manager/spec/auth_spec.rb +++ b/ns-manager/spec/auth_spec.rb @@ -90,7 +90,6 @@ def app context 'given a valid token' do let(:response) { post '/validation', {token: token.token}.to_json, rack_env={'CONTENT_TYPE' => 'application/json'} } it 'responds with a 200' do - puts token.token expect(response.status).to eq 200 end end @@ -140,7 +139,6 @@ def app let(:response) { put '/invalid_id/update_password', {name: 'teste'}.to_json, rack_env={'CONTENT_TYPE' => 'application/x-www-form-urlencoded'} } it 'responds with a 415' do - puts user.id expect(response.status).to eq 415 end @@ -165,12 +163,10 @@ def app let(:response) { put '/' + user.id.to_s + '/update_password', {old_password: "secret2", password: "secret2", re_password: "secret2"}.to_json, rack_env={'CONTENT_TYPE' => 'application/json'} } it 'responds with a 404' do - puts user.id expect(response.status).to eq 404 end it 'response body should contain a String' do - puts user.id expect(response.body).to be_a String end end @@ -179,7 +175,6 @@ def app let(:response) { put '/' + user.id.to_s + '/update_password', {old_password: "secret", password: "secret2", re_password: "secret3"}.to_json, rack_env={'CONTENT_TYPE' => 'application/json'} } it 'responds with a 404' do - puts user.id expect(response.status).to eq 404 end @@ -192,9 +187,6 @@ def app let(:response) { put '/' + user.id.to_s + '/update_password', {old_password: "secret", password: "secret2", re_password: "secret2"}.to_json, rack_env={'CONTENT_TYPE' => 'application/json'} } it 'responds with a 200' do - - puts user.name - puts user.password expect(response.status).to eq 200 end diff --git a/ns-manager/spec/dc_spec.rb b/ns-manager/spec/dc_spec.rb index c658ef7..920c1e6 100644 --- a/ns-manager/spec/dc_spec.rb +++ b/ns-manager/spec/dc_spec.rb @@ -173,5 +173,60 @@ def app end describe 'PUT /dc/:id' do + let(:dc) { create :dc } + + context 'given an invalid content type' do + let(:response) { put '/dc/' + dc._id.to_s, {name: 'teste'}.to_json, rack_env={'CONTENT_TYPE' => 'application/x-www-form-urlencoded'} } + + it 'responds with a 415' do + expect(response.status).to eq 415 + end + + it 'responds with an empty body' do + expect(response.body).to be_empty + end + end + + context 'given an invalid DC id' do + let(:response) { put '/dc/invalidId', {name: "name", host: "host", user: "user", password: "", tenant_name: "tenan", extra_info: "extra..."}.to_json, rack_env={'CONTENT_TYPE' => 'application/json'} } + + it 'responds with a 404' do + expect(response.status).to eq 404 + end + + it 'responds with an empty body' do + expect(response.body).to be_empty + end + end + + context 'given a valid DC' do + let(:response) { put '/dc/' + dc._id.to_s, {name: "name222", host: "host222", user: "user", password: "", tenant_name: "tenan", extra_info: "extra..."}.to_json, rack_env={'CONTENT_TYPE' => 'application/json'} } + + it 'responds with a 200' do + expect(response.status).to eq 200 + end + + it 'responds with an empty body' do + expect(response.body).to be_empty + end + end + + context 'given a valid DC' do + let(:response) { get '/dc/' + dc._id.to_s } + + it 'responds with a 200' do + expect(response.status).to eq 200 + end + + it 'response body should contain a Hash (DC)' do + expect(JSON.parse response.body).to be_a Hash + end + + it 'response body should be equal than the PUT request' do + skip "is skipped" do + end + end + + end end end From 3edafe30df7357da98c8673e7537d5a9cf7fa130 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Mon, 7 Nov 2016 12:01:02 +0100 Subject: [PATCH 25/35] NS provisioning call WICM if the resource is reserved --- ns-provisioning/helpers/ns.rb | 2 +- ns-provisioning/routes/ns.rb | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/ns-provisioning/helpers/ns.rb b/ns-provisioning/helpers/ns.rb index 615ec9e..c4e7552 100644 --- a/ns-provisioning/helpers/ns.rb +++ b/ns-provisioning/helpers/ns.rb @@ -286,7 +286,7 @@ def instantiate(instance, nsd, instantiation_info) return handleError(@instance, errors) if errors resource_reservation = @instance['resource_reservation'] - resource_reservation << { wicm_stack: stack, pop_id: pop_auth['pop_id'] } + resource_reservation << { wicm_stack: stack, pop_id: pop_auth['pop_id'] } @instance.update_attribute('resource_reservation', resource_reservation) end end diff --git a/ns-provisioning/routes/ns.rb b/ns-provisioning/routes/ns.rb index e848e46..08f5dc4 100644 --- a/ns-provisioning/routes/ns.rb +++ b/ns-provisioning/routes/ns.rb @@ -346,6 +346,18 @@ class Provisioner < NsProvisioning end end + if @instance['resource_reservation'].find { |resource| resource.has_key?('wicm_stack')} + logger.info 'Starting traffic redirection in the WICM' + Thread.new do + begin + response = RestClient.put settings.wicm + '/vnf-connectivity/' + nsr_id, '', content_type: :json, accept: :json + rescue => e + logger.error e + end + logger.info response + end + end + logger.info 'Starting monitoring workflow...' Thread.new do sleep(5) From 84973944a233506cb03baee2d66065ae33d639f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Mon, 7 Nov 2016 12:23:11 +0100 Subject: [PATCH 26/35] Rspec colors missing in catalogues modules --- ns-catalogue/.rspec | 2 ++ vnf-catalogue/.rspec | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 ns-catalogue/.rspec create mode 100644 vnf-catalogue/.rspec diff --git a/ns-catalogue/.rspec b/ns-catalogue/.rspec new file mode 100644 index 0000000..83e16f8 --- /dev/null +++ b/ns-catalogue/.rspec @@ -0,0 +1,2 @@ +--color +--require spec_helper diff --git a/vnf-catalogue/.rspec b/vnf-catalogue/.rspec new file mode 100644 index 0000000..83e16f8 --- /dev/null +++ b/vnf-catalogue/.rspec @@ -0,0 +1,2 @@ +--color +--require spec_helper From 5a4f4896140fbfad2d03b339a9f9156d6aace2e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Mon, 7 Nov 2016 15:55:15 +0100 Subject: [PATCH 27/35] Included status bar in instances view --- ui/app/index.html | 1 + ui/app/scripts/filters/progress_status.js | 19 +++++++++++++++++++ ui/app/scripts/filters/vnfDuplicates.js | 4 ++-- ui/app/views/t-nova/nsInstances.html | 10 +++++----- 4 files changed, 27 insertions(+), 7 deletions(-) create mode 100644 ui/app/scripts/filters/progress_status.js diff --git a/ui/app/index.html b/ui/app/index.html index 7656a78..05e4061 100644 --- a/ui/app/index.html +++ b/ui/app/index.html @@ -115,6 +115,7 @@ + diff --git a/ui/app/scripts/filters/progress_status.js b/ui/app/scripts/filters/progress_status.js new file mode 100644 index 0000000..dd705fa --- /dev/null +++ b/ui/app/scripts/filters/progress_status.js @@ -0,0 +1,19 @@ +'use strict'; + +angular.module('tNovaApp') +.filter('progress', function ($filter) { + + return function (item, filterOn) { + var status = [ + {id: "INIT", progress: "10"}, + {id: "MAPPED FOUND", progress: "20"}, + {id: "NETWORK CREATED", progress: "30"}, + {id: "INSTANTIATING VNFs", progress: "60"}, + {id: "INSTANTIATED", progress: "100"}, + {id: "START", progress: "100"}, + {id: "DELETING", progress: "50"} + ]; + var t = $filter('filter')(status, {id: item})[0]; + return t.progress; + }; + }); diff --git a/ui/app/scripts/filters/vnfDuplicates.js b/ui/app/scripts/filters/vnfDuplicates.js index c66109a..9542e07 100644 --- a/ui/app/scripts/filters/vnfDuplicates.js +++ b/ui/app/scripts/filters/vnfDuplicates.js @@ -15,7 +15,7 @@ angular.module('tNovaApp') break; } } - + if (!isDuplicate) { newItems.push(item); } @@ -25,4 +25,4 @@ angular.module('tNovaApp') } return items; }; - }); \ No newline at end of file + }); diff --git a/ui/app/views/t-nova/nsInstances.html b/ui/app/views/t-nova/nsInstances.html index 0932a5c..45b622c 100644 --- a/ui/app/views/t-nova/nsInstances.html +++ b/ui/app/views/t-nova/nsInstances.html @@ -48,11 +48,11 @@ {{row.vendor}} {{row.version}} {{row.status}} - {{row.created_at| date:'yyyy-MM-dd HH:mm:ss'}} - Instantiated - Tear-up - In progress - Terminated +
+
+
+ + {{row.created_at| date:'yyyy-MM-dd HH:mm:ss'}} From 902063349f54c5edbbcacc65d4f00c6e083879de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Mon, 7 Nov 2016 17:40:19 +0100 Subject: [PATCH 28/35] Fix NS Manager get DC list --- ns-manager/routes/ns_provisioning.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ns-manager/routes/ns_provisioning.rb b/ns-manager/routes/ns_provisioning.rb index 45085b8..5629cd3 100644 --- a/ns-manager/routes/ns_provisioning.rb +++ b/ns-manager/routes/ns_provisioning.rb @@ -49,7 +49,8 @@ class NsProvisioner < TnovaManager pop_list = [] mapping_info = {} if instantiation_info['pop_id'].nil? - pop_list = JSON.parse(getDcs()) + pop_list, errors = JSON.parse(getDcs()) + halt 400, "Error getting DC list." if errors if pop_list.empty? halt 400, "No PoPs registereds." end From 2afcf0c24cbb60bb97665e1a1ec574b99f0af478 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Mon, 7 Nov 2016 17:41:24 +0100 Subject: [PATCH 29/35] Included more status in Provisioning and UI --- ns-provisioning/helpers/ns.rb | 3 +++ ns-provisioning/routes/ns.rb | 2 ++ ui/app/scripts/filters/progress_status.js | 6 ++++-- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/ns-provisioning/helpers/ns.rb b/ns-provisioning/helpers/ns.rb index c4e7552..f664870 100644 --- a/ns-provisioning/helpers/ns.rb +++ b/ns-provisioning/helpers/ns.rb @@ -216,6 +216,7 @@ def instantiate(instance, nsd, instantiation_info) @instance['vnfrs'] = [] #@instance['authentication'] = [] + @instance.update_attribute('status', 'CREATING AUTHENTICATIONS') # if mapping of all VNFs are in the same PoP. Create Authentication and network 1 time mapping['vnf_mapping'].each do |vnf| logger.info 'Start authentication process of ' + vnf.to_s @@ -236,6 +237,8 @@ def instantiate(instance, nsd, instantiation_info) # check if @instance['authentication'] has the credentials for each PoP in mapping['vnf_mapping'] ? compare sizes? + @instance.update_attribute('status', 'CREATING NETWORKS') + # generate networks in each PoP? if @instance['authentication'].size > 1 logger.info 'More than 1 PoP is defined. WICM is required.' diff --git a/ns-provisioning/routes/ns.rb b/ns-provisioning/routes/ns.rb index 08f5dc4..fed37b8 100644 --- a/ns-provisioning/routes/ns.rb +++ b/ns-provisioning/routes/ns.rb @@ -131,6 +131,8 @@ class Provisioner < NsProvisioning halt 404 end + @nsInstance.update_attribute('status', 'DELETING') + if params[:status] === 'terminate' logger.info 'Starting thread for removing VNF and NS instances.' Thread.abort_on_exception = false diff --git a/ui/app/scripts/filters/progress_status.js b/ui/app/scripts/filters/progress_status.js index dd705fa..c86fdec 100644 --- a/ui/app/scripts/filters/progress_status.js +++ b/ui/app/scripts/filters/progress_status.js @@ -7,8 +7,10 @@ angular.module('tNovaApp') var status = [ {id: "INIT", progress: "10"}, {id: "MAPPED FOUND", progress: "20"}, - {id: "NETWORK CREATED", progress: "30"}, - {id: "INSTANTIATING VNFs", progress: "60"}, + {id: "CREATING_AUTHENTICATIONS", progress: "30"}, + {id: "CREATING NETWORKS", progress: "50"}, + {id: "NETWORK CREATED", progress: "60"}, + {id: "INSTANTIATING VNFs", progress: "70"}, {id: "INSTANTIATED", progress: "100"}, {id: "START", progress: "100"}, {id: "DELETING", progress: "50"} From eac91ebebeacaad9df344911f98e35ba96c6937a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Mon, 7 Nov 2016 17:43:02 +0100 Subject: [PATCH 30/35] VNF provisioning saves the creation time of each stack resource --- vnf-provisioning/helpers/hot.rb | 24 ++++++++-- vnf-provisioning/helpers/init.rb | 1 + vnf-provisioning/helpers/utils.rb | 77 +++++++++++++++++++++++++++++++ vnf-provisioning/main.rb | 3 +- vnf-provisioning/models/vnfr.rb | 1 + vnf-provisioning/routes/vnf.rb | 11 ++++- 6 files changed, 112 insertions(+), 5 deletions(-) create mode 100644 vnf-provisioning/helpers/utils.rb diff --git a/vnf-provisioning/helpers/hot.rb b/vnf-provisioning/helpers/hot.rb index 9519dbe..9944821 100644 --- a/vnf-provisioning/helpers/hot.rb +++ b/vnf-provisioning/helpers/hot.rb @@ -29,16 +29,16 @@ def deleteStack(stack_url, auth_token) return end - def getStackResources(stack_url, auth_token) + def getStackResources(stack_url, token) begin - response = RestClient.get stack_url + '/resources', 'X-Auth-Token' => auth_token + response = RestClient.get stack_url + '/resources', 'X-Auth-Token' => token rescue Errno::ECONNREFUSED error = { 'info' => 'VIM unrechable.' } return rescue => e logger.error e logger.error e.response - error = { 'info' => 'Error creating the network stack.' } + error = { 'info' => 'Error getting stack resources.' } return end resources, errors = parse_json(response) @@ -47,6 +47,24 @@ def getStackResources(stack_url, auth_token) resources['resources'] end + def getStackEvents(stack_url, token) + begin + response = RestClient.get stack_url + '/events', 'X-Auth-Token' => token + rescue Errno::ECONNREFUSED + error = { 'info' => 'VIM unrechable.' } + return + rescue => e + logger.error e + logger.error e.response + error = { 'info' => 'Error getting stack events.' } + return + end + events, errors = JSON.parse(response) + return 400, errors if errors + + events['events'] + end + def delete_stack_with_wait(stack_url, auth_token) status = 'DELETING' count = 0 diff --git a/vnf-provisioning/helpers/init.rb b/vnf-provisioning/helpers/init.rb index 9809da1..17fbc62 100644 --- a/vnf-provisioning/helpers/init.rb +++ b/vnf-provisioning/helpers/init.rb @@ -15,6 +15,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # +require_relative 'utils' require_relative 'vnf' require_relative 'mapi' require_relative 'hot' diff --git a/vnf-provisioning/helpers/utils.rb b/vnf-provisioning/helpers/utils.rb new file mode 100644 index 0000000..771cd10 --- /dev/null +++ b/vnf-provisioning/helpers/utils.rb @@ -0,0 +1,77 @@ +# +# TeNOR - VNF Provisioning +# +# Copyright 2014-2016 i2CAT Foundation, Portugal Telecom Inovação +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @see ProvisioningHelper +module UtilsHelper + # Checks if a JSON message is valid + # + # @param [JSON] message some JSON message + # @return [Hash] the parsed message + def parse_json(message) + # Check JSON message format + begin + parsed_message = JSON.parse(message) # parse json message + rescue JSON::ParserError => e + # If JSON not valid, return with errors + logger.error "JSON parsing: #{e}" + halt 400, e.to_s + "\n" + end + + parsed_message + end + + # Method which lists all available interfaces + # + # @return [Array] an array of hashes containing all interfaces + def interfaces_list + [ + { + uri: '/', + method: 'GET', + purpose: 'REST API Structure and Capability Discovery' + }, + { + uri: '/vnf-provisioning/vnf-instances', + method: 'POST', + purpose: 'Provision a VNF' + }, + { + uri: '/vnf-provisioning/vnf-instances/:id/destroy', + method: 'POST', + purpose: 'Destroy a VNF' + } + ] + end + + def calculate_event_time(resources, events) + resource_stats = [] + resources.each do |resource| + if resource['resource_status'] == "CREATE_COMPLETE" + puts role['logical_resource_id'].to_s + puts resource['logical_resource_id'].to_s + events_resource = events.find_all{ |role| role['logical_resource_id'].to_s == resource['logical_resource_id'].to_s } + event = events_resource.find{ |role| role['resource_status'] == "CREATE_COMPLETE" } + if !event.nil? + creation_time = DateTime.parse(resource['creation_time']).to_time.to_i + final_time = DateTime.parse(event['event_time']).to_time.to_i + resource_stats << { id: event['logical_resource_id'], type: resource['resource_type'], time: (final_time - creation_time ).to_s } + end + end + end + end + +end diff --git a/vnf-provisioning/main.rb b/vnf-provisioning/main.rb index 43c04fd..a32867b 100644 --- a/vnf-provisioning/main.rb +++ b/vnf-provisioning/main.rb @@ -39,7 +39,8 @@ class VnfProvisioning < Sinatra::Application # Load configurations config_file 'config/config.yml' - helpers ProvisioningHelper + helpers UtilsHelper + helpers ProvisioningHelper helpers MapiHelper helpers HotHelper helpers ComputeHelper diff --git a/vnf-provisioning/models/vnfr.rb b/vnf-provisioning/models/vnfr.rb index 6781af8..b21747a 100644 --- a/vnf-provisioning/models/vnfr.rb +++ b/vnf-provisioning/models/vnfr.rb @@ -54,4 +54,5 @@ class Vnfr field :vdu, type: Array field :security_group_id, type: String field :public_network_id, type: String + field :resource_stats, type: Array end diff --git a/vnf-provisioning/routes/vnf.rb b/vnf-provisioning/routes/vnf.rb index e71b773..3e5292b 100644 --- a/vnf-provisioning/routes/vnf.rb +++ b/vnf-provisioning/routes/vnf.rb @@ -96,7 +96,8 @@ class Provisioning < VnfProvisioning lifecycle_info: vnf['vnfd']['vnf_lifecycle_events'].find { |lifecycle| lifecycle['flavor_id_ref'].casecmp(vnf_flavour.downcase).zero? }, lifecycle_events_values: nil, security_group_id: instantiation_info['security_group_id'], - public_network_id: instantiation_info['reserved_resources']['public_network_id'] + public_network_id: instantiation_info['reserved_resources']['public_network_id'], + resource_stats: [] ) rescue Moped::Errors::OperationFailure => e return 400, 'ERROR: Duplicated VNF ID' if e.message.include? 'E11000' @@ -477,6 +478,14 @@ class Provisioning < VnfProvisioning vnfr.vms_id.each { |_key, value| vnfi_id << value } message = { vnfd_id: vnfr.vnfd_reference, vnfi_id: vnfi_id, vnfr_id: vnfr.id, vnf_addresses: vnf_addresses, stack_resources: vnfr } nsmanager_callback(stack_info['ns_manager_callback'], message) + + Thread.new{ + resource_stats = [] + events, errors = getStackEvents(vnfr.stack_url, auth_token) + resource_stats = calculate_event_time(resources, events) + vnfr.update_attributes!(resource_stats: resource_stats) + + } else # If the stack has failed to create if params[:status] == 'create_failed' From e2e30a04aad8ee58c8e082e5673c6ca84e064aa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Tue, 8 Nov 2016 10:02:08 +0100 Subject: [PATCH 31/35] Fix NS Manager get DC list --- ns-manager/routes/ns_provisioning.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ns-manager/routes/ns_provisioning.rb b/ns-manager/routes/ns_provisioning.rb index 5629cd3..45085b8 100644 --- a/ns-manager/routes/ns_provisioning.rb +++ b/ns-manager/routes/ns_provisioning.rb @@ -49,8 +49,7 @@ class NsProvisioner < TnovaManager pop_list = [] mapping_info = {} if instantiation_info['pop_id'].nil? - pop_list, errors = JSON.parse(getDcs()) - halt 400, "Error getting DC list." if errors + pop_list = JSON.parse(getDcs()) if pop_list.empty? halt 400, "No PoPs registereds." end From 041112904b11808448812723f9aea8079c04a058 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Tue, 8 Nov 2016 10:02:34 +0100 Subject: [PATCH 32/35] NS provisioning DELETING status in the correct place --- ns-provisioning/routes/ns.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ns-provisioning/routes/ns.rb b/ns-provisioning/routes/ns.rb index fed37b8..c35f154 100644 --- a/ns-provisioning/routes/ns.rb +++ b/ns-provisioning/routes/ns.rb @@ -131,10 +131,9 @@ class Provisioner < NsProvisioning halt 404 end - @nsInstance.update_attribute('status', 'DELETING') - if params[:status] === 'terminate' logger.info 'Starting thread for removing VNF and NS instances.' + @nsInstance.update_attribute('status', 'DELETING') Thread.abort_on_exception = false Thread.new do # operation = proc { From 86b9ec5f7f15864089abc134cb0912ff4c19c651 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Tue, 8 Nov 2016 10:14:45 +0100 Subject: [PATCH 33/35] VNF Provisioning calculates the creation time of each resource in a stack. Saved in the VNFR. --- vnf-provisioning/helpers/hot.rb | 30 +++++++++++++++--------------- vnf-provisioning/helpers/utils.rb | 25 +++++++++++-------------- vnf-provisioning/routes/vnf.rb | 14 +++++++------- 3 files changed, 33 insertions(+), 36 deletions(-) diff --git a/vnf-provisioning/helpers/hot.rb b/vnf-provisioning/helpers/hot.rb index 9944821..5cf78e5 100644 --- a/vnf-provisioning/helpers/hot.rb +++ b/vnf-provisioning/helpers/hot.rb @@ -20,7 +20,7 @@ module HotHelper def deleteStack(stack_url, auth_token) response = RestClient.delete stack_url, 'X-Auth-Token' => auth_token, :accept => :json rescue Errno::ECONNREFUSED - # halt 500, 'VIM unreachable' + # halt 500, 'VIM unreachable' rescue RestClient::ResourceNotFound logger.error 'Already removed from the VIM.' return 404 @@ -44,25 +44,25 @@ def getStackResources(stack_url, token) resources, errors = parse_json(response) return 400, errors if errors - resources['resources'] + [resources['resources'], nil] end def getStackEvents(stack_url, token) begin - response = RestClient.get stack_url + '/events', 'X-Auth-Token' => token - rescue Errno::ECONNREFUSED - error = { 'info' => 'VIM unrechable.' } - return - rescue => e - logger.error e - logger.error e.response - error = { 'info' => 'Error getting stack events.' } - return - end - events, errors = JSON.parse(response) + response = RestClient.get stack_url + '/events', 'X-Auth-Token' => token + rescue Errno::ECONNREFUSED + error = { 'info' => 'VIM unrechable.' } + return + rescue => e + logger.error e + logger.error e.response + error = { 'info' => 'Error getting stack events.' } + return + end + events, errors = parse_json(response) return 400, errors if errors - events['events'] + [events['events'], nil] end def delete_stack_with_wait(stack_url, auth_token) @@ -71,7 +71,7 @@ def delete_stack_with_wait(stack_url, auth_token) code = deleteStack(stack_url, auth_token) if code == 404 status = 'DELETE_COMPLETE' - return 200 + return 200 # , "Delete completed." end while status != 'DELETE_COMPLETE' && status != 'DELETE_FAILED' sleep(5) diff --git a/vnf-provisioning/helpers/utils.rb b/vnf-provisioning/helpers/utils.rb index 771cd10..ac914f0 100644 --- a/vnf-provisioning/helpers/utils.rb +++ b/vnf-provisioning/helpers/utils.rb @@ -58,20 +58,17 @@ def interfaces_list end def calculate_event_time(resources, events) + events.each { |a| puts a } resource_stats = [] - resources.each do |resource| - if resource['resource_status'] == "CREATE_COMPLETE" - puts role['logical_resource_id'].to_s - puts resource['logical_resource_id'].to_s - events_resource = events.find_all{ |role| role['logical_resource_id'].to_s == resource['logical_resource_id'].to_s } - event = events_resource.find{ |role| role['resource_status'] == "CREATE_COMPLETE" } - if !event.nil? - creation_time = DateTime.parse(resource['creation_time']).to_time.to_i - final_time = DateTime.parse(event['event_time']).to_time.to_i - resource_stats << { id: event['logical_resource_id'], type: resource['resource_type'], time: (final_time - creation_time ).to_s } - end - end - end + resources.each do |resource| + next unless resource['resource_status'] == 'CREATE_COMPLETE' + events_resource = events.find_all { |role| role['logical_resource_id'].to_s == resource['logical_resource_id'].to_s } + event = events_resource.find { |role| role['resource_status'] == 'CREATE_COMPLETE' } + next if event.nil? + creation_time = DateTime.parse(resource['creation_time']).to_time.to_i + final_time = DateTime.parse(event['event_time']).to_time.to_i + resource_stats << { id: event['logical_resource_id'], type: resource['resource_type'], time: (final_time - creation_time).to_s } + end + resource_stats end - end diff --git a/vnf-provisioning/routes/vnf.rb b/vnf-provisioning/routes/vnf.rb index 3e5292b..5c71df7 100644 --- a/vnf-provisioning/routes/vnf.rb +++ b/vnf-provisioning/routes/vnf.rb @@ -256,7 +256,7 @@ class Provisioning < VnfProvisioning logger.info 'Removing the VNFR from the database...' vnfr.destroy - halt 200, response.body + halt 200 # , response.body end # @method post_vnf_provisioning_instances_id_config @@ -329,7 +329,8 @@ class Provisioning < VnfProvisioning vms = [] vms_id = {} # get stack resources - resources = getStackResources(vnfr.stack_url, auth_token) + resources, errors = getStackResources(vnfr.stack_url, auth_token) + logger.error errors if errors resources.each do |resource| # map ports to openstack_port_id unless vnfr.port_instances.detect { |port| resource['resource_name'] == port['id'] }.nil? @@ -403,11 +404,11 @@ class Provisioning < VnfProvisioning vnfr.lifecycle_info['events'].each do |event, event_info| next if event_info.nil? JSON.parse(event_info['template_file']).each do |id, parameter| - #logger.debug parameter + # logger.debug parameter parameter_match = parameter.delete(' ').match(/^get_attr\[(.*)\]$/i).to_a string = parameter_match[1].split(',').map(&:strip) key_string = string.join('#') - #logger.debug 'Key string: ' + key_string.to_s + '. Out_key: ' + output['output_key'].to_s + # logger.debug 'Key string: ' + key_string.to_s + '. Out_key: ' + output['output_key'].to_s if string[1] == 'PublicIp' # DEPRECATED: to be removed when all VNF developers uses the new form vnf_addresses[output['output_key']] = output['output_value'] lifecycle_events_values[event] = {} unless lifecycle_events_values.key?(event) @@ -479,13 +480,12 @@ class Provisioning < VnfProvisioning message = { vnfd_id: vnfr.vnfd_reference, vnfi_id: vnfi_id, vnfr_id: vnfr.id, vnf_addresses: vnf_addresses, stack_resources: vnfr } nsmanager_callback(stack_info['ns_manager_callback'], message) - Thread.new{ + Thread.new do resource_stats = [] events, errors = getStackEvents(vnfr.stack_url, auth_token) resource_stats = calculate_event_time(resources, events) vnfr.update_attributes!(resource_stats: resource_stats) - - } + end else # If the stack has failed to create if params[:status] == 'create_failed' From d7c360f622ffe56dcce7617a2f34d327ad8c852d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Tue, 8 Nov 2016 10:15:28 +0100 Subject: [PATCH 34/35] Progress bar in red when ERROR and DELETING --- ui/app/views/t-nova/nsInstances.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/views/t-nova/nsInstances.html b/ui/app/views/t-nova/nsInstances.html index 45b622c..4516903 100644 --- a/ui/app/views/t-nova/nsInstances.html +++ b/ui/app/views/t-nova/nsInstances.html @@ -49,7 +49,7 @@ {{row.version}} {{row.status}}
-
+
{{row.created_at| date:'yyyy-MM-dd HH:mm:ss'}} From 35f160768ebf00b69a558355d505cd3db3867a68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Batall=C3=A9?= Date: Tue, 8 Nov 2016 11:01:56 +0100 Subject: [PATCH 35/35] v0.9.0. Updated Docker and Vagrant files --- CHANGELOG.md | 9 +++++++++ Dockerfile | 3 ++- Vagrantfile | 5 ++--- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a722ca7..08fd740 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## 0.9.0 +- Refactor. Removed unused files and functions. +- Hide credentials from logs. +- Implemented missing WICM calls. +- UI VNFD JSON editor. +- UI included progress bar in instance status +- Calculation of creation time of each resource in a stack. Saved in the VNFR. +- Updated Dockerfile and Vagrant according last updates. + ## 0.8.0 - Changed authentication method. No external entity is required for authentication. - Authentication between modules enabled when environment is production using JWT. diff --git a/Dockerfile b/Dockerfile index dadcc68..97bd689 100644 --- a/Dockerfile +++ b/Dockerfile @@ -35,7 +35,7 @@ WORKDIR /root RUN apt-get -q -y install curl # Clone the conf files into the docker container -RUN git clone https://github.com/jbatalle/TeNOR /root/TeNOR +RUN git clone https://github.com/T-NOVA/TeNOR /root/TeNOR ENV RAILS_ENV development WORKDIR /root/TeNOR @@ -43,6 +43,7 @@ RUN bundle --version RUN cat Gemfile RUN gem install bundle RUN bundle install +RUN sed -i 's/rake db:seed/bundle exec rake db:seed/g' tenor_install.sh RUN ./tenor_install.sh 1 RUN chown -R mongodb:mongodb /var/lib/mongodb diff --git a/Vagrantfile b/Vagrantfile index 644330d..20d7e9d 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -11,8 +11,7 @@ Vagrant.configure(2) do |config| vb.customize ['modifyvm', :id, '--natdnsproxy1', 'on'] end - # config.vm.network :forwarded_port, guest: 4000, host: 4000 # tenor port - config.vm.network :forwarded_port, guest: 8000, host: 8000 # gatekeeper port + config.vm.network :forwarded_port, guest: 4000, host: 4000 # tenor port config.vm.network :forwarded_port, guest: 9000, host: 9000 # tenor UI port config.vm.network :forwarded_port, guest: 27017, host: 27017 # tenor UI port @@ -36,7 +35,7 @@ Vagrant.configure(2) do |config| rvm group add rvm vagrant rvm fix-permissions cd ~ - git clone https://github.com/TeNOR/TeNOR.git + git clone https://github.com/T-NOVA/TeNOR.git cd TeNOR/ ./dependencies/install_dependencies.sh y y n