From 39f1fb879f263b91d8a68340f99e61cce7cbddf3 Mon Sep 17 00:00:00 2001 From: guange <8863824@gmail.com> Date: Sun, 15 Mar 2015 23:09:44 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AF=B9Gemfile=E4=BD=9C=E4=BA=86=E4=B8=80?= =?UTF-8?q?=E4=BA=9B=E4=BC=98=E5=8C=96=201.=20=20=E6=BA=90=E5=8F=AF?= =?UTF-8?q?=E4=BB=A5=E4=BB=8Etaobao=E6=BA=90=E5=AE=89=E8=A3=85=202.=20?= =?UTF-8?q?=E6=89=80=E6=9C=89=E6=94=BE=E5=9C=A8lib=E4=B8=8B=E7=9A=84gem?= =?UTF-8?q?=E5=88=A0=E9=99=A4=EF=BC=8C=E4=BB=8E=E7=BD=91=E4=B8=8A=E4=B8=8B?= =?UTF-8?q?=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Gemfile | 23 +- lib/better_errors/.travis.yml | 4 - lib/better_errors/.yardopts | 1 - lib/better_errors/CHANGELOG.md | 3 - lib/better_errors/Gemfile | 10 - lib/better_errors/LICENSE.txt | 22 - lib/better_errors/README.md | 103 -- lib/better_errors/Rakefile | 13 - lib/better_errors/better_errors.gemspec | 27 - lib/better_errors/lib/better_errors.rb | 146 --- .../lib/better_errors/code_formatter.rb | 63 - .../lib/better_errors/code_formatter/html.rb | 26 - .../lib/better_errors/code_formatter/text.rb | 14 - .../lib/better_errors/error_page.rb | 110 -- .../lib/better_errors/exception_extension.rb | 17 - .../lib/better_errors/middleware.rb | 141 --- lib/better_errors/lib/better_errors/rails.rb | 28 - .../lib/better_errors/raised_exception.rb | 66 -- lib/better_errors/lib/better_errors/repl.rb | 30 - .../lib/better_errors/repl/basic.rb | 20 - .../lib/better_errors/repl/pry.rb | 78 -- .../lib/better_errors/stack_frame.rb | 111 -- .../lib/better_errors/templates/main.erb | 1031 ----------------- .../lib/better_errors/templates/text.erb | 21 - .../better_errors/templates/variable_info.erb | 70 -- .../lib/better_errors/version.rb | 3 - .../spec/better_errors/code_formatter_spec.rb | 92 -- .../spec/better_errors/error_page_spec.rb | 76 -- .../spec/better_errors/middleware_spec.rb | 146 --- .../better_errors/raised_exception_spec.rb | 52 - .../spec/better_errors/repl/basic_spec.rb | 18 - .../spec/better_errors/repl/pry_spec.rb | 40 - .../better_errors/repl/shared_examples.rb | 18 - .../spec/better_errors/stack_frame_spec.rb | 157 --- .../spec/better_errors/support/my_source.rb | 20 - lib/better_errors/spec/better_errors_spec.rb | 73 -- lib/better_errors/spec/spec_helper.rb | 5 - .../spec/without_binding_of_caller.rb | 9 - lib/rack-mini-profiler/.travis.yml | 9 - lib/rack-mini-profiler/CHANGELOG | 181 --- lib/rack-mini-profiler/Gemfile | 3 - lib/rack-mini-profiler/README.md | 271 ----- lib/rack-mini-profiler/Rakefile | 46 - lib/rack-mini-profiler/autotest/discover.rb | 2 - lib/rack-mini-profiler/lib/html/includes.css | 451 ------- lib/rack-mini-profiler/lib/html/includes.js | 960 --------------- lib/rack-mini-profiler/lib/html/includes.less | 471 -------- lib/rack-mini-profiler/lib/html/includes.tmpl | 222 ---- .../lib/html/jquery.1.7.1.js | 4 - .../lib/html/jquery.tmpl.js | 486 -------- lib/rack-mini-profiler/lib/html/list.css | 9 - lib/rack-mini-profiler/lib/html/list.js | 38 - lib/rack-mini-profiler/lib/html/list.tmpl | 34 - .../lib/html/profile_handler.js | 1 - lib/rack-mini-profiler/lib/html/share.html | 11 - .../lib/mini_profiler/client_settings.rb | 65 -- .../lib/mini_profiler/client_timer_struct.rb | 78 -- .../lib/mini_profiler/config.rb | 65 -- .../lib/mini_profiler/context.rb | 11 - .../lib/mini_profiler/custom_timer_struct.rb | 22 - .../lib/mini_profiler/gc_profiler.rb | 181 --- .../lib/mini_profiler/page_timer_struct.rb | 58 - .../lib/mini_profiler/profiler.rb | 567 --------- .../lib/mini_profiler/profiling_methods.rb | 151 --- .../lib/mini_profiler/request_timer_struct.rb | 115 -- .../lib/mini_profiler/sql_timer_struct.rb | 58 - .../mini_profiler/storage/abstract_store.rb | 32 - .../lib/mini_profiler/storage/file_store.rb | 133 --- .../mini_profiler/storage/memcache_store.rb | 53 - .../lib/mini_profiler/storage/memory_store.rb | 86 -- .../lib/mini_profiler/storage/redis_store.rb | 54 - .../lib/mini_profiler/timer_struct.rb | 33 - .../lib/mini_profiler/version.rb | 5 - .../lib/mini_profiler_rails/railtie.rb | 106 -- .../lib/patches/net_patches.rb | 14 - .../lib/patches/sql_patches.rb | 284 ----- .../lib/rack-mini-profiler.rb | 7 - .../rack-mini-profiler.gemspec | 35 - .../spec/components/client_settings_spec.rb | 45 - .../components/client_timer_struct_spec.rb | 162 --- .../spec/components/config_spec.rb | 14 - .../spec/components/file_store_spec.rb | 46 - .../spec/components/gc_profiler_spec.rb | 69 -- .../spec/components/memcache_store_spec.rb | 59 - .../spec/components/memory_store_spec.rb | 40 - .../spec/components/page_timer_struct_spec.rb | 33 - .../spec/components/profiler_spec.rb | 131 --- .../spec/components/redis_store_spec.rb | 79 -- .../components/request_timer_struct_spec.rb | 148 --- .../spec/components/sql_timer_struct_spec.rb | 80 -- .../spec/components/timer_struct_spec.rb | 54 - .../spec/fixtures/simple_client_request.yml | 17 - .../spec/fixtures/weird_client_request.yml | 14 - .../spec/integration/mini_profiler_spec.rb | 261 ----- lib/rack-mini-profiler/spec/spec_helper.rb | 31 - .../spec/support/expand_each_to_matcher.rb | 8 - lib/rack-mini-profiler/test_old/config.ru | 40 - lib/seems_rateable/Gemfile | 23 - lib/seems_rateable/MIT-LICENSE | 20 - lib/seems_rateable/README.md | 111 -- lib/seems_rateable/Rakefile | 17 - .../images/seems_rateable/bg_jRatingInfos.png | Bin 572 -> 0 bytes .../assets/images/seems_rateable/small.png | Bin 427 -> 0 bytes .../assets/images/seems_rateable/stars.png | Bin 1018 -> 0 bytes .../javascripts/seems_rateable/application.js | 15 - .../seems_rateable/application.css | 62 - .../seems_rateable/application_controller.rb | 7 - .../seems_rateable/ratings_controller.rb | 16 - .../models/seems_rateable/cached_rating.rb | 5 - .../app/models/seems_rateable/rate.rb | 6 - lib/seems_rateable/bin/rails | 8 - lib/seems_rateable/config/routes.rb | 3 - .../install/install_generator.rb | 42 - .../templates/cached_ratings_migration.rb | 17 - .../install/templates/initializer.rb | 4 - .../install/templates/jRating.js.erb | 225 ---- .../install/templates/rateable.js.erb | 25 - .../install/templates/rates_migration.rb | 18 - lib/seems_rateable/lib/seems_rateable.rb | 16 - .../lib/seems_rateable/engine.rb | 16 - .../lib/seems_rateable/errors.rb | 21 - .../lib/seems_rateable/helpers.rb | 28 - .../lib/seems_rateable/model.rb | 91 -- .../lib/seems_rateable/routes.rb | 7 - .../lib/seems_rateable/version.rb | 3 - lib/seems_rateable/seems_rateable.gemspec | 25 - plugins/redmine_ckeditor/Gemfile | 2 +- 127 files changed, 15 insertions(+), 10448 deletions(-) delete mode 100644 lib/better_errors/.travis.yml delete mode 100644 lib/better_errors/.yardopts delete mode 100644 lib/better_errors/CHANGELOG.md delete mode 100644 lib/better_errors/Gemfile delete mode 100644 lib/better_errors/LICENSE.txt delete mode 100644 lib/better_errors/README.md delete mode 100644 lib/better_errors/Rakefile delete mode 100644 lib/better_errors/better_errors.gemspec delete mode 100644 lib/better_errors/lib/better_errors.rb delete mode 100644 lib/better_errors/lib/better_errors/code_formatter.rb delete mode 100644 lib/better_errors/lib/better_errors/code_formatter/html.rb delete mode 100644 lib/better_errors/lib/better_errors/code_formatter/text.rb delete mode 100644 lib/better_errors/lib/better_errors/error_page.rb delete mode 100644 lib/better_errors/lib/better_errors/exception_extension.rb delete mode 100644 lib/better_errors/lib/better_errors/middleware.rb delete mode 100644 lib/better_errors/lib/better_errors/rails.rb delete mode 100644 lib/better_errors/lib/better_errors/raised_exception.rb delete mode 100644 lib/better_errors/lib/better_errors/repl.rb delete mode 100644 lib/better_errors/lib/better_errors/repl/basic.rb delete mode 100644 lib/better_errors/lib/better_errors/repl/pry.rb delete mode 100644 lib/better_errors/lib/better_errors/stack_frame.rb delete mode 100644 lib/better_errors/lib/better_errors/templates/main.erb delete mode 100644 lib/better_errors/lib/better_errors/templates/text.erb delete mode 100644 lib/better_errors/lib/better_errors/templates/variable_info.erb delete mode 100644 lib/better_errors/lib/better_errors/version.rb delete mode 100644 lib/better_errors/spec/better_errors/code_formatter_spec.rb delete mode 100644 lib/better_errors/spec/better_errors/error_page_spec.rb delete mode 100644 lib/better_errors/spec/better_errors/middleware_spec.rb delete mode 100644 lib/better_errors/spec/better_errors/raised_exception_spec.rb delete mode 100644 lib/better_errors/spec/better_errors/repl/basic_spec.rb delete mode 100644 lib/better_errors/spec/better_errors/repl/pry_spec.rb delete mode 100644 lib/better_errors/spec/better_errors/repl/shared_examples.rb delete mode 100644 lib/better_errors/spec/better_errors/stack_frame_spec.rb delete mode 100644 lib/better_errors/spec/better_errors/support/my_source.rb delete mode 100644 lib/better_errors/spec/better_errors_spec.rb delete mode 100644 lib/better_errors/spec/spec_helper.rb delete mode 100644 lib/better_errors/spec/without_binding_of_caller.rb delete mode 100644 lib/rack-mini-profiler/.travis.yml delete mode 100644 lib/rack-mini-profiler/CHANGELOG delete mode 100644 lib/rack-mini-profiler/Gemfile delete mode 100644 lib/rack-mini-profiler/README.md delete mode 100644 lib/rack-mini-profiler/Rakefile delete mode 100644 lib/rack-mini-profiler/autotest/discover.rb delete mode 100644 lib/rack-mini-profiler/lib/html/includes.css delete mode 100644 lib/rack-mini-profiler/lib/html/includes.js delete mode 100644 lib/rack-mini-profiler/lib/html/includes.less delete mode 100644 lib/rack-mini-profiler/lib/html/includes.tmpl delete mode 100644 lib/rack-mini-profiler/lib/html/jquery.1.7.1.js delete mode 100644 lib/rack-mini-profiler/lib/html/jquery.tmpl.js delete mode 100644 lib/rack-mini-profiler/lib/html/list.css delete mode 100644 lib/rack-mini-profiler/lib/html/list.js delete mode 100644 lib/rack-mini-profiler/lib/html/list.tmpl delete mode 100644 lib/rack-mini-profiler/lib/html/profile_handler.js delete mode 100644 lib/rack-mini-profiler/lib/html/share.html delete mode 100644 lib/rack-mini-profiler/lib/mini_profiler/client_settings.rb delete mode 100644 lib/rack-mini-profiler/lib/mini_profiler/client_timer_struct.rb delete mode 100644 lib/rack-mini-profiler/lib/mini_profiler/config.rb delete mode 100644 lib/rack-mini-profiler/lib/mini_profiler/context.rb delete mode 100644 lib/rack-mini-profiler/lib/mini_profiler/custom_timer_struct.rb delete mode 100644 lib/rack-mini-profiler/lib/mini_profiler/gc_profiler.rb delete mode 100644 lib/rack-mini-profiler/lib/mini_profiler/page_timer_struct.rb delete mode 100644 lib/rack-mini-profiler/lib/mini_profiler/profiler.rb delete mode 100644 lib/rack-mini-profiler/lib/mini_profiler/profiling_methods.rb delete mode 100644 lib/rack-mini-profiler/lib/mini_profiler/request_timer_struct.rb delete mode 100644 lib/rack-mini-profiler/lib/mini_profiler/sql_timer_struct.rb delete mode 100644 lib/rack-mini-profiler/lib/mini_profiler/storage/abstract_store.rb delete mode 100644 lib/rack-mini-profiler/lib/mini_profiler/storage/file_store.rb delete mode 100644 lib/rack-mini-profiler/lib/mini_profiler/storage/memcache_store.rb delete mode 100644 lib/rack-mini-profiler/lib/mini_profiler/storage/memory_store.rb delete mode 100644 lib/rack-mini-profiler/lib/mini_profiler/storage/redis_store.rb delete mode 100644 lib/rack-mini-profiler/lib/mini_profiler/timer_struct.rb delete mode 100644 lib/rack-mini-profiler/lib/mini_profiler/version.rb delete mode 100644 lib/rack-mini-profiler/lib/mini_profiler_rails/railtie.rb delete mode 100644 lib/rack-mini-profiler/lib/patches/net_patches.rb delete mode 100644 lib/rack-mini-profiler/lib/patches/sql_patches.rb delete mode 100644 lib/rack-mini-profiler/lib/rack-mini-profiler.rb delete mode 100644 lib/rack-mini-profiler/rack-mini-profiler.gemspec delete mode 100644 lib/rack-mini-profiler/spec/components/client_settings_spec.rb delete mode 100644 lib/rack-mini-profiler/spec/components/client_timer_struct_spec.rb delete mode 100644 lib/rack-mini-profiler/spec/components/config_spec.rb delete mode 100644 lib/rack-mini-profiler/spec/components/file_store_spec.rb delete mode 100644 lib/rack-mini-profiler/spec/components/gc_profiler_spec.rb delete mode 100644 lib/rack-mini-profiler/spec/components/memcache_store_spec.rb delete mode 100644 lib/rack-mini-profiler/spec/components/memory_store_spec.rb delete mode 100644 lib/rack-mini-profiler/spec/components/page_timer_struct_spec.rb delete mode 100644 lib/rack-mini-profiler/spec/components/profiler_spec.rb delete mode 100644 lib/rack-mini-profiler/spec/components/redis_store_spec.rb delete mode 100644 lib/rack-mini-profiler/spec/components/request_timer_struct_spec.rb delete mode 100644 lib/rack-mini-profiler/spec/components/sql_timer_struct_spec.rb delete mode 100644 lib/rack-mini-profiler/spec/components/timer_struct_spec.rb delete mode 100644 lib/rack-mini-profiler/spec/fixtures/simple_client_request.yml delete mode 100644 lib/rack-mini-profiler/spec/fixtures/weird_client_request.yml delete mode 100644 lib/rack-mini-profiler/spec/integration/mini_profiler_spec.rb delete mode 100644 lib/rack-mini-profiler/spec/spec_helper.rb delete mode 100644 lib/rack-mini-profiler/spec/support/expand_each_to_matcher.rb delete mode 100644 lib/rack-mini-profiler/test_old/config.ru delete mode 100644 lib/seems_rateable/Gemfile delete mode 100644 lib/seems_rateable/MIT-LICENSE delete mode 100644 lib/seems_rateable/README.md delete mode 100644 lib/seems_rateable/Rakefile delete mode 100644 lib/seems_rateable/app/assets/images/seems_rateable/bg_jRatingInfos.png delete mode 100644 lib/seems_rateable/app/assets/images/seems_rateable/small.png delete mode 100644 lib/seems_rateable/app/assets/images/seems_rateable/stars.png delete mode 100644 lib/seems_rateable/app/assets/javascripts/seems_rateable/application.js delete mode 100644 lib/seems_rateable/app/assets/stylesheets/seems_rateable/application.css delete mode 100644 lib/seems_rateable/app/controllers/seems_rateable/application_controller.rb delete mode 100644 lib/seems_rateable/app/controllers/seems_rateable/ratings_controller.rb delete mode 100644 lib/seems_rateable/app/models/seems_rateable/cached_rating.rb delete mode 100644 lib/seems_rateable/app/models/seems_rateable/rate.rb delete mode 100644 lib/seems_rateable/bin/rails delete mode 100644 lib/seems_rateable/config/routes.rb delete mode 100644 lib/seems_rateable/lib/generators/seems_rateable/install/install_generator.rb delete mode 100644 lib/seems_rateable/lib/generators/seems_rateable/install/templates/cached_ratings_migration.rb delete mode 100644 lib/seems_rateable/lib/generators/seems_rateable/install/templates/initializer.rb delete mode 100644 lib/seems_rateable/lib/generators/seems_rateable/install/templates/jRating.js.erb delete mode 100644 lib/seems_rateable/lib/generators/seems_rateable/install/templates/rateable.js.erb delete mode 100644 lib/seems_rateable/lib/generators/seems_rateable/install/templates/rates_migration.rb delete mode 100644 lib/seems_rateable/lib/seems_rateable.rb delete mode 100644 lib/seems_rateable/lib/seems_rateable/engine.rb delete mode 100644 lib/seems_rateable/lib/seems_rateable/errors.rb delete mode 100644 lib/seems_rateable/lib/seems_rateable/helpers.rb delete mode 100644 lib/seems_rateable/lib/seems_rateable/model.rb delete mode 100644 lib/seems_rateable/lib/seems_rateable/routes.rb delete mode 100644 lib/seems_rateable/lib/seems_rateable/version.rb delete mode 100644 lib/seems_rateable/seems_rateable.gemspec diff --git a/Gemfile b/Gemfile index 03b349c18..0fc84e5f9 100644 --- a/Gemfile +++ b/Gemfile @@ -1,5 +1,7 @@ -source 'http://rubygems.org' +source 'http://ruby.taobao.org' #source 'http://ruby.sdutlinux.org/' +# +puts unless RUBY_PLATFORM =~ /w32/ # unix-like only @@ -10,11 +12,11 @@ end gem 'grape', '~> 0.9.0' gem 'grape-entity' -gem 'seems_rateable', path: 'lib/seems_rateable' +gem 'seems_rateable', '~> 1.0.13' gem "rails", "3.2.13" gem "jquery-rails", "~> 2.0.2" gem "i18n", "~> 0.6.0" -gem "coderay", "~> 1.0.6" +gem 'coderay', '~> 1.1.0' gem "fastercsv", "~> 1.5.0", :platforms => [:mri_18, :mingw_18, :jruby] gem "builder", "3.0.0" gem 'acts-as-taggable-on', '2.4.1' @@ -27,12 +29,15 @@ group :development do gem 'grape-swagger' #gem 'grape-swagger-ui', git: 'https://github.com/guange2015/grape-swagger-ui.git' #gem 'puma' - #gem 'pry-rails' - #gem 'pry-byebug' - #gem 'pry-stack_explorer' - #gem 'pry-debugger' - gem 'better_errors', path: 'lib/better_errors' - gem 'rack-mini-profiler', path: 'lib/rack-mini-profiler' + gem 'pry-rails' + if RUBY_VERSION >= '2.0.0' + gem 'pry-byebug' + else + gem 'pry-debugger' + end + gem 'pry-stack_explorer' + gem 'better_errors', '~> 1.1.0' + gem 'rack-mini-profiler', '~> 0.9.3' end group :test do diff --git a/lib/better_errors/.travis.yml b/lib/better_errors/.travis.yml deleted file mode 100644 index ce51187cf..000000000 --- a/lib/better_errors/.travis.yml +++ /dev/null @@ -1,4 +0,0 @@ -language: ruby -rvm: - - 2.1.0 - - 2.0.0 diff --git a/lib/better_errors/.yardopts b/lib/better_errors/.yardopts deleted file mode 100644 index 73034ccf8..000000000 --- a/lib/better_errors/.yardopts +++ /dev/null @@ -1 +0,0 @@ ---markup markdown --no-private diff --git a/lib/better_errors/CHANGELOG.md b/lib/better_errors/CHANGELOG.md deleted file mode 100644 index 00fc2466b..000000000 --- a/lib/better_errors/CHANGELOG.md +++ /dev/null @@ -1,3 +0,0 @@ -# Changelog - -See https://github.com/charliesome/better_errors/releases diff --git a/lib/better_errors/Gemfile b/lib/better_errors/Gemfile deleted file mode 100644 index 287f7749b..000000000 --- a/lib/better_errors/Gemfile +++ /dev/null @@ -1,10 +0,0 @@ -source 'https://rubygems.org' - -gemspec - -gem "rake" -gem "rspec", "2.14.1" -gem "binding_of_caller", platforms: :ruby -gem "pry", "0.9.12" -gem "yard" -gem "kramdown" diff --git a/lib/better_errors/LICENSE.txt b/lib/better_errors/LICENSE.txt deleted file mode 100644 index 755ce77a8..000000000 --- a/lib/better_errors/LICENSE.txt +++ /dev/null @@ -1,22 +0,0 @@ -Copyright (c) 2014 Charlie Somerville - -MIT License - -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/lib/better_errors/README.md b/lib/better_errors/README.md deleted file mode 100644 index 91488695a..000000000 --- a/lib/better_errors/README.md +++ /dev/null @@ -1,103 +0,0 @@ -# Better Errors [![Gem Version](http://img.shields.io/gem/v/better_errors.svg)](https://rubygems.org/gems/better_errors) [![Build Status](https://travis-ci.org/charliesome/better_errors.svg)](https://travis-ci.org/charliesome/better_errors) [![Code Climate](http://img.shields.io/codeclimate/github/charliesome/better_errors.svg)](https://codeclimate.com/github/charliesome/better_errors) - -Better Errors replaces the standard Rails error page with a much better and more useful error page. It is also usable outside of Rails in any Rack app as Rack middleware. - -![image](http://i.imgur.com/6zBGAAb.png) - -## Features - -* Full stack trace -* Source code inspection for all stack frames (with highlighting) -* Local and instance variable inspection -* Live REPL on every stack frame - -## Installation - -Add this to your Gemfile: - -```ruby -group :development do - gem "better_errors" -end -``` - -If you would like to use Better Errors' **advanced features** (REPL, local/instance variable inspection, pretty stack frame names), you need to add the [`binding_of_caller`](https://github.com/banister/binding_of_caller) gem by [@banisterfiend](http://twitter.com/banisterfiend) to your Gemfile: - -```ruby -gem "binding_of_caller" -``` - -This is an optional dependency however, and Better Errors will work without it. - -_Note: If you discover that Better Errors isn't working - particularly after upgrading from version 0.5.0 or less - be sure to set `config.consider_all_requests_local = true` in `config/environments/development.rb`._ - -## Security - -**NOTE:** It is *critical* you put better\_errors in the **development** section. **Do NOT run better_errors in production, or on Internet facing hosts.** - -You will notice that the only machine that gets the Better Errors page is localhost, which means you get the default error page if you are developing on a remote host (or a virtually remote host, such as a Vagrant box). Obviously, the REPL is not something you want to expose to the public, but there may also be other pieces of sensitive information available in the backtrace. - -To poke selective holes in this security mechanism, you can add a line like this to your startup (for example, on Rails it would be `config/environments/development.rb`) - -```ruby -BetterErrors::Middleware.allow_ip! ENV['TRUSTED_IP'] if ENV['TRUSTED_IP'] -``` - -Then run Rails like this: - -```shell -TRUSTED_IP=66.68.96.220 rails s -``` - -Note that the `allow_ip!` is actually backed by a `Set`, so you can add more than one IP address or subnet. - -**Tip:** You can find your apparent IP by hitting the old error page's "Show env dump" and looking at "REMOTE_ADDR". - -**VirtualBox:** If you are using VirtualBox and are accessing the guest from your host's browser, you will need to use `allow_ip!` to see the error page. - -## Usage - -If you're using Rails, there's nothing else you need to do. - -If you're not using Rails, you need to insert `BetterErrors::Middleware` into your middleware stack, and optionally set `BetterErrors.application_root` if you'd like Better Errors to abbreviate filenames within your application. - -Here's an example using Sinatra: - -```ruby -require "sinatra" -require "better_errors" - -configure :development do - use BetterErrors::Middleware - BetterErrors.application_root = __dir__ -end - -get "/" do - raise "oops" -end -``` - -### Unicorn, Puma, and other multi-worker servers - -Better Errors works by leaving a lot of context in server process memory. If -you're using a web server that runs multiple "workers" it's likely that a second -request (as happens when you click on a stack frame) will hit a different -worker. That worker won't have the necessary context in memory, and you'll see -a `Session Expired` message. - -If this is the case for you, consider turning the number of workers to one (1) -in `development`. Another option would be to use Webrick, Mongrel, Thin, -or another single-process server as your `rails server`, when you are trying -to troubleshoot an issue in development. - -## Get in touch! - -If you're using better_errors, I'd love to hear from you. Drop me a line and tell me what you think! - -## Contributing - -1. Fork it -2. Create your feature branch (`git checkout -b my-new-feature`) -3. Commit your changes (`git commit -am 'Add some feature'`) -4. Push to the branch (`git push origin my-new-feature`) -5. Create new Pull Request diff --git a/lib/better_errors/Rakefile b/lib/better_errors/Rakefile deleted file mode 100644 index b6329726d..000000000 --- a/lib/better_errors/Rakefile +++ /dev/null @@ -1,13 +0,0 @@ -require "bundler/gem_tasks" -require "rspec/core/rake_task" - -namespace :test do - RSpec::Core::RakeTask.new(:with_binding_of_caller) - - without_task = RSpec::Core::RakeTask.new(:without_binding_of_caller) - without_task.ruby_opts = "-I spec -r without_binding_of_caller" - - task :all => [:with_binding_of_caller, :without_binding_of_caller] -end - -task :default => "test:all" diff --git a/lib/better_errors/better_errors.gemspec b/lib/better_errors/better_errors.gemspec deleted file mode 100644 index 315c110c5..000000000 --- a/lib/better_errors/better_errors.gemspec +++ /dev/null @@ -1,27 +0,0 @@ -lib = File.expand_path('../lib', __FILE__) -$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) -require 'better_errors/version' - -Gem::Specification.new do |s| - s.name = "better_errors" - s.version = BetterErrors::VERSION - s.authors = ["Charlie Somerville"] - s.email = ["charlie@charliesomerville.com"] - s.description = %q{Provides a better error page for Rails and other Rack apps. Includes source code inspection, a live REPL and local/instance variable inspection for all stack frames.} - s.summary = %q{Better error page for Rails and other Rack apps} - s.homepage = "https://github.com/charliesome/better_errors" - s.license = "MIT" - - s.files = `git ls-files`.split($/) - s.test_files = s.files.grep(%r{^(test|spec|features)/}) - s.require_paths = ["lib"] - - s.required_ruby_version = ">= 2.0.0" - - s.add_dependency "erubis", ">= 2.6.6" - s.add_dependency "coderay", ">= 1.0.0" - - # optional dependencies: - # s.add_dependency "binding_of_caller" - # s.add_dependency "pry" -end diff --git a/lib/better_errors/lib/better_errors.rb b/lib/better_errors/lib/better_errors.rb deleted file mode 100644 index 394060ecf..000000000 --- a/lib/better_errors/lib/better_errors.rb +++ /dev/null @@ -1,146 +0,0 @@ -require "pp" -require "erubis" -require "coderay" -require "uri" - -require "better_errors/code_formatter" -require "better_errors/error_page" -require "better_errors/middleware" -require "better_errors/raised_exception" -require "better_errors/repl" -require "better_errors/stack_frame" -require "better_errors/version" - -module BetterErrors - POSSIBLE_EDITOR_PRESETS = [ - { symbols: [:emacs, :emacsclient], sniff: /emacs/i, url: "emacs://open?url=file://%{file}&line=%{line}" }, - { symbols: [:macvim, :mvim], sniff: /vim/i, url: proc { |file, line| "mvim://open?url=file://#{file}&line=#{line}" } }, - { symbols: [:sublime, :subl, :st], sniff: /subl/i, url: "subl://open?url=file://%{file}&line=%{line}" }, - { symbols: [:textmate, :txmt, :tm], sniff: /mate/i, url: "txmt://open?url=file://%{file}&line=%{line}" }, - ] - - class << self - # The path to the root of the application. Better Errors uses this property - # to determine if a file in a backtrace should be considered an application - # frame. If you are using Better Errors with Rails, you do not need to set - # this attribute manually. - # - # @return [String] - attr_accessor :application_root - - # The logger to use when logging exception details and backtraces. If you - # are using Better Errors with Rails, you do not need to set this attribute - # manually. If this attribute is `nil`, nothing will be logged. - # - # @return [Logger, nil] - attr_accessor :logger - - # @private - attr_accessor :binding_of_caller_available - - # @private - alias_method :binding_of_caller_available?, :binding_of_caller_available - - # The ignored instance variables. - # @return [Array] - attr_accessor :ignored_instance_variables - end - @ignored_instance_variables = [] - - # Returns a proc, which when called with a filename and line number argument, - # returns a URL to open the filename and line in the selected editor. - # - # Generates TextMate URLs by default. - # - # BetterErrors.editor["/some/file", 123] - # # => txmt://open?url=file:///some/file&line=123 - # - # @return [Proc] - def self.editor - @editor - end - - # Configures how Better Errors generates open-in-editor URLs. - # - # @overload BetterErrors.editor=(sym) - # Uses one of the preset editor configurations. Valid symbols are: - # - # * `:textmate`, `:txmt`, `:tm` - # * `:sublime`, `:subl`, `:st` - # * `:macvim` - # - # @param [Symbol] sym - # - # @overload BetterErrors.editor=(str) - # Uses `str` as the format string for generating open-in-editor URLs. - # - # Use `%{file}` and `%{line}` as placeholders for the actual values. - # - # @example - # BetterErrors.editor = "my-editor://open?url=%{file}&line=%{line}" - # - # @param [String] str - # - # @overload BetterErrors.editor=(proc) - # Uses `proc` to generate open-in-editor URLs. The proc will be called - # with `file` and `line` parameters when a URL needs to be generated. - # - # Your proc should take care to escape `file` appropriately with - # `URI.encode_www_form_component` (please note that `URI.escape` is **not** - # a suitable substitute.) - # - # @example - # BetterErrors.editor = proc { |file, line| - # "my-editor://open?url=#{URI.encode_www_form_component file}&line=#{line}" - # } - # - # @param [Proc] proc - # - def self.editor=(editor) - POSSIBLE_EDITOR_PRESETS.each do |config| - if config[:symbols].include?(editor) - return self.editor = config[:url] - end - end - - if editor.is_a? String - self.editor = proc { |file, line| editor % { file: URI.encode_www_form_component(file), line: line } } - else - if editor.respond_to? :call - @editor = editor - else - raise TypeError, "Expected editor to be a valid editor key, a format string or a callable." - end - end - end - - # Enables experimental Pry support in the inline REPL - # - # If you encounter problems while using Pry, *please* file a bug report at - # https://github.com/charliesome/better_errors/issues - def self.use_pry! - REPL::PROVIDERS.unshift const: :Pry, impl: "better_errors/repl/pry" - end - - # Automatically sniffs a default editor preset based on the EDITOR - # environment variable. - # - # @return [Symbol] - def self.default_editor - POSSIBLE_EDITOR_PRESETS.detect(-> { {} }) { |config| - ENV["EDITOR"] =~ config[:sniff] - }[:url] || :textmate - end - - BetterErrors.editor = default_editor -end - -begin - require "binding_of_caller" - require "better_errors/exception_extension" - BetterErrors.binding_of_caller_available = true -rescue LoadError => e - BetterErrors.binding_of_caller_available = false -end - -require "better_errors/rails" if defined? Rails::Railtie diff --git a/lib/better_errors/lib/better_errors/code_formatter.rb b/lib/better_errors/lib/better_errors/code_formatter.rb deleted file mode 100644 index 77827241e..000000000 --- a/lib/better_errors/lib/better_errors/code_formatter.rb +++ /dev/null @@ -1,63 +0,0 @@ -module BetterErrors - # @private - class CodeFormatter - require "better_errors/code_formatter/html" - require "better_errors/code_formatter/text" - - FILE_TYPES = { - ".rb" => :ruby, - "" => :ruby, - ".html" => :html, - ".erb" => :erb, - ".haml" => :haml - } - - attr_reader :filename, :line, :context - - def initialize(filename, line, context = 5) - @filename = filename - @line = line - @context = context - end - - def output - formatted_code - rescue Errno::ENOENT, Errno::EINVAL - source_unavailable - end - - def formatted_code - formatted_lines.join - end - - def coderay_scanner - ext = File.extname(filename) - FILE_TYPES[ext] || :text - end - - def each_line_of(lines, &blk) - line_range.zip(lines).map { |current_line, str| - yield (current_line == line), current_line, str - } - end - - def highlighted_lines - CodeRay.scan(context_lines.join, coderay_scanner).div(wrap: nil).lines - end - - def context_lines - range = line_range - source_lines[(range.begin - 1)..(range.end - 1)] or raise Errno::EINVAL - end - - def source_lines - @source_lines ||= File.readlines(filename) - end - - def line_range - min = [line - context, 1].max - max = [line + context, source_lines.count].min - min..max - end - end -end diff --git a/lib/better_errors/lib/better_errors/code_formatter/html.rb b/lib/better_errors/lib/better_errors/code_formatter/html.rb deleted file mode 100644 index b3ab05430..000000000 --- a/lib/better_errors/lib/better_errors/code_formatter/html.rb +++ /dev/null @@ -1,26 +0,0 @@ -module BetterErrors - # @private - class CodeFormatter::HTML < CodeFormatter - def source_unavailable - "

