tuttle 0.0.6 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +17 -0
  3. data/Rakefile +0 -1
  4. data/app/controllers/tuttle/active_job_controller.rb +1 -0
  5. data/app/controllers/tuttle/active_model_serializers_controller.rb +1 -0
  6. data/app/controllers/tuttle/active_support_controller.rb +1 -0
  7. data/app/controllers/tuttle/application_controller.rb +19 -2
  8. data/app/controllers/tuttle/cancancan_controller.rb +2 -0
  9. data/app/controllers/tuttle/devise_controller.rb +1 -0
  10. data/app/controllers/tuttle/execjs_controller.rb +12 -0
  11. data/app/controllers/tuttle/gems_controller.rb +3 -2
  12. data/app/controllers/tuttle/home_controller.rb +1 -0
  13. data/app/controllers/tuttle/i18n_controller.rb +27 -0
  14. data/app/controllers/tuttle/paperclip_controller.rb +1 -0
  15. data/app/controllers/tuttle/rack_attack_controller.rb +26 -0
  16. data/app/controllers/tuttle/rack_mini_profiler_controller.rb +1 -0
  17. data/app/controllers/tuttle/rails_controller.rb +19 -5
  18. data/app/controllers/tuttle/request_controller.rb +1 -0
  19. data/app/controllers/tuttle/ruby_controller.rb +15 -2
  20. data/app/helpers/tuttle/application_helper.rb +64 -2
  21. data/app/models/tuttle/configuration_registry.rb +1 -0
  22. data/app/models/tuttle/version_detector.rb +1 -0
  23. data/app/views/layouts/tuttle/application.html.erb +22 -6
  24. data/app/views/tuttle/active_support/dependencies.html.erb +7 -7
  25. data/app/views/tuttle/active_support/inflectors.html.erb +1 -1
  26. data/app/views/tuttle/cancancan/index.html.erb +1 -1
  27. data/app/views/tuttle/cancancan/rule_tester.html.erb +3 -3
  28. data/app/views/tuttle/execjs/index.html.erb +87 -0
  29. data/app/views/tuttle/gems/http_clients.html.erb +13 -12
  30. data/app/views/tuttle/gems/index.html.erb +4 -4
  31. data/app/views/tuttle/gems/json.html.erb +10 -10
  32. data/app/views/tuttle/home/index.html.erb +6 -6
  33. data/app/views/tuttle/i18n/_translation_entry.html.erb +10 -0
  34. data/app/views/tuttle/i18n/index.html.erb +111 -0
  35. data/app/views/tuttle/i18n/localize.html.erb +53 -0
  36. data/app/views/tuttle/i18n/translations.html.erb +12 -0
  37. data/app/views/tuttle/rack_attack/index.html.erb +227 -0
  38. data/app/views/tuttle/rails/assets.html.erb +4 -4
  39. data/app/views/tuttle/rails/cache.html.erb +4 -8
  40. data/app/views/tuttle/rails/controllers.html.erb +54 -7
  41. data/app/views/tuttle/rails/database.html.erb +14 -1
  42. data/app/views/tuttle/rails/engines.html.erb +1 -1
  43. data/app/views/tuttle/rails/helpers.html.erb +1 -1
  44. data/app/views/tuttle/rails/index.html.erb +72 -19
  45. data/app/views/tuttle/rails/models.html.erb +150 -73
  46. data/app/views/tuttle/rails/routes.html.erb +10 -8
  47. data/app/views/tuttle/rails/schema_cache.html.erb +2 -2
  48. data/app/views/tuttle/ruby/constants.html.erb +29 -0
  49. data/app/views/tuttle/ruby/extensions.html.erb +24 -0
  50. data/app/views/tuttle/ruby/index.html.erb +21 -15
  51. data/app/views/tuttle/ruby/tuning.html.erb +6 -9
  52. data/config/routes.rb +15 -1
  53. data/lib/tuttle.rb +1 -0
  54. data/lib/tuttle/engine.rb +3 -4
  55. data/lib/tuttle/instrumenter.rb +3 -1
  56. data/lib/tuttle/middleware/request_profiler.rb +11 -11
  57. data/lib/tuttle/presenters/action_dispatch/routing/route_wrapper.rb +34 -2
  58. data/lib/tuttle/presenters/active_record/reflection_presenter.rb +54 -0
  59. data/lib/tuttle/presenters/active_support/callbacks.rb +26 -0
  60. data/lib/tuttle/presenters/base_presenter.rb +19 -0
  61. data/lib/tuttle/presenters/rack_mini_profiler/client_settings.rb +1 -0
  62. data/lib/tuttle/ruby_prof/fast_call_stack_printer.rb +2 -1
  63. data/lib/tuttle/version.rb +2 -1
  64. metadata +27 -18
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 49cad804b33f2b81f6a9bc6a2e6504e4cf37c962
4
- data.tar.gz: e8e15e4dee3836b696168ad3a89b102b4f4af856
2
+ SHA256:
3
+ metadata.gz: 9a62a3da7ea3c2565f1f91d6b9a446b95a951dbc2b3ac140102f27fc7f49c1bb
4
+ data.tar.gz: bcad3944fdbf4fc00790142e0de00318a8bbc52fae9bf3e8ad1811cfdace59e5
5
5
  SHA512:
6
- metadata.gz: a03f4de6b82666e963e1b6c1b5b4347389e8a2cd5ae00a2ece02953954a84d17fb37668adf43e88a473263cd15780e59afb8adbc66b11e2e1472f89ebb3d54a3
7
- data.tar.gz: a8b9074ed5bbcfeae270e7b2ab875710acd826b383e76f3e2169945f23df06c20f542cad4f35821bbcfe88fb902db747110b4da6439fc40e22956365be0a3bf0
6
+ metadata.gz: 7e0f1e91acf1a8775c379136e09b84749b6e29af8a1728209236867764ed78c07c606ab059d6781137961070771b6ec343df5e8fbb6de513e8d1d9876b846961
7
+ data.tar.gz: 56aa10ea1db3241284ca712a867c8752554fcfeb34e1a23c15f664fedfed1d9e796cf2b79010a5004a31b4479a10f4109008bff9be708a4cd02d10c0b71b8ff2
@@ -1,3 +1,20 @@
1
+ ### 0.0.8
2
+
3
+ * Features
4
+ * New ExecJS inspector
5
+ * New Rack::Attack inspector
6
+ * Improved ActiveRecord models inspector with associations and validations
7
+ * Improved Rails Controllers link to matched routes (excluding wildcards and implicit renders)
8
+
9
+ ### 0.0.7
10
+
11
+ * Features
12
+ * Rails 5.1 support (drops Rails 4.0)
13
+ * New I18n inspector
14
+ * New Constants and Object extensions inspector
15
+ * Improved Rails routes inspector to show route validity
16
+ * Improved listing display formatting
17
+
1
18
  ### 0.0.6
2
19
 
3
20
  * Features
data/Rakefile CHANGED
@@ -1,4 +1,3 @@
1
- #!/usr/bin/env rake
2
1
  begin
3
2
  require 'bundler/setup'
4
3
  rescue LoadError
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require_dependency 'tuttle/application_controller'
2
3
 
3
4
  module Tuttle
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require_dependency 'tuttle/application_controller'
2
3
 
3
4
  module Tuttle
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require_dependency 'tuttle/application_controller'
2
3
 
3
4
  module Tuttle
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
1
2
  module Tuttle
2
3
  class ApplicationController < ActionController::Base
3
4
  abstract!
4
5
  protect_from_forgery with: :exception
5
6
 
6
7
  before_action :check_reload_status
8
+ around_action :set_locale
7
9
 
8
10
  private
9
11
 
@@ -11,8 +13,23 @@ module Tuttle
11
13
  return unless Tuttle::Engine.reload_needed && !Rails.configuration.eager_load
12
14
  Tuttle::Engine.logger.warn('Eager-loading application')
13
15
  ActiveSupport::Notifications.instrument 'tuttle.perform_eager_load' do
14
- Rails.application.eager_load!
15
- Tuttle::Engine.reload_needed = false
16
+ begin
17
+ Rails.application.eager_load!
18
+ rescue
19
+ Tuttle::Engine.logger.warn('Failed to eager-load application')
20
+ ensure
21
+ Tuttle::Engine.reload_needed = false
22
+ end
23
+ end
24
+ end
25
+
26
+ def set_locale
27
+ if params[:hl] && I18n.locale_available?(params[:hl])
28
+ I18n.with_locale(params[:hl]) do
29
+ yield
30
+ end
31
+ else
32
+ yield
16
33
  end
17
34
  end