Source is not available

" - end - - def formatted_lines - each_line_of(highlighted_lines) { |highlight, current_line, str| - class_name = highlight ? "highlight" : "" - sprintf '
%s
', class_name, str - } - end - - def formatted_nums - each_line_of(highlighted_lines) { |highlight, current_line, str| - class_name = highlight ? "highlight" : "" - sprintf '%5d', class_name, current_line - } - end - - def formatted_code - %{
#{formatted_nums.join}
#{super}
} - end - end -end diff --git a/lib/better_errors/lib/better_errors/code_formatter/text.rb b/lib/better_errors/lib/better_errors/code_formatter/text.rb deleted file mode 100644 index cd63806d8..000000000 --- a/lib/better_errors/lib/better_errors/code_formatter/text.rb +++ /dev/null @@ -1,14 +0,0 @@ -module BetterErrors - # @private - class CodeFormatter::Text < CodeFormatter - def source_unavailable - "# Source is not available" - end - - def formatted_lines - each_line_of(context_lines) { |highlight, current_line, str| - sprintf '%s %3d %s', (highlight ? '>' : ' '), current_line, str - } - end - end -end diff --git a/lib/better_errors/lib/better_errors/error_page.rb b/lib/better_errors/lib/better_errors/error_page.rb deleted file mode 100644 index 849020f19..000000000 --- a/lib/better_errors/lib/better_errors/error_page.rb +++ /dev/null @@ -1,110 +0,0 @@ -require "cgi" -require "json" -require "securerandom" - -module BetterErrors - # @private - class ErrorPage - def self.template_path(template_name) - File.expand_path("../templates/#{template_name}.erb", __FILE__) - end - - def self.template(template_name) - Erubis::EscapedEruby.new(File.read(template_path(template_name))) - end - - attr_reader :exception, :env, :repls - - def initialize(exception, env) - @exception = RaisedException.new(exception) - @env = env - @start_time = Time.now.to_f - @repls = [] - end - - def id - @id ||= SecureRandom.hex(8) - end - - def render(template_name = "main") - self.class.template(template_name).result binding - end - - def do_variables(opts) - index = opts["index"].to_i - @frame = backtrace_frames[index] - @var_start_time = Time.now.to_f - { html: render("variable_info") } - end - - def do_eval(opts) - index = opts["index"].to_i - code = opts["source"] - - unless binding = backtrace_frames[index].frame_binding - return { error: "REPL unavailable in this stack frame" } - end - - result, prompt, prefilled_input = - (@repls[index] ||= REPL.provider.new(binding)).send_input(code) - - { result: result, - prompt: prompt, - prefilled_input: prefilled_input, - highlighted_input: CodeRay.scan(code, :ruby).div(wrap: nil) } - end - - def backtrace_frames - exception.backtrace - end - - def application_frames - backtrace_frames.select(&:application?) - end - - def first_frame - application_frames.first || backtrace_frames.first - end - - private - def editor_url(frame) - BetterErrors.editor[frame.filename, frame.line] - end - - def rack_session - env['rack.session'] - end - - def rails_params - env['action_dispatch.request.parameters'] - end - - def uri_prefix - env["SCRIPT_NAME"] || "" - end - - def request_path - env["PATH_INFO"] - end - - def html_formatted_code_block(frame) - CodeFormatter::HTML.new(frame.filename, frame.line).output - end - - def text_formatted_code_block(frame) - CodeFormatter::Text.new(frame.filename, frame.line).output - end - - def text_heading(char, str) - str + "\n" + char*str.size - end - - def inspect_value(obj) - CGI.escapeHTML(obj.inspect) - rescue NoMethodError - "(object doesn't support inspect)" - rescue Exception => e - "(exception was raised in inspect)" - end - end -end diff --git a/lib/better_errors/lib/better_errors/exception_extension.rb b/lib/better_errors/lib/better_errors/exception_extension.rb deleted file mode 100644 index e97b052f3..000000000 --- a/lib/better_errors/lib/better_errors/exception_extension.rb +++ /dev/null @@ -1,17 +0,0 @@ -module BetterErrors - module ExceptionExtension - prepend_features Exception - - def set_backtrace(*) - if caller_locations.none? { |loc| loc.path == __FILE__ } - @__better_errors_bindings_stack = binding.callers.drop(1) - end - - super - end - - def __better_errors_bindings_stack - @__better_errors_bindings_stack || [] - end - end -end diff --git a/lib/better_errors/lib/better_errors/middleware.rb b/lib/better_errors/lib/better_errors/middleware.rb deleted file mode 100644 index ce9aaad4b..000000000 --- a/lib/better_errors/lib/better_errors/middleware.rb +++ /dev/null @@ -1,141 +0,0 @@ -require "json" -require "ipaddr" -require "set" - -module BetterErrors - # Better Errors' error handling middleware. Including this in your middleware - # stack will show a Better Errors error page for exceptions raised below this - # middleware. - # - # If you are using Ruby on Rails, you do not need to manually insert this - # middleware into your middleware stack. - # - # @example Sinatra - # require "better_errors" - # - # if development? - # use BetterErrors::Middleware - # end - # - # @example Rack - # require "better_errors" - # if ENV["RACK_ENV"] == "development" - # use BetterErrors::Middleware - # end - # - class Middleware - # The set of IP addresses that are allowed to access Better Errors. - # - # Set to `{ "127.0.0.1/8", "::1/128" }` by default. - ALLOWED_IPS = Set.new - - # Adds an address to the set of IP addresses allowed to access Better - # Errors. - def self.allow_ip!(addr) - ALLOWED_IPS << IPAddr.new(addr) - end - - allow_ip! "127.0.0.0/8" - allow_ip! "::1/128" rescue nil # windows ruby doesn't have ipv6 support - - # A new instance of BetterErrors::Middleware - # - # @param app The Rack app/middleware to wrap with Better Errors - # @param handler The error handler to use. - def initialize(app, handler = ErrorPage) - @app = app - @handler = handler - end - - # Calls the Better Errors middleware - # - # @param [Hash] env - # @return [Array] - def call(env) - if allow_ip? env - better_errors_call env - else - @app.call env - end - end - - private - - def allow_ip?(env) - # REMOTE_ADDR is not in the rack spec, so some application servers do - # not provide it. - return true unless env["REMOTE_ADDR"] and !env["REMOTE_ADDR"].strip.empty? - ip = IPAddr.new env["REMOTE_ADDR"].split("%").first - ALLOWED_IPS.any? { |subnet| subnet.include? ip } - end - - def better_errors_call(env) - case env["PATH_INFO"] - when %r{/__better_errors/(?.+?)/(?\w+)\z} - internal_call env, $~ - when %r{/__better_errors/?\z} - show_error_page env - else - protected_app_call env - end - end - - def protected_app_call(env) - @app.call env - rescue Exception => ex - @error_page = @handler.new ex, env - log_exception - show_error_page(env, ex) - end - - def show_error_page(env, exception=nil) - type, content = if @error_page - if text?(env) - [ 'plain', @error_page.render('text') ] - else - [ 'html', @error_page.render ] - end - else - [ 'html', no_errors_page ] - end - - status_code = 500 - if defined? ActionDispatch::ExceptionWrapper - status_code = ActionDispatch::ExceptionWrapper.new(env, exception).status_code - end - - [status_code, { "Content-Type" => "text/#{type}; charset=utf-8" }, [content]] - end - - def text?(env) - env["HTTP_X_REQUESTED_WITH"] == "XMLHttpRequest" || - !env["HTTP_ACCEPT"].to_s.include?('html') - end - - def log_exception - return unless BetterErrors.logger - - message = "\n#{@error_page.exception.type} - #{@error_page.exception.message}:\n" - @error_page.backtrace_frames.each do |frame| - message << " #{frame}\n" - end - - BetterErrors.logger.fatal message - end - - def internal_call(env, opts) - if opts[:id] != @error_page.id - return [200, { "Content-Type" => "text/plain; charset=utf-8" }, [JSON.dump(error: "Session expired")]] - end - - env["rack.input"].rewind - response = @error_page.send("do_#{opts[:method]}", JSON.parse(env["rack.input"].read)) - [200, { "Content-Type" => "text/plain; charset=utf-8" }, [JSON.dump(response)]] - end - - def no_errors_page - "