18
35
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require_dependency 'tuttle/application_controller'
2
3
 
3
4
  module Tuttle
@@ -6,6 +7,7 @@ module Tuttle
6
7
  def index
7
8
  @cancan_user = current_user || User.new
8
9
  @ability = Ability.new(@cancan_user)
10
+ @rules = @ability.instance_variable_get('@rules')
9
11
  end
10
12
 
11
13
  def rule_tester
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require_dependency 'tuttle/application_controller'
2
3
  require 'devise/version' if defined?(Devise)
3
4
 
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ require_dependency 'tuttle/application_controller'
3
+ require 'execjs/version' if defined?(::ExecJS)
4
+
5
+ module Tuttle
6
+ class ExecjsController < ApplicationController
7
+
8
+ def index
9
+ end
10
+
11
+ end
12
+ end
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
1
2
  require_dependency 'tuttle/application_controller'
2
3
 
3
4
  module Tuttle
4
5
  class GemsController < ApplicationController
5
6
 
6
7
  def index
8
+ @gemspecs = Bundler.rubygems.all_specs.sort_by(&:name)
7
9
  end
8
10
 
9
11
  def http_clients
@@ -12,8 +14,7 @@ module Tuttle
12
14
  def json
13
15
  end
14
16
 
15
- # rubocop:disable Style/AccessorMethodName
16
- def get_process_mem
17
+ def get_process_mem # rubocop:disable Naming/AccessorMethodName
17
18
  require 'get_process_mem'
18
19
  require 'get_process_mem/version'
19
20
  @memory_self = GetProcessMem.new
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require_dependency 'tuttle/application_controller'
2
3
  require 'tuttle/version'
3
4
 
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+ require_dependency 'tuttle/application_controller'
3
+
4
+ module Tuttle
5
+ class I18nController < ApplicationController
6
+
7
+ before_action :set_sorted_locales
8
+
9
+ def index
10
+ end
11
+
12
+ def localize
13
+ end
14
+
15
+ def translations
16
+ @translations = I18n.backend.send(:translations)
17
+ end
18
+
19
+ private
20
+
21
+ def set_sorted_locales
22
+ @sorted_locales = [I18n.default_locale] +
23
+ (I18n.available_locales.map(&:to_s).sort.map(&:to_sym) - [I18n.default_locale])
24
+ end
25
+
26
+ end
27
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require_dependency 'tuttle/application_controller'
2
3
  require 'paperclip/version' if defined?(Paperclip)
3
4
 
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+ require_dependency 'tuttle/application_controller'
3
+
4
+ module Tuttle
5
+ class RackAttackController < ApplicationController
6
+
7
+ def index
8
+ require 'rack/attack/version'
9
+ if ::Rack::Attack::VERSION < '5'
10
+ render plain: 'Tuttle Rack::Attack support requires version 5.x' && return
11
+ end
12
+
13
+ default_keys = %w[rack.attack.matched rack.attack.match_discriminator rack.attack.match_type rack.attack.match_data]
14
+ rack_attack_env_vars = request.env.select { |k, _v| k.to_s.start_with?('rack.attack') }
15
+ @rack_attack_env_settings = (rack_attack_env_vars.keys + default_keys).uniq
16
+
17
+ @throttles = Rack::Attack.throttles
18
+ @safelists = Rack::Attack.safelists
19
+ @blocklists = Rack::Attack.blocklists
20
+ @tracks = Rack::Attack.tracks
21
+
22
+ @asn_listeners = ActiveSupport::Notifications.notifier.listeners_for("rack.attack")
23
+ end
24
+
25
+ end
26
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require_dependency 'tuttle/application_controller'
2
3
 
3
4
  module Tuttle
@@ -1,6 +1,9 @@
1
+ # frozen_string_literal: true
1
2
  require 'rails/generators'
2
3
  require_dependency 'tuttle/application_controller'
3
4
  require_dependency 'tuttle/presenters/action_dispatch/routing/route_wrapper'
5
+ require_dependency 'tuttle/presenters/active_support/callbacks'
6
+ require_dependency 'tuttle/presenters/active_record/reflection_presenter'
4
7
 
5
8
  module Tuttle
6
9
  class RailsController < ApplicationController
@@ -10,12 +13,23 @@ module Tuttle
10
13
  end
11
14
 
12
15
  def controllers
13
- # TODO: Both ObjectSpace and .descendants approaches have issues with class reloading during development
16
+ @routes = Rails.application.routes.routes.collect do |route|
17
+ Tuttle::Presenters::ActionDispatch::Routing::RouteWrapper.new(route)
18
+ end
19
+
14
20
  # It seems likely that .descendants will work best when Tuttle and Rails classes are not modified
15
21
  # but both approaches also require eager_load to be true
16
22
  # @controllers = ObjectSpace.each_object(::Class).select {|klass| klass < ActionController::Base }
17
23
  @controllers = ActionController::Base.descendants
18
- @controllers.reject! {|controller| controller <= Tuttle::ApplicationController || controller.abstract?}
24
+ @controllers.reject! do |controller|
25
+ controller.abstract? || controller <= Tuttle::ApplicationController
26
+ end
27
+
28
+ # Rails 5.1 introduced Rails::ApplicationController which really should be abstract
29
+ if defined?(Rails::ApplicationController)
30
+ @controllers.reject! { |controller| controller == Rails::ApplicationController }
31
+ end
32
+
19
33
  @controllers.sort_by!(&:name)
20
34
  end
21
35
 
@@ -24,12 +38,12 @@ module Tuttle
24
38
  end
25
39
 
26
40
  def generators
27
- Rails::Generators.lookup! if 'true' == params[:load_all_generators]
41
+ Rails::Generators.lookup! if params[:load_all_generators] == 'true'
28
42
  @generators = Rails::Generators.subclasses.group_by(&:base_name)
29
43
  end
30
44
 
31
45
  def models
32
- @models = ActiveRecord::Base.descendants
46
+ @models = ActiveRecord::Base.descendants.reject { |model| model.abstract_class? || !model.table_exists? }
33
47
  @models.sort_by!(&:name)
34
48
  end
35
49
 
@@ -101,7 +115,7 @@ module Tuttle
101
115
 
102
116
  def recognize_paths(path)
103
117
  results = {}
104
- [:get, :post, :put, :delete, :patch].each {|method| results[method] = recognize_path(path, method: method)}
118
+ %i[get post put delete patch].each {|method| results[method] = recognize_path(path, method: method)}
105
119
  results
106
120
  end
107
121
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require_dependency 'tuttle/application_controller'
2
3
 
3
4
  module Tuttle
@@ -1,4 +1,4 @@
1
- # frozen-string-literal: true
1
+ # frozen_string_literal: true
2
2
 
3
3
  require_dependency 'tuttle/application_controller'
4
4
 
@@ -18,7 +18,6 @@ module Tuttle
18
18
  @gc_enabled = (GC.disable ? false : GC.enable)
19
19
 
20
20
  # taken verbatim from the ruby 2.2 man page