No errors

No errors have been recorded yet.


" + - "Better Errors v#{BetterErrors::VERSION}" - end - end -end diff --git a/lib/better_errors/lib/better_errors/rails.rb b/lib/better_errors/lib/better_errors/rails.rb deleted file mode 100644 index 36e386a55..000000000 --- a/lib/better_errors/lib/better_errors/rails.rb +++ /dev/null @@ -1,28 +0,0 @@ -module BetterErrors - # @private - class Railtie < Rails::Railtie - initializer "better_errors.configure_rails_initialization" do - if use_better_errors? - insert_middleware - BetterErrors.logger = Rails.logger - BetterErrors.application_root = Rails.root.to_s - end - end - - def insert_middleware - if defined? ActionDispatch::DebugExceptions - app.middleware.insert_after ActionDispatch::DebugExceptions, BetterErrors::Middleware - else - app.middleware.use BetterErrors::Middleware - end - end - - def use_better_errors? - !Rails.env.production? and app.config.consider_all_requests_local - end - - def app - Rails.application - end - end -end diff --git a/lib/better_errors/lib/better_errors/raised_exception.rb b/lib/better_errors/lib/better_errors/raised_exception.rb deleted file mode 100644 index 07d0d7b28..000000000 --- a/lib/better_errors/lib/better_errors/raised_exception.rb +++ /dev/null @@ -1,66 +0,0 @@ -# @private -module BetterErrors - class RaisedException - attr_reader :exception, :message, :backtrace - - def initialize(exception) - if exception.respond_to?(:original_exception) && exception.original_exception - exception = exception.original_exception - end - - @exception = exception - @message = exception.message - - setup_backtrace - massage_syntax_error - end - - def type - exception.class - end - - private - def has_bindings? - exception.respond_to?(:__better_errors_bindings_stack) && exception.__better_errors_bindings_stack.any? - end - - def setup_backtrace - if has_bindings? - setup_backtrace_from_bindings - else - setup_backtrace_from_backtrace - end - end - - def setup_backtrace_from_bindings - @backtrace = exception.__better_errors_bindings_stack.map { |binding| - file = binding.eval "__FILE__" - line = binding.eval "__LINE__" - name = binding.frame_description - StackFrame.new(file, line, name, binding) - } - end - - def setup_backtrace_from_backtrace - @backtrace = (exception.backtrace || []).map { |frame| - if /\A(?.*?):(?\d+)(:in `(?.*)')?/ =~ frame - StackFrame.new(file, line.to_i, name) - end - }.compact - end - - def massage_syntax_error - case exception.class.to_s - when "Haml::SyntaxError" - if /\A(.+?):(\d+)/ =~ exception.backtrace.first - backtrace.unshift(StackFrame.new($1, $2.to_i, "")) - end - when "SyntaxError" - if /\A(.+?):(\d+): (.*)/m =~ exception.message - backtrace.unshift(StackFrame.new($1, $2.to_i, "")) - @message = $3 - end - end - end - end -end diff --git a/lib/better_errors/lib/better_errors/repl.rb b/lib/better_errors/lib/better_errors/repl.rb deleted file mode 100644 index c0f6463ed..000000000 --- a/lib/better_errors/lib/better_errors/repl.rb +++ /dev/null @@ -1,30 +0,0 @@ -module BetterErrors - # @private - module REPL - PROVIDERS = [ - { impl: "better_errors/repl/basic", - const: :Basic }, - ] - - def self.provider - @provider ||= const_get detect[:const] - end - - def self.provider=(prov) - @provider = prov - end - - def self.detect - PROVIDERS.find { |prov| - test_provider prov - } - end - - def self.test_provider(provider) - require provider[:impl] - true - rescue LoadError - false - end - end -end diff --git a/lib/better_errors/lib/better_errors/repl/basic.rb b/lib/better_errors/lib/better_errors/repl/basic.rb deleted file mode 100644 index 7011e4488..000000000 --- a/lib/better_errors/lib/better_errors/repl/basic.rb +++ /dev/null @@ -1,20 +0,0 @@ -module BetterErrors - module REPL - class Basic - def initialize(binding) - @binding = binding - end - - def send_input(str) - [execute(str), ">>", ""] - end - - private - def execute(str) - "=> #{@binding.eval(str).inspect}\n" - rescue Exception => e - "!! #{e.inspect rescue e.class.to_s rescue "Exception"}\n" - end - end - end -end diff --git a/lib/better_errors/lib/better_errors/repl/pry.rb b/lib/better_errors/lib/better_errors/repl/pry.rb deleted file mode 100644 index 412be013d..000000000 --- a/lib/better_errors/lib/better_errors/repl/pry.rb +++ /dev/null @@ -1,78 +0,0 @@ -require "fiber" -require "pry" - -module BetterErrors - module REPL - class Pry - class Input - def readline - Fiber.yield - end - end - - class Output - def initialize - @buffer = "" - end - - def puts(*args) - args.each do |arg| - @buffer << "#{arg.chomp}\n" - end - end - - def tty? - false - end - - def read_buffer - @buffer - ensure - @buffer = "" - end - end - - def initialize(binding) - @fiber = Fiber.new do - @pry.repl binding - end - @input = Input.new - @output = Output.new - @pry = ::Pry.new input: @input, output: @output - @pry.hooks.clear_all if defined?(@pry.hooks.clear_all) - @fiber.resume - end - - def send_input(str) - local ::Pry.config, color: false, pager: false do - @fiber.resume "#{str}\n" - [@output.read_buffer, *prompt] - end - end - - def prompt - if indent = @pry.instance_variable_get(:@indent) and !indent.indent_level.empty? - ["..", indent.indent_level] - else - [">>", ""] - end - rescue - [">>", ""] - end - - private - def local(obj, attrs) - old_attrs = {} - attrs.each do |k, v| - old_attrs[k] = obj.send k - obj.send "#{k}=", v - end - yield - ensure - old_attrs.each do |k, v| - obj.send "#{k}=", v - end - end - end - end -end diff --git a/lib/better_errors/lib/better_errors/stack_frame.rb b/lib/better_errors/lib/better_errors/stack_frame.rb deleted file mode 100644 index 4130425f7..000000000 --- a/lib/better_errors/lib/better_errors/stack_frame.rb +++ /dev/null @@ -1,111 +0,0 @@ -require "set" - -module BetterErrors - # @private - class StackFrame - def self.from_exception(exception) - RaisedException.new(exception).backtrace - end - - attr_reader :filename, :line, :name, :frame_binding - - def initialize(filename, line, name, frame_binding = nil) - @filename = filename - @line = line - @name = name - @frame_binding = frame_binding - - set_pretty_method_name if frame_binding - end - - def application? - if root = BetterErrors.application_root - filename.index(root) == 0 && filename.index("#{root}/vendor") != 0 - end - end - - def application_path - filename[(BetterErrors.application_root.length+1)..-1] - end - - def gem? - Gem.path.any? { |path| filename.index(path) == 0 } - end - - def gem_path - if path = Gem.path.detect { |path| filename.index(path) == 0 } - gem_name_and_version, path = filename.sub("#{path}/gems/", "").split("/", 2) - /(?.+)-(?[\w.]+)/ =~ gem_name_and_version - "#{gem_name} (#{gem_version}) #{path}" - end - end - - def class_name - @class_name - end - - def method_name - @method_name || @name - end - - def context - if gem? - :gem - elsif application? - :application - else - :dunno - end - end - - def pretty_path - case context - when :application; application_path - when :gem; gem_path - else filename - end - end - - def local_variables - return {} unless frame_binding - frame_binding.eval("local_variables").each_with_object({}) do |name, hash| - if defined?(frame_binding.local_variable_get) - hash[name] = frame_binding.local_variable_get(name) - else - hash[name] = frame_binding.eval(name.to_s) - end - end - end - - def instance_variables - return {} unless frame_binding - Hash[visible_instance_variables.map { |x| - [x, frame_binding.eval(x.to_s)] - }] - end - - def visible_instance_variables - frame_binding.eval("instance_variables") - BetterErrors.ignored_instance_variables - end - - def to_s - "#{pretty_path}:#{line}:in `#{name}'" - end - - private - def set_pretty_method_name - name =~ /\A(block (\([^)]+\) )?in )?/ - recv = frame_binding.eval("self") - - return unless method_name = frame_binding.eval("::Kernel.__method__") - - if Module === recv - @class_name = "#{$1}#{recv}" - @method_name = ".#{method_name}" - else - @class_name = "#{$1}#{Kernel.instance_method(:class).bind(recv).call}" - @method_name = "##{method_name}" - end - end - end -end diff --git a/lib/better_errors/lib/better_errors/templates/main.erb b/lib/better_errors/lib/better_errors/templates/main.erb deleted file mode 100644 index 7c3ff9fe1..000000000 --- a/lib/better_errors/lib/better_errors/templates/main.erb +++ /dev/null @@ -1,1031 +0,0 @@ - - - - <%= exception.type %> at <%= request_path %> - - - <%# Stylesheets are placed in the for Turbolinks compatibility. %> - - - <%# IE8 compatibility crap %> - - - <%# - If Rails's Turbolinks is used, the Better Errors page is probably - rendered in the host app's layout. Let's empty out the styles of the - host app. - %> - - -
-
-

<%= exception.type %> at <%= request_path %>

-

<%= exception.message %>

-
-
- -
- - - <% backtrace_frames.each_with_index do |frame, index| %> - - <% end %> -
- - - - - diff --git a/lib/better_errors/lib/better_errors/templates/text.erb b/lib/better_errors/lib/better_errors/templates/text.erb deleted file mode 100644 index fe9068bbb..000000000 --- a/lib/better_errors/lib/better_errors/templates/text.erb +++ /dev/null @@ -1,21 +0,0 @@ -<%== text_heading("=", "%s at %s" % [exception.type, request_path]) %> - -> <%== exception.message %> -<% if backtrace_frames.any? %> - -<%== text_heading("-", "%s, line %i" % [first_frame.pretty_path, first_frame.line]) %> - -``` ruby -<%== text_formatted_code_block(first_frame) %>``` - -App backtrace -------------- - -<%== application_frames.map { |s| " - #{s}" }.join("\n") %> - -Full backtrace --------------- - -<%== backtrace_frames.map { |s| " - #{s}" }.join("\n") %> - -<% end %> diff --git a/lib/better_errors/lib/better_errors/templates/variable_info.erb b/lib/better_errors/lib/better_errors/templates/variable_info.erb deleted file mode 100644 index bde5daab8..000000000 --- a/lib/better_errors/lib/better_errors/templates/variable_info.erb +++ /dev/null @@ -1,70 +0,0 @@ -
-
-

<%= @frame.name %>

- -
-
- <%== html_formatted_code_block @frame %> -
- - <% if BetterErrors.binding_of_caller_available? && @frame.frame_binding %> -
-
-

-                
>>
-
-
- <% end %> -
- -<% if BetterErrors.binding_of_caller_available? && @frame.frame_binding %> -
- This is a live shell. Type in here. -
- -
-<% end %> - -<% unless BetterErrors.binding_of_caller_available? %> -
- Tip: add gem "binding_of_caller" to your Gemfile to enable the REPL and local/instance variable inspection. -
-<% end %> - -
-

Request info

-
- - <% if rails_params %> - - <% end %> - <% if rack_session %> - - <% end %> -
Request parameters
<%== inspect_value rails_params %>
Rack session
<%== inspect_value rack_session %>
-
-
- -
-

Local Variables

-
- - <% @frame.local_variables.each do |name, value| %> - - <% end %> -
<%= name %>
<%== inspect_value value %>
-
-
- -
-

Instance Variables

-
- - <% @frame.instance_variables.each do |name, value| %> - - <% end %> -
<%= name %>
<%== inspect_value value %>
-
-
- - diff --git a/lib/better_errors/lib/better_errors/version.rb b/lib/better_errors/lib/better_errors/version.rb deleted file mode 100644 index 81769ce8b..000000000 --- a/lib/better_errors/lib/better_errors/version.rb +++ /dev/null @@ -1,3 +0,0 @@ -module BetterErrors - VERSION = "1.1.0" -end diff --git a/lib/better_errors/spec/better_errors/code_formatter_spec.rb b/lib/better_errors/spec/better_errors/code_formatter_spec.rb deleted file mode 100644 index c084e2f91..000000000 --- a/lib/better_errors/spec/better_errors/code_formatter_spec.rb +++ /dev/null @@ -1,92 +0,0 @@ -require "spec_helper" - -module BetterErrors - describe CodeFormatter do - let(:filename) { File.expand_path("../support/my_source.rb", __FILE__) } - - let(:formatter) { CodeFormatter.new(filename, 8) } - - it "picks an appropriate scanner" do - formatter.coderay_scanner.should == :ruby - end - - it "shows 5 lines of context" do - formatter.line_range.should == (3..13) - - formatter.context_lines.should == [ - "three\n", - "four\n", - "five\n", - "six\n", - "seven\n", - "eight\n", - "nine\n", - "ten\n", - "eleven\n", - "twelve\n", - "thirteen\n" - ] - end - - it "works when the line is right on the edge" do - formatter = CodeFormatter.new(filename, 20) - formatter.line_range.should == (15..20) - end - - describe CodeFormatter::HTML do - it "highlights the erroring line" do - formatter = CodeFormatter::HTML.new(filename, 8) - formatter.output.should =~ /highlight.*eight/ - end - - it "works when the line is right on the edge" do - formatter = CodeFormatter::HTML.new(filename, 20) - formatter.output.should_not == formatter.source_unavailable - end - - it "doesn't barf when the lines don't make any sense" do - formatter = CodeFormatter::HTML.new(filename, 999) - formatter.output.should == formatter.source_unavailable - end - - it "doesn't barf when the file doesn't exist" do - formatter = CodeFormatter::HTML.new("fkdguhskd7e l", 1) - formatter.output.should == formatter.source_unavailable - end - end - - describe CodeFormatter::Text do - it "highlights the erroring line" do - formatter = CodeFormatter::Text.new(filename, 8) - formatter.output.should == <<-TEXT.gsub(/^ /, "") - 3 three - 4 four - 5 five - 6 six - 7 seven - > 8 eight - 9 nine - 10 ten - 11 eleven - 12 twelve - 13 thirteen - TEXT - end - - it "works when the line is right on the edge" do - formatter = CodeFormatter::Text.new(filename, 20) - formatter.output.should_not == formatter.source_unavailable - end - - it "doesn't barf when the lines don't make any sense" do - formatter = CodeFormatter::Text.new(filename, 999) - formatter.output.should == formatter.source_unavailable - end - - it "doesn't barf when the file doesn't exist" do - formatter = CodeFormatter::Text.new("fkdguhskd7e l", 1) - formatter.output.should == formatter.source_unavailable - end - end - end -end diff --git a/lib/better_errors/spec/better_errors/error_page_spec.rb b/lib/better_errors/spec/better_errors/error_page_spec.rb deleted file mode 100644 index daea57be6..000000000 --- a/lib/better_errors/spec/better_errors/error_page_spec.rb +++ /dev/null @@ -1,76 +0,0 @@ -require "spec_helper" - -module BetterErrors - describe ErrorPage do - let!(:exception) { raise ZeroDivisionError, "you divided by zero you silly goose!" rescue $! } - - let(:error_page) { ErrorPage.new exception, { "PATH_INFO" => "/some/path" } } - - let(:response) { error_page.render } - - let(:empty_binding) { - local_a = :value_for_local_a - local_b = :value_for_local_b - - @inst_c = :value_for_inst_c - @inst_d = :value_for_inst_d - - binding - } - - it "includes the error message" do - response.should include("you divided by zero you silly goose!") - end - - it "includes the request path" do - response.should include("/some/path") - end - - it "includes the exception class" do - response.should include("ZeroDivisionError") - end - - context "variable inspection" do - let(:exception) { empty_binding.eval("raise") rescue $! } - - if BetterErrors.binding_of_caller_available? - it "shows local variables" do - html = error_page.do_variables("index" => 0)[:html] - html.should include("local_a") - html.should include(":value_for_local_a") - html.should include("local_b") - html.should include(":value_for_local_b") - end - else - it "tells the user to add binding_of_caller to their gemfile to get fancy features" do - html = error_page.do_variables("index" => 0)[:html] - html.should include(%{gem "binding_of_caller"}) - end - end - - it "shows instance variables" do - html = error_page.do_variables("index" => 0)[:html] - html.should include("inst_c") - html.should include(":value_for_inst_c") - html.should include("inst_d") - html.should include(":value_for_inst_d") - end - - it "shows filter instance variables" do - BetterErrors.stub(:ignored_instance_variables).and_return([ :@inst_d ]) - html = error_page.do_variables("index" => 0)[:html] - html.should include("inst_c") - html.should include(":value_for_inst_c") - html.should_not include('@inst_d') - html.should_not include("
:value_for_inst_d
") - end - end - - it "doesn't die if the source file is not a real filename" do - exception.stub(:backtrace).and_return([ - ":10:in `spawn_rack_application'" - ]) - response.should include("Source unavailable") - end - end -end diff --git a/lib/better_errors/spec/better_errors/middleware_spec.rb b/lib/better_errors/spec/better_errors/middleware_spec.rb deleted file mode 100644 index 2c638bfab..000000000 --- a/lib/better_errors/spec/better_errors/middleware_spec.rb +++ /dev/null @@ -1,146 +0,0 @@ -require "spec_helper" - -module BetterErrors - describe Middleware do - let(:app) { Middleware.new(->env { ":)" }) } - let(:exception) { RuntimeError.new("oh no :(") } - - it "passes non-error responses through" do - app.call({}).should == ":)" - end - - it "calls the internal methods" do - app.should_receive :internal_call - app.call("PATH_INFO" => "/__better_errors/1/preform_awesomness") - end - - it "calls the internal methods on any subfolder path" do - app.should_receive :internal_call - app.call("PATH_INFO" => "/any_sub/folder/path/__better_errors/1/preform_awesomness") - end - - it "shows the error page" do - app.should_receive :show_error_page - app.call("PATH_INFO" => "/__better_errors/") - end - - it "shows the error page on any subfolder path" do - app.should_receive :show_error_page - app.call("PATH_INFO" => "/any_sub/folder/path/__better_errors/") - end - - it "doesn't show the error page to a non-local address" do - app.should_not_receive :better_errors_call - app.call("REMOTE_ADDR" => "1.2.3.4") - end - - it "shows to a whitelisted IP" do - BetterErrors::Middleware.allow_ip! '77.55.33.11' - app.should_receive :better_errors_call - app.call("REMOTE_ADDR" => "77.55.33.11") - end - - it "doesn't blow up when given a blank REMOTE_ADDR" do - expect { app.call("REMOTE_ADDR" => " ") }.to_not raise_error - end - - it "doesn't blow up when given an IP address with a zone index" do - expect { app.call("REMOTE_ADDR" => "0:0:0:0:0:0:0:1%0" ) }.to_not raise_error - end - - context "when requesting the /__better_errors manually" do - let(:app) { Middleware.new(->env { ":)" }) } - - it "shows that no errors have been recorded" do - status, headers, body = app.call("PATH_INFO" => "/__better_errors") - body.join.should match /No errors have been recorded yet./ - end - - it "shows that no errors have been recorded on any subfolder path" do - status, headers, body = app.call("PATH_INFO" => "/any_sub/folder/path/__better_errors") - body.join.should match /No errors have been recorded yet./ - end - end - - context "when handling an error" do - let(:app) { Middleware.new(->env { raise exception }) } - - it "returns status 500" do - status, headers, body = app.call({}) - - status.should == 500 - end - - context "original_exception" do - class OriginalExceptionException < Exception - attr_reader :original_exception - - def initialize(message, original_exception = nil) - super(message) - @original_exception = original_exception - end - end - - it "shows Original Exception if it responds_to and has an original_exception" do - app = Middleware.new(->env { - raise OriginalExceptionException.new("Other Exception", Exception.new("Original Exception")) - }) - - status, _, body = app.call({}) - - status.should == 500 - body.join.should_not match(/Other Exception/) - body.join.should match(/Original Exception/) - end - - it "won't crash if the exception responds_to but doesn't have an original_exception" do - app = Middleware.new(->env { - raise OriginalExceptionException.new("Other Exception") - }) - - status, _, body = app.call({}) - - status.should == 500 - body.join.should match(/Other Exception/) - end - end - - it "returns ExceptionWrapper's status_code" do - ad_ew = double("ActionDispatch::ExceptionWrapper") - ad_ew.stub('new').with({}, exception ){ double("ExceptionWrapper", status_code: 404) } - stub_const('ActionDispatch::ExceptionWrapper', ad_ew) - - status, headers, body = app.call({}) - - status.should == 404 - end - - it "returns UTF-8 error pages" do - status, headers, body = app.call({}) - - headers["Content-Type"].should match /charset=utf-8/ - end - - it "returns text pages by default" do - status, headers, body = app.call({}) - - headers["Content-Type"].should match /text\/plain/ - end - - it "returns HTML pages by default" do - # Chrome's 'Accept' header looks similar this. - status, headers, body = app.call("HTTP_ACCEPT" => "text/html,application/xhtml+xml;q=0.9,*/*") - - headers["Content-Type"].should match /text\/html/ - end - - it "logs the exception" do - logger = Object.new - logger.should_receive :fatal - BetterErrors.stub(:logger).and_return(logger) - - app.call({}) - end - end - end -end diff --git a/lib/better_errors/spec/better_errors/raised_exception_spec.rb b/lib/better_errors/spec/better_errors/raised_exception_spec.rb deleted file mode 100644 index 605ab409c..000000000 --- a/lib/better_errors/spec/better_errors/raised_exception_spec.rb +++ /dev/null @@ -1,52 +0,0 @@ -require "spec_helper" - -module BetterErrors - describe RaisedException do - let(:exception) { RuntimeError.new("whoops") } - subject { RaisedException.new(exception) } - - its(:exception) { should == exception } - its(:message) { should == "whoops" } - its(:type) { should == RuntimeError } - - context "when the exception wraps another exception" do - let(:original_exception) { RuntimeError.new("something went wrong!") } - let(:exception) { double(:original_exception => original_exception) } - - its(:exception) { should == original_exception } - its(:message) { should == "something went wrong!" } - end - - context "when the exception is a syntax error" do - let(:exception) { SyntaxError.new("foo.rb:123: you made a typo!") } - - its(:message) { should == "you made a typo!" } - its(:type) { should == SyntaxError } - - it "has the right filename and line number in the backtrace" do - subject.backtrace.first.filename.should == "foo.rb" - subject.backtrace.first.line.should == 123 - end - end - - context "when the exception is a HAML syntax error" do - before do - stub_const("Haml::SyntaxError", Class.new(SyntaxError)) - end - - let(:exception) { - Haml::SyntaxError.new("you made a typo!").tap do |ex| - ex.set_backtrace(["foo.rb:123", "haml/internals/blah.rb:123456"]) - end - } - - its(:message) { should == "you made a typo!" } - its(:type) { should == Haml::SyntaxError } - - it "has the right filename and line number in the backtrace" do - subject.backtrace.first.filename.should == "foo.rb" - subject.backtrace.first.line.should == 123 - end - end - end -end diff --git a/lib/better_errors/spec/better_errors/repl/basic_spec.rb b/lib/better_errors/spec/better_errors/repl/basic_spec.rb deleted file mode 100644 index c533f632c..000000000 --- a/lib/better_errors/spec/better_errors/repl/basic_spec.rb +++ /dev/null @@ -1,18 +0,0 @@ -require "spec_helper" -require "better_errors/repl/basic" -require "better_errors/repl/shared_examples" - -module BetterErrors - module REPL - describe Basic do - let(:fresh_binding) { - local_a = 123 - binding - } - - let(:repl) { Basic.new fresh_binding } - - it_behaves_like "a REPL provider" - end - end -end diff --git a/lib/better_errors/spec/better_errors/repl/pry_spec.rb b/lib/better_errors/spec/better_errors/repl/pry_spec.rb deleted file mode 100644 index 1aa502c56..000000000 --- a/lib/better_errors/spec/better_errors/repl/pry_spec.rb +++ /dev/null @@ -1,40 +0,0 @@ -require "spec_helper" -require "pry" -require "better_errors/repl/pry" -require "better_errors/repl/shared_examples" - -module BetterErrors - module REPL - describe Pry do - let(:fresh_binding) { - local_a = 123 - binding - } - - let(:repl) { Pry.new fresh_binding } - - it "does line continuation" do - output, prompt, filled = repl.send_input "" - output.should == "=> nil\n" - prompt.should == ">>" - filled.should == "" - - output, prompt, filled = repl.send_input "def f(x)" - output.should == "" - prompt.should == ".." - filled.should == " " - - output, prompt, filled = repl.send_input "end" - if RUBY_VERSION >= "2.1.0" - output.should == "=> :f\n" - else - output.should == "=> nil\n" - end - prompt.should == ">>" - filled.should == "" - end - - it_behaves_like "a REPL provider" - end - end -end diff --git a/lib/better_errors/spec/better_errors/repl/shared_examples.rb b/lib/better_errors/spec/better_errors/repl/shared_examples.rb deleted file mode 100644 index 0154851db..000000000 --- a/lib/better_errors/spec/better_errors/repl/shared_examples.rb +++ /dev/null @@ -1,18 +0,0 @@ -shared_examples_for "a REPL provider" do - it "evaluates ruby code in a given context" do - repl.send_input("local_a = 456") - fresh_binding.eval("local_a").should == 456 - end - - it "returns a tuple of output and the new prompt" do - output, prompt = repl.send_input("1 + 2") - output.should == "=> 3\n" - prompt.should == ">>" - end - - it "doesn't barf if the code throws an exception" do - output, prompt = repl.send_input("raise Exception") - output.should include "Exception: Exception" - prompt.should == ">>" - end -end diff --git a/lib/better_errors/spec/better_errors/stack_frame_spec.rb b/lib/better_errors/spec/better_errors/stack_frame_spec.rb deleted file mode 100644 index 420111eec..000000000 --- a/lib/better_errors/spec/better_errors/stack_frame_spec.rb +++ /dev/null @@ -1,157 +0,0 @@ -require "spec_helper" - -module BetterErrors - describe StackFrame do - context "#application?" do - it "is true for application filenames" do - BetterErrors.stub(:application_root).and_return("/abc/xyz") - frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index") - - frame.application?.should be_true - end - - it "is false for everything else" do - BetterErrors.stub(:application_root).and_return("/abc/xyz") - frame = StackFrame.new("/abc/nope", 123, "foo") - - frame.application?.should be_false - end - - it "doesn't care if no application_root is set" do - frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index") - - frame.application?.should be_false - end - end - - context "#gem?" do - it "is true for gem filenames" do - Gem.stub(:path).and_return(["/abc/xyz"]) - frame = StackFrame.new("/abc/xyz/gems/whatever-1.2.3/lib/whatever.rb", 123, "foo") - - frame.gem?.should be_true - end - - it "is false for everything else" do - Gem.stub(:path).and_return(["/abc/xyz"]) - frame = StackFrame.new("/abc/nope", 123, "foo") - - frame.gem?.should be_false - end - end - - context "#application_path" do - it "chops off the application root" do - BetterErrors.stub(:application_root).and_return("/abc/xyz") - frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index") - - frame.application_path.should == "app/controllers/crap_controller.rb" - end - end - - context "#gem_path" do - it "chops of the gem path and stick (gem) there" do - Gem.stub(:path).and_return(["/abc/xyz"]) - frame = StackFrame.new("/abc/xyz/gems/whatever-1.2.3/lib/whatever.rb", 123, "foo") - - frame.gem_path.should == "whatever (1.2.3) lib/whatever.rb" - end - - it "prioritizes gem path over application path" do - BetterErrors.stub(:application_root).and_return("/abc/xyz") - Gem.stub(:path).and_return(["/abc/xyz/vendor"]) - frame = StackFrame.new("/abc/xyz/vendor/gems/whatever-1.2.3/lib/whatever.rb", 123, "foo") - - frame.gem_path.should == "whatever (1.2.3) lib/whatever.rb" - end - end - - context "#pretty_path" do - it "returns #application_path for application paths" do - BetterErrors.stub(:application_root).and_return("/abc/xyz") - frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index") - frame.pretty_path.should == frame.application_path - end - - it "returns #gem_path for gem paths" do - Gem.stub(:path).and_return(["/abc/xyz"]) - frame = StackFrame.new("/abc/xyz/gems/whatever-1.2.3/lib/whatever.rb", 123, "foo") - - frame.pretty_path.should == frame.gem_path - end - end - - it "special cases SyntaxErrors" do - begin - eval(%{ raise SyntaxError, "you wrote bad ruby!" }, nil, "my_file.rb", 123) - rescue SyntaxError => syntax_error - end - frames = StackFrame.from_exception(syntax_error) - frames.first.filename.should == "my_file.rb" - frames.first.line.should == 123 - end - - it "doesn't blow up if no method name is given" do - error = StandardError.allocate - - error.stub(:backtrace).and_return(["foo.rb:123"]) - frames = StackFrame.from_exception(error) - frames.first.filename.should == "foo.rb" - frames.first.line.should == 123 - - error.stub(:backtrace).and_return(["foo.rb:123: this is an error message"]) - frames = StackFrame.from_exception(error) - frames.first.filename.should == "foo.rb" - frames.first.line.should == 123 - end - - it "ignores a backtrace line if its format doesn't make any sense at all" do - error = StandardError.allocate - error.stub(:backtrace).and_return(["foo.rb:123:in `foo'", "C:in `find'", "bar.rb:123:in `bar'"]) - frames = StackFrame.from_exception(error) - frames.count.should == 2 - end - - it "doesn't blow up if a filename contains a colon" do - error = StandardError.allocate - error.stub(:backtrace).and_return(["crap:filename.rb:123"]) - frames = StackFrame.from_exception(error) - frames.first.filename.should == "crap:filename.rb" - end - - it "doesn't blow up with a BasicObject as frame binding" do - obj = BasicObject.new - def obj.my_binding - ::Kernel.binding - end - frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index", obj.my_binding) - frame.class_name.should == 'BasicObject' - end - - it "sets method names properly" do - obj = "string" - def obj.my_method - begin - raise "foo" - rescue => err - err - end - end - - frame = StackFrame.from_exception(obj.my_method).first - if BetterErrors.binding_of_caller_available? - frame.method_name.should == "#my_method" - frame.class_name.should == "String" - else - frame.method_name.should == "my_method" - frame.class_name.should == nil - end - end - - if RUBY_ENGINE == "java" - it "doesn't blow up on a native Java exception" do - expect { StackFrame.from_exception(java.lang.Exception.new) }.to_not raise_error - end - end - end -end diff --git a/lib/better_errors/spec/better_errors/support/my_source.rb b/lib/better_errors/spec/better_errors/support/my_source.rb deleted file mode 100644 index 6dfea0f66..000000000 --- a/lib/better_errors/spec/better_errors/support/my_source.rb +++ /dev/null @@ -1,20 +0,0 @@ -one -two -three -four -five -six -seven -eight -nine -ten -eleven -twelve -thirteen -fourteen -fifteen -sixteen -seventeen -eighteen -nineteen -twenty diff --git a/lib/better_errors/spec/better_errors_spec.rb b/lib/better_errors/spec/better_errors_spec.rb deleted file mode 100644 index e9b26b67d..000000000 --- a/lib/better_errors/spec/better_errors_spec.rb +++ /dev/null @@ -1,73 +0,0 @@ -require "spec_helper" - -describe BetterErrors do - context ".editor" do - it "defaults to textmate" do - subject.editor["foo.rb", 123].should == "txmt://open?url=file://foo.rb&line=123" - end - - it "url escapes the filename" do - subject.editor["&.rb", 0].should == "txmt://open?url=file://%26.rb&line=0" - end - - [:emacs, :emacsclient].each do |editor| - it "uses emacs:// scheme when set to #{editor.inspect}" do - subject.editor = editor - subject.editor[].should start_with "emacs://" - end - end - - [:macvim, :mvim].each do |editor| - it "uses mvim:// scheme when set to #{editor.inspect}" do - subject.editor = editor - subject.editor[].should start_with "mvim://" - end - end - - [:sublime, :subl, :st].each do |editor| - it "uses subl:// scheme when set to #{editor.inspect}" do - subject.editor = editor - subject.editor[].should start_with "subl://" - end - end - - [:textmate, :txmt, :tm].each do |editor| - it "uses txmt:// scheme when set to #{editor.inspect}" do - subject.editor = editor - subject.editor[].should start_with "txmt://" - end - end - - ["emacsclient", "/usr/local/bin/emacsclient"].each do |editor| - it "uses emacs:// scheme when EDITOR=#{editor}" do - ENV["EDITOR"] = editor - subject.editor = subject.default_editor - subject.editor[].should start_with "emacs://" - end - end - - ["mvim -f", "/usr/local/bin/mvim -f"].each do |editor| - it "uses mvim:// scheme when EDITOR=#{editor}" do - ENV["EDITOR"] = editor - subject.editor = subject.default_editor - subject.editor[].should start_with "mvim://" - end - end - - ["subl -w", "/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl"].each do |editor| - it "uses mvim:// scheme when EDITOR=#{editor}" do - ENV["EDITOR"] = editor - subject.editor = subject.default_editor - subject.editor[].should start_with "subl://" - end - end - - ["mate -w", "/usr/bin/mate -w"].each do |editor| - it "uses txmt:// scheme when EDITOR=#{editor}" do - ENV["EDITOR"] = editor - subject.editor = subject.default_editor - subject.editor[].should start_with "txmt://" - end - end - end -end diff --git a/lib/better_errors/spec/spec_helper.rb b/lib/better_errors/spec/spec_helper.rb deleted file mode 100644 index 40d63261e..000000000 --- a/lib/better_errors/spec/spec_helper.rb +++ /dev/null @@ -1,5 +0,0 @@ -$: << File.expand_path("../../lib", __FILE__) - -ENV["EDITOR"] = nil - -require "better_errors" diff --git a/lib/better_errors/spec/without_binding_of_caller.rb b/lib/better_errors/spec/without_binding_of_caller.rb deleted file mode 100644 index 035e2e90f..000000000 --- a/lib/better_errors/spec/without_binding_of_caller.rb +++ /dev/null @@ -1,9 +0,0 @@ -module Kernel - alias_method :require_with_binding_of_caller, :require - - def require(feature) - raise LoadError if feature == "binding_of_caller" - - require_with_binding_of_caller(feature) - end -end diff --git a/lib/rack-mini-profiler/.travis.yml b/lib/rack-mini-profiler/.travis.yml deleted file mode 100644 index 61ab0d68e..000000000 --- a/lib/rack-mini-profiler/.travis.yml +++ /dev/null @@ -1,9 +0,0 @@ -language: ruby -rvm: - - 1.9.3 - - 2.0.0 - - 2.1.1 -bundler_args: "" -services: - - redis - - memcached diff --git a/lib/rack-mini-profiler/CHANGELOG b/lib/rack-mini-profiler/CHANGELOG deleted file mode 100644 index 7c08a89e1..000000000 --- a/lib/rack-mini-profiler/CHANGELOG +++ /dev/null @@ -1,181 +0,0 @@ -28-June-2012 - Sam - - * Started change log - * Corrected profiler so it properly captures POST requests (was supressing non 200s) - * Amended Rack.MiniProfiler.config[:user_provider] to use ip addres for identity - * Fixed bug where unviewed missing ids never got cleared - * Supress all '/assets/' in the rails tie (makes debugging easier) - * record_sql was mega buggy - * added MemcacheStore - -9-July-2012 - Sam - - * Cleaned up mechanism for profiling in production, all you need to do now - is call Rack::MiniProfiler.authorize_request to get profiling working in - production - * Added option to display full backtraces pp=full-backtrace - * Cleaned up railties, got rid of the post authorize callback - * Version 0.1.3 - -12-July-2012 - Sam - - * Fixed incorrect profiling steps (was not indenting or measuring start time right - * Implemented native PG and MySql2 interceptors, this gives way more accurate times - * Refactored context so its a proper class and not a hash - * Added some more client probing built in to rails - * More tests - -18-July-2012 - Sam - - * Added First Paint time for chrome - * Bug fix to ensure non Rails installs have mini profiler - * Version 0.1.7 - -30-July-2012 - Sam - - * Made compliant with ancient versions of Rack (including Rack used by Rails2) - * Fixed broken share link - * Fixed crashes on startup (in MemoryStore and FileStore) - * Version 0.1.8 - * Unicode fix - * Version 0.1.9 - -7-August-2012 - Sam - - * Added option to disable profiler for the current session (pp=disable / pp=enable) - * yajl compatability contributed by Sven Riedel - -10-August-2012 - Sam - - * Added basic prepared statement profiling for postgres - -20-August-2012 - Sam - - * 1.12.pre - * Cap X-MiniProfiler-Ids at 10, otherwise the header can get killed - -3-September-2012 - Sam - - * 1.13.pre - * pg gem prepared statements were not being logged correctly - * added setting config.backtrace_ignores = [] - an array of regexes that match on caller lines that get ignored - * added setting config.backtrace_includes = [] - an array of regexes that get included in the trace by default - * cleaned up the way client settings are stored - * made pp=full-backtrace "sticky" - * added pp=normal-backtrace to clear the "sticky" state - * change "pp=sample" to work with "caller" no need for stack trace gem - -4-September-2012 - Sam - - * 1.15.pre - * fixed annoying bug where client settings were not sticking - * fixed long standing issue with Rack::ConditionalGet stopping MiniProfiler from working properly - -5-September-2012 - Sam - - * 1.16 - * fixed long standing problem specs (issue with memory store) - * fixed issue where profiler would be dumped when you got a 404 in production (and any time rails is bypassed) - * implemented stacktrace properly - -9-September-2012 - Sam - - * 1.17 - * pp=sample was bust unless stacktrace was installed - -10-September-2012 - Sam - - * 1.19 - * fix compat issue with 1.8.7 - -12-September-2012 - Sam - - * 1.20 - * Added pp=profile-gc , it allows you to profile the GC in Ruby 1.9.3 - -17-September-2012 - * 1.21 - * New MemchacedStore - * Rails 4 support - -17-September-2012 - * Allow rack-mini-profiler to be sourced from github - * Extracted the pp=profile-gc-time out, the object space profiler needs to disable gc - -20-September-2012 - * 1.22 - * Fix permission issue in the gem - -8-April-2013 - * 1.24 - * Flame Graph Support see: http://samsaffron.com/archive/2013/03/19/flame-graphs-in-ruby-miniprofiler - * Fix file retention leak in file_store - * New toggle_shortcut and start_hidden options - * Fix for AngularJS support and MooTools - * More robust gc profiling - * Mongoid support - * Fix for html5 implicit body tags - * script tag initialized via data-attributes - * new - Rack::MiniProfiler.counter counter_name {} - * Allow usage of existing jQuery if its already loaded - * Fix pp=enable - * 1.8.7 support ... grrr - * Net:HTTP profiling - * pre authorize to run in all non development? and production? modes - -8-April-2013 - * 1.25 - * Missed flamegraph.html from build - -11-April-2013 - * 1.26 - * (minor) allow Rack::MiniProfilerRails.initialize!(Rails.application), for post config intialization - -26-June-2013 - * 1.27 - * Disable global ajax handlers on MP requests @JP - * Add Rack::MiniProfiler.config.backtrace_threshold_ms - * jQuery 2.0 support - -18-July-2013 - * 1.28 - * diagnostics in abstract storage was raising not implemented killing - ?pp=env and others - * SOLR xml unescaped by mistake - -20-August-2013 - * 1.29 - * Bugfix: SOLR patching had an incorrect monkey patch - * Implemented exception tracing using TracePoint see pp=trace-exceptions - -30-August-2013 - - * 1.30 - * Feature: Added Rack::MiniProfiler.counter_method(klass,name) for injecting counters - * Bug: Counters were not shifting the table correctly - -3-September-2013 - - * Ripped out flamegraph so it can be isolated into a gem - * Flamegraph now has much increased fidelity - * Ripped out pp=sample it just was never really used - -17-September-2013 - Ross Wilson - * Instead of supressing all "/assets/" requests we now check the configured - config.assets.prefix path since developers can rename the path to serve Asset Pipeline - files from - -12-December-2013 - Sam Saffron - * Version 0.9.0.pre (bumped up to reflect the stability of the project) - * Improved reports for pp=profile-gc - * pp=flamegraph&flamegraph_sample_rate=1 , allow you to specify sampling rates - -13-March-2014 - Sam Saffron - * Version 0.9.1 - * Added back Ruby 1.8 support (thanks Malet) - * Corrected Rails 3.0 support (thanks Zlatko) - * Corrected fix possible XSS (admin only) - * Amend Railstie so MiniProfiler can be launched with action view or action controller (Thanks Akira) - * Corrected Sql patching to avoid setting instance vars on nil which is frozen (thanks Andy, huoxito) - - diff --git a/lib/rack-mini-profiler/Gemfile b/lib/rack-mini-profiler/Gemfile deleted file mode 100644 index d65e2a669..000000000 --- a/lib/rack-mini-profiler/Gemfile +++ /dev/null @@ -1,3 +0,0 @@ -source 'http://rubygems.org' - -gemspec diff --git a/lib/rack-mini-profiler/README.md b/lib/rack-mini-profiler/README.md deleted file mode 100644 index 550dc1e07..000000000 --- a/lib/rack-mini-profiler/README.md +++ /dev/null @@ -1,271 +0,0 @@ -# rack-mini-profiler - -[![Code Climate](https://codeclimate.com/github/MiniProfiler/rack-mini-profiler.png)](https://codeclimate.com/github/MiniProfiler/rack-mini-profiler) [![Build Status](https://travis-ci.org/MiniProfiler/rack-mini-profiler.png)](https://travis-ci.org/MiniProfiler/rack-mini-profiler) - -Middleware that displays speed badge for every html page. Designed to work both in production and in development. - -#### Features - -* database profiling. Currently supports Mysql2, Postgres, and Mongoid3 (with fallback support to ActiveRecord) - -#### Learn more - -* [Visit our community](http://community.miniprofiler.com) -* [Watch the RailsCast](http://railscasts.com/episodes/368-miniprofiler) -* [Read about Flame graphs in rack-mini-profiler](http://samsaffron.com/archive/2013/03/19/flame-graphs-in-ruby-miniprofiler) -* [Read the announcement posts from 2012](http://samsaffron.com/archive/2012/07/12/miniprofiler-ruby-edition) - -## rack-mini-profiler needs your help - -We have decided to restructure our repository so there is a central UI repo and the various language implementation have their own. - -**WE NEED HELP.** - -- Setting up a build that reuses https://github.com/MiniProfiler/ui -- Migrating the internal data structures [per the spec](https://github.com/MiniProfiler/ui) -- Cleaning up the [horrendous class structure that is using strings as keys and crazy non-objects](https://github.com/MiniProfiler/rack-mini-profiler/blob/master/lib/mini_profiler/sql_timer_struct.rb#L36-L44) - -If you feel like taking on any of this start an issue and update us on your progress. - -## Installation - -Install/add to Gemfile - -```ruby -gem 'rack-mini-profiler' -``` - -NOTE: Be sure to require rack_mini_profiler below the `pg` and `mysql` gems in your Gemfile. rack_mini_profiler will identify these gems if they are loaded to insert instrumentation. If included too early no SQL will show up. - -#### Rails - -All you have to do is include the Gem and you're good to go in development. See notes below for use in production. - -#### Rails and manual initialization - -In case you need to make sure rack_mini_profiler initialized after all other gems. -Or you want to execute some code before rack_mini_profiler required. - -```ruby -gem 'rack-mini-profiler', require: false -``` -Note the `require: false` part - if omitted, it will cause the Railtie for the mino-profiler to -be loaded outright, and an attempt to re-initialize it manually will raise an exception. - -Then put initialize code in file like `config/initializers/rack_profiler.rb` - -```ruby -if Rails.env == 'development' - require 'rack-mini-profiler' - - # initialization is skipped so trigger it - Rack::MiniProfilerRails.initialize!(Rails.application) -end -``` - -#### Rack Builder - -```ruby -require 'rack-mini-profiler' -builder = Rack::Builder.new do - use Rack::MiniProfiler - - map('/') { run get } -end -``` - -#### Sinatra - -```ruby -require 'rack-mini-profiler' -class MyApp < Sinatra::Base - use Rack::MiniProfiler -end -``` - -### Flamegraphs - -To generate [flamegraphs](http://samsaffron.com/archive/2013/03/19/flame-graphs-in-ruby-miniprofiler): - -* add the **flamegraph** gem to your Gemfile -* visit a page in your app with `?pp=flamegraph` - -Flamegraph generation is supported in MRI 2.0 and 2.1 only. - - -## Access control in production - -rack-mini-profiler is designed with production profiling in mind. To enable that just run `Rack::MiniProfiler.authorize_request` once you know a request is allowed to profile. - -```ruby -# A hook in your ApplicationController -def authorize - if current_user.is_admin? - Rack::MiniProfiler.authorize_request - end -end -``` - -## Configuration - -Various aspects of rack-mini-profiler's behavior can be configured when your app boots. -For example in a Rails app, this should be done in an initializer: -**config/initializers/mini_profiler.rb** - -### Storage - -rack-mini-profiler stores its results so they can be shared later and aren't lost at the end of the request. - -There are 4 storage options: `MemoryStore`, `RedisStore`, `MemcacheStore`, and `FileStore`. - -`FileStore` is the default in Rails environments and will write files to `tmp/miniprofiler/*`. `MemoryStore` is the default otherwise. - -```ruby -# set MemoryStore -Rack::MiniProfiler.config.storage = Rack::MiniProfiler::MemoryStore - -# set RedisStore -if Rails.env.production? - uri = URI.parse(ENV["REDIS_SERVER_URL"]) - Rack::MiniProfiler.config.storage_options = { :host => uri.host, :port => uri.port, :password => uri.password } - Rack::MiniProfiler.config.storage = Rack::MiniProfiler::RedisStore -end -``` - -MemoryStore stores results in a processes heap - something that does not work well in a multi process environment. -FileStore stores results in the file system - something that may not work well in a multi machine environment. -RedisStore/MemcacheStore work in multi process and multi machine environments (RedisStore only saves results for up to 24 hours so it won't continue to fill up Redis). - -Additionally you may implement an AbstractStore for your own provider. - -### User result segregation - -MiniProfiler will attempt to keep all user results isolated, out-of-the-box the user provider uses the ip address: - -```ruby -Rack::MiniProfiler.config.user_provider = Proc.new{|env| Rack::Request.new(env).ip} -``` - -You can override (something that is very important in a multi-machine production setup): - -```ruby -Rack::MiniProfiler.config.user_provider = Proc.new{ |env| CurrentUser.get(env) } -``` - -The string this function returns should be unique for each user on the system (for anonymous you may need to fall back to ip address) - -### Configuration Options - -You can set configuration options using the configuration accessor on `Rack::MiniProfiler`. -For example: - -```ruby -Rack::MiniProfiler.config.position = 'right' -Rack::MiniProfiler.config.start_hidden = true -``` -The available configuration options are: - -* pre_authorize_cb - A lambda callback you can set to determine whether or not mini_profiler should be visible on a given request. Default in a Rails environment is only on in development mode. If in a Rack app, the default is always on. -* position - Can either be 'right' or 'left'. Default is 'left'. -* skip_schema_queries - Whether or not you want to log the queries about the schema of your tables. Default is 'false', 'true' in rails development. -* auto_inject (default true) - when false the miniprofiler script is not injected in the page -* backtrace_filter - a regex you can use to filter out unwanted lines from the backtraces -* toggle_shortcut (default Alt+P) - a jquery.hotkeys.js-style keyboard shortcut, used to toggle the mini_profiler's visibility. See http://code.google.com/p/js-hotkeys/ for more info. -* start_hidden (default false) - Whether or not you want the mini_profiler to be visible when loading a page -* backtrace_threshold_ms (default zero) - Minimum SQL query elapsed time before a backtrace is recorded. Backtrace recording can take a couple of milliseconds on rubies earlier than 2.0, impacting performance for very small queries. -* flamegraph_sample_rate (default 0.5ms) - How often fast_stack should get stack trace info to generate flamegraphs - -### Custom middleware ordering (required if using `Rack::Deflate` with Rails) - -If you are using `Rack::Deflate` with rails and rack-mini-profiler in its default configuration, -`Rack::MiniProfiler` will be injected (as always) at position 0 in the middleware stack. This -will result in it attempting to inject html into the already-compressed response body. To fix this, -the middleware ordering must be overriden. - -To do this, first add `, require: false` to the gemfile entry for rack-mini-profiler. -This will prevent the railtie from running. Then, customize the initialization -in the initializer like so: - -```ruby -require 'rack-mini-profiler' - -Rack::MiniProfilerRails.initialize!(Rails.application) - -Rails.application.middleware.delete(Rack::MiniProfiler) -Rails.application.middleware.insert_after(Rack::Deflater, Rack::MiniProfiler) -``` - -Deleting the middleware and then reinserting it is a bit inelegant, but -a sufficient and costless solution. It is possible that rack-mini-profiler might -support this scenario more directly if it is found that -there is significant need for this confriguration or that -the above recipe causes problems. - - -## Special query strings - -If you include the query string `pp=help` at the end of your request you will see the various options available. You can use these options to extend or contract the amount of diagnostics rack-mini-profiler gathers. - - -## Rails 2.X support - -To get MiniProfiler working with Rails 2.3.X you need to do the initialization manually as well as monkey patch away an incompatibility between activesupport and json_pure. - -Add the following code to your environment.rb (or just in a specific environment such as development.rb) for initialization and configuration of MiniProfiler. - -```ruby -# configure and initialize MiniProfiler -require 'rack-mini-profiler' -c = ::Rack::MiniProfiler.config -c.pre_authorize_cb = lambda { |env| - Rails.env.development? || Rails.env.production? -} -tmp = Rails.root.to_s + "/tmp/miniprofiler" -FileUtils.mkdir_p(tmp) unless File.exists?(tmp) -c.storage_options = {:path => tmp} -c.storage = ::Rack::MiniProfiler::FileStore -config.middleware.use(::Rack::MiniProfiler) -::Rack::MiniProfiler.profile_method(ActionController::Base, :process) {|action| "Executing action: #{action}"} -::Rack::MiniProfiler.profile_method(ActionView::Template, :render) {|x,y| "Rendering: #{path_without_format_and_extension}"} - -# monkey patch away an activesupport and json_pure incompatability -# http://pivotallabs.com/users/alex/blog/articles/1332-monkey-patch-of-the-day-activesupport-vs-json-pure-vs-ruby-1-8 -if JSON.const_defined?(:Pure) - class JSON::Pure::Generator::State - include ActiveSupport::CoreExtensions::Hash::Except - end -end -``` - -## Running the Specs - -``` -$ rake build -$ rake spec -``` - -Additionally you can also run `autotest` if you like. - -## Licence - -The MIT License (MIT) - -Copyright (c) 2013 Sam Saffron - -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/lib/rack-mini-profiler/Rakefile b/lib/rack-mini-profiler/Rakefile deleted file mode 100644 index a908b5b62..000000000 --- a/lib/rack-mini-profiler/Rakefile +++ /dev/null @@ -1,46 +0,0 @@ -# Rakefile -require 'rubygems' -require 'bundler' -Bundler.setup(:default, :test) - -task :default => [:spec] - -require 'rspec/core' -require 'rspec/core/rake_task' -RSpec::Core::RakeTask.new(:spec) do |spec| - spec.pattern = FileList['spec/**/*_spec.rb'] -end - -desc "builds a gem" -task :build => :update_asset_version do - `gem build rack-mini-profiler.gemspec 1>&2` -end - -desc "compile less" -task :compile_less => :copy_files do - `lessc lib/html/includes.less > lib/html/includes.css` -end - -desc "update asset version file" -task :update_asset_version => :compile_less do - require 'digest/md5' - h = [] - Dir.glob('lib/html/*.{js,html,css,tmpl}').each do |f| - h << Digest::MD5.hexdigest(::File.read(f)) - end - File.open('lib/mini_profiler/version.rb','w') do |f| - f.write \ -"module Rack - class MiniProfiler - VERSION = '#{Digest::MD5.hexdigest(h.sort.join(''))}'.freeze - end -end" - end -end - - -desc "copy files from other parts of the tree" -task :copy_files do - # TODO grab files from MiniProfiler/UI -end - diff --git a/lib/rack-mini-profiler/autotest/discover.rb b/lib/rack-mini-profiler/autotest/discover.rb deleted file mode 100644 index de32a0121..000000000 --- a/lib/rack-mini-profiler/autotest/discover.rb +++ /dev/null @@ -1,2 +0,0 @@ -Autotest.add_discovery { "rspec2" } - diff --git a/lib/rack-mini-profiler/lib/html/includes.css b/lib/rack-mini-profiler/lib/html/includes.css deleted file mode 100644 index d96528b8d..000000000 --- a/lib/rack-mini-profiler/lib/html/includes.css +++ /dev/null @@ -1,451 +0,0 @@ -.profiler-result, -.profiler-queries { - color: #555; - line-height: 1; - font-size: 12px; -} -.profiler-result pre, -.profiler-queries pre, -.profiler-result code, -.profiler-queries code, -.profiler-result label, -.profiler-queries label, -.profiler-result table, -.profiler-queries table, -.profiler-result tbody, -.profiler-queries tbody, -.profiler-result thead, -.profiler-queries thead, -.profiler-result tfoot, -.profiler-queries tfoot, -.profiler-result tr, -.profiler-queries tr, -.profiler-result th, -.profiler-queries th, -.profiler-result td, -.profiler-queries td { - margin: 0; - padding: 0; - border: 0; - font-size: 100%; - font: inherit; - vertical-align: baseline; - background-color: transparent; - overflow: visible; - max-height: none; -} -.profiler-result table, -.profiler-queries table { - border-collapse: collapse; - border-spacing: 0; -} -.profiler-result a, -.profiler-queries a, -.profiler-result a:hover, -.profiler-queries a:hover { - cursor: pointer; - color: #0077cc; -} -.profiler-result a, -.profiler-queries a { - text-decoration: none; -} -.profiler-result a:hover, -.profiler-queries a:hover { - text-decoration: underline; -} -.profiler-result { - font-family: Helvetica, Arial, sans-serif; -} -.profiler-result .profiler-toggle-duration-with-children { - float: right; -} -.profiler-result table.profiler-client-timings { - margin-top: 10px; -} -.profiler-result .profiler-label { - color: #555555; - overflow: hidden; - text-overflow: ellipsis; -} -.profiler-result .profiler-unit { - color: #aaaaaa; -} -.profiler-result .profiler-trivial { - display: none; -} -.profiler-result .profiler-trivial td, -.profiler-result .profiler-trivial td * { - color: #aaaaaa !important; -} -.profiler-result pre, -.profiler-result code, -.profiler-result .profiler-number, -.profiler-result .profiler-unit { - font-family: Consolas, monospace, serif; -} -.profiler-result .profiler-number { - color: #111111; -} -.profiler-result .profiler-info { - text-align: right; -} -.profiler-result .profiler-info .profiler-name { - float: left; -} -.profiler-result .profiler-info .profiler-server-time { - white-space: nowrap; -} -.profiler-result .profiler-timings th { - background-color: #fff; - color: #aaaaaa; - text-align: right; -} -.profiler-result .profiler-timings th, -.profiler-result .profiler-timings td { - white-space: nowrap; -} -.profiler-result .profiler-timings .profiler-duration-with-children { - display: none; -} -.profiler-result .profiler-timings .profiler-duration { - font-family: Consolas, monospace, serif; - color: #111111; - text-align: right; -} -.profiler-result .profiler-timings .profiler-indent { - letter-spacing: 4px; -} -.profiler-result .profiler-timings .profiler-queries-show .profiler-number, -.profiler-result .profiler-timings .profiler-queries-show .profiler-unit { - color: #0077cc; -} -.profiler-result .profiler-timings .profiler-queries-duration { - padding-left: 6px; -} -.profiler-result .profiler-timings .profiler-percent-in-sql { - white-space: nowrap; - text-align: right; -} -.profiler-result .profiler-timings tfoot td { - padding-top: 10px; - text-align: right; -} -.profiler-result .profiler-timings tfoot td a { - font-size: 95%; - display: inline-block; - margin-left: 12px; -} -.profiler-result .profiler-timings tfoot td a:first-child { - float: left; - margin-left: 0px; -} -.profiler-result .profiler-timings tfoot td a.profiler-custom-link { - float: left; -} -.profiler-result .profiler-queries { - font-family: Helvetica, Arial, sans-serif; -} -.profiler-result .profiler-queries .profiler-stack-trace { - margin-bottom: 15px; -} -.profiler-result .profiler-queries pre { - font-family: Consolas, monospace, serif; - white-space: pre-wrap; -} -.profiler-result .profiler-queries th { - background-color: #fff; - border-bottom: 1px solid #555; - font-weight: bold; - padding: 15px; - white-space: nowrap; -} -.profiler-result .profiler-queries td { - padding: 15px; - text-align: left; - background-color: #fff; -} -.profiler-result .profiler-queries td:last-child { - padding-right: 25px; -} -.profiler-result .profiler-queries .profiler-odd td { - background-color: #e5e5e5; -} -.profiler-result .profiler-queries .profiler-since-start, -.profiler-result .profiler-queries .profiler-duration { - text-align: right; -} -.profiler-result .profiler-queries .profiler-info div { - text-align: right; - margin-bottom: 5px; -} -.profiler-result .profiler-queries .profiler-gap-info, -.profiler-result .profiler-queries .profiler-gap-info td { - background-color: #ccc; -} -.profiler-result .profiler-queries .profiler-gap-info .profiler-unit { - color: #777; -} -.profiler-result .profiler-queries .profiler-gap-info .profiler-info { - text-align: right; -} -.profiler-result .profiler-queries .profiler-gap-info.profiler-trivial-gaps { - display: none; -} -.profiler-result .profiler-queries .profiler-trivial-gap-container { - text-align: center; -} -.profiler-result .profiler-queries .str { - color: #800000; -} -.profiler-result .profiler-queries .kwd { - color: #00008b; -} -.profiler-result .profiler-queries .com { - color: #808080; -} -.profiler-result .profiler-queries .typ { - color: #2b91af; -} -.profiler-result .profiler-queries .lit { - color: #800000; -} -.profiler-result .profiler-queries .pun { - color: #000000; -} -.profiler-result .profiler-queries .pln { - color: #000000; -} -.profiler-result .profiler-queries .tag { - color: #800000; -} -.profiler-result .profiler-queries .atn { - color: #ff0000; -} -.profiler-result .profiler-queries .atv { - color: #0000ff; -} -.profiler-result .profiler-queries .dec { - color: #800080; -} -.profiler-result .profiler-warning, -.profiler-result .profiler-warning *, -.profiler-result .profiler-warning .profiler-queries-show, -.profiler-result .profiler-warning .profiler-queries-show .profiler-unit { - color: #f00; -} -.profiler-result .profiler-warning:hover, -.profiler-result .profiler-warning *:hover, -.profiler-result .profiler-warning .profiler-queries-show:hover, -.profiler-result .profiler-warning .profiler-queries-show .profiler-unit:hover { - color: #f00; -} -.profiler-result .profiler-nuclear { - color: #f00; - font-weight: bold; - padding-right: 2px; -} -.profiler-result .profiler-nuclear:hover { - color: #f00; -} -.profiler-results { - z-index: 2147483643; - position: fixed; - top: 0px; -} -.profiler-results.profiler-left { - left: 0px; -} -.profiler-results.profiler-left.profiler-no-controls .profiler-result:last-child .profiler-button, -.profiler-results.profiler-left .profiler-controls { - -webkit-border-bottom-right-radius: 10px; - -moz-border-radius-bottomright: 10px; - border-bottom-right-radius: 10px; -} -.profiler-results.profiler-left .profiler-button, -.profiler-results.profiler-left .profiler-controls { - border-right: 1px solid #888888; -} -.profiler-results.profiler-right { - right: 0px; -} -.profiler-results.profiler-right.profiler-no-controls .profiler-result:last-child .profiler-button, -.profiler-results.profiler-right .profiler-controls { - -webkit-border-bottom-left-radius: 10px; - -moz-border-radius-bottomleft: 10px; - border-bottom-left-radius: 10px; -} -.profiler-results.profiler-right .profiler-button, -.profiler-results.profiler-right .profiler-controls { - border-left: 1px solid #888888; -} -.profiler-results .profiler-button, -.profiler-results .profiler-controls { - display: none; - z-index: 2147483640; - border-bottom: 1px solid #888888; - background-color: #fff; - padding: 4px 7px; - text-align: right; - cursor: pointer; -} -.profiler-results .profiler-button.profiler-button-active, -.profiler-results .profiler-controls.profiler-button-active { - background-color: maroon; -} -.profiler-results .profiler-button.profiler-button-active .profiler-number, -.profiler-results .profiler-controls.profiler-button-active .profiler-number, -.profiler-results .profiler-button.profiler-button-active .profiler-nuclear, -.profiler-results .profiler-controls.profiler-button-active .profiler-nuclear { - color: #fff; - font-weight: bold; -} -.profiler-results .profiler-button.profiler-button-active .profiler-unit, -.profiler-results .profiler-controls.profiler-button-active .profiler-unit { - color: #fff; - font-weight: normal; -} -.profiler-results .profiler-controls { - display: block; - font-size: 12px; - font-family: Consolas, monospace, serif; - cursor: default; - text-align: center; -} -.profiler-results .profiler-controls span { - border-right: 1px solid #aaaaaa; - padding-right: 5px; - margin-right: 5px; - cursor: pointer; -} -.profiler-results .profiler-controls span:last-child { - border-right: none; -} -.profiler-results .profiler-popup { - display: none; - z-index: 2147483641; - position: absolute; - background-color: #fff; - border: 1px solid #aaa; - padding: 5px 10px; - text-align: left; - line-height: 18px; - overflow: auto; - -moz-box-shadow: 0px 1px 15px #555555; - -webkit-box-shadow: 0px 1px 15px #555555; - box-shadow: 0px 1px 15px #555555; -} -.profiler-results .profiler-popup .profiler-info { - margin-bottom: 3px; - padding-bottom: 2px; - border-bottom: 1px solid #ddd; -} -.profiler-results .profiler-popup .profiler-info .profiler-name { - font-size: 110%; - font-weight: bold; -} -.profiler-results .profiler-popup .profiler-info .profiler-name .profiler-overall-duration { - display: none; -} -.profiler-results .profiler-popup .profiler-info .profiler-server-time { - font-size: 95%; -} -.profiler-results .profiler-popup .profiler-timings th, -.profiler-results .profiler-popup .profiler-timings td { - padding-left: 6px; - padding-right: 6px; -} -.profiler-results .profiler-popup .profiler-timings th { - font-size: 95%; - padding-bottom: 3px; -} -.profiler-results .profiler-popup .profiler-timings .profiler-label { - max-width: 275px; -} -.profiler-results .profiler-queries { - display: none; - z-index: 2147483643; - position: absolute; - overflow-y: auto; - overflow-x: auto; - background-color: #fff; -} -.profiler-results .profiler-queries th { - font-size: 17px; -} -.profiler-results.profiler-min .profiler-result { - display: none; -} -.profiler-results.profiler-min .profiler-controls span { - display: none; -} -.profiler-results.profiler-min .profiler-controls .profiler-min-max { - border-right: none; - padding: 0px; - margin: 0px; -} -.profiler-queries-bg { - z-index: 2147483642; - display: none; - background: #000; - opacity: 0.7; - position: absolute; - top: 0px; - left: 0px; - min-width: 100%; -} -.profiler-result-full .profiler-result { - width: 950px; - margin: 30px auto; -} -.profiler-result-full .profiler-result .profiler-button { - display: none; -} -.profiler-result-full .profiler-result .profiler-popup .profiler-info { - font-size: 25px; - border-bottom: 1px solid #aaaaaa; - padding-bottom: 3px; - margin-bottom: 25px; -} -.profiler-result-full .profiler-result .profiler-popup .profiler-info .profiler-overall-duration { - padding-right: 20px; - font-size: 80%; - color: #888; -} -.profiler-result-full .profiler-result .profiler-popup .profiler-timings td, -.profiler-result-full .profiler-result .profiler-popup .profiler-timings th { - padding-left: 8px; - padding-right: 8px; -} -.profiler-result-full .profiler-result .profiler-popup .profiler-timings th { - padding-bottom: 7px; -} -.profiler-result-full .profiler-result .profiler-popup .profiler-timings td { - font-size: 14px; - padding-bottom: 4px; -} -.profiler-result-full .profiler-result .profiler-popup .profiler-timings td:first-child { - padding-left: 10px; -} -.profiler-result-full .profiler-result .profiler-popup .profiler-timings .profiler-label { - max-width: 550px; -} -.profiler-result-full .profiler-result .profiler-queries { - margin: 25px 0; -} -.profiler-result-full .profiler-result .profiler-queries table { - width: 100%; -} -.profiler-result-full .profiler-result .profiler-queries th { - font-size: 16px; - color: #555; - line-height: 20px; -} -.profiler-result-full .profiler-result .profiler-queries td { - padding: 15px 10px; - text-align: left; -} -.profiler-result-full .profiler-result .profiler-queries .profiler-info div { - text-align: right; - margin-bottom: 5px; -} diff --git a/lib/rack-mini-profiler/lib/html/includes.js b/lib/rack-mini-profiler/lib/html/includes.js deleted file mode 100644 index d8b4de083..000000000 --- a/lib/rack-mini-profiler/lib/html/includes.js +++ /dev/null @@ -1,960 +0,0 @@ -"use strict"; -var MiniProfiler = (function () { - var $; - - var options, - container, - controls, - fetchedIds = [], - fetchingIds = [], // so we never pull down a profiler twice - ajaxStartTime - ; - - var hasLocalStorage = function () { - try { - return 'localStorage' in window && window['localStorage'] !== null; - } catch (e) { - return false; - } - }; - - var getVersionedKey = function (keyPrefix) { - return keyPrefix + '-' + options.version; - }; - - var save = function (keyPrefix, value) { - if (!hasLocalStorage()) { return; } - - // clear old keys with this prefix, if any - for (var i = 0; i < localStorage.length; i++) { - if ((localStorage.key(i) || '').indexOf(keyPrefix) > -1) { - localStorage.removeItem(localStorage.key(i)); - } - } - - // save under this version - localStorage[getVersionedKey(keyPrefix)] = value; - }; - - var load = function (keyPrefix) { - if (!hasLocalStorage()) { return null; } - - return localStorage[getVersionedKey(keyPrefix)]; - }; - - var fetchTemplates = function (success) { - var key = 'templates', - cached = load(key); - - if (cached) { - $('body').append(cached); - success(); - } - else { - $.get(options.path + 'includes.tmpl?v=' + options.version, function (data) { - if (data) { - save(key, data); - $('body').append(data); - success(); - } - }); - } - }; - - var getClientPerformance = function() { - return window.performance == null ? null : window.performance; - }; - - var fetchResults = function (ids) { - var clientPerformance, clientProbes, i, j, p, id, idx; - - for (i = 0; i < ids.length; i++) { - id = ids[i]; - - clientPerformance = null; - clientProbes = null; - - if (window.mPt) { - clientProbes = mPt.results(); - for (j = 0; j < clientProbes.length; j++) { - clientProbes[j].d = clientProbes[j].d.getTime(); - } - mPt.flush(); - } - - if (id == options.currentId) { - - clientPerformance = getClientPerformance(); - - if (clientPerformance != null) { - // ie is buggy strip out functions - var copy = { navigation: {}, timing: {} }; - - var timing = $.extend({}, clientPerformance.timing); - - for (p in timing) { - if (timing.hasOwnProperty(p) && !$.isFunction(timing[p])) { - copy.timing[p] = timing[p]; - } - } - if (clientPerformance.navigation) { - copy.navigation.redirectCount = clientPerformance.navigation.redirectCount; - } - clientPerformance = copy; - - // hack to add chrome timings - if (window.chrome && window.chrome.loadTimes) { - var chromeTimes = window.chrome.loadTimes(); - if (chromeTimes.firstPaintTime) { - clientPerformance.timing["First Paint Time"] = Math.round(chromeTimes.firstPaintTime * 1000); - } - if (chromeTimes.firstPaintTime) { - clientPerformance.timing["First Paint After Load Time"] = Math.round(chromeTimes.firstPaintAfterLoadTime * 1000); - } - - } - } - } else if (ajaxStartTime != null && clientProbes && clientProbes.length > 0) { - clientPerformance = { timing: { navigationStart: ajaxStartTime.getTime() } }; - ajaxStartTime = null; - } - - if ($.inArray(id, fetchedIds) < 0 && $.inArray(id, fetchingIds) < 0) { - idx = fetchingIds.push(id) - 1; - - $.ajax({ - url: options.path + 'results', - data: { id: id, clientPerformance: clientPerformance, clientProbes: clientProbes, popup: 1 }, - dataType: 'json', - global: false, - type: 'POST', - success: function (json) { - fetchedIds.push(id); - if (json != "hidden") { - buttonShow(json); - } - }, - complete: function () { - fetchingIds.splice(idx, 1); - } - }); - } - } - }; - - var renderTemplate = function (json) { - return $('#profilerTemplate').tmpl(json); - }; - - var buttonShow = function (json) { - var result = renderTemplate(json); - - if (controls) - result.insertBefore(controls); - else - result.appendTo(container); - - var button = result.find('.profiler-button'), - popup = result.find('.profiler-popup'); - - // button will appear in corner with the total profiling duration - click to show details - button.click(function () { buttonClick(button, popup); }); - - // small duration steps and the column with aggregate durations are hidden by default; allow toggling - toggleHidden(popup); - - // lightbox in the queries - popup.find('.profiler-queries-show').click(function () { queriesShow($(this), result); }); - - // limit count - if (container.find('.profiler-result').length > options.maxTracesToShow) - container.find('.profiler-result').first().remove(); - button.show(); - }; - - var toggleHidden = function (popup) { - var trivial = popup.find('.profiler-toggle-trivial'); - var childrenTime = popup.find('.profiler-toggle-duration-with-children'); - var trivialGaps = popup.parent().find('.profiler-toggle-trivial-gaps'); - - var toggleIt = function (node) { - var link = $(node), - klass = "profiler-" + link.attr('class').substr('profiler-toggle-'.length), - isHidden = link.text().indexOf('show') > -1; - - popup.parent().find('.' + klass).toggle(isHidden); - link.text(link.text().replace(isHidden ? 'show' : 'hide', isHidden ? 'hide' : 'show')); - - popupPreventHorizontalScroll(popup); - }; - - childrenTime.add(trivial).add(trivialGaps).click(function () { - toggleIt(this); - }); - - // if option is set or all our timings are trivial, go ahead and show them - if (options.showTrivial || trivial.data('show-on-load')) { - toggleIt(trivial); - } - // if option is set, go ahead and show time with children - if (options.showChildrenTime) { - toggleIt(childrenTime); - } - }; - - var buttonClick = function (button, popup) { - // we're toggling this button/popup - if (popup.is(':visible')) { - popupHide(button, popup); - } - else { - var visiblePopups = container.find('.profiler-popup:visible'), - theirButtons = visiblePopups.siblings('.profiler-button'); - - // hide any other popups - popupHide(theirButtons, visiblePopups); - - // before showing the one we clicked - popupShow(button, popup); - } - }; - - var popupShow = function (button, popup) { - button.addClass('profiler-button-active'); - - popupSetDimensions(button, popup); - - popup.show(); - - popupPreventHorizontalScroll(popup); - }; - - var popupSetDimensions = function (button, popup) { - var top = button.position().top - 1, // position next to the button we clicked - windowHeight = $(window).height(), - maxHeight = windowHeight - top - 40; // make sure the popup doesn't extend below the fold - - popup - .css({ 'top': top, 'max-height': maxHeight }) - .css(options.renderPosition, button.outerWidth() - 3); // move left or right, based on config - }; - - var popupPreventHorizontalScroll = function (popup) { - var childrenHeight = 0; - - popup.children().each(function () { childrenHeight += $(this).height(); }); - - popup.css({ 'padding-right': childrenHeight > popup.height() ? 40 : 10 }); - }; - - var popupHide = function (button, popup) { - button.removeClass('profiler-button-active'); - popup.hide(); - }; - - var queriesShow = function (link, result) { - - var px = 30, - win = $(window), - width = win.width() - 2 * px, - height = win.height() - 2 * px, - queries = result.find('.profiler-queries'); - - // opaque background - $('
').appendTo('body').css({ 'height': $(document).height() }).show(); - - // center the queries and ensure long content is scrolled - queries.css({ 'top': px, 'max-height': height, 'width': width }).css(options.renderPosition, px) - .find('table').css({ 'width': width }); - - // have to show everything before we can get a position for the first query - queries.show(); - - queriesScrollIntoView(link, queries, queries); - - // syntax highlighting - prettyPrint(); - }; - - var queriesScrollIntoView = function (link, queries, whatToScroll) { - var id = link.closest('tr').attr('data-timing-id'), - cells = queries.find('tr[data-timing-id="' + id + '"] td'); - - // ensure they're in view - whatToScroll.scrollTop(whatToScroll.scrollTop() + cells.first().position().top - 100); - - // highlight and then fade back to original bg color; do it ourselves to prevent any conflicts w/ jquery.UI or other implementations of Resig's color plugin - cells.each(function () { - var cell = $(this), - highlightHex = '#FFFFBB', - highlightRgb = getRGB(highlightHex), - originalRgb = getRGB(cell.css('background-color')), - getColorDiff = function (fx, i) { - // adapted from John Resig's color plugin: http://plugins.jquery.com/project/color - return Math.max(Math.min(parseInt((fx.pos * (originalRgb[i] - highlightRgb[i])) + highlightRgb[i], 10), 255), 0); - }; - - // we need to animate some other property to piggy-back on the step function, so I choose you, opacity! - cell.css({ 'opacity': 1, 'background-color': highlightHex }) - .animate({ 'opacity': 1 }, { duration: 2000, step: function (now, fx) { - fx.elem.style.backgroundColor = "rgb(" + [getColorDiff(fx, 0), getColorDiff(fx, 1), getColorDiff(fx, 2)].join(",") + ")"; - } - }); - }); - }; - - // Color Conversion functions from highlightFade - // By Blair Mitchelmore - // http://jquery.offput.ca/highlightFade/ - // Parse strings looking for color tuples [255,255,255] - var getRGB = function (color) { - var result; - - // Check if we're already dealing with an array of colors - if (color && color.constructor == Array && color.length == 3) return color; - - // Look for rgb(num,num,num) - if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color)) return [parseInt(result[1]), parseInt(result[2]), parseInt(result[3])]; - - // Look for rgb(num%,num%,num%) - if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color)) return [parseFloat(result[1]) * 2.55, parseFloat(result[2]) * 2.55, parseFloat(result[3]) * 2.55]; - - // Look for #a0b1c2 - if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color)) return [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)]; - - // Look for #fff - if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color)) return [parseInt(result[1] + result[1], 16), parseInt(result[2] + result[2], 16), parseInt(result[3] + result[3], 16)]; - - // Look for rgba(0, 0, 0, 0) == transparent in Safari 3 - if (result = /rgba\(0, 0, 0, 0\)/.exec(color)) return colors['transparent']; - - return null; - }; - - var bindDocumentEvents = function () { - $(document).bind('click keyup', function (e) { - - // this happens on every keystroke, and :visible is crazy expensive in IE <9 - // and in this case, the display:none check is sufficient. - var popup = $('.profiler-popup').filter(function () { return $(this).css("display") !== "none"; }); - - if (!popup.length) { - return; - } - - var button = popup.siblings('.profiler-button'), - queries = popup.closest('.profiler-result').find('.profiler-queries'), - bg = $('.profiler-queries-bg'), - isEscPress = e.type == 'keyup' && e.which == 27, - hidePopup = false, - hideQueries = false; - - if (bg.is(':visible')) { - hideQueries = isEscPress || (e.type == 'click' && !$.contains(queries[0], e.target) && !$.contains(popup[0], e.target)); - } - else if (popup.is(':visible')) { - hidePopup = isEscPress || (e.type == 'click' && !$.contains(popup[0], e.target) && !$.contains(button[0], e.target) && button[0] != e.target); - } - - if (hideQueries) { - bg.remove(); - queries.hide(); - } - - if (hidePopup) { - popupHide(button, popup); - } - }); - $(document).bind('keydown', options.toggleShortcut, function(e) { - $('.profiler-results').toggle(); - }); - }; - - var initFullView = function () { - - // first, get jquery tmpl, then render and bind handlers - fetchTemplates(function () { - - // profiler will be defined in the full page's head - renderTemplate(profiler).appendTo(container); - - var popup = $('.profiler-popup'); - - toggleHidden(popup); - - prettyPrint(); - - // since queries are already shown, just highlight and scroll when clicking a "1 sql" link - popup.find('.profiler-queries-show').click(function () { - queriesScrollIntoView($(this), $('.profiler-queries'), $(document)); - }); - }); - }; - - var initControls = function (container) { - if (options.showControls) { - controls = $('
mc
').appendTo(container); - - $('.profiler-controls .profiler-min-max').click(function () { - container.toggleClass('profiler-min'); - }); - - container.hover(function () { - if ($(this).hasClass('profiler-min')) { - $(this).find('.profiler-min-max').show(); - } - }, - function () { - if ($(this).hasClass('profiler-min')) { - $(this).find('.profiler-min-max').hide(); - } - }); - - $('.profiler-controls .profiler-clear').click(function () { - container.find('.profiler-result').remove(); - }); - } - else { - container.addClass('profiler-no-controls'); - } - }; - - var initPopupView = function () { - - if (options.authorized) { - // all fetched profilings will go in here - container = $('
').appendTo('body'); - - // MiniProfiler.RenderIncludes() sets which corner to render in - default is upper left - container.addClass("profiler-" + options.renderPosition); - - //initialize the controls - initControls(container); - - // we'll render results json via a jquery.tmpl - after we get the templates, we'll fetch the initial json to populate it - fetchTemplates(function () { - // get master page profiler results - fetchResults(options.ids); - }); - if (options.startHidden) container.hide(); - } - else { - fetchResults(options.ids); - } - - var jQueryAjaxComplete = function (e, xhr, settings) { - if (xhr) { - // should be an array of strings, e.g. ["008c4813-9bd7-443d-9376-9441ec4d6a8c","16ff377b-8b9c-4c20-a7b5-97cd9fa7eea7"] - var stringIds = xhr.getResponseHeader('X-MiniProfiler-Ids'); - if (stringIds) { - var ids = typeof JSON != 'undefined' ? JSON.parse(stringIds) : eval(stringIds); - fetchResults(ids); - } - } - }; - - // fetch profile results for any ajax calls - // note, this does not use $ cause we want to hook into the main jQuery - if (jQuery && jQuery(document) && jQuery(document).ajaxComplete) { - jQuery(document).ajaxComplete(jQueryAjaxComplete); - } - - if (jQuery && jQuery(document).ajaxStart) - jQuery(document).ajaxStart(function () { ajaxStartTime = new Date(); }); - - // fetch results after ASP Ajax calls - if (typeof (Sys) != 'undefined' && typeof (Sys.WebForms) != 'undefined' && typeof (Sys.WebForms.PageRequestManager) != 'undefined') { - // Get the instance of PageRequestManager. - var PageRequestManager = Sys.WebForms.PageRequestManager.getInstance(); - - PageRequestManager.add_endRequest(function (sender, args) { - if (args) { - var response = args.get_response(); - if (response.get_responseAvailable() && response._xmlHttpRequest != null) { - var stringIds = args.get_response().getResponseHeader('X-MiniProfiler-Ids'); - if (stringIds) { - var ids = typeof JSON != 'undefined' ? JSON.parse(stringIds) : eval(stringIds); - fetchResults(ids); - } - } - } - }); - } - - // more Asp.Net callbacks - if (typeof (WebForm_ExecuteCallback) == "function") { - WebForm_ExecuteCallback = (function (callbackObject) { - // Store original function - var original = WebForm_ExecuteCallback; - - return function (callbackObject) { - original(callbackObject); - - var stringIds = callbackObject.xmlRequest.getResponseHeader('X-MiniProfiler-Ids'); - if (stringIds) { - var ids = typeof JSON != 'undefined' ? JSON.parse(stringIds) : eval(stringIds); - fetchResults(ids); - } - }; - - })(); - } - - // also fetch results after ExtJS requests, in case it is being used - if (typeof (Ext) != 'undefined' && typeof (Ext.Ajax) != 'undefined' && typeof (Ext.Ajax.on) != 'undefined') { - // Ext.Ajax is a singleton, so we just have to attach to its 'requestcomplete' event - Ext.Ajax.on('requestcomplete', function (e, xhr, settings) { - //iframed file uploads don't have headers - if (!xhr || !xhr.getResponseHeader) { - return; - } - - var stringIds = xhr.getResponseHeader('X-MiniProfiler-Ids'); - if (stringIds) { - var ids = typeof JSON != 'undefined' ? JSON.parse(stringIds) : eval(stringIds); - fetchResults(ids); - } - }); - } - - if (typeof (MooTools) != 'undefined' && typeof (Request) != 'undefined') { - Request.prototype.addEvents({ - onComplete: function() { - var stringIds = this.xhr.getResponseHeader('X-MiniProfiler-Ids'); - if (stringIds) { - var ids = typeof JSON != 'undefined' ? JSON.parse(stringIds) : eval(stringIds); - fetchResults(ids); - } - } - }); - } - - // add support for AngularJS, which use the basic XMLHttpRequest object. - if (window.angular && typeof (XMLHttpRequest) != 'undefined') { - var _send = XMLHttpRequest.prototype.send; - - XMLHttpRequest.prototype.send = function sendReplacement(data) { - this._onreadystatechange = this.onreadystatechange; - - this.onreadystatechange = function onReadyStateChangeReplacement() { - if (this.readyState == 4) { - var stringIds = this.getResponseHeader('X-MiniProfiler-Ids'); - if (stringIds) { - var ids = typeof JSON != 'undefined' ? JSON.parse(stringIds) : eval(stringIds); - fetchResults(ids); - } - } - - return this._onreadystatechange.apply(this, arguments); - }; - - return _send.apply(this, arguments); - }; - } - - // some elements want to be hidden on certain doc events - bindDocumentEvents(); - }; - - return { - - init: function () { - var script = document.getElementById('mini-profiler'); - if (!script || !script.getAttribute) return; - - options = (function () { - var version = script.getAttribute('data-version'); - var path = script.getAttribute('data-path'); - - var currentId = script.getAttribute('data-current-id'); - - var ids = script.getAttribute('data-ids'); - if (ids) ids = ids.split(','); - - var position = script.getAttribute('data-position'); - - var toggleShortcut = script.getAttribute('data-toggle-shortcut'); - - if (script.getAttribute('data-max-traces')) { - var maxTraces = parseInt(script.getAttribute('data-max-traces'), 10); - } - - if (script.getAttribute('data-trivial') === 'true') var trivial = true; - if (script.getAttribute('data-children') == 'true') var children = true; - if (script.getAttribute('data-controls') == 'true') var controls = true; - if (script.getAttribute('data-authorized') == 'true') var authorized = true; - if (script.getAttribute('data-start-hidden') == 'true') var startHidden = true; - - return { - ids: ids, - path: path, - version: version, - renderPosition: position, - showTrivial: trivial, - showChildrenTime: children, - maxTracesToShow: maxTraces, - showControls: controls, - currentId: currentId, - authorized: authorized, - toggleShortcut: toggleShortcut, - startHidden: startHidden - }; - })(); - - var doInit = function () { - // when rendering a shared, full page, this div will exist - container = $('.profiler-result-full'); - if (container.length) { - if (window.location.href.indexOf("&trivial=1") > 0) { - options.showTrivial = true; - } - initFullView(); - } - else { - initPopupView(); - } - }; - - // this preserves debugging - var load = function (s, f) { - var sc = document.createElement("script"); - sc.async = "async"; - sc.type = "text/javascript"; - sc.src = s; - var done = false; - sc.onload = sc.onreadystatechange = function (_, abort) { - if (!sc.readyState || /loaded|complete/.test(sc.readyState)) { - if (!abort && !done) { done = true; f(); } - } - }; - document.getElementsByTagName('head')[0].appendChild(sc); - }; - - var wait = 0; - var finish = false; - var deferInit = function() { - if (finish) return; - if (window.performance && window.performance.timing && window.performance.timing.loadEventEnd === 0 && wait < 10000) { - setTimeout(deferInit, 100); - wait += 100; - } else { - finish = true; - init(); - } - }; - - var init = function() { - if (options.authorized) { - var url = options.path + "includes.css?v=" + options.version; - if (document.createStyleSheet) { - document.createStyleSheet(url); - } else { - $('head').append($('')); - } - if (!$.tmpl) { - load(options.path + 'jquery.tmpl.js?v=' + options.version, doInit); - } else { - doInit(); - } - } else { - doInit(); - } - - // jquery.hotkeys.js - // https://github.com/jeresig/jquery.hotkeys/blob/master/jquery.hotkeys.js - - (function(d){function h(g){if("string"===typeof g.data){var h=g.handler,j=g.data.toLowerCase().split(" ");g.handler=function(b){if(!(this!==b.target&&(/textarea|select/i.test(b.target.nodeName)||"text"===b.target.type))){var c="keypress"!==b.type&&d.hotkeys.specialKeys[b.which],e=String.fromCharCode(b.which).toLowerCase(),a="",f={};b.altKey&&"alt"!==c&&(a+="alt+");b.ctrlKey&&"ctrl"!==c&&(a+="ctrl+");b.metaKey&&(!b.ctrlKey&&"meta"!==c)&&(a+="meta+");b.shiftKey&&"shift"!==c&&(a+="shift+");c?f[a+c]= - !0:(f[a+e]=!0,f[a+d.hotkeys.shiftNums[e]]=!0,"shift+"===a&&(f[d.hotkeys.shiftNums[e]]=!0));c=0;for(e=j.length;c","/":"?","\\":"|"}};d.each(["keydown","keyup","keypress"],function(){d.event.special[this]={add:h}})})(MiniProfiler.jQuery); - - }; - - var major, minor; - if (typeof(jQuery) == 'function') { - var jQueryVersion = jQuery.fn.jquery.split('.'); - major = parseInt(jQueryVersion[0], 10); - minor = parseInt(jQueryVersion[1], 10); - } - - - if (major === 2 || (major === 1 && minor >= 7)) { - MiniProfiler.jQuery = $ = jQuery; - $(deferInit); - } else { - load(options.path + "jquery.1.7.1.js?v=" + options.version, function() { - MiniProfiler.jQuery = $ = jQuery.noConflict(true); - $(deferInit); - }); - } - }, - - getClientTimingByName: function (clientTiming, name) { - - for (var i = 0; i < clientTiming.Timings.length; i++) { - if (clientTiming.Timings[i].Name == name) { - return clientTiming.Timings[i]; - } - } - return { Name: name, Duration: "", Start: "" }; - }, - - renderDate: function (jsonDate) { // JavaScriptSerializer sends dates as /Date(1308024322065)/ - if (jsonDate) { - return (typeof jsonDate === 'string') ? new Date(parseInt(jsonDate.replace("/Date(", "").replace(")/", ""), 10)).toUTCString() : jsonDate; - } - }, - - renderIndent: function (depth) { - var result = ''; - for (var i = 0; i < depth; i++) { - result += ' '; - } - return result; - }, - - renderExecuteType: function (typeId) { - // see StackExchange.Profiling.ExecuteType enum - switch (typeId) { - case 0: return 'None'; - case 1: return 'NonQuery'; - case 2: return 'Scalar'; - case 3: return 'Reader'; - } - }, - - shareUrl: function (id) { - return options.path + 'results?id=' + id; - }, - - getClientTimings: function (clientTimings) { - var list = []; - var t; - - if (!clientTimings.Timings) return []; - - for (var i = 0; i < clientTimings.Timings.length; i++) { - t = clientTimings.Timings[i]; - var trivial = t.Name != "Dom Complete" && t.Name != "Response" && t.Name != "First Paint Time"; - trivial = t.Duration < 2 ? trivial : false; - list.push( - { - isTrivial: trivial, - name: t.Name, - duration: t.Duration, - start: t.Start - }); - } - - list.sort(function (a, b) { return a.start - b.start; }); - return list; - }, - - getSqlTimings: function (root) { - var result = [], - addToResults = function (timing) { - if (timing.SqlTimings) { - for (var i = 0, sqlTiming; i < timing.SqlTimings.length; i++) { - sqlTiming = timing.SqlTimings[i]; - - // HACK: add info about the parent Timing to each SqlTiming so UI can render - sqlTiming.ParentTimingName = timing.Name; - result.push(sqlTiming); - } - } - - if (timing.Children) { - for (var i = 0; i < timing.Children.length; i++) { - addToResults(timing.Children[i]); - } - } - }; - - // start adding at the root and recurse down - addToResults(root); - - var removeDuration = function(list, duration) { - - var newList = []; - for (var i = 0; i < list.length; i++) { - - var item = list[i]; - if (duration.start > item.start) { - if (duration.start > item.finish) { - newList.push(item); - continue; - } - newList.push({ start: item.start, finish: duration.start }); - } - - if (duration.finish < item.finish) { - if (duration.finish < item.start) { - newList.push(item); - continue; - } - newList.push({ start: duration.finish, finish: item.finish }); - } - } - - return newList; - }; - - var processTimes = function (elem, parent) { - var duration = { start: elem.StartMilliseconds, finish: (elem.StartMilliseconds + elem.DurationMilliseconds) }; - elem.richTiming = [duration]; - if (parent != null) { - elem.parent = parent; - elem.parent.richTiming = removeDuration(elem.parent.richTiming, duration); - } - - if (elem.Children) { - for (var i = 0; i < elem.Children.length; i++) { - processTimes(elem.Children[i], elem); - } - } - }; - - processTimes(root, null); - - // sort results by time - result.sort(function (a, b) { return a.StartMilliseconds - b.StartMilliseconds; }); - - var determineOverlap = function(gap, node) { - var overlap = 0; - for (var i = 0; i < node.richTiming.length; i++) { - var current = node.richTiming[i]; - if (current.start > gap.finish) { - break; - } - if (current.finish < gap.start) { - continue; - } - - overlap += Math.min(gap.finish, current.finish) - Math.max(gap.start, current.start); - } - return overlap; - }; - - var determineGap = function (gap, node, match) { - var overlap = determineOverlap(gap, node); - if (match == null || overlap > match.duration) { - match = { name: node.Name, duration: overlap }; - } - else if (match.name == node.Name) { - match.duration += overlap; - } - - if (node.Children) { - for (var i = 0; i < node.Children.length; i++) { - match = determineGap(gap, node.Children[i], match); - } - } - return match; - }; - - var time = 0; - var prev = null; - $.each(result, function () { - this.prevGap = { - duration: (this.StartMilliseconds - time).toFixed(2), - start: time, - finish: this.StartMilliseconds - }; - - this.prevGap.topReason = determineGap(this.prevGap, root, null); - - time = this.StartMilliseconds + this.DurationMilliseconds; - prev = this; - }); - - - if (result.length > 0) { - var me = result[result.length - 1]; - me.nextGap = { - duration: (root.DurationMilliseconds - time).toFixed(2), - start: time, - finish: root.DurationMilliseconds - }; - me.nextGap.topReason = determineGap(me.nextGap, root, null); - } - - return result; - }, - - getSqlTimingsCount: function (root) { - var result = 0, - countSql = function (timing) { - if (timing.SqlTimings) { - result += timing.SqlTimings.length; - } - - if (timing.Children) { - for (var i = 0; i < timing.Children.length; i++) { - countSql(timing.Children[i]); - } - } - }; - countSql(root); - return result; - }, - - fetchResultsExposed: function (ids) { - return fetchResults(ids); - }, - - formatDuration: function (duration) { - return (duration || 0).toFixed(1); - } - }; -})(); - -MiniProfiler.init(); - -if (typeof prettyPrint === "undefined") { - - // prettify.js - // http://code.google.com/p/google-code-prettify/ - - window.PR_SHOULD_USE_CONTINUATION=true;window.PR_TAB_WIDTH=8;window.PR_normalizedHtml=window.PR=window.prettyPrintOne=window.prettyPrint=void 0;window._pr_isIE6=function(){var y=navigator&&navigator.userAgent&&navigator.userAgent.match(/\bMSIE ([678])\./);y=y?+y[1]:false;window._pr_isIE6=function(){return y};return y}; - (function(){function y(b){return b.replace(L,"&").replace(M,"<").replace(N,">")}function H(b,f,i){switch(b.nodeType){case 1:var o=b.tagName.toLowerCase();f.push("<",o);var l=b.attributes,n=l.length;if(n){if(i){for(var r=[],j=n;--j>=0;)r[j]=l[j];r.sort(function(q,m){return q.name"); - for(l=b.firstChild;l;l=l.nextSibling)H(l,f,i);if(b.firstChild||!/^(?:br|link|img)$/.test(o))f.push("");break;case 3:case 4:f.push(y(b.nodeValue));break}}function O(b){function f(c){if(c.charAt(0)!=="\\")return c.charCodeAt(0);switch(c.charAt(1)){case "b":return 8;case "t":return 9;case "n":return 10;case "v":return 11;case "f":return 12;case "r":return 13;case "u":case "x":return parseInt(c.substring(2),16)||c.charCodeAt(1);case "0":case "1":case "2":case "3":case "4":case "5":case "6":case "7":return parseInt(c.substring(1), - 8);default:return c.charCodeAt(1)}}function i(c){if(c<32)return(c<16?"\\x0":"\\x")+c.toString(16);c=String.fromCharCode(c);if(c==="\\"||c==="-"||c==="["||c==="]")c="\\"+c;return c}function o(c){var d=c.substring(1,c.length-1).match(RegExp("\\\\u[0-9A-Fa-f]{4}|\\\\x[0-9A-Fa-f]{2}|\\\\[0-3][0-7]{0,2}|\\\\[0-7]{1,2}|\\\\[\\s\\S]|-|[^-\\\\]","g"));c=[];for(var a=[],k=d[0]==="^",e=k?1:0,h=d.length;e122)){s<65||g>90||a.push([Math.max(65,g)|32,Math.min(s,90)|32]);s<97||g>122||a.push([Math.max(97,g)&-33,Math.min(s,122)&-33])}}a.sort(function(v,w){return v[0]-w[0]||w[1]-v[1]});d=[];g=[NaN,NaN];for(e=0;eh[0]){h[1]+1>h[0]&&a.push("-"); - a.push(i(h[1]))}}a.push("]");return a.join("")}function l(c){for(var d=c.source.match(RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g")),a=d.length,k=[],e=0,h=0;e=2&&c==="[")d[e]=o(g);else if(c!=="\\")d[e]=g.replace(/[a-zA-Z]/g,function(s){s=s.charCodeAt(0);return"["+String.fromCharCode(s&-33,s|32)+"]"})}return d.join("")}for(var n=0,r=false,j=false,q=0,m=b.length;q=0;l-=16)o.push(" ".substring(0,l));l=n+1;break;case "\n":f=0;break;default:++f}if(!o)return i;o.push(i.substring(l));return o.join("")}}function I(b, - f,i,o){if(f){b={source:f,c:b};i(b);o.push.apply(o,b.d)}}function B(b,f){var i={},o;(function(){for(var r=b.concat(f),j=[],q={},m=0,t=r.length;m=0;)i[c.charAt(d)]=p;p=p[1];c=""+p;if(!q.hasOwnProperty(c)){j.push(p);q[c]=null}}j.push(/[\0-\uffff]/);o=O(j)})();var l=f.length;function n(r){for(var j=r.c,q=[j,z],m=0,t=r.source.match(o)||[],p={},c=0,d=t.length;c=5&&"lang-"===k.substring(0,5))&&!(e&&typeof e[1]==="string")){h=false;k=P}h||(p[a]=k)}g=m;m+=a.length;if(h){h=e[1];var s=a.indexOf(h),v=s+h.length;if(e[2]){v=a.length-e[2].length;s=v-h.length}k=k.substring(5);I(j+g,a.substring(0,s),n,q);I(j+g+s,h,Q(k,h),q);I(j+g+v,a.substring(v),n,q)}else q.push(j+g,k)}r.d=q}return n}function x(b){var f=[],i=[];if(b.tripleQuotedStrings)f.push([A,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/, - null,"'\""]);else b.multiLineStrings?f.push([A,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"]):f.push([A,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"]);b.verbatimStrings&&i.push([A,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null]);if(b.hashComments)if(b.cStyleComments){f.push([C,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"]);i.push([A,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/, - null])}else f.push([C,/^#[^\r\n]*/,null,"#"]);if(b.cStyleComments){i.push([C,/^\/\/[^\r\n]*/,null]);i.push([C,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}b.regexLiterals&&i.push(["lang-regex",RegExp("^"+Z+"(/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/)")]);b=b.keywords.replace(/^\s+|\s+$/g,"");b.length&&i.push([R,RegExp("^(?:"+b.replace(/\s+/g,"|")+")\\b"),null]);f.push([z,/^\s+/,null," \r\n\t\u00a0"]);i.push([J,/^@[a-z_$][a-z_$@0-9]*/i,null],[S,/^@?[A-Z]+[a-z][A-Za-z_$@0-9]*/, - null],[z,/^[a-z_$][a-z_$@0-9]*/i,null],[J,/^(?:0x[a-f0-9]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+\-]?\d+)?)[a-z]*/i,null,"0123456789"],[E,/^.[^\s\w\.$@\'\"\`\/\#]*/,null]);return B(f,i)}function $(b){function f(D){if(D>r){if(j&&j!==q){n.push("");j=null}if(!j&&q){j=q;n.push('')}var T=y(p(i.substring(r,D))).replace(e?d:c,"$1 ");e=k.test(T);n.push(T.replace(a,s));r=D}}var i=b.source,o=b.g,l=b.d,n=[],r=0,j=null,q=null,m=0,t=0,p=Y(window.PR_TAB_WIDTH),c=/([\r\n ]) /g, - d=/(^| ) /gm,a=/\r\n?|\n/g,k=/[ \r\n]$/,e=true,h=window._pr_isIE6();h=h?b.b.tagName==="PRE"?h===6?" \r\n":h===7?" 
\r":" \r":" 
":"
";var g=b.b.className.match(/\blinenums\b(?::(\d+))?/),s;if(g){for(var v=[],w=0;w<10;++w)v[w]=h+'
  • ';var F=g[1]&&g[1].length?g[1]-1:0;n.push('
    1. ");s=function(){var D=v[++F%10];return j?""+D+'':D}}else s=h; - for(;;)if(m");j=null}n.push(o[m+1]);m+=2}else if(t");g&&n.push("
    ");b.a=n.join("")}function u(b,f){for(var i=f.length;--i>=0;){var o=f[i];if(G.hasOwnProperty(o))"console"in window&&console.warn("cannot override language handler %s",o);else G[o]=b}}function Q(b,f){b&&G.hasOwnProperty(b)||(b=/^\s*1&&m.charAt(0)==="<"){if(!ba.test(m))if(ca.test(m)){f.push(m.substring(9,m.length-3));n+=m.length-12}else if(da.test(m)){f.push("\n");++n}else if(m.indexOf(V)>=0&&m.replace(/\s(\w+)\s*=\s*(?:\"([^\"]*)\"|'([^\']*)'|(\S+))/g,' $1="$2$3$4"').match(/[cC][lL][aA][sS][sS]=\"[^\"]*\bnocode\b/)){var t=m.match(W)[2],p=1,c;c=j+1;a:for(;c=0;){var e=p.indexOf(";",k);if(e>=0){var h=p.substring(k+3,e),g=10;if(h&&h.charAt(0)==="x"){h=h.substring(1);g=16}var s=parseInt(h,g);isNaN(s)||(p=p.substring(0,k)+String.fromCharCode(s)+p.substring(e+1))}}a=p.replace(ea,"<").replace(fa,">").replace(ga,"'").replace(ha,'"').replace(ia," ").replace(ja, - "&")}f.push(a);n+=a.length}}o={source:f.join(""),h:r};var v=o.source;b.source=v;b.c=0;b.g=o.h;Q(i,v)(b);$(b)}catch(w){if("console"in window)console.log(w&&w.stack?w.stack:w)}}var A="str",R="kwd",C="com",S="typ",J="lit",E="pun",z="pln",P="src",V="nocode",Z=function(){for(var b=["!","!=","!==","#","%","%=","&","&&","&&=","&=","(","*","*=","+=",",","-=","->","/","/=",":","::",";","<","<<","<<=","<=","=","==","===",">",">=",">>",">>=",">>>",">>>=","?","@","[","^","^=","^^","^^=","{","|","|=","||","||=", - "~","break","case","continue","delete","do","else","finally","instanceof","return","throw","try","typeof"],f="(?:^^|[+-]",i=0;i:&a-z])/g,"\\$1");f+=")\\s*";return f}(),L=/&/g,M=//g,X=/\"/g,ea=/</g,fa=/>/g,ga=/'/g,ha=/"/g,ja=/&/g,ia=/ /g,ka=/[\r\n]/g,K=null,aa=RegExp("[^<]+|