21
- # rubocop:disable Metrics/LineLength
22
21
  @gc_params = {
23
22
  'RUBY_GC_HEAP_INIT_SLOTS' => 'Initial allocation slots. Introduced in Ruby 2.1, default: 10000.',
24
23
  'RUBY_GC_HEAP_FREE_SLOTS' => 'Prepare at least this amount of slots after GC. Allocate this number slots if there are not enough slots. Introduced in Ruby 2.1, default: 4096',
@@ -37,5 +36,19 @@ module Tuttle
37
36
  def miscellaneous
38
37
  end
39
38
 
39
+ def constants
40
+ # Global constants minus a few deprecated constants (to prevent warnings)
41
+ @constants = (Object.constants - %i[Bignum Fixnum NIL TRUE FALSE TimeoutError Data]).
42
+ sort.
43
+ map { |sym| [sym, Object.const_get(sym).class, Object.const_get(sym)] }.
44
+ reject { |_sym, klass, _val| klass == Class || klass == Module }
45
+ end
46
+
47
+ def extensions
48
+ @obj_extensions = Object.methods.select { |meth| Object.method(meth).source_location }.
49
+ sort.
50
+ map { |meth| [meth, *Object.method(meth).source_location] }
51
+ end
52
+
40
53
  end
41
54
  end
@@ -1,12 +1,19 @@
1
- # frozen-string-literal: true
2
-
1
+ # frozen_string_literal: true
3
2
  module Tuttle
4
3
  module ApplicationHelper
4
+ BUNDLER_GEM_PATHS_REGEX = %r{(#{Bundler.rubygems.gem_dir}|#{File.realpath(Bundler.rubygems.gem_dir)})+(/bundler)*/gems}
5
+
6
+ # Display true/false label with text overrides
5
7
  def truth_label(is_true, true_label = 'true', false_label = 'false')
6
8
  content_tag(:span, is_true ? true_label : false_label,
7
9
  class: ['label', is_true ? 'label-success' : 'label-danger'])
8
10
  end
9
11
 
12
+ # Display label if condition is true
13
+ def true_label(is_true, true_label = 'true')
14
+ content_tag(:span, true_label, class: %w[label label-success]) if is_true
15
+ end
16
+
10
17
  def tuttle_redacted(enumarator)
11
18
  enumarator.collect do |key, value|
12
19
  yield key, redact_by_key(key, value)
@@ -21,10 +28,65 @@ module Tuttle
21
28
  main_app.respond_to?(:root_url) ? main_app.root_url : '/'
22
29
  end
23
30
 
31
+ def link_to_rails_guide(file, title)
32
+ content_tag(:a, title, :href => rails_guides_versioned_url(file + '.html'))
33
+ end
34
+
24
35
  def rails_guides_versioned_url(path)
25
36
  "http://guides.rubyonrails.org/v#{Tuttle::VersionDetector.rails_major_minor}/#{path}"
26
37
  end
27
38
 
39
+ def display_path(path)
40
+ return if path.blank?
41
+ display_location =
42
+ if path.start_with?(Rails.root.to_s)
43
+ path.sub(Rails.root.to_s, "$RAILS_ROOT")
44
+ elsif File.realpath(path).start_with?(File.realpath(Bundler.rubygems.gem_dir))
45
+ File.realpath(path).sub(BUNDLER_GEM_PATHS_REGEX, "$GEMS")
46
+ else
47
+ path
48
+ end
49
+ expanded_path = File.expand_path(path)
50
+ content_tag(:span, display_location, :class => 'tuttle-path', :data => { :initial => path, :expanded => expanded_path })
51
+ end
52
+
53
+ def display_source_locaction(path, line)
54
+ return content_tag(:span, "Unknown", :class => 'tuttle-path') if path.nil?
55
+
56
+ display_location = file_location(path)
57
+ expanded_path = File.expand_path(path)
58
+ content_tag(:span, :class => 'tuttle-path', :data => { :initial => path, :expanded => expanded_path }) do
59
+ "#{display_location}##{line}"
60
+ end
61
+ end
62
+
63
+ def file_location(path)
64
+ if path.start_with?(Rails.root.to_s)
65
+ path.gsub(Rails.root.to_s, "$RAILS_ROOT")
66
+ elsif path.start_with?(RbConfig::CONFIG['rubylibdir'])
67
+ path.gsub(RbConfig::CONFIG['rubylibdir'], "$RUBY_LIB_DIR")
68
+ elsif path == "<internal:prelude>"
69
+ path
70
+ elsif File.realpath(path).start_with?(File.realpath(Bundler.rubygems.gem_dir))
71
+ File.realpath(path).gsub(BUNDLER_GEM_PATHS_REGEX, "$GEMS")
72
+ else
73
+ path
74
+ end
75
+ end
76
+
77
+ def value_inspect(val, hide_nil: false)
78
+ case val
79
+ when NilClass
80
+ content_tag(:code, val.inspect) unless hide_nil
81
+ when String
82
+ content_tag(:code, val.inspect)
83
+ when Symbol
84
+ content_tag(:code, val.inspect)
85
+ else
86
+ val.inspect
87
+ end
88
+ end
89
+
28
90
  private
29
91
 
30
92
  def redact_by_key(key, value)
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Tuttle
2
3
  class ConfigurationRegistry
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Tuttle
2
3
  class VersionDetector
3
4
 
@@ -2,28 +2,30 @@
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="utf-8">
5
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
6
5
  <meta name="viewport" content="width=device-width, initial-scale=1">
7
6
  <title>Tuttle</title>
8
7
  <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
9
8
  <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
10
- <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css" integrity="sha384-T8Gy5hrqNKT+hzMclPo118YTQO6cYprQmhrYwIiQ/3axmI1hQomh7Ud2hPOy8SP1" crossorigin="anonymous">
11
- <%= stylesheet_link_tag "//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.6.0/styles/default.min.css" %>
9
+ <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
10
+ <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/github.min.css" integrity="sha256-3YM6A3pH4QFCl9WbSU8oXF5N6W/2ylvW0o2g+Z6TmLQ=" crossorigin="anonymous" />
12
11
  <%= content_for(:stylesheets) -%>
13
12
  <link rel="icon" href="//s3.amazonaws.com/tuttle-assets/images/favicon.ico">
14
13
  <style>
15
14
  html { overflow: -moz-scrollbars-vertical; overflow-y: scroll; }
16
15
  body { padding-top: 50px; }
17
16
  table.not-wide { width: auto; }
18
- pre code.hljs { background-color: #f5f5f5; }
17
+ table code { color: black; background-color: inherit; padding: 0; }
18
+ table.table-condensed tbody tr td:first-child { padding-left: 0; }
19
+ table .nowrap { white-space: nowrap; }
19
20
  a[href*="github.com"] { white-space: nowrap; }
20
21
  a[href*="github.com"]:after { font-family: FontAwesome; content: "\f09b"; display: inline-block; color: initial; padding-left: 3px; }
22
+ details :focus { outline: none; }
21
23
  </style>
22
24
  <%= csrf_meta_tags %>
23
25
  </head>
24
26
  <body>
25
27
 
26
- <nav class="navbar-wrapper navbar-inverse navbar-fixed-top" role="navigation">
28
+ <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
27
29
  <div class="container">
28
30
  <div class="navbar-header">
29
31
  <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">
@@ -50,6 +52,12 @@
50
52
  <li><%= link_to 'Asset Pipeline', rails_assets_path %></li>
51
53
  <li><%= link_to 'Caching', rails_cache_path %></li>
52
54
  <li role="separator" class="divider"></li>
55
+ <%- if defined?(::I18n) %>
56
+ <li><%= link_to 'Internationalization', i18n_path %></li>
57
+ <li><%= link_to 'Localization', i18n_localize_path %></li>
58
+ <li><%= link_to 'Translations', i18n_translations_path %></li>
59
+ <li role="separator" class="divider"></li>
60
+ <% end %>
53
61
  <li><%= link_to 'Database', rails_database_path %></li>
54
62
  <li><%= link_to 'Schema Cache', rails_schema_cache_path %></li>
55
63
  <li role="separator" class="divider"></li>
@@ -88,6 +96,12 @@
88
96
  <%- if defined?(::GetProcessMem) %>
89
97
  <li><%= link_to 'GetProcessMem', gems_get_process_mem_path %></li>
90
98
  <%- end %>
99
+ <%- if defined?(::ExecJS) %>
100
+ <li><%= link_to 'ExecJS', execjs_path %></li>
101
+ <%- end %>
102
+ <%- if defined?(::Rack::Attack) %>
103
+ <li><%= link_to 'Rack::Attack', rack_attack_path %></li>
104
+ <%- end %>
91
105
  <li><%= link_to 'HTTP Clients', gems_http_clients_path %></li>
92
106
  <li><%= link_to 'JSON', gems_json_path %></li>
93
107
  <li><%= link_to 'Other', gems_other_path %></li>
@@ -99,6 +113,8 @@
99
113
  <li><%= link_to 'Overview', ruby_path %></li>
100
114
  <li class="divider"></li>
101
115
  <li><%= link_to 'Tuning', ruby_tuning_path %></li>
116
+ <li><%= link_to 'Extensions', ruby_extensions_path %></li>
117
+ <li><%= link_to 'Constants', ruby_constants_path %></li>
102
118
  <li><%= link_to 'Miscellaneous', ruby_miscellaneous_path %></li>
103
119
  </ul>
104
120
  </li>
@@ -115,7 +131,7 @@
115
131
 
116
132
  <script src="//code.jquery.com/jquery-2.2.4.min.js" integrity="sha384-rY/jv8mMhqDabXSo+UCggqKtdmBfd3qC2/KvyTDNQ6PcUJXaxK1tMepoQda4g5vB" crossorigin="anonymous"></script>
117
133
  <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
118
- <%= javascript_include_tag "//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/highlight.min.js" %>
134
+ <script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js" integrity="sha256-/BfiIkHlHoVihZdc6TFuj7MmJ0TWcWsMXkeDFwhi0zw=" crossorigin="anonymous"></script>
119
135
  <%= content_for(:javascripts) -%>
120
136
  <script>hljs.initHighlightingOnLoad();</script>
121
137
  </body>